From 12e65d01b8b1399995811a67ac1af2a93ad0e1e6 Mon Sep 17 00:00:00 2001 From: ysyneu <9045284+ysyneu@users.noreply.github.com> Date: Sun, 18 Oct 2026 05:52:49 +0000 Subject: [PATCH] chore: sync OpenAPI spec from flashduty-docs + regenerate --- a2a_agents.go | 2 +- alert_enrichment.go | 14 +- alert_rules.go | 8 +- alerts.go | 4 +- analytics.go | 16 +- applications.go | 2 +- artifacts.go | 2 +- automations.go | 16 +- calendars.go | 14 +- channels.go | 72 +- dashboards.go | 4 +- data_sources.go | 10 +- diagnostics.go | 2 +- error_ingestion_rules.go | 2 +- incidents.go | 60 +- issues.go | 2 +- members.go | 10 +- models_gen.go | 3979 +-- notification_templates.go | 8 +- openapi/openapi.en.json | 53171 +++++++++++++++++++----------------- openapi/openapi.zh.json | 52575 ++++++++++++++++++----------------- roles_permissions.go | 8 +- rule_folders.go | 8 +- schedules.go | 14 +- sessions.go | 4 +- skills.go | 2 +- sourcemaps.go | 2 +- status_pages.go | 34 +- teams.go | 2 +- 29 files changed, 57463 insertions(+), 52584 deletions(-) diff --git a/a2a_agents.go b/a2a_agents.go index 8d69067..ec96ff0 100644 --- a/a2a_agents.go +++ b/a2a_agents.go @@ -9,7 +9,7 @@ type A2aAgentsService service // Get A2A agent detail. // -// Get one A2A agent by ID. +// Return one A2A agent's configuration by ID, with auth secrets masked. // // API: POST /safari/a2a-agent/get (remote-agent-read-get). func (s *A2aAgentsService) ReadGet(ctx context.Context, req *A2aAgentIDRequest) (*A2aAgentItem, *Response, error) { diff --git a/alert_enrichment.go b/alert_enrichment.go index 9b8c161..63bcfd8 100644 --- a/alert_enrichment.go +++ b/alert_enrichment.go @@ -37,7 +37,7 @@ func (s *AlertEnrichmentService) EnrichmentReadList(ctx context.Context, req *En // Upsert enrichment rules. // -// Create or fully replace the enrichment rule set for an integration. The entire `rules` array is replaced atomically. +// Create or replace the whole enrichment rule set of an integration. // // API: POST /enrichment/upsert (enrichment-write-upsert). func (s *AlertEnrichmentService) EnrichmentWriteUpsert(ctx context.Context, req *EnrichmentUpsertRequest) (*Response, error) { @@ -120,7 +120,7 @@ func (s *AlertEnrichmentService) MappingAPIReadInfo(ctx context.Context, req *Ma // List mapping APIs. // -// Return all mapping APIs configured for the account. +// Return all mapping APIs of the account, newest first. // // API: POST /enrichment/mapping/api/list (mapping-api-read-list). func (s *AlertEnrichmentService) MappingAPIReadList(ctx context.Context) (*MappingAPIListResponse, *Response, error) { @@ -134,7 +134,7 @@ func (s *AlertEnrichmentService) MappingAPIReadList(ctx context.Context) (*Mappi // Create mapping API. // -// Create a new external HTTP API endpoint used to enrich alerts via HTTP lookup. +// Register an external HTTP API that enrichment rules call to look up alert labels. // // API: POST /enrichment/mapping/api/create (mapping-api-write-create). func (s *AlertEnrichmentService) MappingAPIWriteCreate(ctx context.Context, req *MappingAPICreateRequest) (*MappingAPICreateResponse, *Response, error) { @@ -148,7 +148,7 @@ func (s *AlertEnrichmentService) MappingAPIWriteCreate(ctx context.Context, req // Delete mapping API. // -// Delete a mapping API. Deletion is blocked if the API is referenced by any enrichment rule. +// Soft-delete a mapping API; refused while an enrichment rule uses it. // // API: POST /enrichment/mapping/api/delete (mapping-api-write-delete). func (s *AlertEnrichmentService) MappingAPIWriteDelete(ctx context.Context, req *MappingApiidRequest) (*Response, error) { @@ -237,7 +237,7 @@ func (s *AlertEnrichmentService) MappingSchemaReadInfo(ctx context.Context, req // List mapping schemas. // -// Return all mapping schemas for the account, sorted by creation time ascending. +// Return all mapping schemas of the account, newest first. // // API: POST /enrichment/mapping/schema/list (mapping-schema-read-list). func (s *AlertEnrichmentService) MappingSchemaReadList(ctx context.Context) (*MappingSchemaListResponse, *Response, error) { @@ -251,7 +251,7 @@ func (s *AlertEnrichmentService) MappingSchemaReadList(ctx context.Context) (*Ma // Create mapping schema. // -// Create a new mapping schema defining source lookup labels and the result labels to populate. Requires a Pro plan. +// Create a mapping schema that defines the lookup labels and the result labels to fill. // // API: POST /enrichment/mapping/schema/create (mapping-schema-write-create). func (s *AlertEnrichmentService) MappingSchemaWriteCreate(ctx context.Context, req *MappingSchemaCreateRequest) (*MappingSchemaCreateResponse, *Response, error) { @@ -265,7 +265,7 @@ func (s *AlertEnrichmentService) MappingSchemaWriteCreate(ctx context.Context, r // Delete mapping schema. // -// Delete a mapping schema and all its associated data. Deletion is blocked if the schema is referenced by any enrichment rule or webhook. +// Delete a mapping schema and all of its data rows; refused while an enrichment rule or robot webhook uses it. // // API: POST /enrichment/mapping/schema/delete (mapping-schema-write-delete). func (s *AlertEnrichmentService) MappingSchemaWriteDelete(ctx context.Context, req *MappingSchemaIDRequest) (*Response, error) { diff --git a/alert_rules.go b/alert_rules.go index d5b48f3..9842c6e 100644 --- a/alert_rules.go +++ b/alert_rules.go @@ -9,7 +9,7 @@ type AlertRulesService service // Get rule audit snapshot. // -// Return the audit record (including the `content` field, a JSON string of the rule snapshot at that point in time). +// Return one audit record of an alert rule, including the rule snapshot stored in `content`. // // API: POST /monit/rule/audit/detail (monit-rule-read-audit-detail). func (s *AlertRulesService) ReadAuditDetail(ctx context.Context, req *AuditRecordIDRequest) (*AlertRuleAudit, *Response, error) { @@ -37,7 +37,7 @@ func (s *AlertRulesService) ReadAudits(ctx context.Context, req *RuleIDRequest) // Get rule counts by channel. // -// Return an object mapping channel name to the number of rules routing alerts to that channel. If a channel name cannot be resolved, the channel ID (as a string) is used as the key. +// Return how many alert rules route alerts to each collaboration space, keyed by space name. // // API: POST /monit/rule/counter/channel (monit-rule-read-counter-channel). func (s *AlertRulesService) ReadCounterChannel(ctx context.Context) (*RuleCounterChannelResponse, *Response, error) { @@ -79,7 +79,7 @@ func (s *AlertRulesService) ReadInfoV2(ctx context.Context, req *RuleIDRequest) // List alert rules. // -// Return the basic information of all alert rules in a folder. For full rule details, call `POST /monit/rule/v2/info`. +// Return basic information for the alert rules in a folder; call `POST /monit/rule/v2/info` for full details. // // API: POST /monit/rule/list/basic (monit-rule-read-list). func (s *AlertRulesService) ReadList(ctx context.Context, req *RuleListRequest) (*RuleBasicListResponse, *Response, error) { @@ -125,7 +125,7 @@ func (s *AlertRulesService) WriteDeleteBatch(ctx context.Context, req *RuleIDsRe // Batch update rule fields. // -// Update specific fields across multiple alert rules at once. Only the fields listed in `fields` are applied. +// Update the fields listed in `fields` on multiple alert rules in one call. // // API: POST /monit/rule/update/fields (monit-rule-write-fields-update). func (s *AlertRulesService) WriteFieldsUpdate(ctx context.Context, req *RuleFieldsUpdateRequest) (*RuleNameMessageListResponse, *Response, error) { diff --git a/alerts.go b/alerts.go index d04b55a..ce4c423 100644 --- a/alerts.go +++ b/alerts.go @@ -79,7 +79,7 @@ func (s *AlertsService) ReadList(ctx context.Context, req *AlertListRequest) (*A // List alerts by IDs. // -// Return the details of multiple alerts by their IDs in a single request. Note: this endpoint does not paginate — `total` and `has_next_page` are always `0`/`false` and `search_after_ctx` is never set. +// Return the details of several alerts by ID in one request, without pagination. // // API: POST /alert/list-by-ids (alert-read-list-by-ids). func (s *AlertsService) ReadListByIDs(ctx context.Context, req *AlertListByIDsRequest) (*AlertListResponse, *Response, error) { @@ -121,7 +121,7 @@ func (s *AlertsService) ReadPipelineList(ctx context.Context, req *AlertPipeline // Merge alerts into an incident. // -// Associate one or more alerts with an existing incident. If a source alert previously belonged to a different incident and that incident becomes empty after the merge, it will be automatically closed. +// Move one or more alerts into an existing incident and close source incidents left empty. // // API: POST /alert/merge (alert-write-merge). func (s *AlertsService) WriteMerge(ctx context.Context, req *AlertMergeRequest) (*Response, error) { diff --git a/analytics.go b/analytics.go index 46f700c..42b7e6d 100644 --- a/analytics.go +++ b/analytics.go @@ -9,7 +9,7 @@ type AnalyticsService service // Get account-level insight. // -// Return aggregated incident insight metrics for the entire account. +// Return incident and alert metrics for the whole account, one row per time bucket. // // API: POST /insight/account (insightByAccount). func (s *AnalyticsService) ByAccount(ctx context.Context, req *InsightQueryRequest) (*DimensionInsightResponse, *Response, error) { @@ -23,7 +23,7 @@ func (s *AnalyticsService) ByAccount(ctx context.Context, req *InsightQueryReque // Get channel insight. // -// Return insight metrics aggregated by channel. +// Return incident and alert metrics grouped by channel, one row per channel per time bucket. // // API: POST /insight/channel (insightByChannel). func (s *AnalyticsService) ByChannel(ctx context.Context, req *InsightQueryRequest) (*DimensionInsightResponse, *Response, error) { @@ -37,7 +37,7 @@ func (s *AnalyticsService) ByChannel(ctx context.Context, req *InsightQueryReque // Get responder insight. // -// Return insight metrics aggregated by responder. +// Return per-responder incident handling metrics, one row per responder per time bucket. // // API: POST /insight/responder (insightByResponder). func (s *AnalyticsService) ByResponder(ctx context.Context, req *InsightQueryRequest) (*ResponderInsightResponse, *Response, error) { @@ -51,7 +51,7 @@ func (s *AnalyticsService) ByResponder(ctx context.Context, req *InsightQueryReq // Get team insight. // -// Return insight metrics aggregated by team. +// Return incident and alert metrics grouped by team, one row per team per time bucket. // // API: POST /insight/team (insightByTeam). func (s *AnalyticsService) ByTeam(ctx context.Context, req *InsightQueryRequest) (*DimensionInsightResponse, *Response, error) { @@ -65,7 +65,7 @@ func (s *AnalyticsService) ByTeam(ctx context.Context, req *InsightQueryRequest) // Export channel insight. // -// Export channel insight metrics as a CSV file — one row per channel (and per time/hour bucket when `aggregate_unit`/`split_hours` is used). The response is a CSV stream delivered with `Content-Disposition: attachment` — it is not a JSON envelope. `time_zone` defaults to UTC. Rows without a valid channel ID are skipped. Valid `export_fields` keys: channel_id, channel_name, total_incident_cnt, total_incidents_acknowledged, total_incidents_closed, total_incidents_auto_closed, total_incidents_manually_closed, total_incidents_timeout_closed, total_incidents_escalated, total_incidents_manually_escalated, total_incidents_timeout_escalated, total_incidents_reassigned, total_interruptions, total_notifications, total_engaged_seconds, mean_seconds_to_ack, mean_seconds_to_close, noise_reduction_pct, acknowledgement_pct, total_alert_cnt, total_alert_event_cnt, hours. The `hours` column is included by default only when `split_hours` is true. For compatibility, incident-export column keys are also accepted but produce empty columns. +// Export channel insight metrics as a CSV file with the same rows as `/insight/channel`. // // The success body is a file, not a JSON envelope: it is returned on Response.Raw. // @@ -76,7 +76,7 @@ func (s *AnalyticsService) ChannelExport(ctx context.Context, req *InsightQueryR // Export insight incidents. // -// Export the filtered incident analytics list as a CSV file. The response is a CSV stream delivered with `Content-Disposition: attachment` — it is not a JSON envelope. CSV headers and formatted values use the request locale, falling back to the member locale and then the account locale. `time_zone` defaults to the account time zone, then `Asia/Shanghai`. Export stops after at most 100,000 rows. Valid `export_fields` keys: incident_id, title, severity, progress, channel_id, channel_name, team_id, team_name, created_at, alert_cnt, active_alert_cnt, alert_event_cnt, seconds_to_ack, seconds_to_close, closed_by, owner_id, owner_name, creator_id, creator_name, closer_id, closer_name, engaged_seconds, hours, notifications, interruptions, acknowledgements, ackers, assignments, reassignments, escalations, manual_escalations, timeout_escalations, assigned_to, raw_assigned_to, escalate_rule_name, responders, raw_responders, snooze_status, snoozed_before, ever_muted, frequency, is_rare, description, labels, fields. When `export_fields` is omitted, all columns are exported. +// Export the incidents matched by the analytics filters as a CSV file, one row per incident. // // The success body is a file, not a JSON envelope: it is returned on Response.Raw. // @@ -101,7 +101,7 @@ func (s *AnalyticsService) IncidentList(ctx context.Context, req *InsightInciden // Export responder insight. // -// Export responder insight metrics as a CSV file — one row per responder (and per time/hour bucket when `aggregate_unit`/`split_hours` is used). The response is a CSV stream delivered with `Content-Disposition: attachment` — it is not a JSON envelope. `time_zone` defaults to UTC. Rows without a valid responder ID are skipped. Valid `export_fields` keys: responder_id, responder_name, total_incident_cnt, total_incidents_acknowledged, total_incidents_reassigned, total_incidents_escalated, total_incidents_manually_escalated, total_incidents_timeout_escalated, total_interruptions, total_notifications, total_engaged_seconds, mean_seconds_to_ack, acknowledgement_pct, hours. The `hours` column is included by default only when `split_hours` is true. For compatibility, incident-export column keys are also accepted but produce empty columns. +// Export responder insight metrics as a CSV file with the same rows as `/insight/responder`. // // The success body is a file, not a JSON envelope: it is returned on Response.Raw. // @@ -112,7 +112,7 @@ func (s *AnalyticsService) ResponderExport(ctx context.Context, req *InsightQuer // Export team insight. // -// Export team insight metrics as a CSV file — one row per team (and per time/hour bucket when `aggregate_unit`/`split_hours` is used). The response is a CSV stream delivered with `Content-Disposition: attachment` — it is not a JSON envelope. `time_zone` defaults to UTC. Rows without a valid team ID are skipped. Valid `export_fields` keys: team_id, team_name, total_incident_cnt, total_incidents_acknowledged, total_incidents_closed, total_incidents_auto_closed, total_incidents_manually_closed, total_incidents_timeout_closed, total_incidents_escalated, total_incidents_manually_escalated, total_incidents_timeout_escalated, total_incidents_reassigned, total_interruptions, total_notifications, total_engaged_seconds, mean_seconds_to_ack, mean_seconds_to_close, noise_reduction_pct, acknowledgement_pct, total_alert_cnt, total_alert_event_cnt, hours. The `hours` column is included by default only when `split_hours` is true. For compatibility, incident-export column keys are also accepted but produce empty columns. +// Export team insight metrics as a CSV file with the same rows as `/insight/team`. // // The success body is a file, not a JSON envelope: it is returned on Response.Raw. // diff --git a/applications.go b/applications.go index 8169441..972872b 100644 --- a/applications.go +++ b/applications.go @@ -158,7 +158,7 @@ func (s *ApplicationsService) WriteDelete(ctx context.Context, req *RUMApplicati // Update application. // -// Update an existing RUM application. All fields except `application_id` are optional — only provided fields are updated. +// Update selected fields of a RUM application; fields left out of the request keep their current values. // // API: POST /rum/application/update (rum-application-write-update). func (s *ApplicationsService) WriteUpdate(ctx context.Context, req *RUMApplicationUpdateRequest) (*Response, error) { diff --git a/artifacts.go b/artifacts.go index 6c7eff0..f72c9ef 100644 --- a/artifacts.go +++ b/artifacts.go @@ -9,7 +9,7 @@ type ArtifactsService service // Get artifact detail. // -// Get a single published artifact by ID. +// Get one published artifact by ID, including its source file, owner and public-share state. // // API: POST /safari/artifact/gallery/get (artifact-read-get). func (s *ArtifactsService) ReadGet(ctx context.Context, req *ArtifactIDRequest) (*PublishedArtifactItem, *Response, error) { diff --git a/automations.go b/automations.go index e0132a8..09a9f50 100644 --- a/automations.go +++ b/automations.go @@ -9,7 +9,7 @@ type AutomationsService service // Get Automation rule. // -// Get one Automation rule by ID. +// Get one Automation rule by ID, including its trigger settings and execution destination. // // API: POST /safari/automation/rule/get (automation-rule-read-get). func (s *AutomationsService) RuleReadGet(ctx context.Context, req *AutomationRuleIDRequest) (*AutomationRuleItem, *Response, error) { @@ -23,7 +23,7 @@ func (s *AutomationsService) RuleReadGet(ctx context.Context, req *AutomationRul // List Automation rules. // -// List Automation rules visible to the caller. +// List Automation rules visible to the caller, newest update first, with pagination and filters. // // API: POST /safari/automation/rule/list (automation-rule-read-list). func (s *AutomationsService) RuleReadList(ctx context.Context, req *AutomationRuleListRequest) (*AutomationRuleListResponse, *Response, error) { @@ -37,7 +37,7 @@ func (s *AutomationsService) RuleReadList(ctx context.Context, req *AutomationRu // Create Automation rule. // -// Create an Automation rule with schedule, HTTP POST, and On-call incident triggers. +// Create an Automation rule with schedule, HTTP POST, On-call incident, and war room triggers. // // API: POST /safari/automation/rule/create (automation-rule-write-create). func (s *AutomationsService) RuleWriteCreate(ctx context.Context, req *AutomationRuleCreateRequest) (*AutomationRuleItem, *Response, error) { @@ -51,7 +51,7 @@ func (s *AutomationsService) RuleWriteCreate(ctx context.Context, req *Automatio // Delete Automation rule. // -// Delete an Automation rule. +// Delete an Automation rule together with all of its triggers and their subscriptions. // // API: POST /safari/automation/rule/delete (automation-rule-write-delete). func (s *AutomationsService) RuleWriteDelete(ctx context.Context, req *AutomationRuleIDRequest) (*any, *Response, error) { @@ -65,7 +65,7 @@ func (s *AutomationsService) RuleWriteDelete(ctx context.Context, req *Automatio // Run Automation rule. // -// Manually run an Automation rule immediately, outside its schedule. +// Run an Automation rule once right now, regardless of its triggers or enabled state. // // API: POST /safari/automation/rule/run (automation-rule-write-run). func (s *AutomationsService) RuleWriteRun(ctx context.Context, req *AutomationRuleIDRequest) (*ManualRunRuleResult, *Response, error) { @@ -79,7 +79,7 @@ func (s *AutomationsService) RuleWriteRun(ctx context.Context, req *AutomationRu // Update Automation rule. // -// Update mutable Automation rule fields, including HTTP POST and On-call incident trigger settings. +// Update an Automation rule's fields and trigger settings; omitted fields keep their current values. // // API: POST /safari/automation/rule/update (automation-rule-write-update). func (s *AutomationsService) RuleWriteUpdate(ctx context.Context, req *AutomationRuleUpdateRequest) (*AutomationRuleItem, *Response, error) { @@ -93,7 +93,7 @@ func (s *AutomationsService) RuleWriteUpdate(ctx context.Context, req *Automatio // List Automation runs. // -// List run history for a rule the caller can manage. +// List the run history of one Automation rule, newest first, with status, trigger, and time filters. // // API: POST /safari/automation/run/list (automation-run-read-list). func (s *AutomationsService) RunReadList(ctx context.Context, req *AutomationRunListRequest) (*AutomationRunListResponse, *Response, error) { @@ -107,7 +107,7 @@ func (s *AutomationsService) RunReadList(ctx context.Context, req *AutomationRun // List Automation templates. // -// List preset Automation templates for the requested locale. +// List built-in Automation templates that prefill the create-rule form, in Chinese or English. // // API: POST /safari/automation/template/list (automation-template-read-list). func (s *AutomationsService) TemplateReadList(ctx context.Context, req *AutomationTemplateListRequest) (*AutomationTemplateListResponse, *Response, error) { diff --git a/calendars.go b/calendars.go index e7fc44e..fff2811 100644 --- a/calendars.go +++ b/calendars.go @@ -9,7 +9,7 @@ type CalendarsService service // Delete calendar event. // -// Delete one event of a personal calendar by event_id, or clear the calendar's own events off the days [start_at, end_at). Pass either event_id or both start_at and end_at. Cleared days fall back to the linked holiday calendars and the weekly workdays. +// Delete one personal-calendar event by ID, or clear the calendar's own events from a date range. // // API: POST /calendar/event/delete (calEventDelete). func (s *CalendarsService) CalEventDelete(ctx context.Context, req *CalEventIDRequest) (*Response, error) { @@ -18,7 +18,7 @@ func (s *CalendarsService) CalEventDelete(ctx context.Context, req *CalEventIDRe // List calendar events. // -// Return events for a personal calendar within a year/month/day scope. When month and day are both omitted the whole year is returned. The response also carries days, the resolved state of every day in the scope. +// Return a personal calendar's events for a year, month or day, plus the resolved state of each day. // // API: POST /calendar/event/list (calEventList). func (s *CalendarsService) CalEventList(ctx context.Context, req *CalEventListRequest) (*CalEventListResponse, *Response, error) { @@ -32,7 +32,7 @@ func (s *CalendarsService) CalEventList(ctx context.Context, req *CalEventListRe // Upsert calendar event. // -// Create or update an event the calendar owns (a day off or a working-day override) over the days [start_at, end_at). Omit event_id to create a new event; a given event_id must be an existing event of this calendar. The write clears the calendar's other own events off the same days: an event fully inside the range is deleted, one partly inside is shortened, and one spanning the range is split in two, so the latest write decides those days. end_at must be later than start_at. +// Create or update one of a personal calendar's own events: a day off or a working-day override. // // API: POST /calendar/event/upsert (calEventUpsert). func (s *CalendarsService) CalEventUpsert(ctx context.Context, req *CalEventUpsertRequest) (*CalEventUpsertResponse, *Response, error) { @@ -46,7 +46,7 @@ func (s *CalendarsService) CalEventUpsert(ctx context.Context, req *CalEventUpse // Create calendar. // -// Create a personal service calendar. Each account is limited to 5 calendars unless the Flashcat-Break-Cal-Limit header is set. +// Create a personal service calendar with its weekly workdays and linked holiday calendars. // // API: POST /calendar/create (calendarCreate). func (s *CalendarsService) CalendarCreate(ctx context.Context, req *CalendarCreateRequest) (*CalendarCreateResponse, *Response, error) { @@ -60,7 +60,7 @@ func (s *CalendarsService) CalendarCreate(ctx context.Context, req *CalendarCrea // Delete calendar. // -// Delete a personal service calendar. The call fails when referenced by escalation or silence rules. +// Delete a personal service calendar and its events when no rule references it. // // API: POST /calendar/delete (calendarDelete). func (s *CalendarsService) CalendarDelete(ctx context.Context, req *CalendarIDRequest) (*Response, error) { @@ -69,7 +69,7 @@ func (s *CalendarsService) CalendarDelete(ctx context.Context, req *CalendarIDRe // Get calendar info. // -// Return details of a service calendar. +// Return the details of one service calendar of the account by its ID. // // API: POST /calendar/info (calendarInfo). func (s *CalendarsService) CalendarInfo(ctx context.Context, req *CalendarIDRequest) (*CalendarItem, *Response, error) { @@ -97,7 +97,7 @@ func (s *CalendarsService) CalendarList(ctx context.Context, req *CalendarListRe // Update calendar. // -// Update a personal service calendar. Only non-null fields are updated. +// Update a personal service calendar; only the fields you send are changed. // // API: POST /calendar/update (calendarUpdate). func (s *CalendarsService) CalendarUpdate(ctx context.Context, req *CalendarUpdateRequest) (*Response, error) { diff --git a/channels.go b/channels.go index f980f46..c80240c 100644 --- a/channels.go +++ b/channels.go @@ -9,7 +9,7 @@ type ChannelsService service // Create channel. // -// Create a new channel for incident management. +// Create a channel, optionally with a default escalation rule and channel-exclusive integrations. // // API: POST /channel/create (channelCreate). func (s *ChannelsService) ChannelCreate(ctx context.Context, req *CreateChannelRequest) (*ChannelCreateResponse, *Response, error) { @@ -23,7 +23,7 @@ func (s *ChannelsService) ChannelCreate(ctx context.Context, req *CreateChannelR // Delete channel. // -// Delete a channel. Only a `disabled` channel can be deleted; all of its escalation, silence, drop and inhibit rules are deleted with it. The call fails when an integration route still references the channel. +// Delete a disabled channel together with its rules and channel-exclusive integrations. // // API: POST /channel/delete (channelDelete). func (s *ChannelsService) ChannelDelete(ctx context.Context, req *ChannelIDRequest) (*Response, error) { @@ -32,7 +32,7 @@ func (s *ChannelsService) ChannelDelete(ctx context.Context, req *ChannelIDReque // Disable channel. // -// Disable a channel to stop incident routing without deleting it; a disabled channel discards incoming events. Only an `enabled` channel can be disabled. +// Disable a channel; while disabled it discards all incoming alert events. // // API: POST /channel/disable (channelDisable). func (s *ChannelsService) ChannelDisable(ctx context.Context, req *ChannelIDRequest) (*Response, error) { @@ -41,7 +41,7 @@ func (s *ChannelsService) ChannelDisable(ctx context.Context, req *ChannelIDRequ // Enable channel. // -// Enable a channel to resume incident routing. Only a `disabled` channel can be enabled. +// Enable a disabled channel so it processes incoming alert events again. // // API: POST /channel/enable (channelEnable). func (s *ChannelsService) ChannelEnable(ctx context.Context, req *ChannelIDRequest) (*Response, error) { @@ -50,7 +50,7 @@ func (s *ChannelsService) ChannelEnable(ctx context.Context, req *ChannelIDReque // Create escalation rule. // -// Create an escalation rule defining who gets notified and when during an incident. +// Create an escalation rule that decides who is notified about a channel's incidents, and how. // // API: POST /channel/escalate/rule/create (channelEscalateRuleCreate). func (s *ChannelsService) ChannelEscalateRuleCreate(ctx context.Context, req *CreateEscalationRuleRequest) (*RuleCreateResponse, *Response, error) { @@ -64,7 +64,7 @@ func (s *ChannelsService) ChannelEscalateRuleCreate(ctx context.Context, req *Cr // Delete escalation rule. // -// Delete an escalation rule. Only a `disabled` rule can be deleted. +// Delete a disabled escalation rule so it no longer appears in the channel's rule list. // // API: POST /channel/escalate/rule/delete (channelEscalateRuleDelete). func (s *ChannelsService) ChannelEscalateRuleDelete(ctx context.Context, req *ChannelRuleIDRequest) (*Response, error) { @@ -73,7 +73,7 @@ func (s *ChannelsService) ChannelEscalateRuleDelete(ctx context.Context, req *Ch // Disable escalation rule. // -// Disable an escalation rule without deleting it. Only an `enabled` rule can be disabled. +// Disable an escalation rule without deleting it. // // API: POST /channel/escalate/rule/disable (channelEscalateRuleDisable). func (s *ChannelsService) ChannelEscalateRuleDisable(ctx context.Context, req *ChannelRuleIDRequest) (*Response, error) { @@ -82,7 +82,7 @@ func (s *ChannelsService) ChannelEscalateRuleDisable(ctx context.Context, req *C // Enable escalation rule. // -// Enable a disabled escalation rule. Only a `disabled` rule can be enabled. +// Enable a disabled escalation rule so it can take new incidents again. // // API: POST /channel/escalate/rule/enable (channelEscalateRuleEnable). func (s *ChannelsService) ChannelEscalateRuleEnable(ctx context.Context, req *ChannelRuleIDRequest) (*Response, error) { @@ -91,7 +91,7 @@ func (s *ChannelsService) ChannelEscalateRuleEnable(ctx context.Context, req *Ch // Get escalation rule detail. // -// Retrieve detailed information for a specific escalation rule. +// Return one escalation rule of a channel, including its levels, time windows and filters. // // API: POST /channel/escalate/rule/info (channelEscalateRuleInfo). func (s *ChannelsService) ChannelEscalateRuleInfo(ctx context.Context, req *ChannelRuleIDRequest) (*EscalateRuleItem, *Response, error) { @@ -105,7 +105,7 @@ func (s *ChannelsService) ChannelEscalateRuleInfo(ctx context.Context, req *Chan // List escalation rules. // -// List all escalation rules for a channel. +// List a channel's escalation rules in the order they are evaluated. // // API: POST /channel/escalate/rule/list (channelEscalateRuleList). func (s *ChannelsService) ChannelEscalateRuleList(ctx context.Context, req *ChannelScopedListRequest) (*ListEscalationRulesResponse, *Response, error) { @@ -119,7 +119,7 @@ func (s *ChannelsService) ChannelEscalateRuleList(ctx context.Context, req *Chan // Update escalation rule. // -// Update an existing escalation rule configuration. +// Replace the configuration of an existing escalation rule. // // API: POST /channel/escalate/rule/update (channelEscalateRuleUpdate). func (s *ChannelsService) ChannelEscalateRuleUpdate(ctx context.Context, req *UpdateEscalationRuleRequest) (*Response, error) { @@ -128,7 +128,7 @@ func (s *ChannelsService) ChannelEscalateRuleUpdate(ctx context.Context, req *Up // Get channel detail. // -// Retrieve detailed information for a specific channel. +// Return one channel's full configuration with counts of its active incidents from the last 30 days. // // API: POST /channel/info (channelInfo). func (s *ChannelsService) ChannelInfo(ctx context.Context, req *ChannelInfoRequest) (*ChannelItem, *Response, error) { @@ -142,7 +142,7 @@ func (s *ChannelsService) ChannelInfo(ctx context.Context, req *ChannelInfoReque // Batch get channels. // -// Retrieve multiple channels by their IDs. +// Return the ID, name and status of up to 1,000 channels in one call. // // API: POST /channel/infos (channelInfos). func (s *ChannelsService) ChannelInfos(ctx context.Context, req *ChannelInfosRequest) (*ChannelInfosResponse, *Response, error) { @@ -156,7 +156,7 @@ func (s *ChannelsService) ChannelInfos(ctx context.Context, req *ChannelInfosReq // Create inhibit rule. // -// Create an inhibit rule to suppress lower-priority alerts when higher-priority ones are firing. +// Create an inhibit rule that mutes alert events while a related source alert is still active. // // API: POST /channel/inhibit/rule/create (channelInhibitRuleCreate). func (s *ChannelsService) ChannelInhibitRuleCreate(ctx context.Context, req *CreateInhibitRuleRequest) (*RuleCreateResponse, *Response, error) { @@ -170,7 +170,7 @@ func (s *ChannelsService) ChannelInhibitRuleCreate(ctx context.Context, req *Cre // Delete inhibit rule. // -// Delete an inhibit rule. Only a `disabled` rule can be deleted. +// Delete a disabled inhibit rule so it no longer appears in the channel's rule list. // // API: POST /channel/inhibit/rule/delete (channelInhibitRuleDelete). func (s *ChannelsService) ChannelInhibitRuleDelete(ctx context.Context, req *ChannelRuleIDRequest) (*Response, error) { @@ -179,7 +179,7 @@ func (s *ChannelsService) ChannelInhibitRuleDelete(ctx context.Context, req *Cha // Disable inhibit rule. // -// Disable an inhibit rule without deleting it. Only an `enabled` rule can be disabled. +// Disable an inhibit rule without deleting it. // // API: POST /channel/inhibit/rule/disable (channelInhibitRuleDisable). func (s *ChannelsService) ChannelInhibitRuleDisable(ctx context.Context, req *ChannelRuleIDRequest) (*Response, error) { @@ -188,7 +188,7 @@ func (s *ChannelsService) ChannelInhibitRuleDisable(ctx context.Context, req *Ch // Enable inhibit rule. // -// Enable a disabled inhibit rule. Only a `disabled` rule can be enabled. +// Enable a disabled inhibit rule so it mutes matching alert events again. // // API: POST /channel/inhibit/rule/enable (channelInhibitRuleEnable). func (s *ChannelsService) ChannelInhibitRuleEnable(ctx context.Context, req *ChannelRuleIDRequest) (*Response, error) { @@ -197,7 +197,7 @@ func (s *ChannelsService) ChannelInhibitRuleEnable(ctx context.Context, req *Cha // List inhibit rules. // -// List all inhibit rules configured for a channel. +// List a channel's inhibit rules, oldest first. // // API: POST /channel/inhibit/rule/list (channelInhibitRuleList). func (s *ChannelsService) ChannelInhibitRuleList(ctx context.Context, req *ChannelScopedListRequest) (*ListInhibitRulesResponse, *Response, error) { @@ -211,7 +211,7 @@ func (s *ChannelsService) ChannelInhibitRuleList(ctx context.Context, req *Chann // Update inhibit rule. // -// Update an existing inhibit rule configuration. +// Replace the configuration of an existing inhibit rule. // // API: POST /channel/inhibit/rule/update (channelInhibitRuleUpdate). func (s *ChannelsService) ChannelInhibitRuleUpdate(ctx context.Context, req *UpdateInhibitRuleRequest) (*Response, error) { @@ -220,7 +220,7 @@ func (s *ChannelsService) ChannelInhibitRuleUpdate(ctx context.Context, req *Upd // List channels. // -// List channels accessible to the current user with optional filters. +// List the channels visible to the caller, with filters, sorting and pagination. // // API: POST /channel/list (channelList). func (s *ChannelsService) ChannelList(ctx context.Context, req *ListChannelsRequest) (*ListChannelsResponse, *Response, error) { @@ -234,7 +234,7 @@ func (s *ChannelsService) ChannelList(ctx context.Context, req *ListChannelsRequ // Create silence rule. // -// Create a silence rule to suppress notifications matching specified conditions. +// Create a silence rule that mutes or drops matching alert events during a time window. // // API: POST /channel/silence/rule/create (channelSilenceRuleCreate). func (s *ChannelsService) ChannelSilenceRuleCreate(ctx context.Context, req *CreateSilenceRuleRequest) (*RuleCreateResponse, *Response, error) { @@ -248,7 +248,7 @@ func (s *ChannelsService) ChannelSilenceRuleCreate(ctx context.Context, req *Cre // Delete silence rule. // -// Delete a silence rule. Only a `disabled` rule can be deleted. +// Delete a disabled silence rule so it no longer appears in the channel's rule list. // // API: POST /channel/silence/rule/delete (channelSilenceRuleDelete). func (s *ChannelsService) ChannelSilenceRuleDelete(ctx context.Context, req *ChannelRuleIDRequest) (*Response, error) { @@ -257,7 +257,7 @@ func (s *ChannelsService) ChannelSilenceRuleDelete(ctx context.Context, req *Cha // Disable silence rule. // -// Disable a silence rule without deleting it. Only an `enabled` rule can be disabled. +// Disable a silence rule without deleting it. // // API: POST /channel/silence/rule/disable (channelSilenceRuleDisable). func (s *ChannelsService) ChannelSilenceRuleDisable(ctx context.Context, req *ChannelRuleIDRequest) (*Response, error) { @@ -266,7 +266,7 @@ func (s *ChannelsService) ChannelSilenceRuleDisable(ctx context.Context, req *Ch // Enable silence rule. // -// Enable a disabled silence rule. Only a `disabled` rule can be enabled. +// Enable a disabled silence rule so it silences matching alert events again. // // API: POST /channel/silence/rule/enable (channelSilenceRuleEnable). func (s *ChannelsService) ChannelSilenceRuleEnable(ctx context.Context, req *ChannelRuleIDRequest) (*Response, error) { @@ -275,7 +275,7 @@ func (s *ChannelsService) ChannelSilenceRuleEnable(ctx context.Context, req *Cha // List silence rules. // -// List all silence rules configured for a channel. +// List a channel's silence rules and whether each one is in effect right now. // // API: POST /channel/silence/rule/list (channelSilenceRuleList). func (s *ChannelsService) ChannelSilenceRuleList(ctx context.Context, req *ChannelScopedListRequest) (*ListSilenceRulesResponse, *Response, error) { @@ -289,7 +289,7 @@ func (s *ChannelsService) ChannelSilenceRuleList(ctx context.Context, req *Chann // Update silence rule. // -// Update an existing silence rule configuration. +// Replace the configuration of an existing silence rule. // // API: POST /channel/silence/rule/update (channelSilenceRuleUpdate). func (s *ChannelsService) ChannelSilenceRuleUpdate(ctx context.Context, req *UpdateSilenceRuleRequest) (*Response, error) { @@ -298,7 +298,7 @@ func (s *ChannelsService) ChannelSilenceRuleUpdate(ctx context.Context, req *Upd // Create drop rule. // -// Create a drop rule to filter out unwanted alerts before they become incidents. +// Create a drop rule that discards matching alert events before any alert or incident is created. // // API: POST /channel/unsubscribe/rule/create (channelUnsubscribeRuleCreate). func (s *ChannelsService) ChannelUnsubscribeRuleCreate(ctx context.Context, req *CreateDropRuleRequest) (*RuleCreateResponse, *Response, error) { @@ -312,7 +312,7 @@ func (s *ChannelsService) ChannelUnsubscribeRuleCreate(ctx context.Context, req // Delete drop rule. // -// Delete a drop rule. Only a `disabled` rule can be deleted. +// Delete a disabled drop rule so it no longer appears in the channel's rule list. // // API: POST /channel/unsubscribe/rule/delete (channelUnsubscribeRuleDelete). func (s *ChannelsService) ChannelUnsubscribeRuleDelete(ctx context.Context, req *ChannelRuleIDRequest) (*Response, error) { @@ -321,7 +321,7 @@ func (s *ChannelsService) ChannelUnsubscribeRuleDelete(ctx context.Context, req // Disable drop rule. // -// Disable a drop rule without deleting it. Only an `enabled` rule can be disabled. +// Disable a drop rule without deleting it. // // API: POST /channel/unsubscribe/rule/disable (channelUnsubscribeRuleDisable). func (s *ChannelsService) ChannelUnsubscribeRuleDisable(ctx context.Context, req *ChannelRuleIDRequest) (*Response, error) { @@ -330,7 +330,7 @@ func (s *ChannelsService) ChannelUnsubscribeRuleDisable(ctx context.Context, req // Enable drop rule. // -// Enable a disabled drop rule. Only a `disabled` rule can be enabled. +// Enable a disabled drop rule so it discards matching alert events again. // // API: POST /channel/unsubscribe/rule/enable (channelUnsubscribeRuleEnable). func (s *ChannelsService) ChannelUnsubscribeRuleEnable(ctx context.Context, req *ChannelRuleIDRequest) (*Response, error) { @@ -339,7 +339,7 @@ func (s *ChannelsService) ChannelUnsubscribeRuleEnable(ctx context.Context, req // List drop rules. // -// List drop rules for a channel. +// List a channel's drop rules, oldest first. // // API: POST /channel/unsubscribe/rule/list (channelUnsubscribeRuleList). func (s *ChannelsService) ChannelUnsubscribeRuleList(ctx context.Context, req *ChannelScopedListRequest) (*ListDropRulesResponse, *Response, error) { @@ -353,7 +353,7 @@ func (s *ChannelsService) ChannelUnsubscribeRuleList(ctx context.Context, req *C // Update drop rule. // -// Update an existing drop rule configuration. +// Replace the name, description and conditions of an existing drop rule. // // API: POST /channel/unsubscribe/rule/update (channelUnsubscribeRuleUpdate). func (s *ChannelsService) ChannelUnsubscribeRuleUpdate(ctx context.Context, req *UpdateDropRuleRequest) (*Response, error) { @@ -362,7 +362,7 @@ func (s *ChannelsService) ChannelUnsubscribeRuleUpdate(ctx context.Context, req // Update channel. // -// Update an existing channel's configuration and settings. +// Update a channel's settings; only the fields present in the request are changed. // // API: POST /channel/update (channelUpdate). func (s *ChannelsService) ChannelUpdate(ctx context.Context, req *UpdateChannelRequest) (*UpdateChannelResponse, *Response, error) { @@ -376,7 +376,7 @@ func (s *ChannelsService) ChannelUpdate(ctx context.Context, req *UpdateChannelR // Get routing rule detail. // -// Retrieve the routing rule configuration for a specific integration. Returns null when the integration has no routing rule configured. +// Return the routing rule of one shared integration. // // API: POST /route/info (routeInfo). func (s *ChannelsService) RouteInfo(ctx context.Context, req *RouteInfoRequest) (*RouteItem, *Response, error) { @@ -390,7 +390,7 @@ func (s *ChannelsService) RouteInfo(ctx context.Context, req *RouteInfoRequest) // List routing rules. // -// Return routing rules for the specified integrations. Integrations without a configured rule are omitted from the response. +// Return the routing rules of several shared integrations in one call. // // API: POST /route/list (routeList). func (s *ChannelsService) RouteList(ctx context.Context, req *ListRoutesRequest) (*ListRoutesResponse, *Response, error) { @@ -404,7 +404,7 @@ func (s *ChannelsService) RouteList(ctx context.Context, req *ListRoutesRequest) // Upsert routing rule. // -// Create or update routing rules for an integration to direct alerts to specific channels. At least one of `cases` or `default` must be provided. +// Create or replace the routing rule that sends a shared integration's alerts to channels. // // API: POST /route/upsert (routeUpsert). func (s *ChannelsService) RouteUpsert(ctx context.Context, req *UpsertRouteRequest) (*Response, error) { diff --git a/dashboards.go b/dashboards.go index 0be75d1..41aff97 100644 --- a/dashboards.go +++ b/dashboards.go @@ -65,7 +65,7 @@ func (s *DashboardsService) ReadGet(ctx context.Context, req *DashboardIDRequest // List dashboards. // -// List the dashboards in one folder. +// List the dashboards stored directly in one folder, with word search and paging. // // API: POST /monit/dashboard/list (monit-dashboard-read-list). func (s *DashboardsService) ReadList(ctx context.Context, req *DashboardListRequest) (*DashboardListOutput, *Response, error) { @@ -191,7 +191,7 @@ func (s *DashboardsService) WriteCreate(ctx context.Context, req *DashboardCreat // Delete dashboard. // -// Move a dashboard to the trash. +// Move a dashboard to the trash, where it can be restored for 30 days. // // API: POST /monit/dashboard/delete (monit-dashboard-write-delete). func (s *DashboardsService) WriteDelete(ctx context.Context, req *DashboardDeleteRequest) (*DashboardDeleteOutput, *Response, error) { diff --git a/data_sources.go b/data_sources.go index dc51bbe..7e8b31b 100644 --- a/data_sources.go +++ b/data_sources.go @@ -9,7 +9,7 @@ type DataSourcesService service // Get datasource detail. // -// Retrieve full details of a single data source by its ID, including the `payload` configuration with its configured connection and authentication settings; treat the response as sensitive and avoid logging or forwarding it. Supports diagnostic types redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka; enabled and alerting_enabled are independent. +// Return one datasource by ID, including its full `payload` configuration. // // API: POST /monit/datasource/info (monit-datasource-read-info). func (s *DataSourcesService) ReadInfo(ctx context.Context, req *IDRequest) (*DataSourceItem, *Response, error) { @@ -23,7 +23,7 @@ func (s *DataSourcesService) ReadInfo(ctx context.Context, req *IDRequest) (*Dat // List datasources. // -// Return all data sources for the current account. Optionally filter by `type_ident`. Supports diagnostic types redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka; enabled and alerting_enabled are independent. +// List the account's datasources that the caller can query, optionally filtered by type or exact name. // // API: POST /monit/datasource/list (monit-datasource-read-list). func (s *DataSourcesService) ReadList(ctx context.Context, req *DataSourceListRequest) (*DataSourceListResponse, *Response, error) { @@ -79,7 +79,7 @@ func (s *DataSourcesService) ToolsInvoke(ctx context.Context, req *DatasourceToo // Create datasource. // -// Create a new monitoring data source. The `payload` must include the type-specific configuration block. Supports diagnostic types redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka; enabled and alerting_enabled are independent. +// Create a monitoring datasource of one of 15 supported types and bind it to a Monitors edge cluster. // // API: POST /monit/datasource/create (monit-datasource-write-create). func (s *DataSourcesService) WriteCreate(ctx context.Context, req *DataSourceUpsertRequest) (*DataSourceItem, *Response, error) { @@ -93,7 +93,7 @@ func (s *DataSourcesService) WriteCreate(ctx context.Context, req *DataSourceUps // Delete datasource. // -// Delete a data source by ID. Alert rules referencing this datasource are not blocked: the datasource is removed from their monitoring scope and their open alerts on it are closed automatically. +// Delete a datasource by ID; alert rules that reference it are not blocked. // // API: POST /monit/datasource/delete (monit-datasource-write-delete). func (s *DataSourcesService) WriteDelete(ctx context.Context, req *IDRequest) (*Response, error) { @@ -102,7 +102,7 @@ func (s *DataSourcesService) WriteDelete(ctx context.Context, req *IDRequest) (* // Update datasource. // -// Update an existing data source. Supply `id` plus the fields to change. Supports diagnostic types redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka; enabled and alerting_enabled are independent. +// Update a datasource by ID, replacing its name, note, address, payload and edge cluster. // // API: POST /monit/datasource/update (monit-datasource-write-update). func (s *DataSourcesService) WriteUpdate(ctx context.Context, req *DataSourceUpsertRequest) (*DataSourceItem, *Response, error) { diff --git a/diagnostics.go b/diagnostics.go index 29a9cb4..492bc3f 100644 --- a/diagnostics.go +++ b/diagnostics.go @@ -9,7 +9,7 @@ type DiagnosticsService service // Query structured data. // -// Run a synchronous ad-hoc query against a configured data source and return a stable `query_result.v1` result whose natural shape is frames, records, or samples. This public API requires monit-edge v0.65.0 or later. +// Run a synchronous ad-hoc query against a data source and return a `query_result.v1` result as frames, records, or samples. // // API: POST /monit/query/data (monit-read-query-data). func (s *DiagnosticsService) QueryData(ctx context.Context, req *QueryDataRequest) (*QueryDataResponse, *Response, error) { diff --git a/error_ingestion_rules.go b/error_ingestion_rules.go index 79eae99..83febbc 100644 --- a/error_ingestion_rules.go +++ b/error_ingestion_rules.go @@ -9,7 +9,7 @@ type ErrorIngestionRulesService service // Create an error ingestion rule. // -// Create a new error ingestion rule that filters which errors are stored. +// Create a rule whose matching errors are kept out of issue grouping; matched errors are still stored. // // API: POST /rum/error-ingestion/rules/create (rum-error-ingestion-rules-create). func (s *ErrorIngestionRulesService) Create(ctx context.Context, req *RUMErrorIngestionCreateRequest) (*RUMErrorIngestionCreateResponse, *Response, error) { diff --git a/incidents.go b/incidents.go index c0dc3e8..bd52161 100644 --- a/incidents.go +++ b/incidents.go @@ -23,7 +23,7 @@ func (s *IncidentsService) PostMortemWriteResetContent(ctx context.Context, req // Get war-room default observers. // -// Return historical responders suggested as default observers when opening a war room. +// Return people assigned to an incident earlier who are no longer responders, as suggested war-room observers. // // API: POST /incident/war-room/default-observers (incident-read-get-war-room-default-observers). func (s *IncidentsService) ReadGetWarRoomDefaultObservers(ctx context.Context, req *GetWarRoomDefaultObserversRequest) (*GetWarRoomDefaultObserversResponse, *Response, error) { @@ -51,7 +51,7 @@ func (s *IncidentsService) ServiceDeskPlusRequestReadList(ctx context.Context, r // Add war-room member. // -// Add one or more members to the IM war room bound to an incident integration. +// Add members to an existing incident war room on Feishu (Lark), DingTalk, WeCom, or Slack. // // API: POST /incident/war-room/add-member (incident-write-add-war-room-member). func (s *IncidentsService) WriteAddWarRoomMember(ctx context.Context, req *AddWarRoomMemberRequest) (*string, *Response, error) { @@ -88,7 +88,7 @@ func (s *IncidentsService) AlertList(ctx context.Context, req *ListIncidentAlert // Assign incident. // -// Dispatch an incident to a specific escalation level or responder. +// Reassign incidents to members or an escalation rule, replacing the current responders. // // API: POST /incident/assign (incidentAssign). func (s *IncidentsService) Assign(ctx context.Context, req *AssignIncidentRequest) (*Response, error) { @@ -120,7 +120,7 @@ func (s *IncidentsService) CommentTypeCreate(ctx context.Context, req *CreateInc // Delete a comment type. // -// Delete a comment type. Comments that used it keep their text but lose the type label. +// Permanently delete a comment type; comments that used it keep their text but lose the label. // // API: POST /incident/comment-type/delete (incidentCommentTypeDelete). func (s *IncidentsService) CommentTypeDelete(ctx context.Context, req *DeleteIncidentCommentTypeRequest) (*Response, error) { @@ -189,7 +189,7 @@ func (s *IncidentsService) CustomActionDo(ctx context.Context, req *DoIncidentCu // Disable incident merge. // -// Disable automatic merging for a specific incident. +// Stop new alerts and events from being merged into the given incidents. // // API: POST /incident/disable-merge (incidentDisableMerge). func (s *IncidentsService) DisableMerge(ctx context.Context, req *DisableIncidentMergeRequest) (*Response, error) { @@ -198,7 +198,7 @@ func (s *IncidentsService) DisableMerge(ctx context.Context, req *DisableInciden // Get incident timeline. // -// Retrieve the timeline feed for a specific incident, including state changes, comments and system events. +// List an incident's timeline entries, such as state changes, assignments, notifications, comments, and work item events. // // API: POST /incident/feed (incidentFeed). func (s *IncidentsService) Feed(ctx context.Context, req *ListIncidentFeedRequest) (*ListIncidentFeedResponse, *Response, error) { @@ -221,7 +221,7 @@ func (s *IncidentsService) FieldReset(ctx context.Context, req *ResetIncidentFie // Get incident detail. // -// Retrieve detailed information for a single incident including timeline, alerts, responders and custom fields. +// Get one incident by ID or short number, with responders, assignment, custom fields, and alert counts. // // API: POST /incident/info (incidentInfo). func (s *IncidentsService) Info(ctx context.Context, req *IncidentInfoRequest) (*IncidentInfo, *Response, error) { @@ -272,7 +272,7 @@ func (s *IncidentsService) Merge(ctx context.Context, req *MergeIncidentsRequest // List past incidents. // -// List historical incidents related to the current incident for reference during triage. +// List closed incidents in the same channel that resemble a given incident, to reuse past root causes and resolutions. // // API: POST /incident/past/list (incidentPastList). func (s *IncidentsService) PastList(ctx context.Context, req *ListPastIncidentsRequest) (*ListPastIncidentsResponse, *Response, error) { @@ -286,7 +286,7 @@ func (s *IncidentsService) PastList(ctx context.Context, req *ListPastIncidentsR // Delete post-mortem. // -// Delete a post-mortem report. +// Permanently delete a post-mortem report together with its uploaded media. // // API: POST /incident/post-mortem/delete (incidentPostMortemDelete). func (s *IncidentsService) PostMortemDelete(ctx context.Context, req *DeletePostMortemRequest) (*Response, error) { @@ -295,7 +295,7 @@ func (s *IncidentsService) PostMortemDelete(ctx context.Context, req *DeletePost // Get post-mortem. // -// Retrieve a post-mortem report by its `post_mortem_id`. List reports via `/incident/post-mortem/list` first — each row carries the incident it covers — then fetch the full report here by that id. +// Get the full content and auto-aggregated basics of a post-mortem report by its ID. // // API: GET /incident/post-mortem/info (incidentPostMortemInfo). func (s *IncidentsService) PostMortemInfo(ctx context.Context, req *IncidentsPostMortemInfoRequest) (*PostMortemItem, *Response, error) { @@ -309,7 +309,7 @@ func (s *IncidentsService) PostMortemInfo(ctx context.Context, req *IncidentsPos // List post-mortems. // -// List post-mortem reports with optional filters. +// List post-mortem reports, optionally filtered by status, team, channel, and creation time. // // API: POST /incident/post-mortem/list (incidentPostMortemList). func (s *IncidentsService) PostMortemList(ctx context.Context, req *ListPostMortemsRequest) (*ListPostMortemsResponse, *Response, error) { @@ -323,7 +323,7 @@ func (s *IncidentsService) PostMortemList(ctx context.Context, req *ListPostMort // Delete an incident. // -// Permanently delete an incident and all associated data. +// Permanently delete incidents together with their alerts, raw events, and timelines. // // API: POST /incident/remove (incidentRemove). func (s *IncidentsService) Remove(ctx context.Context, req *RemoveIncidentRequest) (*Response, error) { @@ -332,7 +332,7 @@ func (s *IncidentsService) Remove(ctx context.Context, req *RemoveIncidentReques // Reopen incident. // -// Reopen a previously resolved incident. +// Reopen closed incidents and dispatch them again from the first escalation level. // // API: POST /incident/reopen (incidentReopen). func (s *IncidentsService) Reopen(ctx context.Context, req *ReopenIncidentRequest) (*Response, error) { @@ -341,7 +341,7 @@ func (s *IncidentsService) Reopen(ctx context.Context, req *ReopenIncidentReques // Update incident fields. // -// Update one or more editable fields of an incident in a single call, including title, description, impact, root cause, resolution, and severity. At least one field must be provided. +// Update an incident's title, description, impact, root cause, resolution, or severity in one call. // // API: POST /incident/reset (incidentReset). func (s *IncidentsService) Reset(ctx context.Context, req *UpdateIncidentFieldsRequest) (*Response, error) { @@ -350,7 +350,7 @@ func (s *IncidentsService) Reset(ctx context.Context, req *UpdateIncidentFieldsR // Resolve incident. // -// Mark an incident as resolved. +// Close one or more incidents, optionally recording root cause, resolution, and resolution form values. // // API: POST /incident/resolve (incidentResolve). func (s *IncidentsService) Resolve(ctx context.Context, req *ResolveIncidentRequest) (*Response, error) { @@ -359,7 +359,7 @@ func (s *IncidentsService) Resolve(ctx context.Context, req *ResolveIncidentRequ // Add incident responder. // -// Add a responder to an existing incident. +// Add members as responders to an open incident and notify them. // // API: POST /incident/responder/add (incidentResponderAdd). func (s *IncidentsService) ResponderAdd(ctx context.Context, req *AddIncidentResponderRequest) (*Response, error) { @@ -368,7 +368,7 @@ func (s *IncidentsService) ResponderAdd(ctx context.Context, req *AddIncidentRes // Snooze incident. // -// Temporarily snooze notifications for an incident until a specified time. +// Pause notifications for acknowledged incidents for a given number of minutes. // // API: POST /incident/snooze (incidentSnooze). func (s *IncidentsService) Snooze(ctx context.Context, req *SnoozeIncidentRequest) (*Response, error) { @@ -377,7 +377,7 @@ func (s *IncidentsService) Snooze(ctx context.Context, req *SnoozeIncidentReques // Unacknowledge incident. // -// Remove the acknowledge status from an incident. +// Withdraw the calling member's acknowledgement of one or more incidents. // // API: POST /incident/unack (incidentUnack). func (s *IncidentsService) Unack(ctx context.Context, req *UnackIncidentRequest) (*Response, error) { @@ -386,7 +386,7 @@ func (s *IncidentsService) Unack(ctx context.Context, req *UnackIncidentRequest) // Wake incident. // -// Cancel the snooze on an incident and resume notifications. +// End the snooze on incidents so that their notifications resume immediately. // // API: POST /incident/wake (incidentWake). func (s *IncidentsService) Wake(ctx context.Context, req *WakeIncidentRequest) (*Response, error) { @@ -395,7 +395,7 @@ func (s *IncidentsService) Wake(ctx context.Context, req *WakeIncidentRequest) ( // Create war room. // -// Create a war room channel for collaborative incident response. +// Create an IM group chat as the war room for an incident and invite members into it. // // API: POST /incident/war-room/create (incidentWarRoomCreate). func (s *IncidentsService) WarRoomCreate(ctx context.Context, req *CreateWarRoomRequest) (*WarRoom, *Response, error) { @@ -409,7 +409,7 @@ func (s *IncidentsService) WarRoomCreate(ctx context.Context, req *CreateWarRoom // Delete war room. // -// Delete an incident war room. +// Dissolve an incident's war room group on the IM platform and unlink it from the incident. // // API: POST /incident/war-room/delete (incidentWarRoomDelete). func (s *IncidentsService) WarRoomDelete(ctx context.Context, req *DeleteWarRoomRequest) (*Response, error) { @@ -418,7 +418,7 @@ func (s *IncidentsService) WarRoomDelete(ctx context.Context, req *DeleteWarRoom // Get war room detail. // -// Retrieve the war room configuration and members for an incident. +// Fetch the current name and join link of a war room group from the IM platform. // // API: POST /incident/war-room/detail (incidentWarRoomDetail). func (s *IncidentsService) WarRoomDetail(ctx context.Context, req *GetWarRoomDetailRequest) (*WarRoom, *Response, error) { @@ -432,7 +432,7 @@ func (s *IncidentsService) WarRoomDetail(ctx context.Context, req *GetWarRoomDet // List war rooms. // -// List all war rooms associated with an incident. +// List the IM war room groups linked to an incident. // // API: POST /incident/war-room/list (incidentWarRoomList). func (s *IncidentsService) WarRoomList(ctx context.Context, req *ListWarRoomsRequest) (*ListWarRoomsResponse, *Response, error) { @@ -460,7 +460,7 @@ func (s *IncidentsService) WorkItemBindPostMortem(ctx context.Context, req *Bind // Complete a work item. // -// Mark a work item as completed by setting a client-defined target status. +// Mark a work item as done; only its current assignees can do this. // // API: POST /incident/work-item/complete (incidentWorkItemComplete). func (s *IncidentsService) WorkItemComplete(ctx context.Context, req *CompleteWorkItemRequest) (*WorkItemMutationResult, *Response, error) { @@ -488,7 +488,7 @@ func (s *IncidentsService) WorkItemConvert(ctx context.Context, req *ConvertWork // Create a work item. // -// Create an action on an active incident or a follow-up on one of its post-mortems. +// Create an action on an open incident, or a follow-up on a closed incident. // // API: POST /incident/work-item/create (incidentWorkItemCreate). func (s *IncidentsService) WorkItemCreate(ctx context.Context, req *CreateWorkItemRequest) (*WorkItemCreateResult, *Response, error) { @@ -502,7 +502,7 @@ func (s *IncidentsService) WorkItemCreate(ctx context.Context, req *CreateWorkIt // Delete a work item. // -// Soft-delete a work item. +// Soft-delete a work item so it no longer appears in work item lists. // // API: POST /incident/work-item/delete (incidentWorkItemDelete). func (s *IncidentsService) WorkItemDelete(ctx context.Context, req *DeleteWorkItemRequest) (*WorkItemMutationResult, *Response, error) { @@ -558,7 +558,7 @@ func (s *IncidentsService) WorkItemUpdate(ctx context.Context, req *UpdateWorkIt // List post-mortem templates. // -// Return built-in and custom post-mortem templates for the account. +// Return the built-in post-mortem template followed by the account's custom templates. // // API: POST /incident/post-mortem/template/list (postmortem-read-list-templates). func (s *IncidentsService) PostmortemReadListTemplates(ctx context.Context, req *ListPostMortemTemplatesRequest) (*ListPostMortemTemplatesResponse, *Response, error) { @@ -609,7 +609,7 @@ func (s *IncidentsService) PostmortemWriteInit(ctx context.Context, req *InitPos // Update post-mortem basics. // -// Replace the incident facts stored in a post-mortem report. +// Overwrite the incident facts (severity, times, responders) stored on a post-mortem report. // // API: POST /incident/post-mortem/basics/reset (postmortem-write-reset-basics). func (s *IncidentsService) PostmortemWriteResetBasics(ctx context.Context, req *ResetPostMortemBasicsRequest) (*Response, error) { @@ -618,7 +618,7 @@ func (s *IncidentsService) PostmortemWriteResetBasics(ctx context.Context, req * // Update post-mortem follow-ups. // -// Replace the follow-up action items on a post-mortem report. +// Replace the free-text follow-ups string stored on a post-mortem report. // // API: POST /incident/post-mortem/follow-ups/reset (postmortem-write-reset-follow-ups). func (s *IncidentsService) PostmortemWriteResetFollowUps(ctx context.Context, req *ResetPostMortemFollowUpsRequest) (*Response, error) { @@ -645,7 +645,7 @@ func (s *IncidentsService) PostmortemWriteResetTitle(ctx context.Context, req *R // Create or update post-mortem template. // -// Create a custom post-mortem template or update an existing one. +// Create a custom post-mortem template, or replace an existing one identified by `template_id`. // // API: POST /incident/post-mortem/template/upsert (postmortem-write-upsert-template). func (s *IncidentsService) PostmortemWriteUpsertTemplate(ctx context.Context, req *UpsertPostMortemTemplateRequest) (*PostMortemTemplate, *Response, error) { diff --git a/issues.go b/issues.go index a6048ad..cda5c3b 100644 --- a/issues.go +++ b/issues.go @@ -9,7 +9,7 @@ type IssuesService service // Export issues as CSV. // -// Export the filtered RUM error tracking issues as a CSV file. The response is a `text/csv` stream delivered with `Content-Disposition: attachment` — it is not a JSON envelope; non-console callers can read the `X-Export-Total` and `X-Export-Truncated` response headers. +// Export the issues matching the `POST /rum/issue/list` filters as a CSV file of at most 100 rows. // // The success body is a file, not a JSON envelope: it is returned on Response.Raw. // diff --git a/members.go b/members.go index 9214b55..8d95a48 100644 --- a/members.go +++ b/members.go @@ -18,7 +18,7 @@ func (s *MembersService) MemberDelete(ctx context.Context, req *MemberDeleteRequ // Grant role to member. // -// Add role assignments to a member. Role IDs that do not exist are silently ignored; if none resolve, the call is a no-op success. +// Add one or more roles to a member's existing role assignments. // // API: POST /member/role/grant (memberGrantRole). func (s *MembersService) MemberGrantRole(ctx context.Context, req *MemberRoleGrantRequest) (*Response, error) { @@ -27,7 +27,7 @@ func (s *MembersService) MemberGrantRole(ctx context.Context, req *MemberRoleGra // Get current member info. // -// Return the profile of the member the credential belongs to. Requires a member-scoped credential — calls authenticated as the account principal (e.g. an account-level app key) are rejected with a 400. +// Return the profile and account context of the member who owns the credential. // // API: POST /member/info (memberInfo). func (s *MembersService) MemberInfo(ctx context.Context) (*MemberInfoResponse, *Response, error) { @@ -69,7 +69,7 @@ func (s *MembersService) MemberList(ctx context.Context, req *MemberListRequest) // Notify members. // -// Send an email to account members on behalf of the caller, with content the caller supplies. Only callable with a credential minted for an AI SRE session; any other credential is rejected with `AccessDenied`. Delivery is asynchronous — `accepted` means the email was queued, not that it was delivered. +// Email account members a message written by the calling AI SRE session. // // API: POST /member/notify (memberNotify). func (s *MembersService) MemberNotify(ctx context.Context, req *MemberNotifyRequest) (*MemberNotifyResponse, *Response, error) { @@ -92,7 +92,7 @@ func (s *MembersService) MemberResetInfo(ctx context.Context, req *MemberResetIn // Revoke role from member. // -// Remove role assignments from a member. Role IDs that do not exist are silently ignored; if none resolve, the call is a no-op success. +// Remove one or more roles from a member's role assignments. // // API: POST /member/role/revoke (memberRevokeRole). func (s *MembersService) MemberRevokeRole(ctx context.Context, req *MemberRoleRevokeRequest) (*Response, error) { @@ -101,7 +101,7 @@ func (s *MembersService) MemberRevokeRole(ctx context.Context, req *MemberRoleRe // Update member roles. // -// Replace all role assignments for a member at once. Role IDs that do not exist are silently dropped; an empty `role_ids` resets the member to the built-in Viewer role (ID 8). +// Replace a member's role assignments with the given set of roles. // // API: POST /member/role/update (memberUpdateRole). func (s *MembersService) MemberUpdateRole(ctx context.Context, req *MemberRoleUpdateRequest) (*Response, error) { diff --git a/models_gen.go b/models_gen.go index 09581a5..577ea5f 100644 --- a/models_gen.go +++ b/models_gen.go @@ -32,7 +32,7 @@ type CustomFieldValues map[string]any // DataSourceListResponse is a list response payload. type DataSourceListResponse []DataSourceItem -// ErrorCode Flashduty error code enum. Every failed API response sets `error.code` to one of these stable wire strings. HTTP status is informational — the authoritative signal is the enum value. +// ErrorCode Error code. Every failed response sets `error.code` to one of these stable strings; branch on it rather than on the HTTP status. type ErrorCode string const ( @@ -49,11 +49,11 @@ const ( ErrorCodeRouteNotFound ErrorCode = "RouteNotFound" ErrorCodeMethodNotAllowed ErrorCode = "MethodNotAllowed" ErrorCodeUndonedOrderExist ErrorCode = "UndonedOrderExist" - ErrorCodeRequestLocked ErrorCode = "RequestLocked" ErrorCodeEntityTooLarge ErrorCode = "EntityTooLarge" - ErrorCodeRequestTooFrequently ErrorCode = "RequestTooFrequently" + ErrorCodeRequestLocked ErrorCode = "RequestLocked" ErrorCodeRequestVerifyRequired ErrorCode = "RequestVerifyRequired" ErrorCodeDangerousOperation ErrorCode = "DangerousOperation" + ErrorCodeRequestTooFrequently ErrorCode = "RequestTooFrequently" ErrorCodeInternalError ErrorCode = "InternalError" ErrorCodeServiceUnavailable ErrorCode = "ServiceUnavailable" ) @@ -84,40 +84,41 @@ type IncidentCardHiddenFields map[string][]string type IncidentFeedType string const ( - IncidentFeedTypeINew IncidentFeedType = "i_new" - IncidentFeedTypeIAssign IncidentFeedType = "i_assign" - IncidentFeedTypeIARspd IncidentFeedType = "i_a_rspd" - IncidentFeedTypeINotify IncidentFeedType = "i_notify" - IncidentFeedTypeIStorm IncidentFeedType = "i_storm" - IncidentFeedTypeISnooze IncidentFeedType = "i_snooze" - IncidentFeedTypeIWake IncidentFeedType = "i_wake" - IncidentFeedTypeIAck IncidentFeedType = "i_ack" - IncidentFeedTypeIUnack IncidentFeedType = "i_unack" - IncidentFeedTypeIComm IncidentFeedType = "i_comm" - IncidentFeedTypeIRslv IncidentFeedType = "i_rslv" - IncidentFeedTypeIReopen IncidentFeedType = "i_reopen" - IncidentFeedTypeIMerge IncidentFeedType = "i_merge" - IncidentFeedTypeIRTitle IncidentFeedType = "i_r_title" - IncidentFeedTypeIRDesc IncidentFeedType = "i_r_desc" - IncidentFeedTypeIRImpact IncidentFeedType = "i_r_impact" - IncidentFeedTypeIRRc IncidentFeedType = "i_r_rc" - IncidentFeedTypeIRRsltn IncidentFeedType = "i_r_rsltn" - IncidentFeedTypeIRSeverity IncidentFeedType = "i_r_severity" - IncidentFeedTypeIRField IncidentFeedType = "i_r_field" - IncidentFeedTypeIMFlapping IncidentFeedType = "i_m_flapping" - IncidentFeedTypeIMReply IncidentFeedType = "i_m_reply" - IncidentFeedTypeICustom IncidentFeedType = "i_custom" - IncidentFeedTypeIWrCreate IncidentFeedType = "i_wr_create" - IncidentFeedTypeIWrDelete IncidentFeedType = "i_wr_delete" - IncidentFeedTypeIAutoRefresh IncidentFeedType = "i_auto_refresh" - IncidentFeedTypeIWiCreated IncidentFeedType = "i_wi_created" - IncidentFeedTypeIWiUpdated IncidentFeedType = "i_wi_updated" - IncidentFeedTypeIWiAssignees IncidentFeedType = "i_wi_assignees" - IncidentFeedTypeIWiCompleted IncidentFeedType = "i_wi_completed" - IncidentFeedTypeIWiConverted IncidentFeedType = "i_wi_converted" - IncidentFeedTypeIWiBound IncidentFeedType = "i_wi_bound" - IncidentFeedTypeIWiDeleted IncidentFeedType = "i_wi_deleted" - IncidentFeedTypeAMerge IncidentFeedType = "a_merge" + IncidentFeedTypeINew IncidentFeedType = "i_new" + IncidentFeedTypeIAssign IncidentFeedType = "i_assign" + IncidentFeedTypeIARspd IncidentFeedType = "i_a_rspd" + IncidentFeedTypeINotify IncidentFeedType = "i_notify" + IncidentFeedTypeIStorm IncidentFeedType = "i_storm" + IncidentFeedTypeISnooze IncidentFeedType = "i_snooze" + IncidentFeedTypeIWake IncidentFeedType = "i_wake" + IncidentFeedTypeIAck IncidentFeedType = "i_ack" + IncidentFeedTypeIUnack IncidentFeedType = "i_unack" + IncidentFeedTypeIComm IncidentFeedType = "i_comm" + IncidentFeedTypeIRslv IncidentFeedType = "i_rslv" + IncidentFeedTypeIReopen IncidentFeedType = "i_reopen" + IncidentFeedTypeIMerge IncidentFeedType = "i_merge" + IncidentFeedTypeIRTitle IncidentFeedType = "i_r_title" + IncidentFeedTypeIRDesc IncidentFeedType = "i_r_desc" + IncidentFeedTypeIRImpact IncidentFeedType = "i_r_impact" + IncidentFeedTypeIRRc IncidentFeedType = "i_r_rc" + IncidentFeedTypeIRRsltn IncidentFeedType = "i_r_rsltn" + IncidentFeedTypeIRSeverity IncidentFeedType = "i_r_severity" + IncidentFeedTypeIRField IncidentFeedType = "i_r_field" + IncidentFeedTypeIMFlapping IncidentFeedType = "i_m_flapping" + IncidentFeedTypeIMReply IncidentFeedType = "i_m_reply" + IncidentFeedTypeICustom IncidentFeedType = "i_custom" + IncidentFeedTypeIWrCreate IncidentFeedType = "i_wr_create" + IncidentFeedTypeIWrDelete IncidentFeedType = "i_wr_delete" + IncidentFeedTypeIAutoRefresh IncidentFeedType = "i_auto_refresh" + IncidentFeedTypeIWiCreated IncidentFeedType = "i_wi_created" + IncidentFeedTypeIWiUpdated IncidentFeedType = "i_wi_updated" + IncidentFeedTypeIWiAssignees IncidentFeedType = "i_wi_assignees" + IncidentFeedTypeIWiCompleted IncidentFeedType = "i_wi_completed" + IncidentFeedTypeIWiConverted IncidentFeedType = "i_wi_converted" + IncidentFeedTypeIWiBound IncidentFeedType = "i_wi_bound" + IncidentFeedTypeIWiDeleted IncidentFeedType = "i_wi_deleted" + IncidentFeedTypeIWiAutoConverted IncidentFeedType = "i_wi_auto_converted" + IncidentFeedTypeAMerge IncidentFeedType = "a_merge" ) // String returns the underlying string value, implementing fmt.Stringer. @@ -169,19 +170,29 @@ func (e StatusPageSubscriberExportResponse) String() string { return string(e) } // A2aAgentCreateRequest is generated from the Flashduty OpenAPI schema. type A2aAgentCreateRequest struct { - // Agent display name. + // Agent display name, used to address the agent in sessions. Must not contain `@`, must not be `general` or `explore`, and must be unique within its scope (account-wide or one team). AgentName string `json:"agent_name" toon:"agent_name"` // Allow non-loopback HTTP OAuth discovery/metadata endpoints for this agent instead of requiring HTTPS. Defaults to false. AllowInsecureOauthHTTP bool `json:"allow_insecure_oauth_http,omitempty" toon:"allow_insecure_oauth_http,omitempty"` // Skip TLS certificate verification when connecting to this agent's endpoint (self-signed/private certs). Defaults to false. AllowInsecureTlsSkipVerify bool `json:"allow_insecure_tls_skip_verify,omitempty" toon:"allow_insecure_tls_skip_verify,omitempty"` - // Authentication config key-values, e.g. the API key or bearer token. Values under credential-looking keys (name containing KEY, SECRET, TOKEN, PASSWORD, etc.) are masked back in responses. + // Shared credential key-values: `header` and `api_key` for `auth_type=api_key`, `token` for `auth_type=bearer`. Values of `api_key`, `token`, and `client_secret` are encrypted at rest and masked in responses. AuthConfig map[string]string `json:"auth_config,omitempty" toon:"auth_config,omitempty"` - // Authentication mode: `shared` (default) shares one credential across all users; `per_user_secret` requires `secret_schema.header_name`; `per_user_oauth` runs per-user OAuth. + // Who supplies the credential: + // - `shared` (default; an empty value behaves the same): one credential stored on the agent (`auth_type` + `auth_config`) is used for every caller. + // - `per_user_secret`: each user stores their own secret, sent in the header named by `secret_schema.header_name`. + // - `per_user_oauth`: each user completes their own OAuth authorization; discovery and client registration run on first use. + // + // `per_user_secret` requires `secret_schema` with a non-empty `header_name`; any other value returns `InvalidParameter`. AuthMode string `json:"auth_mode,omitempty" toon:"auth_mode,omitempty"` - // Authentication type for reaching the remote agent: `none` (default when omitted), `api_key`, or `bearer`. + // Authentication used to reach the remote agent with a shared credential: + // - `none`: no credential header. + // - `api_key`: sends `auth_config.api_key` in the header named by `auth_config.header`. + // - `bearer`: sends `Authorization: Bearer `. + // + // When omitted the value is stored as an empty string, which behaves like `none`. AuthType string `json:"auth_type,omitempty" toon:"auth_type,omitempty"` - // URL of the remote agent card. Must be an absolute `http` or `https` URL with a non-empty host; reachability is enforced by the execution environment, not at creation time. + // URL of the remote agent card. Must be an absolute `http` or `https` URL with a non-empty host; a URL with no path is resolved to `/.well-known/agent-card.json`. If an execution environment is online, the card is fetched and must declare an A2A 1.x `JSONRPC` or `HTTP+JSON` interface. CardURL string `json:"card_url" toon:"card_url"` // Execution environments this agent is callable from: `cloud` and/or BYOC runner environment IDs. Omitted or empty means all environments. Environments []string `json:"environments,omitempty" toon:"environments,omitempty"` @@ -213,9 +224,9 @@ type A2aAgentIDRequest struct { type A2aAgentItem struct { // Owning account ID. AccountID int64 `json:"account_id" toon:"account_id"` - // Agent name resolved from the remote card. Omitted until the card has been fetched. + // Agent name read from the remote card on older records. The server no longer fills this in, so it is omitted for new agents. AgentCardName string `json:"agent_card_name" toon:"agent_card_name"` - // Skills advertised by the remote card. Omitted until the card has been fetched. + // Skill names read from the remote card on older records. The server no longer fills this in, so it is omitted for new agents. AgentCardSkills []string `json:"agent_card_skills" toon:"agent_card_skills"` // Unique A2A agent ID (prefix `a2a_`). AgentID string `json:"agent_id" toon:"agent_id"` @@ -225,13 +236,21 @@ type A2aAgentItem struct { AllowInsecureOauthHTTP bool `json:"allow_insecure_oauth_http" toon:"allow_insecure_oauth_http"` // Skip TLS certificate verification when connecting to this agent's endpoint. AllowInsecureTlsSkipVerify bool `json:"allow_insecure_tls_skip_verify" toon:"allow_insecure_tls_skip_verify"` - // Authentication config key-values. Values under credential-looking keys (name containing KEY, SECRET, TOKEN, PASSWORD, etc.) are masked. Omitted when empty. + // Shared credential key-values (`header`, `api_key`, `token`, …). Values of `api_key`, `token`, `client_secret`, and any other value stored encrypted are masked: longer than 8 characters shows the first and last 4 characters around `****`, otherwise `****`. Omitted when empty. AuthConfig map[string]string `json:"auth_config" toon:"auth_config"` - // Authentication mode. One of: `shared` (a single static credential saved on the resource and shared by all callers in the account; the default — an empty value behaves the same), `per_user_secret` (each user stores their own secret per `secret_schema`, injected per user at runtime), `per_user_oauth` (each user completes their own OAuth grant; discovery and registration run lazily on first use). + // Who supplies the credential; omitted when empty, which behaves like `shared`: + // - `shared`: one credential stored on the agent (`auth_type` + `auth_config`) is used for every caller. + // - `per_user_secret`: each user stores their own secret, sent in the header named by `secret_schema.header_name`. + // - `per_user_oauth`: each user completes their own OAuth authorization; discovery and client registration run on first use. AuthMode string `json:"auth_mode" toon:"auth_mode"` - // Authentication type for reaching the remote agent: `none`, `api_key`, or `bearer`. Rows created before validation was tightened may return an empty string, equivalent to `none`. + // Authentication used to reach the remote agent with a shared credential: + // - `none`: no credential header. + // - `api_key`: sends `auth_config.api_key` in the header named by `auth_config.header`. + // - `bearer`: sends `Authorization: Bearer `. + // + // An empty string means `auth_type` was omitted at creation and behaves like `none`. AuthType string `json:"auth_type" toon:"auth_type"` - // Whether the caller may edit this agent. + // Whether the caller may update, enable, disable, or delete this agent: `true` for an account-scoped agent only for the account owner or an admin, for a team agent only for members of that team. CanEdit bool `json:"can_edit" toon:"can_edit"` // Card-resolution timeout in seconds. Always 0 today — the API does not yet expose a way to set it. CardResolveTimeout int64 `json:"card_resolve_timeout" toon:"card_resolve_timeout"` @@ -249,7 +268,9 @@ type A2aAgentItem struct { OauthMetadata string `json:"oauth_metadata" toon:"oauth_metadata"` // JSON-encoded secret schema (per_user_secret mode). SecretSchema string `json:"secret_schema" toon:"secret_schema"` - // Agent status. + // Whether the agent is offered to AI SRE sessions: + // - `enabled`: available for dispatch (the state after create). + // - `disabled`: kept but not offered; re-enable with `POST /safari/a2a-agent/enable`. Status string `json:"status" toon:"status"` // Whether the remote agent supports streaming responses. Streaming bool `json:"streaming" toon:"streaming"` @@ -263,9 +284,9 @@ type A2aAgentItem struct { // A2aAgentListRequest is generated from the Flashduty OpenAPI schema. type A2aAgentListRequest struct { - // Include account-scoped (team_id=0) rows. Defaults to true. + // Include account-scoped (`team_id=0`) rows. Defaults to `true`; ignored when `scope` is `account` (always included) or `team` (never included). IncludeAccount *bool `json:"include_account,omitempty" toon:"include_account,omitempty"` - // Page size. + // Page size; 0 or less falls back to 20. No upper bound is enforced. Limit int64 `json:"limit,omitempty" toon:"limit,omitempty"` // Pagination offset — number of rows to skip, starting from 0. Offset int64 `json:"offset,omitempty" toon:"offset,omitempty"` @@ -273,7 +294,7 @@ type A2aAgentListRequest struct { Query string `json:"query,omitempty" toon:"query,omitempty"` // Visibility scope: `all` (account-scope plus the caller's visible teams), `account` (account-scope only), or `team` (team-scoped rows across the caller's visible teams). Scope string `json:"scope,omitempty" toon:"scope,omitempty"` - // Filter to these team IDs; empty = the caller's visible set. + // Restrict to these team IDs. IDs of teams the caller does not belong to are ignored; empty means all of the caller's teams. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` } @@ -289,7 +310,7 @@ type A2aAgentListResponse struct { type A2aAgentUpdateRequest struct { // Target agent ID, from the list returned by `POST /safari/a2a-agent/list`. AgentID string `json:"agent_id" toon:"agent_id"` - // New display name. Omit to leave unchanged. + // New display name; omit to leave unchanged. Same rules as create: no `@`, not `general` / `explore`, unique within the scope. AgentName *string `json:"agent_name,omitempty" toon:"agent_name,omitempty"` // Toggle non-loopback HTTP OAuth discovery for this agent. Omit to leave unchanged. AllowInsecureOauthHTTP *bool `json:"allow_insecure_oauth_http,omitempty" toon:"allow_insecure_oauth_http,omitempty"` @@ -297,23 +318,31 @@ type A2aAgentUpdateRequest struct { AllowInsecureTlsSkipVerify *bool `json:"allow_insecure_tls_skip_verify,omitempty" toon:"allow_insecure_tls_skip_verify,omitempty"` // Replace the whole auth config; omit to leave unchanged. Keys missing from the map are dropped. For a sensitive key, sending back the masked value keeps the stored secret, while sending an empty string clears it. AuthConfig map[string]string `json:"auth_config,omitempty" toon:"auth_config,omitempty"` - // New auth mode: shared, per_user_secret, or per_user_oauth. Changing it always rewrites secret_schema together with it. + // New auth mode; omit to leave unchanged. Values (who supplies the credential): + // - `shared` (default; an empty value behaves the same): one credential stored on the agent (`auth_type` + `auth_config`) is used for every caller. + // - `per_user_secret`: each user stores their own secret, sent in the header named by `secret_schema.header_name`. + // - `per_user_oauth`: each user completes their own OAuth authorization; discovery and client registration run on first use. + // + // When sent, `secret_schema` is overwritten with the value in the same request. AuthMode *string `json:"auth_mode,omitempty" toon:"auth_mode,omitempty"` - // New auth type: `none`, `api_key`, or `bearer`. Omit to leave unchanged. + // New auth type; omit to leave unchanged. + // - `none`: no credential header. + // - `api_key`: sends `auth_config.api_key` in the header named by `auth_config.header`. + // - `bearer`: sends `Authorization: Bearer `. AuthType *string `json:"auth_type,omitempty" toon:"auth_type,omitempty"` - // New card URL. Omit to leave unchanged. + // New card URL; omit to leave unchanged. Validated and compatibility-checked the same way as on create; a real change also clears `oauth_metadata` unless a new one is sent. CardURL *string `json:"card_url,omitempty" toon:"card_url,omitempty"` // Execution environments this agent is callable from: `cloud` and/or BYOC runner environment IDs. Omit (null) to leave unchanged; send a list to set it — an empty list clears the restriction back to all environments. Environments []string `json:"environments,omitempty" toon:"environments,omitempty"` // New instructions document (same contract as create: optional `summary` frontmatter, non-empty body, at most 50 KiB). Omit to leave unchanged. A deprecated `description` field is also accepted; if both are sent they must match. Instructions *string `json:"instructions,omitempty" toon:"instructions,omitempty"` - // New JSON OAuth metadata. If omitted while auth_mode changes, it is cleared to empty. + // New JSON OAuth metadata. A non-empty value is stored as sent. When omitted or empty, the stored value is kept unless `auth_mode` or `card_url` changes, in which case it is cleared. OauthMetadata *string `json:"oauth_metadata,omitempty" toon:"oauth_metadata,omitempty"` - // New JSON secret schema. + // New JSON secret schema, e.g. `{"header_name":"X-Api-Key"}`. Applied only together with `auth_mode`; sent alone it is ignored. SecretSchema *string `json:"secret_schema,omitempty" toon:"secret_schema,omitempty"` // Toggle streaming support. Omit to leave unchanged. Streaming *bool `json:"streaming,omitempty" toon:"streaming,omitempty"` - // Reassign team scope. Omit to leave unchanged. Reassigning requires rights on the destination team; if the team changes without also sending a new environment binding, the existing runner binding must remain selectable by the caller or the update is rejected. + // Reassign team scope; omit to leave unchanged. Moving to a team requires membership in it; moving to account scope (`0`) requires the account owner or an admin. If the team changes without `environments` in the same request, the current runner entries must stay selectable by the caller or the update is rejected. TeamID *int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` } @@ -321,7 +350,7 @@ type A2aAgentUpdateRequest struct { type AccountInfo struct { // Account identifier. AccountID uint64 `json:"account_id" toon:"account_id"` - // Account name. + // Account (organization) name shown in the console. AccountName string `json:"account_name" toon:"account_name"` // Account avatar URL. Avatar string `json:"avatar" toon:"avatar"` @@ -335,17 +364,17 @@ type AccountInfo struct { Email string `json:"email" toon:"email"` // Additional account domains. ExtraDomains []string `json:"extra_domains" toon:"extra_domains"` - // Account language preference (e.g. zh-CN, en-US). + // Account language preference (`zh-CN` or `en-US`); empty string when not set. Locale string `json:"locale" toon:"locale"` // Account identifier on the marketplace platform. Omitted together with `mp_plat`. MpAccountID string `json:"mp_account_id" toon:"mp_account_id"` - // Cloud marketplace platform the account was provisioned from. Omitted when the account did not come from a marketplace. + // Cloud marketplace the account was provisioned from: `aws` — AWS Marketplace. Omitted when the account did not come from a marketplace. MpPlat string `json:"mp_plat" toon:"mp_plat"` // Account contact phone, masked for privacy. Phone string `json:"phone" toon:"phone"` // Account access restrictions. Omitted when none are configured. Restrictions AccountInfoRestrictions `json:"restrictions" toon:"restrictions"` - // Account default timezone (IANA name, e.g. Asia/Shanghai). + // Account default time zone (IANA name, e.g. `Asia/Shanghai`); members without their own setting follow it. Empty string when not set. TimeZone string `json:"time_zone" toon:"time_zone"` } @@ -365,19 +394,19 @@ type AckIncidentRequest struct { type AddIncidentResponderRequest struct { // Incident ID (MongoDB ObjectID). IncidentID string `json:"incident_id" toon:"incident_id"` - // Optional notification override. Defaults to following each person's personal preference. + // Notification settings for the newly added responders. Defaults to `{"follow_preference": true}`. Notify AddIncidentResponderRequestNotify `json:"notify,omitzero" toon:"notify,omitempty"` - // Member IDs to add as responders. + // Member IDs to add as responders. IDs that are already responders, or that do not exist in the account, are skipped. PersonIDs []int64 `json:"person_ids" toon:"person_ids"` } // AddWarRoomMemberRequest is generated from the Flashduty OpenAPI schema. type AddWarRoomMemberRequest struct { - // Chat ID of the war room within the IM platform. + // Chat ID of the war-room group on the IM platform, as returned for the war room by `POST /incident/war-room/list`. ChatID string `json:"chat_id" toon:"chat_id"` // ID of the IM integration hosting the war room; obtain it from `POST /datasource/im/war-room-enabled/list`. IntegrationID int64 `json:"integration_id" toon:"integration_id"` - // Person IDs to add to the war room. + // Person IDs (member IDs, or the account ID for the owner) to add. Must not be empty. MemberIDs []int64 `json:"member_ids" toon:"member_ids"` } @@ -415,7 +444,7 @@ type AlertEventGlobalListRequest struct { ListOptions // Sort ascending when `true`. Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` - // Filter by channel IDs. At most 100 entries. + // Filter by channel IDs. At most 100 entries. Channels the caller cannot access are dropped; if none remain, the result is empty. ChannelIDs []int64 `json:"channel_ids,omitempty" toon:"channel_ids,omitempty"` // End of the search window, Unix epoch seconds. Must be greater than `start_time`; the span must not exceed 31 days. EndTime int64 `json:"end_time" toon:"end_time"` @@ -425,7 +454,7 @@ type AlertEventGlobalListRequest struct { IntegrationTypes []string `json:"integration_types,omitempty" toon:"integration_types,omitempty"` // Sort field; only `event_time` is supported. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` - // Comma-separated severity filter, e.g. `Critical,Warning`. Accepted values: `Critical`, `Warning`, `Info`, `Ok`. + // Comma-separated filter on `event_severity`, e.g. `Critical,Warning`. Meaningful values: `Critical`, `Warning`, `Info`. Values are not validated; an unknown value (or `Ok`) matches nothing. Severities string `json:"severities,omitempty" toon:"severities,omitempty"` // Start of the search window, Unix epoch seconds. Must be greater than 0. StartTime int64 `json:"start_time" toon:"start_time"` @@ -445,7 +474,7 @@ type AlertEventGlobalListResponse struct { // AlertEventItem is generated from the Flashduty OpenAPI schema. type AlertEventItem struct { - // Account ID. + // ID of the account that owns this record; the same for every record returned to one `app_key`. AccountID int64 `json:"account_id" toon:"account_id"` // Parent alert ID (MongoDB ObjectID). AlertID string `json:"alert_id" toon:"alert_id"` @@ -473,7 +502,7 @@ type AlertEventItem struct { Images []AlertImage `json:"images" toon:"images"` // Integration that produced this event. IntegrationID int64 `json:"integration_id" toon:"integration_id"` - // Type/plugin key of the integration that produced this event. + // Plugin type of the integration, such as `prometheus.alert`, `grafana.alert`, `zabbix.alert`, `monit.alert`, or `email.alert`. The set is open and grows with new integrations; `POST /integration/type/list` returns the full list. IntegrationType string `json:"integration_type" toon:"integration_type"` // Label key-value pairs. Labels map[string]string `json:"labels" toon:"labels"` @@ -527,7 +556,7 @@ type AlertFeedResponse struct { // AlertImage is generated from the Flashduty OpenAPI schema. type AlertImage struct { - // Alt text. + // Alternative text shown when the image cannot be displayed; empty when not set. Alt string `json:"alt" toon:"alt"` // Optional link URL when the image is clicked. Href string `json:"href" toon:"href"` @@ -537,7 +566,7 @@ type AlertImage struct { // AlertInfo is generated from the Flashduty OpenAPI schema. type AlertInfo struct { - // Account ID. + // ID of the account that owns this record; the same for every record returned to one `app_key`. AccountID int64 `json:"account_id" toon:"account_id"` // Alert ID (MongoDB ObjectID). AlertID string `json:"alert_id" toon:"alert_id"` @@ -547,11 +576,11 @@ type AlertInfo struct { AlertSeverity string `json:"alert_severity" toon:"alert_severity"` // Current status. AlertStatus string `json:"alert_status" toon:"alert_status"` - // Channel ID. + // ID of the channel the alert was routed to; its name is in `channel_name`. ChannelID int64 `json:"channel_id" toon:"channel_id"` // Channel display name. ChannelName string `json:"channel_name" toon:"channel_name"` - // Channel status. + // Status of the channel: `enabled`, `disabled`, or `deleted`. Empty string when the record has no channel or the channel no longer exists. ChannelStatus string `json:"channel_status" toon:"channel_status"` // Creation timestamp (seconds). CreatedAt Timestamp `json:"created_at" toon:"created_at"` @@ -561,7 +590,7 @@ type AlertInfo struct { DataSourceName string `json:"data_source_name" toon:"data_source_name"` // Deprecated. Use `integration_ref_id`. DataSourceRefID string `json:"data_source_ref_id" toon:"data_source_ref_id"` - // Deprecated. Use `integration_type`. + // Deprecated; same value as `integration_type`. DataSourceType string `json:"data_source_type" toon:"data_source_type"` // Soft-delete timestamp (seconds). Zero if not deleted. DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` @@ -577,7 +606,7 @@ type AlertInfo struct { Events []AlertEventItem `json:"events" toon:"events"` // Whether this alert has ever been silenced. EverMuted bool `json:"ever_muted" toon:"ever_muted"` - // Attached images. + // Images attached to the alert; `null` when there are none. Images []Image `json:"images" toon:"images"` // Parent incident reference, if the alert has been merged into one. Incident IncidentShort `json:"incident" toon:"incident"` @@ -587,15 +616,15 @@ type AlertInfo struct { IntegrationName string `json:"integration_name" toon:"integration_name"` // Integration reference ID. IntegrationRefID string `json:"integration_ref_id" toon:"integration_ref_id"` - // Integration type string. + // Plugin type of the integration, such as `prometheus.alert`, `grafana.alert`, `zabbix.alert`, `monit.alert`, or `email.alert`. The set is open and grows with new integrations; `POST /integration/type/list` returns the full list. IntegrationType string `json:"integration_type" toon:"integration_type"` // Alert labels. Labels map[string]string `json:"labels" toon:"labels"` // Unix timestamp (seconds) of the most recent event. LastTime Timestamp `json:"last_time" toon:"last_time"` - // Primary responder email, if any. + // Always an empty string in API responses; filled only when the alert is rendered for notifications. ResponderEmail string `json:"responder_email" toon:"responder_email"` - // Primary responder name, if any. + // Always an empty string in API responses; filled only when the alert is rendered for notifications. ResponderName string `json:"responder_name" toon:"responder_name"` // Unix timestamp (seconds) when the alert first fired. StartTime Timestamp `json:"start_time" toon:"start_time"` @@ -615,7 +644,7 @@ type AlertInfoRequest struct { // AlertItem is generated from the Flashduty OpenAPI schema. type AlertItem struct { - // Account ID. + // ID of the account that owns the alert. AccountID int64 `json:"account_id" toon:"account_id"` // Unique alert ID (ObjectID hex string). AlertID string `json:"alert_id" toon:"alert_id"` @@ -639,7 +668,7 @@ type AlertItem struct { DataSourceName string `json:"data_source_name" toon:"data_source_name"` // Deprecated: use `integration_ref_id` instead. DataSourceRefID string `json:"data_source_ref_id" toon:"data_source_ref_id"` - // Deprecated: use `integration_type` instead. Omitted when empty. + // Deprecated: use `integration_type` instead (same value, e.g. `prometheus.alert`). Omitted when empty. DataSourceType string `json:"data_source_type" toon:"data_source_type"` // Soft-delete time, Unix epoch seconds. Omitted when the alert is not deleted. DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` @@ -655,7 +684,7 @@ type AlertItem struct { Events []AlertEventItem `json:"events" toon:"events"` // True if this alert has ever been silenced. EverMuted bool `json:"ever_muted" toon:"ever_muted"` - // Images attached to the alert. + // Images attached to the alert; `null` when there are none. Images []AlertImage `json:"images" toon:"images"` // Associated incident, if any. Incident IncidentShort `json:"incident" toon:"incident"` @@ -663,11 +692,11 @@ type AlertItem struct { IntegrationID int64 `json:"integration_id" toon:"integration_id"` // Display name of the integration. IntegrationName string `json:"integration_name" toon:"integration_name"` - // External reference ID of the integration. + // Owner reference of the integration: `a_` for an account-level integration, `c_` for a channel-owned one. IntegrationRefID string `json:"integration_ref_id" toon:"integration_ref_id"` - // Type/plugin key of the integration. + // Type key of the integration that produced the alert, e.g. `prometheus.alert` or `zabbix.alert`; same values as `plugin_type` from `POST /integration/type/list`. IntegrationType string `json:"integration_type" toon:"integration_type"` - // Label key-value pairs. + // Label key-value pairs; `null` when the alert has no labels. Labels map[string]string `json:"labels" toon:"labels"` // Last-event time, Unix epoch seconds. LastTime Timestamp `json:"last_time" toon:"last_time"` @@ -687,7 +716,7 @@ type AlertItem struct { // AlertListByIDsRequest is generated from the Flashduty OpenAPI schema. type AlertListByIDsRequest struct { - // Alert IDs (ObjectID hex strings) to fetch. + // Alert IDs (ObjectID hex strings) to fetch. A malformed ID fails the request; IDs not found in the account are left out of the result. AlertIDs []string `json:"alert_ids" toon:"alert_ids"` } @@ -698,15 +727,15 @@ type AlertListRequest struct { AlertIDs []string `json:"alert_ids,omitempty" toon:"alert_ids,omitempty"` // Filter by alert deduplication keys. AlertKeys []string `json:"alert_keys,omitempty" toon:"alert_keys,omitempty"` - // Comma-separated severity filter, e.g. `Critical,Warning`. Allowed values: `Critical`, `Warning`, `Info`, `Ok`. + // Comma-separated filter on `alert_severity`, e.g. `Critical,Warning`. Allowed values: `Critical`, `Warning`, `Info`, `Ok`; other values return `InvalidParameter`. `Ok` matches nothing because `alert_severity` is never `Ok`. AlertSeverity string `json:"alert_severity,omitempty" toon:"alert_severity,omitempty"` // Sort ascending by `start_time` when `true`; default is descending. Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` - // When `true`, the time range filter is applied on `updated_at` rather than `start_time`. + // When `true`, also require the alert's `updated_at` to fall within [`start_time`, `end_time`], in addition to the `start_time` filter; the span must then not exceed 7 days. ByUpdatedAt bool `json:"by_updated_at,omitempty" toon:"by_updated_at,omitempty"` // Filter by channel IDs. ChannelIDs []int64 `json:"channel_ids,omitempty" toon:"channel_ids,omitempty"` - // End of the search window, Unix epoch seconds. Must be greater than `start_time`; the span must not exceed 31 days and must lie within the account's data retention period. + // End of the search window, Unix epoch seconds. Must be greater than `start_time`; the span must not exceed 31 days (7 days with `by_updated_at`). A value before the start of the data retention period returns `InvalidParameter`. EndTime int64 `json:"end_time" toon:"end_time"` // Filter by whether the alert has ever been silenced. EverMuted *bool `json:"ever_muted,omitempty" toon:"ever_muted,omitempty"` @@ -714,19 +743,19 @@ type AlertListRequest struct { IntegrationIDs []int64 `json:"integration_ids,omitempty" toon:"integration_ids,omitempty"` // Filter by lifecycle: `true` returns only firing alerts (status `Critical`/`Warning`/`Info`), `false` returns only recovered alerts (status `Ok`). Omit or pass `null` to return both. IsActive *bool `json:"is_active,omitempty" toon:"is_active,omitempty"` - // Start of the search window, Unix epoch seconds. + // Start of the search window, Unix epoch seconds, applied to the alert's `start_time`. A value earlier than the account's data retention period is moved up to the retention start. StartTime int64 `json:"start_time" toon:"start_time"` } // AlertListResponse is generated from the Flashduty OpenAPI schema. type AlertListResponse struct { - // True if more pages are available. + // `true` when another page exists. Exact in both cursor mode (`search_after_ctx` sent) and page-number mode, including past the 1,000 cap of `total`. HasNextPage bool `json:"has_next_page" toon:"has_next_page"` // Alerts on the current page. Items []AlertItem `json:"items" toon:"items"` - // Cursor for the next page — the ObjectID hex of the last alert on this page; pass it back as `search_after_ctx`. Present only when `has_next_page` is true. + // Cursor for the next page — the ObjectID hex of the last alert on this page; pass it back as `search_after_ctx`. Omitted when the page is empty; in cursor mode also omitted when there is no next page. SearchAfterCtx string `json:"search_after_ctx" toon:"search_after_ctx"` - // Total matching alerts, capped at 1000. + // Number of matching alerts, capped at 1,000. Total int64 `json:"total" toon:"total"` } @@ -746,7 +775,7 @@ type AlertMergeRequest struct { // AlertPipeline is generated from the Flashduty OpenAPI schema. type AlertPipeline struct { - // AND-filter list — the rule applies only when every condition matches. `null` or omitted means the rule applies to all events. + // AND-filter list — the rule applies only when every condition matches the incoming event. Keys: `severity` (aliases `alert_severity`, `event_severity`), `status`, `title`, `title_rule`, `description`, `alert_key`, `integration_id` (alias `data_source_id`), and `labels.`; other keys return `InvalidParameter`. `null` or omitted means the rule applies to all events. If []FilterCondition `json:"if,omitempty" toon:"if,omitempty"` // Rule type. Rules run in array order; when the `if` condition matches, the event is processed according to `kind`. // | Value | Meaning | @@ -806,9 +835,9 @@ type AlertPipelineListResponse struct { // AlertPipelineUpsertRequest is generated from the Flashduty OpenAPI schema. type AlertPipelineUpsertRequest struct { - // Integration ID to configure. + // ID of the integration to configure; account-level and channel-owned integrations are both accepted. IntegrationID int64 `json:"integration_id" toon:"integration_id"` - // Rules to apply, evaluated in array order. Between 1 and 50 entries. + // Rules to apply, evaluated in array order. At most 50 entries; an empty array removes all rules. Rules []AlertPipeline `json:"rules" toon:"rules"` } @@ -896,7 +925,7 @@ type AlertRuleAudit struct { Action string `json:"action" toon:"action"` // ID of the alert rule this record belongs to. AlertRuleID uint64 `json:"alert_rule_id" toon:"alert_rule_id"` - // JSON string of the full rule snapshot at audit time. Populated on `/monit/rule/audit/detail`, omitted on list responses. + // JSON string of the full rule right after the change. Populated on `/monit/rule/audit/detail`, omitted on list responses. Records written by `/monit/rule/v2/create` and `/monit/rule/v2/update` use the `AlertRuleV2` shape; records written by `/monit/rule/update/fields` and `/monit/rule/move` use the stored rule shape, whose checker configs carry legacy recovery settings instead of `recovery_mode` / `end_mode`. Content string `json:"content" toon:"content"` // When this audit record was produced, as a Unix timestamp in seconds; equals the rule's `updated_at` at change time. CreatedAt Timestamp `json:"created_at" toon:"created_at"` @@ -910,7 +939,7 @@ type AlertRuleAudit struct { // AlertRuleBasic is generated from the Flashduty OpenAPI schema. type AlertRuleBasic struct { - // Account ID. + // ID of the account that owns the rule; `0` in `include_descendants: true` listings. AccountID uint64 `json:"account_id" toon:"account_id"` // Number of currently active (unrecovered) alerts fired by this rule. `triggered` equals `active_alert_count > 0`. ActiveAlertCount int64 `json:"active_alert_count" toon:"active_alert_count"` @@ -922,21 +951,21 @@ type AlertRuleBasic struct { CreatorName string `json:"creator_name" toon:"creator_name"` // Schedule expression: a 6-field cron with seconds, e.g. `0 * * * * *`, or an `@every 30s` interval descriptor. Must not start with `CRON_TZ=` or `TZ=`; use the `timezone` field instead. CronPattern string `json:"cron_pattern" toon:"cron_pattern"` - // Whether debug logging is enabled. + // Whether debug logging is on; when `true` the edge writes detailed evaluation logs for this rule. DebugLogEnabled bool `json:"debug_log_enabled" toon:"debug_log_enabled"` - // Evaluation delay in seconds. + // Seconds the evaluation query window is shifted back to allow for data ingestion latency. DelaySeconds int64 `json:"delay_seconds" toon:"delay_seconds"` - // Data source type, e.g. `prometheus`. + // Datasource type the rule queries. Types that support alerting: `prometheus`, `elasticsearch`, `loki`, `clickhouse`, `mysql`, `oracle`, `postgres`, `sls`, `tencent_cls`, `victorialogs`. Only enabled rules are checked against this list, so a disabled rule may carry another value; empty in `include_descendants: true` listings. DsType string `json:"ds_type" toon:"ds_type"` // Whether the rule is enabled. Enabled bool `json:"enabled" toon:"enabled"` - // Folder ID. + // ID of the folder that directly contains the rule; in `include_descendants: true` listings it can be a descendant of the requested folder. FolderID uint64 `json:"folder_id" toon:"folder_id"` // Unique rule ID. ID uint64 `json:"id" toon:"id"` - // Custom labels. + // Custom labels the rule adds to its alert events; `null` in `include_descendants: true` listings. Labels map[string]string `json:"labels" toon:"labels"` - // Rule name. + // Rule name, unique within its folder (at most 128 characters). Name string `json:"name" toon:"name"` // Runtime evaluation state, derived from edge heartbeats and the edge-reported rule status. Omitted when the state is unavailable. // @@ -973,7 +1002,7 @@ type AlertRuleConfigsV2 struct { CheckThreshold AlertRuleThresholdV2 `json:"check_threshold,omitzero" toon:"check_threshold,omitempty"` // Query list with at least one entry; each needs a unique `name` (`R` and `__all__` are reserved) and a non-empty, non-duplicated `expr`. Queries []AlertRuleConfigsV2QueriesItem `json:"queries" toon:"queries"` - // Optional auxiliary queries whose results attach to alert events as context. Each entry needs a unique `name` (not colliding with any query name) and a non-empty `expr`. + // Optional auxiliary queries whose results attach to alert events as context. Each entry needs a unique `name` (not colliding with any query name) and a non-empty `expr`. Always returned, as `[]` when there are none. RelateQueries []AlertRuleConfigsV2RelateQueriesItem `json:"relate_queries,omitempty" toon:"relate_queries,omitempty"` } @@ -1094,13 +1123,13 @@ type AlertRuleV2 struct { CreatorID uint64 `json:"creator_id,omitempty" toon:"creator_id,omitempty"` // Creator name, filled by the server; any client-supplied value is ignored. CreatorName string `json:"creator_name,omitempty" toon:"creator_name,omitempty"` - // Schedule expression: a 6-field cron (with seconds) or an `@every 30s` interval. Must not start with `CRON_TZ=` or `TZ=`; set the timezone in the `timezone` field instead. + // Schedule expression: a 6-field cron with seconds (e.g. `0 * * * * *`), a descriptor such as `@hourly`, or `@every ` with a whole number of seconds of at least `1s` (e.g. `@every 30s`). Must not start with `CRON_TZ=` or `TZ=`; set the timezone in the `timezone` field instead. CronPattern string `json:"cron_pattern" toon:"cron_pattern"` // Enable debug logging; the edge then emits detailed evaluation logs for this rule, useful when the rule does not trigger as expected. DebugLogEnabled bool `json:"debug_log_enabled,omitempty" toon:"debug_log_enabled,omitempty"` // Seconds the evaluation query window is shifted back, compensating for data ingestion latency. DelaySeconds int64 `json:"delay_seconds,omitempty" toon:"delay_seconds,omitempty"` - // Rule description, Markdown format. + // Rule description; rendered as plain text or Markdown according to `description_type`. Description string `json:"description,omitempty" toon:"description,omitempty"` // Format of the description content. Empty or omitted defaults to `text`. `text` = plain text; `markdown` = Markdown, rendered as such in alert details. DescriptionType string `json:"description_type,omitempty" toon:"description_type,omitempty"` @@ -1108,7 +1137,7 @@ type AlertRuleV2 struct { DsIDs []uint64 `json:"ds_ids,omitempty" toon:"ds_ids,omitempty"` // Datasource name match patterns (wildcards supported). At least one of `ds_list` / `ds_ids` must be non-empty; both are merged to decide which datasources the rule monitors. DsList []string `json:"ds_list,omitempty" toon:"ds_list,omitempty"` - // Datasource type identifier (e.g. `prometheus`, `elasticsearch`). + // Datasource type the rule queries. When the rule is enabled it must be a type that supports alerting: `prometheus`, `elasticsearch`, `loki`, `clickhouse`, `mysql`, `oracle`, `postgres`, `sls`, `tencent_cls`, `victorialogs`. DsType string `json:"ds_type" toon:"ds_type"` // Whether the rule is enabled. Required — the server enforces an explicit value (including `false`) while decoding. Setting it to `false` on update clears the rule's active alerts. Enabled bool `json:"enabled" toon:"enabled"` @@ -1118,15 +1147,15 @@ type AlertRuleV2 struct { FolderID uint64 `json:"folder_id" toon:"folder_id"` // Rule ID. Required on update; omit on create (assigned by the server). ID uint64 `json:"id,omitempty" toon:"id,omitempty"` - // Drill-down entries linked from the alert event detail page; at most 20 items, duplicates rejected. On update the field is presence-based: omit it to keep the current value, pass `[]` to clear. + // Drill-down entries linked from the alert event detail page; at most 20 items, duplicates rejected, and at most 32 KiB once serialized. On update the field is presence-based: omit it to keep the current value, pass `[]` to clear; `null` is rejected. InvestigationTargets []InvestigationTarget `json:"investigation_targets,omitzero" toon:"investigation_targets,omitempty"` - // Custom labels. + // Custom labels added to every alert event of the rule. Keys are trimmed, must not be empty and must not start with `__alert_rule_` (reserved); values containing `{{` are rendered as templates when events are delivered; `job` and `instance` values are limited to 255 characters. The serialized object may not exceed 1024 characters. Labels map[string]string `json:"labels,omitempty" toon:"labels,omitempty"` // Rule name. Must be unique within the folder and at most 128 characters. Name string `json:"name" toon:"name"` - // Notification repeat interval in seconds. Values below 1 fall back to the default 3600. + // Notification repeat interval in seconds. Values below 1 fall back to the default 3600; maximum 2147483647. RepeatInterval int64 `json:"repeat_interval,omitempty" toon:"repeat_interval,omitempty"` - // Maximum number of repeat notifications. Values below 1 fall back to the default 3. + // Maximum number of repeat notifications. Values below 1 fall back to the default 3; maximum 2147483647. RepeatTotal int64 `json:"repeat_total,omitempty" toon:"repeat_total,omitempty"` // Detection configuration: query list plus trigger/recovery conditions. See `AlertRuleConfigsV2`. RuleConfigs AlertRuleConfigsV2 `json:"rule_configs" toon:"rule_configs"` @@ -1153,27 +1182,27 @@ type ApAlertDrop struct{} // ApAlertInhibit is generated from the Flashduty OpenAPI schema. type ApAlertInhibit struct { - // Label keys whose values must be equal between the source and current alert for inhibition to apply. + // Keys whose values must be equal on the source alert and the current event: `title`, `severity`, or `labels.`. An empty list, any other key, or a label missing on the event means the rule never inhibits. Equals []string `json:"equals" toon:"equals"` - // AND-filter list identifying the source alerts to inhibit — every condition must match. + // AND-conditions a source alert must meet. Allowed keys: `severity`, `title`, and `labels.`; other keys return `InvalidParameter`. SourceFilters []FilterCondition `json:"source_filters" toon:"source_filters"` } // ApDescriptionReset is generated from the Flashduty OpenAPI schema. type ApDescriptionReset struct { - // New description template. + // Description template. Only a value starting with `[TPL]` takes effect: the rest is rendered as a Go template against the event and replaces the description. A value without the prefix leaves the description unchanged. Description string `json:"description" toon:"description"` } // ApSeverityReset is generated from the Flashduty OpenAPI schema. type ApSeverityReset struct { - // Target severity level. + // Severity to set: `Critical`, `Warning` or `Info`. The event status is set to the same value. Severity string `json:"severity" toon:"severity"` } // ApTitleReset is generated from the Flashduty OpenAPI schema. type ApTitleReset struct { - // New title template. Supports Golang template syntax referencing alert fields. + // Title rule. A value starting with `[TPL]` is a Go template rendered against the event, e.g. `[TPL]{{.Labels.service}}`. Otherwise it is a `::`-separated list in which each `$name` part is replaced by the value of label `name` and other parts are kept as written. Title string `json:"title" toon:"title"` } @@ -1181,7 +1210,7 @@ type ApTitleReset struct { type ArtifactFileStateItem struct { // Artifact ID (`art_` prefix). Also the key of the public-share link. ArtifactID string `json:"artifact_id" toon:"artifact_id"` - // Echoes the requested presented-file ID. + // The requested presented-file ID this entry answers for. FileID string `json:"file_id" toon:"file_id"` // Console-relative path of the artifact page: `/ai-sre/artifacts/`. GalleryPath string `json:"gallery_path" toon:"gallery_path"` @@ -1191,13 +1220,13 @@ type ArtifactFileStateItem struct { // ArtifactFileStateRequest is generated from the Flashduty OpenAPI schema. type ArtifactFileStateRequest struct { - // Presented-file IDs (`pf_` prefix) to probe. At most 50 per call; duplicates and empty strings are ignored. + // Presented-file IDs (`pf_` prefix) to check. At most 50 entries per call, counted before duplicates and empty strings are removed; more fails with `InvalidParameter`. FileIDs []string `json:"file_ids" toon:"file_ids"` } // ArtifactFileStateResponse is generated from the Flashduty OpenAPI schema. type ArtifactFileStateResponse struct { - // One entry per requested file that has a live published artifact; files without one are omitted. + // One entry per requested file whose session file path currently has a live gallery artifact; files without one, and unknown IDs, are omitted. An empty array when none match. Items []ArtifactFileStateItem `json:"items" toon:"items"` } @@ -1211,23 +1240,23 @@ type ArtifactIDRequest struct { type ArtifactListRequest struct { // Sort ascending when true, descending when false. Applies only when `orderby` is set. Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` - // Page size. Defaults to 20; capped at 100. + // Number of artifacts per page. Values below 1 fall back to 20; values above 100 are capped at 100 (not rejected). Limit int64 `json:"limit,omitempty" toon:"limit,omitempty"` - // Sort field: `created_at` or `updated_at`. Empty means `updated_at` descending. + // Sort field: `created_at` (publish time) or `updated_at` (last change). Empty sorts by `updated_at` descending. In every case the caller's pinned artifacts come first, and `artifact_id` breaks ties. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` - // Page number, 1-based. + // Page number, 1-based. Values below 1 are treated as 1. Page int64 `json:"page,omitempty" toon:"page,omitempty"` // Case-insensitive substring match on the artifact title. Query string `json:"query,omitempty" toon:"query,omitempty"` // Visibility scope. `all` (default) lists the caller's own personal artifacts plus artifacts of every team the caller belongs to; `personal` lists only the caller's own; `team` lists only team-owned artifacts of the caller's teams. Scope string `json:"scope,omitempty" toon:"scope,omitempty"` - // Restrict to artifacts owned by these team IDs, intersected with the caller's visibility — teams the caller does not belong to silently return nothing. + // Restrict to artifacts owned by these team IDs, intersected with the `scope` filter. Non-positive IDs are ignored; teams the caller does not belong to return nothing, and personal artifacts are excluded whenever this is set. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` } // ArtifactListResponse is generated from the Flashduty OpenAPI schema. type ArtifactListResponse struct { - // Artifacts on this page. + // Artifacts on this page; the caller's pinned artifacts come first. An empty array when nothing matches. Items []PublishedArtifactItem `json:"items" toon:"items"` // Total number of artifacts matching the filter across all pages. Total int64 `json:"total" toon:"total"` @@ -1255,13 +1284,13 @@ type ArtifactPublishResponse struct { type ArtifactShareState struct { // Artifact ID (`art_` prefix). Also the key of the public-share link. ArtifactID string `json:"artifact_id" toon:"artifact_id"` - // Anonymous public link served entirely from CDN. Anyone with the link can view the content, no login required. + // Anonymous public link, `/share/artifact/`. Anyone with the link can view the content without signing in. The link is the same on every enable. PublicURL string `json:"public_url" toon:"public_url"` // Always `true` in this response. ShareEnabled bool `json:"share_enabled" toon:"share_enabled"` // Unix timestamp in milliseconds of the last share enable or snapshot sync. SharedAt TimestampMilli `json:"shared_at" toon:"shared_at"` - // Person ID of the member who enabled sharing. + // Person ID of the member who enabled sharing. A snapshot sync keeps the original value. SharedBy int64 `json:"shared_by" toon:"shared_by"` } @@ -1277,15 +1306,15 @@ type ArtifactSignRequest struct { type ArtifactUpdateRequest struct { // Artifact ID (`art_` prefix). Also the key of the public-share link. ArtifactID string `json:"artifact_id" toon:"artifact_id"` - // Transfer target scope. `0` moves the artifact to personal scope (only the creator can manage it); a positive value moves it to a team the caller must belong to. Omit to leave unchanged. + // Transfer target. `0` moves the artifact to personal scope and only its creator may do that; a positive value moves it to that team, and the caller must be a member of the team; a negative value fails with `InvalidParameter`. Omit or send `null` to keep the current scope. The creator (`person_id`) never changes. TeamID *int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` - // New title. Trimmed; must be non-empty when provided. Omit to leave unchanged. + // New title. Leading and trailing spaces are trimmed; a blank value fails with `InvalidParameter`. Omit or send `null` to keep the current title. Title *string `json:"title,omitempty" toon:"title,omitempty"` } // AssignIncidentRequest is generated from the Flashduty OpenAPI schema. type AssignIncidentRequest struct { - // Assign target; at least one of `person_ids` and `escalate_rule_id` must be set. + // Assignment target. Set `person_ids`, `escalate_rule_id`, or `emails`; when none is set, the server re-runs the channel's escalation rule matching. AssignedTo AssignedTo `json:"assigned_to" toon:"assigned_to"` // Single incident ID. Ignored when `incident_ids` is also provided. IncidentID string `json:"incident_id,omitempty" toon:"incident_id,omitempty"` @@ -1295,29 +1324,31 @@ type AssignIncidentRequest struct { // AssignedTo is generated from the Flashduty OpenAPI schema. type AssignedTo struct { - // Unix timestamp (seconds) when the assignment was made. + // Unix timestamp (seconds) when the assignment was made; set by the server. AssignedAt int64 `json:"assigned_at,omitempty" toon:"assigned_at,omitempty"` - // Email recipients, used by integrations such as ServiceNow. + // Member IDs that actually received the assignment: `person_ids` plus the members of the selected escalation level, deduplicated and sorted. Set by the server; omitted when empty. + EffectivePersonIDs []int64 `json:"effective_person_ids,omitempty" toon:"effective_person_ids,omitempty"` + // Member emails; each is resolved to a member ID and merged into `person_ids`. Emails without a matching member are ignored. Emails []string `json:"emails,omitempty" toon:"emails,omitempty"` // Escalation rule ID (MongoDB ObjectID) to drive assignment. EscalateRuleID string `json:"escalate_rule_id,omitempty" toon:"escalate_rule_id,omitempty"` - // Escalation rule display name, filled by the server. + // Escalation rule name, filled by the server in responses; ignored in requests. EscalateRuleName string `json:"escalate_rule_name,omitempty" toon:"escalate_rule_name,omitempty"` - // Opaque assignment ID generated by the server. + // Assignment ID generated by the server for each assignment; set by the server. ID string `json:"id,omitempty" toon:"id,omitempty"` - // Current level index within the escalation rule. + // Zero-based escalation level within `escalate_rule_id` (`0` = first level). Responders are taken from this level. LayerIdx int64 `json:"layer_idx,omitempty" toon:"layer_idx,omitempty"` // Override the notification channels used for this assignment. Notify AssignedToNotify `json:"notify,omitzero" toon:"notify,omitempty"` // Member IDs to assign directly. PersonIDs []int64 `json:"person_ids,omitempty" toon:"person_ids,omitempty"` - // Assignment type: `assign` direct assignment, `reassign` reassignment, `escalate` escalation-rule driven, `reopen` automatic reassignment on reopen. + // How the assignment happened: `assign` first assignment; `reassign` reassignment of an already assigned incident; `escalate` moved by the escalation flow; `reopen` reassignment after the incident was reopened; empty string in responses when the incident was never assigned. Omit it in requests and the server derives it. Type string `json:"type,omitempty" toon:"type,omitempty"` } // AuditLog is generated from the Flashduty OpenAPI schema. type AuditLog struct { - // ID of the account. + // ID of the account the entry belongs to. AccountID uint64 `json:"account_id" toon:"account_id"` // JSON-encoded request body. Bodies containing sensitive fields are base64url-encoded instead; bodies over 10 KB are replaced by a truncation placeholder. Body string `json:"body" toon:"body"` @@ -1341,9 +1372,9 @@ type AuditLog struct { Operation string `json:"operation" toon:"operation"` // Human-readable Chinese label of the operation (e.g. `创建模板`). OperationName string `json:"operation_name" toon:"operation_name"` - // URL path parameters as an array of key-value pairs, or an empty array when none. + // URL path parameters as an array of `Key`/`Value` pairs (an empty array when none). Some deployments return the same array as a JSON-encoded string. Params []AuditLogParamsItem `json:"params" toon:"params"` - // Kind of the caller. `member` — an interactive member session; `service` — an app key credential. + // Kind of the caller. `member` — a member or account-owner session; `service` — an app key or a short-lived key issued to AI SRE. PrincipalKind string `json:"principal_kind" toon:"principal_kind"` // Unique request ID for correlation. RequestID string `json:"request_id" toon:"request_id"` @@ -1368,7 +1399,7 @@ type AuditOperationTypeItem struct { // AuditRecordIDRequest is generated from the Flashduty OpenAPI schema. type AuditRecordIDRequest struct { - // Audit record ID — the `id` of an audit row returned by `POST /monit/rule/audits`, NOT the rule ID. Passing a rule ID returns HTTP 400. + // Audit record ID — the `id` of a row returned by `POST /monit/rule/audits`, not the rule ID. A rule ID is looked up as an audit record ID, which usually returns `InvalidParameter` (`alert rule audit not found`) or an unrelated record. ID uint64 `json:"id" toon:"id"` } @@ -1380,7 +1411,7 @@ type AuditSearchRequest struct { IsDangerous *bool `json:"is_dangerous,omitempty" toon:"is_dangerous,omitempty"` // When true, return only write operations; when false, return only read operations. IsWrite *bool `json:"is_write,omitempty" toon:"is_write,omitempty"` - // Page size, 0–99. Omit or set to 0 for no page-size cap — all matching rows in the window are returned. + // Page size, 0–99. Omit or set to 0 to let the server choose the page size (it may return every matching entry). Limit int64 `json:"limit,omitempty" toon:"limit,omitempty"` // Filter to specific operation names. Use `POST /audit/operation/list` to get the valid set. Operations []string `json:"operations,omitempty" toon:"operations,omitempty"` @@ -1404,54 +1435,44 @@ type AuditSearchResponse struct { Total int64 `json:"total" toon:"total"` } -// AutomationExecutionLocation is generated from the Flashduty OpenAPI schema. -type AutomationExecutionLocation struct { - // Display name of the bound IM conversation when available. - ChatName string `json:"chat_name" toon:"chat_name"` - // Bound IM conversation mode when execution place is `im`. - ConversationMode string `json:"conversation_mode" toon:"conversation_mode"` - // Human-readable destination description. - Description string `json:"description" toon:"description"` - // Execution destination: `im` or `web_console`. - Place string `json:"place" toon:"place"` - // IM platform when execution place is `im`. - Platform string `json:"platform" toon:"platform"` - // Pinned execution scope: `person` or `team`. - RunScope string `json:"run_scope" toon:"run_scope"` - // Pinned scope team ID. 0 means personal scope. - TeamID int64 `json:"team_id" toon:"team_id"` -} - // AutomationRuleCreateRequest is generated from the Flashduty OpenAPI schema. type AutomationRuleCreateRequest struct { - // Run cadence. Supports 4 fields (`hour day month weekday`, minute defaults to 0) and 5 fields (`minute hour day month weekday`). The minute must be one fixed integer; 6-field seconds are not supported. A cron that sets both day-of-month and day-of-week is rejected. The create API currently requires this field even for HTTP-POST-only rules; send a valid cron and set `schedule_trigger_enabled=false`. + // Schedule in local time of `timezone`. Accepts 4 fields (`hour day month weekday`, minute defaults to 0) or 5 fields (`minute hour day month weekday`). The minute must be one fixed integer; seconds (6 fields) are not supported; setting both day-of-month and day-of-week is rejected. Required even for rules that use only other triggers: send a valid expression with `schedule_trigger_enabled=false`. CronExpr string `json:"cron_expr" toon:"cron_expr"` - // Whether the rule is enabled after creation. Omitted API value is false; Chat/CLI create sends true by default unless the user asks for disabled. + // Whether the rule's automatic triggers (schedule, HTTP POST, On-call incident, war room) are armed after creation. Defaults to `false`. Manual runs work either way. Enabled bool `json:"enabled,omitempty" toon:"enabled,omitempty"` - // BYOC Runner ID. Used only when `environment_kind=byoc`. + // BYOC runner ID. Required when `environment_kind=byoc` and rejected for other kinds. A personal rule can only use account-scope runners; a team rule can use account-scope runners or runners of its own team. EnvironmentID string `json:"environment_id,omitempty" toon:"environment_id,omitempty"` // Runtime environment kind. Omit or send an empty value for automatic selection. One of: `cloud` (platform-hosted cloud sandbox), `byoc` (a self-hosted BYOC runner in the account, used with `environment_id`); automatic selection prefers an online BYOC runner and falls back to the cloud sandbox. EnvironmentKind string `json:"environment_kind,omitempty" toon:"environment_kind,omitempty"` - // Whether to create and enable an HTTP POST trigger. When enabled, the response includes a one-time token. + // Whether to create an enabled HTTP POST trigger. When `true`, the response carries `http_post_trigger_url` and the one-time `http_post_token`. HTTPPostTriggerEnabled bool `json:"http_post_trigger_enabled,omitempty" toon:"http_post_trigger_enabled,omitempty"` - // Rule name. + // Display name of the rule, 1–255 characters; leading and trailing spaces are trimmed. Name string `json:"name" toon:"name"` - // On-call integration IDs to watch. Creating or enabling this trigger requires at least one valid ID. + // Channel IDs to watch; incidents in these channels can start a run. Each ID must be positive. OncallIncidentChannelIDs []int64 `json:"oncall_incident_channel_ids,omitempty" toon:"oncall_incident_channel_ids,omitempty"` - // Incident severities to watch. Supported values are Critical, Warning, and Info; creating or enabling this trigger requires at least one value. + // Whether to merge similar incidents into one analysis. When `true` (default), an incident that closely resembles one already being analyzed by this rule (a run in progress or finished within the last 10 minutes) joins that run's session instead of starting a new one; its own run is recorded as `skipped` with `joined_session_id` set. When `false`, every matching incident starts its own run. + OncallIncidentMergeSimilar *bool `json:"oncall_incident_merge_similar,omitempty" toon:"oncall_incident_merge_similar,omitempty"` + // Incident severities to watch: `Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels. OncallIncidentSeverities []string `json:"oncall_incident_severities,omitempty" toon:"oncall_incident_severities,omitempty"` - // Whether the On-call incident trigger is enabled. + // Whether the On-call incident trigger is enabled. When the trigger is created (this is `true`, or channel IDs or severities are sent), both `oncall_incident_channel_ids` and `oncall_incident_severities` must be non-empty. OncallIncidentTriggerEnabled bool `json:"oncall_incident_trigger_enabled,omitempty" toon:"oncall_incident_trigger_enabled,omitempty"` - // Task prompt sent to the AI SRE agent on each run. + // Task instruction sent to the AI SRE agent on every run. Must not be empty after trimming spaces. Prompt string `json:"prompt" toon:"prompt"` - // Execution destination. `current-chat` binds the rule to the authenticated live IM conversation; `web` runs in the web console. Omit it so the server selects `current-chat` for an authenticated IM invocation and `web` otherwise. The server rejects `current-chat` outside a live IM conversation. - RunIn *string `json:"run_in,omitempty" toon:"run_in,omitempty"` - // Whether the schedule trigger is enabled. Defaults to true when omitted; HTTP-POST-only rules should send false. + // Where the rule's runs execute. `web` (default): in a web console session. `current-chat`: in the IM chat the rule is created from; accepted only from a live IM conversation with the AI SRE agent, so API calls that send it get `400`. + RunIn string `json:"run_in,omitempty" toon:"run_in,omitempty"` + // Whether the schedule trigger is enabled. Defaults to `true` when omitted; send `false` for rules that should fire only from other triggers. ScheduleTriggerEnabled *bool `json:"schedule_trigger_enabled,omitempty" toon:"schedule_trigger_enabled,omitempty"` - // Scope team ID. Explicit 0 means personal scope; >0 means a team in the account. Omit it to inherit the authenticated IM conversation scope when one is available, otherwise let the server select the normal default. A current-chat rule must match that conversation's scope. - TeamID *int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` - // IANA timezone `cron_expr` is evaluated in, e.g. `Asia/Shanghai`. Must be a timezone name loadable by the server; an invalid value is rejected. Defaults to the caller's member timezone, then the account timezone, then the server default (Asia/Shanghai) when omitted. + // Scope of the rule. `0` or omitted: a personal rule owned by the caller. `>0`: a team rule; the caller must be a member of that team. The scope cannot be changed after creation. + TeamID int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` + // IANA time zone name used to evaluate `cron_expr`, e.g. `Asia/Shanghai`. Ambiguous names such as `Local`, `CST`, `UTC+8`, and `GMT+8` are rejected. When omitted: the caller's member time zone, then the account time zone, then `Asia/Shanghai`. Timezone string `json:"timezone,omitempty" toon:"timezone,omitempty"` + // Channel IDs whose war rooms start a run. Each ID must be positive. + WarRoomChannelIDs []int64 `json:"war_room_channel_ids,omitempty" toon:"war_room_channel_ids,omitempty"` + // Incident severities that start a run when their war room is created: `Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels. + WarRoomSeverities []string `json:"war_room_severities,omitempty" toon:"war_room_severities,omitempty"` + // Whether the war room trigger is enabled. It fires when a war room (IM group chat) is created for an incident in one of `war_room_channel_ids` with a severity in `war_room_severities`; the agent then runs inside that group chat. When the trigger is created (this is `true`, or `war_room_channel_ids` is sent), both lists must be non-empty. + WarRoomTriggerEnabled bool `json:"war_room_trigger_enabled,omitempty" toon:"war_room_trigger_enabled,omitempty"` } // AutomationRuleIDRequest is generated from the Flashduty OpenAPI schema. @@ -1462,46 +1483,51 @@ type AutomationRuleIDRequest struct { // AutomationRuleItem is generated from the Flashduty OpenAPI schema. type AutomationRuleItem struct { - // Account ID. + // ID of the account that owns the rule. AccountID int64 `json:"account_id" toon:"account_id"` - // True when the caller can manage this rule: the personal rule owner; for team rules, an account admin or a member of the rule's team. + // `true` when the caller can manage (get, update, delete, run) this rule: the owner of a personal rule, or a member of a team rule's team. Account owners and admins get no exemption. CanEdit bool `json:"can_edit" toon:"can_edit"` // Creation time, Unix milliseconds. CreatedAt TimestampMilli `json:"created_at" toon:"created_at"` - // Normalized 5-field cron expression. + // Normalized 5-field cron expression (`minute hour day month weekday`), evaluated in `timezone`. CronExpr string `json:"cron_expr" toon:"cron_expr"` - // Whether the rule is enabled. + // Whether the rule's automatic triggers are armed. A disabled rule can still be run manually. A personal rule is disabled automatically when its owner leaves the account. Enabled bool `json:"enabled" toon:"enabled"` - // BYOC Runner ID. + // BYOC runner ID when `environment_kind=byoc`; empty string otherwise. EnvironmentID string `json:"environment_id" toon:"environment_id"` // Runtime environment kind. Omit or send an empty value for automatic selection. One of: `cloud` (platform-hosted cloud sandbox), `byoc` (self-hosted BYOC runner in the account); an empty value means automatic selection (prefers an online BYOC runner, falls back to the cloud sandbox). - EnvironmentKind string `json:"environment_kind" toon:"environment_kind"` - ExecutionLocation AutomationExecutionLocation `json:"execution_location" toon:"execution_location"` - // Configured execution destination for ordinary triggers. War-room triggers resolve their event war room at execution time. + EnvironmentKind string `json:"environment_kind" toon:"environment_kind"` + // Read-only description of where the rule runs. + ExecutionLocation AutomationRuleItemExecutionLocation `json:"execution_location" toon:"execution_location"` + // Where runs started by the schedule, HTTP POST, On-call incident, and manual triggers execute: `web_console` (a web console session) or `im` (the IM chat the rule was created from). War room runs always execute in the war room's group chat. Fixed at creation. ExecutionPlace string `json:"execution_place" toon:"execution_place"` - // HTTP POST trigger token. Returned only on create or token rotation; save it immediately. + // HTTP POST trigger token. Returned only in the response that issues it: create with `http_post_trigger_enabled=true`, an update that creates the trigger, or an update with `rotate_http_post_trigger_token=true`. Save it; it cannot be read again. HTTPPostToken string `json:"http_post_token" toon:"http_post_token"` // Whether the HTTP POST trigger is enabled. HTTPPostTriggerEnabled bool `json:"http_post_trigger_enabled" toon:"http_post_trigger_enabled"` // HTTP POST trigger ID. Omitted when the rule has no HTTP POST trigger. HTTPPostTriggerID string `json:"http_post_trigger_id" toon:"http_post_trigger_id"` - // HTTP POST trigger path. Omitted when the rule has no HTTP POST trigger. + // Path to fire the HTTP POST trigger, `/safari/automation/triggers/{trigger_id}/fire`, relative to the API base URL. Send `POST` with `Authorization: Bearer `. Omitted when the rule has no HTTP POST trigger. HTTPPostTriggerURL string `json:"http_post_trigger_url" toon:"http_post_trigger_url"` - // Rule name. + // The rule's most recent run. Returned only by List Automation rules, and only when the rule has run at least once. + LastRun AutomationRuleItemLastRun `json:"last_run" toon:"last_run"` + // Display name of the rule. Name string `json:"name" toon:"name"` - // On-call integration IDs to watch. Creating or enabling this trigger requires at least one valid ID. Omitted when no On-call incident trigger is configured. + // Channel IDs the On-call incident trigger watches. Omitted when the rule has no such trigger. OncallIncidentChannelIDs []int64 `json:"oncall_incident_channel_ids" toon:"oncall_incident_channel_ids"` - // Incident severities to watch. Supported values are Critical, Warning, and Info; creating or enabling this trigger requires at least one value. Omitted when no On-call incident trigger is configured. + // Whether similar incidents are merged into one analysis (see the create request). `true` when the rule has no On-call incident trigger. + OncallIncidentMergeSimilar bool `json:"oncall_incident_merge_similar" toon:"oncall_incident_merge_similar"` + // Incident severities the On-call incident trigger watches: `Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels. Omitted when the rule has no such trigger. OncallIncidentSeverities []string `json:"oncall_incident_severities" toon:"oncall_incident_severities"` // Whether the On-call incident trigger is enabled. OncallIncidentTriggerEnabled bool `json:"oncall_incident_trigger_enabled" toon:"oncall_incident_trigger_enabled"` // On-call incident trigger ID. Omitted when the rule has no On-call incident trigger. OncallIncidentTriggerID string `json:"oncall_incident_trigger_id" toon:"oncall_incident_trigger_id"` - // Creator person ID. + // Person ID of the member who created the rule. For a personal rule, the only person who can manage it. OwnerID int64 `json:"owner_id" toon:"owner_id"` - // Task prompt. + // Task instruction sent to the AI SRE agent on every run. Prompt string `json:"prompt" toon:"prompt"` - // Rule ID. + // Rule ID (prefix `arule_`). Pass it as `rule_id` to get, update, delete, run, and list-runs calls. RuleID string `json:"rule_id" toon:"rule_id"` // Hidden session run scope. One of: `person` (personal rule, team_id=0, runs as the creator; disabled when the creator leaves the account), `team` (team rule, team_id>0, owned by the team and shared with its members; survives the creator leaving). Derived from the rule's team_id. RunScope string `json:"run_scope" toon:"run_scope"` @@ -1511,12 +1537,20 @@ type AutomationRuleItem struct { ScheduleTriggerEnabled bool `json:"schedule_trigger_enabled" toon:"schedule_trigger_enabled"` // Schedule trigger ID. Omitted if the rule has no schedule trigger. ScheduleTriggerID string `json:"schedule_trigger_id" toon:"schedule_trigger_id"` - // Scope team ID; 0 means personal rule. + // Scope team ID; `0` means a personal rule. Fixed at creation. TeamID int64 `json:"team_id" toon:"team_id"` // IANA timezone `cron_expr` is evaluated in. Always populated for rules created after this field shipped; empty on legacy rows created before it, which still resolve to UTC when scheduled. Timezone string `json:"timezone" toon:"timezone"` // Last update time, Unix milliseconds. UpdatedAt TimestampMilli `json:"updated_at" toon:"updated_at"` + // Channel IDs whose war rooms start a run. Omitted when the rule has no war room trigger. + WarRoomChannelIDs []int64 `json:"war_room_channel_ids" toon:"war_room_channel_ids"` + // Incident severities whose war rooms start a run: `Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels. Omitted when the rule has no war room trigger. + WarRoomSeverities []string `json:"war_room_severities" toon:"war_room_severities"` + // Whether the war room trigger is enabled. + WarRoomTriggerEnabled bool `json:"war_room_trigger_enabled" toon:"war_room_trigger_enabled"` + // War room trigger ID. Omitted when the rule has no war room trigger. + WarRoomTriggerID string `json:"war_room_trigger_id" toon:"war_room_trigger_id"` } // AutomationRuleListRequest is generated from the Flashduty OpenAPI schema. @@ -1524,11 +1558,11 @@ type AutomationRuleListRequest struct { ListOptions // Filter by enabled state: `true` returns only enabled rules, `false` only disabled; omit or pass null for no filter. Enabled *bool `json:"enabled,omitempty" toon:"enabled,omitempty"` - // Compatibility field; when scope is empty and this is false, behaves like team scope. + // Legacy switch. Only read when `scope` is empty: `false` behaves like `scope=team`; otherwise ignored. IncludePerson *bool `json:"include_person,omitempty" toon:"include_person,omitempty"` - // Filter by name keyword. + // Returns rules whose name contains this text. At most 64 characters. Keyword string `json:"keyword,omitempty" toon:"keyword,omitempty"` - // Scope filter: `all` (own personal + accessible team rules), `personal`, or `team`; default `all`. + // Scope filter: `all` (default) your personal rules plus rules of your teams; `personal` only your personal rules; `team` only rules of your teams. Scope string `json:"scope,omitempty" toon:"scope,omitempty"` // Filter to these team IDs; this narrows results and does not expand access. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` @@ -1538,15 +1572,15 @@ type AutomationRuleListRequest struct { type AutomationRuleListResponse struct { // Array of automation rules for the current page, used with `total` for pagination. Rules []AutomationRuleItem `json:"rules" toon:"rules"` - // Total count. + // Number of rules matching the filters across all pages. Total int64 `json:"total" toon:"total"` } // AutomationRunItem is generated from the Flashduty OpenAPI schema. type AutomationRunItem struct { - // Account ID. + // ID of the account that owns the run. AccountID int64 `json:"account_id" toon:"account_id"` - // Attempt count. + // Number of execution attempts made for this run. Attempts int64 `json:"attempts" toon:"attempts"` // Completion time, Unix milliseconds. 0 means not completed. CompletedAt TimestampMilli `json:"completed_at" toon:"completed_at"` @@ -1558,19 +1592,23 @@ type AutomationRunItem struct { ErrorCode string `json:"error_code" toon:"error_code"` // Error message; empty when the run did not fail. ErrorMessage string `json:"error_message" toon:"error_message"` - // Actual execution destination: `im` or `web_console`. IM runs omit session details and deep links. + // Where this run executed: `web_console` (a web console session; `session_id` links to it) or `im` (an IM chat; session details are withheld). `war_room_created` runs are always `im`. ExecutionPlace string `json:"execution_place" toon:"execution_place"` + // For an On-call incident run merged into a similar incident's analysis (`status=skipped`): the session it joined. Omitted otherwise. + JoinedSessionID string `json:"joined_session_id" toon:"joined_session_id"` + // Display name of `joined_session_id`. Omitted when empty or when the name lookup fails. + JoinedSessionName string `json:"joined_session_name" toon:"joined_session_name"` // Run kind; runs listed for a rule are always `automation_rule`. Kind string `json:"kind" toon:"kind"` - // Idempotency key for this occurrence. + // Idempotency key of this occurrence: `manual:` for manual runs, `:` for schedule runs, `oncall_incident::` for On-call incident runs. OccurrenceKey string `json:"occurrence_key" toon:"occurrence_key"` - // Raw run result JSON (carries the run's `session_id` once started); null when empty. + // Raw run result JSON (carries `session_id` once a session started). `null` when empty or when the run executed in an IM chat. ResultJSON map[string]any `json:"result_json" toon:"result_json"` - // Rule ID. + // ID of the rule this run belongs to. RuleID string `json:"rule_id" toon:"rule_id"` - // Run ID. + // Run ID (prefix `trun_`). RunID string `json:"run_id" toon:"run_id"` - // Session created for this run, extracted from `result_json`. Omitted when the run has not (yet) started a session. + // AI SRE session the run executed in. Omitted when the run has not started a session, when it joined another run (see `joined_session_id`), or when it executed in an IM chat. SessionID string `json:"session_id" toon:"session_id"` // Display name of the run's session, stamped via a batch lookup. Omitted when empty or when the lookup fails. SessionName string `json:"session_name" toon:"session_name"` @@ -1587,7 +1625,7 @@ type AutomationRunItem struct { // | `succeeded` | Completed successfully | // | `partial` | Partially succeeded (currently only produced by memory-consolidation runs; rule runs never reach it) | // | `failed` | Terminal failure, no further retries | - // | `skipped` | Not executed (e.g. grace period expired, trigger or rule invalid); the reason is kept on the run record | + // | `skipped` | Not executed (e.g. grace period expired, trigger or rule invalid); the reason is kept on the run record. Also used for an On-call incident run merged into a similar incident's analysis (see `joined_session_id`) | // | `abandoned` | Still in-flight past the stale threshold and swept as never-completed (e.g. worker died) | // | `blocked` | Terminal: the run produced output but ended with a connector waiting on a human to complete authorization (distinct from `failed`) | Status string `json:"status" toon:"status"` @@ -1596,9 +1634,10 @@ type AutomationRunItem struct { // | --- | --- | // | `schedule` | Fired by the rule's schedule trigger | // | `debug` | Debug run (reserved; current rule runs never carry this kind) | - // | `manual` | Triggered manually by a user | - // | `http_post` | Fired via the rule's HTTP POST webhook | - // | `oncall_incident` | Fired by an on-call incident event | + // | `manual` | Started with Run Automation rule | + // | `http_post` | Fired via the rule's HTTP POST trigger | + // | `oncall_incident` | Fired by a matching On-call incident | + // | `war_room_created` | Fired when a war room was created for a matching incident; runs in that group chat | TriggerKind string `json:"trigger_kind" toon:"trigger_kind"` // Last update time, Unix milliseconds. UpdatedAt TimestampMilli `json:"updated_at" toon:"updated_at"` @@ -1615,7 +1654,7 @@ type AutomationRunListRequest struct { StartedBeforeMs int64 `json:"started_before_ms,omitempty" toon:"started_before_ms,omitempty"` // Run status filter: `queued`, `running`, `retrying`, `succeeded`, `partial` (partially succeeded), `failed`, `skipped` (e.g. rule or trigger no longer valid), `abandoned` (stale run terminated by the system), `blocked` (terminal; produced output but a connector is waiting on a human authorization); omit for no filter. Status string `json:"status,omitempty" toon:"status,omitempty"` - // Trigger source filter: `schedule` cron trigger, `debug` debug run, `manual` manual run, `http_post` HTTP POST trigger, `oncall_incident` on-call incident trigger; omit for no filter. + // Trigger filter: `schedule` schedule trigger, `debug` debug run, `manual` manual run, `http_post` HTTP POST trigger, `oncall_incident` On-call incident trigger, `war_room_created` war room trigger; omit for no filter. TriggerKind string `json:"trigger_kind,omitempty" toon:"trigger_kind,omitempty"` } @@ -1623,7 +1662,7 @@ type AutomationRunListRequest struct { type AutomationRunListResponse struct { // Array of run records for the given `rule_id`, filtered by the request's status/trigger-kind/time-range and paginated. Runs []AutomationRunItem `json:"runs" toon:"runs"` - // Total count. + // Number of runs matching the filters across all pages. Total int64 `json:"total" toon:"total"` } @@ -1631,33 +1670,51 @@ type AutomationRunListResponse struct { type AutomationRunView struct { // Run ID, always populated once a run is created. RunID string `json:"run_id" toon:"run_id"` - // AI SRE session ID for this run. Always populated in a 200 response, since the call only returns after the session has started. + // AI SRE session started for this run. Omitted when the rule executes in an IM chat (`execution_place=im`). SessionID string `json:"session_id" toon:"session_id"` } // AutomationTemplateItem is generated from the Flashduty OpenAPI schema. type AutomationTemplateItem struct { - // Template description. + // Free-text, localized name of the group the template is shown under in the console, e.g. `Incident Response`. Groups appear in the order of their first template. + Category string `json:"category" toon:"category"` + // Prefill for `cron_expr`. Omitted when the template does not use the schedule trigger; the create request still needs a valid `cron_expr`. + CronExpr string `json:"cron_expr" toon:"cron_expr"` + // Localized explanation of what a rule created from this template does. Description string `json:"description" toon:"description"` - // Whether a rule created from this template starts out enabled (prefill value). + // Prefill for the create request's `enabled`. Enabled bool `json:"enabled" toon:"enabled"` - // Icon identifier. + // Prefill for `http_post_trigger_enabled`. + HTTPPostTriggerEnabled bool `json:"http_post_trigger_enabled" toon:"http_post_trigger_enabled"` + // Icon identifier the console displays for the template, e.g. `siren`. Icon string `json:"icon" toon:"icon"` - // Template name. + // Stable, locale-independent template ID (lowercase letters, digits, underscores). Present only on templates that other console pages link to directly; omitted otherwise. + Key string `json:"key" toon:"key"` + // Localized template name; use it as the rule `name`. Name string `json:"name" toon:"name"` - // Template prompt. + // Prefill for `oncall_incident_severities` (`Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels). Omitted when the template does not use the On-call incident trigger. + OncallIncidentSeverities []string `json:"oncall_incident_severities" toon:"oncall_incident_severities"` + // Prefill for `oncall_incident_trigger_enabled`; when `true`, add `oncall_incident_channel_ids` before creating. + OncallIncidentTriggerEnabled bool `json:"oncall_incident_trigger_enabled" toon:"oncall_incident_trigger_enabled"` + // Prefill for the create request's `prompt`. Prompt string `json:"prompt" toon:"prompt"` + // Prefill for `schedule_trigger_enabled`; `true` exactly when `cron_expr` is present. + ScheduleTriggerEnabled bool `json:"schedule_trigger_enabled" toon:"schedule_trigger_enabled"` + // Prefill for `war_room_severities` (`Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels). Omitted when the template does not use the war room trigger. + WarRoomSeverities []string `json:"war_room_severities" toon:"war_room_severities"` + // Prefill for `war_room_trigger_enabled`; when `true`, add `war_room_channel_ids` before creating. + WarRoomTriggerEnabled bool `json:"war_room_trigger_enabled" toon:"war_room_trigger_enabled"` } // AutomationTemplateListRequest is generated from the Flashduty OpenAPI schema. type AutomationTemplateListRequest struct { - // Template locale such as zh-CN or en-US. Omit to detect from the request locale. + // Template language. A value containing `zh` returns Chinese, one containing `en` returns English, any other non-empty value returns Chinese. When omitted, the `locale`/`lang` query parameter or the `Accept-Language` header decides, defaulting to Chinese. Locale string `json:"locale,omitempty" toon:"locale,omitempty"` } // AutomationTemplateListResponse is generated from the Flashduty OpenAPI schema. type AutomationTemplateListResponse struct { - // Array of built-in automation templates, with display text localized by the request `locale` (falling back to request headers). + // Built-in templates in the resolved language, in display order. Templates []AutomationTemplateItem `json:"templates" toon:"templates"` } @@ -1665,7 +1722,7 @@ type AutomationTemplateListResponse struct { type BindWorkItemPostMortemRequest struct { // Client-generated idempotency key (max 128 characters; letters, digits, `_`, `-`, `.`, `:` only). IdempotencyKey string `json:"idempotency_key" toon:"idempotency_key"` - // Incident ID (MongoDB ObjectID) whose converted-but-unbound follow-ups are bound. + // Incident ID (MongoDB ObjectID) whose converted, unbound items are bound. It must be linked to `post_mortem_id`. IncidentID string `json:"incident_id" toon:"incident_id"` // Post-mortem ID (32-character hex string) to bind the follow-ups to. PostMortemID string `json:"post_mortem_id" toon:"post_mortem_id"` @@ -1699,7 +1756,7 @@ type CalEventItem struct { AccountID uint64 `json:"account_id" toon:"account_id"` // Calendar ID. For public events this is a locale key such as zh-cn.china.official. CalID string `json:"cal_id" toon:"cal_id"` - // Creation timestamp (Unix seconds). + // Creation timestamp (Unix seconds); `0` for generated `non_work.*` entries. CreatedAt Timestamp `json:"created_at" toon:"created_at"` // Creator person ID. Only present for private events. CreatorID uint64 `json:"creator_id" toon:"creator_id"` @@ -1707,7 +1764,7 @@ type CalEventItem struct { Description string `json:"description" toon:"description"` // Event end date (YYYY-MM-DD, exclusive). EndAt string `json:"end_at" toon:"end_at"` - // Event ID. + // Event ID. `cale.` for the calendar's own events, `non_work.YYYYMMDD` for generated non-working weekdays, and `.` for events inherited from a holiday calendar. EventID string `json:"event_id" toon:"event_id"` // Whether the event marks a non-working day. IsOff bool `json:"is_off" toon:"is_off"` @@ -1715,7 +1772,7 @@ type CalEventItem struct { StartAt string `json:"start_at" toon:"start_at"` // Event summary. Summary string `json:"summary" toon:"summary"` - // Last update timestamp (Unix seconds). + // Last update timestamp (Unix seconds); `0` for generated `non_work.*` entries. UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` } @@ -1771,17 +1828,17 @@ type CalEventUpsertResponse struct { // CalendarCreateRequest is generated from the Flashduty OpenAPI schema. type CalendarCreateRequest struct { - // Calendar display name. + // Calendar display name; must be unique within the account. CalName string `json:"cal_name" toon:"cal_name"` // Calendar description. Description string `json:"description,omitempty" toon:"description,omitempty"` // Additional public-holiday calendar IDs to inherit events from (for example zh-cn.china.official). ExtraCalIDs []string `json:"extra_cal_ids,omitempty" toon:"extra_cal_ids,omitempty"` - // Owning team ID. 0 means no team. + // Owning team ID; `0` or omitted means no team. A nonzero ID must be a team of the account. TeamID uint64 `json:"team_id,omitempty" toon:"team_id,omitempty"` - // IANA timezone. Defaults to Asia/Shanghai when empty. + // IANA timezone, e.g. `America/New_York`. Defaults to `Asia/Shanghai` when empty; an invalid name returns `InvalidParameter`. Timezone string `json:"timezone,omitempty" toon:"timezone,omitempty"` - // Workday numbers (0 = Sunday, 6 = Saturday). + // Weekly working days, `0` = Sunday … `6` = Saturday. Days not listed are non-working days. When empty, no weekday is treated as non-working. Workdays []int64 `json:"workdays,omitempty" toon:"workdays,omitempty"` } @@ -1804,7 +1861,7 @@ type CalendarIDRequest struct { // CalendarItem is generated from the Flashduty OpenAPI schema. type CalendarItem struct { - // Account ID. + // ID of the account that owns the calendar. AccountID uint64 `json:"account_id" toon:"account_id"` // Calendar ID. CalID string `json:"cal_id" toon:"cal_id"` @@ -1830,7 +1887,7 @@ type CalendarItem struct { UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` // Last updater person ID. UpdatedBy uint64 `json:"updated_by" toon:"updated_by"` - // Workday numbers (0 = Sunday, 6 = Saturday). Omitted when empty. + // Weekly working days, `0` = Sunday … `6` = Saturday. Days not listed are non-working days. When empty, no weekday is treated as non-working. Omitted when empty. Workdays []int64 `json:"workdays" toon:"workdays"` } @@ -1854,17 +1911,17 @@ type CalendarListResponse struct { type CalendarUpdateRequest struct { // Calendar ID; obtain it from `POST /calendar/list`. CalID string `json:"cal_id" toon:"cal_id"` - // New calendar name. + // New calendar name; must be unique within the account. CalName *string `json:"cal_name,omitempty" toon:"cal_name,omitempty"` // New description. Description *string `json:"description,omitempty" toon:"description,omitempty"` - // Additional public-holiday calendar IDs to inherit events from. + // Public holiday calendar IDs to inherit events from (see `POST /calendar/list` with `kind` = `region.official.holiday`). When sent, replaces the stored list; an empty array removes them all; omit to keep it. ExtraCalIDs []string `json:"extra_cal_ids,omitempty" toon:"extra_cal_ids,omitempty"` - // New owning team ID; obtain it from `POST /team/list`. + // New owning team ID; obtain it from `POST /team/list`. `0` removes the team; a nonzero ID must be a team of the account. TeamID *uint64 `json:"team_id,omitempty" toon:"team_id,omitempty"` - // New IANA timezone. + // New IANA timezone, e.g. `Asia/Shanghai`; an invalid name returns `InvalidParameter`. Timezone *string `json:"timezone,omitempty" toon:"timezone,omitempty"` - // Workday numbers (0 = Sunday, 6 = Saturday). + // Weekly working days, `0` = Sunday … `6` = Saturday. Days not listed are non-working days. When empty, no weekday is treated as non-working. When sent, replaces the stored list; omit to keep it. Workdays []int64 `json:"workdays,omitempty" toon:"workdays,omitempty"` } @@ -1934,21 +1991,21 @@ type ChangeItem struct { ChangeStatus string `json:"change_status" toon:"change_status"` // Collaboration channel this change is routed to. ChannelID int64 `json:"channel_id" toon:"channel_id"` - // Name of the collaboration channel. + // Name of the collaboration channel; an empty string when the change is not routed to an existing channel. ChannelName string `json:"channel_name" toon:"channel_name"` - // Status of the collaboration channel: `enabled` or `disabled`. + // Status of the collaboration channel: `enabled` or `disabled`; an empty string when the change is not routed to an existing channel. ChannelStatus string `json:"channel_status" toon:"channel_status"` // Change description. Description string `json:"description" toon:"description"` // Unix timestamp in seconds when the change ended. EndTime Timestamp `json:"end_time" toon:"end_time"` - // Underlying change events, returned only when include_events is true. + // Raw change events reported by the integration that make up this change. Present only when `include_events` is `true`. Events []ChangeEventItem `json:"events" toon:"events"` // Integration that reported this change. IntegrationID int64 `json:"integration_id" toon:"integration_id"` // Name of the reporting integration. IntegrationName string `json:"integration_name" toon:"integration_name"` - // Key-value labels attached to the change. + // Key-value labels attached to the change; `null` when it has none. Labels map[string]string `json:"labels" toon:"labels"` // Unix timestamp in seconds of the most recent change activity. LastTime Timestamp `json:"last_time" toon:"last_time"` @@ -1966,7 +2023,7 @@ type ChannelCreateResponse struct { ChannelID int64 `json:"channel_id" toon:"channel_id"` // Channel name echoed back from the request. ChannelName string `json:"channel_name" toon:"channel_name"` - // External report token. Emitted only when external reporting is enabled. + // Token for external reporters. Returned only when the request set `is_external_report_enabled` to `true`; it can be read again later from `POST /channel/info`. ExternalReportToken string `json:"external_report_token" toon:"external_report_token"` } @@ -1990,7 +2047,7 @@ type ChannelInfosRequest struct { // ChannelInfosResponse is generated from the Flashduty OpenAPI schema. type ChannelInfosResponse struct { - // Brief info for the requested `channel_ids` that actually exist; IDs not found are ignored. + // Requested channels that exist, including deleted ones; unknown IDs are skipped. Ordered by channel creation, not by request order. Items []ChannelShort `json:"items" toon:"items"` } @@ -2004,15 +2061,15 @@ type ChannelItem struct { AutoResolveMode string `json:"auto_resolve_mode" toon:"auto_resolve_mode"` // Auto-resolve timeout in seconds. 0 disables auto-resolve. AutoResolveTimeout int64 `json:"auto_resolve_timeout" toon:"auto_resolve_timeout"` - // Channel ID. + // Channel ID; pass it as `channel_id` to the other channel and rule endpoints. ChannelID int64 `json:"channel_id" toon:"channel_id"` - // Channel name. + // Channel name, unique within the account, 1–59 characters. ChannelName string `json:"channel_name" toon:"channel_name"` // Creation time, Unix timestamp in seconds. CreatedAt Timestamp `json:"created_at" toon:"created_at"` // Member ID who created the channel. CreatorID int64 `json:"creator_id" toon:"creator_id"` - // Name of the member who created the channel (resolved from the member directory; empty when unavailable). + // Name of the member who created the channel. Returned only by `POST /channel/list` without `is_brief`; omitted when the lookup fails. CreatorName string `json:"creator_name" toon:"creator_name"` // Deletion time, Unix timestamp in seconds. Non-zero only for soft-deleted channels. DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` @@ -2022,31 +2079,34 @@ type ChannelItem struct { DisableAutoClose bool `json:"disable_auto_close" toon:"disable_auto_close"` // When true, outlier incident detection is disabled. DisableOutlierDetection bool `json:"disable_outlier_detection" toon:"disable_outlier_detection"` - // Alert event merge configuration. + // Alert event merge configuration. When never set, merging is enabled with a 1,440-minute window. EventGroup EventGroup `json:"event_group" toon:"event_group"` - // Token granted to external reporters. Omitted unless external reporting is enabled on the channel. + // Token external reporters use to file incidents into this channel. Returned only when external reporting is enabled. ExternalReportToken string `json:"external_report_token" toon:"external_report_token"` - // Flapping detection configuration. + // Flapping detection configuration. When never set, the defaults are returned: enabled, 4 changes within 60 minutes, muted for 120 minutes. Flapping Flapping `json:"flapping" toon:"flapping"` - // Alert grouping configuration. + // Alert grouping configuration. When never set, `{"method": "n"}` (no grouping) is returned. Group Group `json:"group" toon:"group"` // Whether external reporters can file incidents into this channel. IsExternalReportEnabled bool `json:"is_external_report_enabled" toon:"is_external_report_enabled"` // When true, the channel is visible only to its managing teams. IsPrivate bool `json:"is_private" toon:"is_private"` - // Whether the current user has starred this channel. Present only in `POST /channel/list` responses. + // Whether the caller has starred this channel. Returned only by `POST /channel/list`. IsStarred bool `json:"is_starred" toon:"is_starred"` // Time of the most recent incident, Unix timestamp in seconds. LastIncidentAt Timestamp `json:"last_incident_at" toon:"last_incident_at"` // Additional teams that can manage the channel. ManagingTeamIDs []int64 `json:"managing_team_ids" toon:"managing_team_ids"` - // Incident counts by progress over the last 30 days. + // Counts of incidents started in the last 30 days that are still open, by progress. Not returned with `is_brief`. ProgressToIncidentCnts IncProgressCnts `json:"progress_to_incident_cnts" toon:"progress_to_incident_cnts"` - // Channel status. `enabled` receives and processes events normally; `disabled` drops incoming events outright; `deleted` is returned only when fetching a channel by ID — list endpoints never return it. + // Channel status: + // - `enabled`: incoming alert events are processed. + // - `disabled`: incoming alert events are discarded. + // - `deleted`: the channel was deleted; returned only by `POST /channel/info` and `POST /channel/infos`, never by `POST /channel/list`. Status string `json:"status" toon:"status"` // Owning team ID. TeamID int64 `json:"team_id" toon:"team_id"` - // Owning team name (resolved from the team directory; empty when unavailable). + // Owning team name, resolved from the team directory. Returned only by `POST /channel/list` without `is_brief`; omitted when the lookup fails. TeamName string `json:"team_name" toon:"team_name"` // Last update time, Unix timestamp in seconds. UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` @@ -2056,23 +2116,26 @@ type ChannelItem struct { type ChannelRuleIDRequest struct { // Owning channel ID; obtain it from `POST /channel/list`. ChannelID int64 `json:"channel_id" toon:"channel_id"` - // Rule ID (MongoDB ObjectID). + // Rule ID (24-character hex), as returned in `rule_id` by the create or list endpoint of the same rule type. RuleID string `json:"rule_id" toon:"rule_id"` } // ChannelScopedListRequest is generated from the Flashduty OpenAPI schema. type ChannelScopedListRequest struct { - // Channel to list rules for. + // Channel whose rules to list; obtain it from `POST /channel/list`. ChannelID int64 `json:"channel_id" toon:"channel_id"` } // ChannelShort is generated from the Flashduty OpenAPI schema. type ChannelShort struct { - // Channel ID. + // Channel ID, one of the requested `channel_ids`. ChannelID int64 `json:"channel_id" toon:"channel_id"` - // Channel name. + // Channel name, unique within the account. ChannelName string `json:"channel_name" toon:"channel_name"` - // Channel status: `enabled` processes events normally; `disabled` discards incoming events; `deleted` is soft-deleted. + // Channel status: + // - `enabled`: incoming alert events are processed. + // - `disabled`: incoming alert events are discarded. + // - `deleted`: the channel was deleted. Status string `json:"status" toon:"status"` } @@ -2110,7 +2173,7 @@ type ContextResolvedItem struct { ResolvedAtMs TimestampMilli `json:"resolved_at_ms" toon:"resolved_at_ms"` // Resolved team-scope knowledge ID. TeamPackID string `json:"team_pack_id" toon:"team_pack_id"` - // Resolved version map, one entry per knowledge. + // Map from knowledge ID to the version the agent last loaded. Versions map[string]int64 `json:"versions" toon:"versions"` } @@ -2118,9 +2181,9 @@ type ContextResolvedItem struct { type ConvertWorkItemRequest struct { // Client-generated idempotency key (max 128 characters; letters, digits, `_`, `-`, `.`, `:` only). IdempotencyKey string `json:"idempotency_key" toon:"idempotency_key"` - // Optional status to set on the converted follow-up. One of `open`, `in_progress`, `done`, `cancelled`. + // Optional status to set on the converted follow-up; omitted or `null` keeps the current status. Values: `open` (not started), `in_progress` (being worked on), `done` (finished), `cancelled` (no longer needed). TargetStatus *string `json:"target_status,omitempty" toon:"target_status,omitempty"` - // Current item version for optimistic locking. Must match the stored version. + // The item's current `version` (≥ 1) for optimistic locking. Version int64 `json:"version" toon:"version"` // Work item ID (opaque string, max 128 characters). WorkItemID string `json:"work_item_id" toon:"work_item_id"` @@ -2128,11 +2191,11 @@ type ConvertWorkItemRequest struct { // CreateChannelRequest is generated from the Flashduty OpenAPI schema. type CreateChannelRequest struct { - // Auto-resolve timing mode: `trigger` starts the timer when the incident triggers, `update` restarts it on every alert update. + // How the auto-resolve timer runs. `trigger` (default) starts the timer once when the incident is triggered; `update` restarts it whenever a new alert merges into the incident. AutoResolveMode string `json:"auto_resolve_mode,omitempty" toon:"auto_resolve_mode,omitempty"` // Auto-resolve timeout in seconds. 0 disables auto-resolve. Max 30 days. AutoResolveTimeout int64 `json:"auto_resolve_timeout,omitempty" toon:"auto_resolve_timeout,omitempty"` - // Channel name. 1 to 59 characters. + // Channel name, 1–59 characters, unique within the account. ChannelName string `json:"channel_name" toon:"channel_name"` // Free-form description. Up to 500 characters. Description string `json:"description,omitempty" toon:"description,omitempty"` @@ -2140,23 +2203,23 @@ type CreateChannelRequest struct { DisableAutoClose bool `json:"disable_auto_close,omitempty" toon:"disable_auto_close,omitempty"` // Disable outlier incident detection. DisableOutlierDetection bool `json:"disable_outlier_detection,omitempty" toon:"disable_outlier_detection,omitempty"` - // Default escalation rule applied to the channel. Omit to skip default escalation. + // Creates an enabled escalation rule named `Default` with a single level that notifies `target` once. Omit to create the channel without escalation rules. EscalateRule CreateChannelRequestEscalateRule `json:"escalate_rule,omitzero" toon:"escalate_rule,omitempty"` // Alert event merge configuration. Omit to use the default (merge enabled, 1440-minute window). EventGroup EventGroup `json:"event_group,omitzero" toon:"event_group,omitempty"` - // Flapping detection configuration. - Flapping CreateChannelRequestFlapping `json:"flapping,omitzero" toon:"flapping,omitempty"` - // Alert grouping configuration. - Group CreateChannelRequestGroup `json:"group,omitzero" toon:"group,omitempty"` - // Allow external reporters to file incidents into this channel. + // Flapping detection configuration. Omit to use the defaults. + Flapping Flapping `json:"flapping,omitzero" toon:"flapping,omitempty"` + // Alert grouping configuration. Omit for no grouping (`method` `n`). + Group Group `json:"group,omitzero" toon:"group,omitempty"` + // When true, external reporters can file incidents into this channel, and the response carries the generated `external_report_token`. IsExternalReportEnabled bool `json:"is_external_report_enabled,omitempty" toon:"is_external_report_enabled,omitempty"` // When true, the channel is visible only to its managing teams. IsPrivate bool `json:"is_private,omitempty" toon:"is_private,omitempty"` // Additional teams that can manage the channel. Up to 3 entries. ManagingTeamIDs []int64 `json:"managing_team_ids,omitempty" toon:"managing_team_ids,omitempty"` - // IDs of plugins (integrations) subscribed to this channel. + // Integration type IDs (the `plugin_id` shown on integrations returned by `POST /integration/list`). For each ID, a channel-exclusive integration of that type is created, named after the type. An unknown ID returns `InvalidParameter`. PluginIDs []int64 `json:"plugin_ids,omitempty" toon:"plugin_ids,omitempty"` - // Owning team ID; obtain it from `POST /team/list`. + // Owning team ID; obtain it from `POST /team/list`. Required and must exist. TeamID int64 `json:"team_id" toon:"team_id"` } @@ -2166,32 +2229,32 @@ type CreateDropRuleRequest struct { ChannelID int64 `json:"channel_id" toon:"channel_id"` // Rule description, up to 500 characters. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Alert event match conditions (OR-of-AND); matching events are discarded entirely — no alert, incident, or notification is produced. When omitted or empty, the rule matches nothing. - Filters [][]CreateDropRuleRequestFiltersItemItem `json:"filters,omitempty" toon:"filters,omitempty"` + // Alert event conditions (OR of AND groups). A matching event is discarded entirely: no alert, incident or notification. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`. When omitted or empty, the rule matches nothing. + Filters FilterGroup `json:"filters,omitempty" toon:"filters,omitempty"` // Rule name, 1 to 39 characters. RuleName string `json:"rule_name" toon:"rule_name"` } // CreateEscalationRuleRequest is generated from the Flashduty OpenAPI schema. type CreateEscalationRuleRequest struct { - // Delay window in seconds. 0 disables delay. + // Delay in seconds, 0–3600, before the first notification for a newly assigned incident; `0` notifies immediately. AggrWindow int64 `json:"aggr_window,omitempty" toon:"aggr_window,omitempty"` // Owning channel ID; obtain it from `POST /channel/list`. ChannelID int64 `json:"channel_id" toon:"channel_id"` // Rule description, up to 500 characters. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Incident-level match conditions (OR-of-AND tree): the rule is matched against the incident the alert was grouped into, not against the alert itself. Omit or leave empty to apply the rule to all incidents in the channel. - Filters [][]CreateEscalationRuleRequestFiltersItemItem `json:"filters,omitempty" toon:"filters,omitempty"` - // Escalation levels in order. At least one level is required. - Layers []CreateEscalationRuleRequestLayersItem `json:"layers" toon:"layers"` - // Evaluation priority. Lower runs first. + // Incident conditions (OR of AND groups), matched against the incident the alert was grouped into, not against the alert. Keys: `title`, `description`, `severity` (alias `incident_severity`, `alert_severity`), `status` (alias `incident_status`, `alert_status`), `dedup_key`, `integration_id` (alias `data_source_id`), or any `labels.`. Omit or leave empty to match every incident in the channel. + Filters FilterGroup `json:"filters,omitempty" toon:"filters,omitempty"` + // Escalation levels in order; the incident starts at the first level. + Layers []EscalateLayer `json:"layers" toon:"layers"` + // Evaluation order from `0` to `200`; lower values are evaluated first. Omit to place the rule after all existing rules (current highest priority + 1). Priority *int64 `json:"priority,omitempty" toon:"priority,omitempty"` // Rule name, 1 to 39 characters. RuleName string `json:"rule_name" toon:"rule_name"` - // Notification template ID (MongoDB ObjectID). + // Notification template ID (24-character hex); obtain it from `POST /template/list`. Must exist. TemplateID string `json:"template_id" toon:"template_id"` - // Optional recurring time windows during which the rule applies. - TimeFilters []CreateEscalationRuleRequestTimeFiltersItem `json:"time_filters,omitempty" toon:"time_filters,omitempty"` + // Recurring time windows during which the rule can match; omit or leave empty to match at any time. + TimeFilters []TimeFilter `json:"time_filters,omitempty" toon:"time_filters,omitempty"` } // CreateFieldRequest is generated from the Flashduty OpenAPI schema. @@ -2202,7 +2265,7 @@ type CreateFieldRequest struct { Description string `json:"description,omitempty" toon:"description,omitempty"` // Human-readable name. Must be unique within the account. DisplayName string `json:"display_name" toon:"display_name"` - // Machine name. Must start with a letter or underscore; 1–40 chars of `[a-zA-Z0-9_]`. Immutable after creation. + // Machine name: 1–39 characters of `[a-zA-Z0-9_]`, starting with a letter or underscore. Immutable after creation. FieldName string `json:"field_name" toon:"field_name"` // Field type, immutable after creation. // | Value | Meaning | @@ -2230,7 +2293,7 @@ type CreateFieldResponse struct { type CreateIncidentCommentTypeRequest struct { // Label color as a hex value in #RRGGBB format. Normalized to uppercase. Color string `json:"color" toon:"color"` - // Display name. Trimmed before storing; must be unique within the account (case-insensitive). At most 40 characters. + // Display name. Trimmed before storing; must be unique within the account (case-insensitive). At most 40 characters. Must not contain control or text-direction characters. Name string `json:"name" toon:"name"` } @@ -2243,9 +2306,9 @@ type CreateIncidentCommentTypeResponse struct { // CreateIncidentRequest is generated from the Flashduty OpenAPI schema. type CreateIncidentRequest struct { - // Incident assignment target. May be omitted entirely: when unset or empty, the channel's default assignment applies; required when the account's create form is in effect. `person_ids`, `escalate_rule_id`, and `emails` can be combined — responders are the union. + // Who to assign. When omitted or empty, the channel's escalation rules decide (a standalone incident gets no responders); required when the account has a create form. `person_ids`, `escalate_rule_id` and `emails` can be combined — responders are the union. Assignment runs after creation, and its failure does not undo the incident. AssignedTo CreateIncidentRequestAssignedTo `json:"assigned_to,omitzero" toon:"assigned_to,omitempty"` - // Channel to file the incident into. Optional; leave unset for a standalone incident. + // Channel to file the incident into; must exist in the account. Optional unless the account has a create form; leave it unset for a standalone incident. ChannelID int64 `json:"channel_id,omitempty" toon:"channel_id,omitempty"` // Incident description, up to 1024 characters. Description string `json:"description,omitempty" toon:"description,omitempty"` @@ -2253,7 +2316,7 @@ type CreateIncidentRequest struct { Fields CustomFieldValues `json:"fields,omitempty" toon:"fields,omitempty"` // Incident severity: `Info`, `Warning` or `Critical` (most severe). IncidentSeverity string `json:"incident_severity" toon:"incident_severity"` - // Incident title, up to 512 characters. + // Incident title, up to 512 characters. Required (non-blank) when the account has a create form. Title string `json:"title,omitempty" toon:"title,omitempty"` } @@ -2261,7 +2324,7 @@ type CreateIncidentRequest struct { type CreateIncidentResponse struct { // Newly created incident ID (MongoDB ObjectID). IncidentID string `json:"incident_id" toon:"incident_id"` - // Echoes the incident title from the request. + // Incident title as sent in the request; empty when the request had no title. Title string `json:"title" toon:"title"` } @@ -2271,16 +2334,16 @@ type CreateInhibitRuleRequest struct { ChannelID int64 `json:"channel_id" toon:"channel_id"` // Rule description, up to 500 characters. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Field keys whose values must be equal between the source (inhibiting) alert and the target (suppressed) alert, e.g. `data_source_id` or `labels.cluster`. + // Keys whose values must be equal on the source alert and the incoming event. Only `title`, `severity` and `labels.` take effect; any other key (for example `data_source_id`) is accepted but makes the rule never fire. Must be present; an empty array also makes the rule inert. Equals []string `json:"equals" toon:"equals"` // When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule. IsDirectlyDiscard bool `json:"is_directly_discard,omitempty" toon:"is_directly_discard,omitempty"` // Rule name, 1 to 39 characters. RuleName string `json:"rule_name" toon:"rule_name"` - // Conditions the source alert must match, evaluated against stored active alerts. Supported keys: `status`, `incident_status`, `alert_status`, `severity`, `incident_severity`, `alert_severity`, `title`, `description`, or any `labels.`. Empty makes the rule inert. - SourceFilters [][]CreateInhibitRuleRequestSourceFiltersItemItem `json:"source_filters,omitempty" toon:"source_filters,omitempty"` - // Conditions the incoming target alert event must match to be suppressed; empty means every event is a target. - TargetFilters [][]CreateInhibitRuleRequestTargetFiltersItemItem `json:"target_filters,omitempty" toon:"target_filters,omitempty"` + // Conditions the source (inhibiting) alert must match, evaluated against active alerts already stored in the channel. Keys: `title`, `description`, `severity` (alias `incident_severity`, `alert_severity`), `status` (alias `incident_status`, `alert_status`), or any `labels.`. Empty makes the rule inert. + SourceFilters FilterGroup `json:"source_filters,omitempty" toon:"source_filters,omitempty"` + // Conditions the incoming target alert event must match to be inhibited; empty means every incoming event is a target. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`. + TargetFilters FilterGroup `json:"target_filters,omitempty" toon:"target_filters,omitempty"` } // CreateIntegrationRequest is generated from the Flashduty OpenAPI schema. @@ -2317,41 +2380,43 @@ type CreateSilenceRuleRequest struct { ChannelID int64 `json:"channel_id" toon:"channel_id"` // Rule description, up to 500 characters. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Alert event match conditions (OR-of-AND). Required and must contain at least one condition. - Filters [][]CreateSilenceRuleRequestFiltersItemItem `json:"filters,omitempty" toon:"filters,omitempty"` - // Incident ID (ObjectID hex) to attach the rule to. Optional; when set, only one enabled silence rule may exist per incident. + // Alert event conditions (OR of AND groups); matching events are silenced while the time window is active. Required, with at least one condition. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`. + Filters FilterGroup `json:"filters,omitempty" toon:"filters,omitempty"` + // ID of the incident this rule is created from (24-character hex). The incident must exist, and only one enabled silence rule may exist per incident. FromIncidentID string `json:"from_incident_id,omitempty" toon:"from_incident_id,omitempty"` - // When true, the silence rule is automatically deleted after its time window expires. Defaults to false. + // When true, a rule with a one-off `time_filter` is permanently removed about 24 hours after `end_time` (or after its last update, whichever is later). Rules created with `from_incident_id` are cleaned up the same way. Rules with recurring `time_filters` are never removed automatically. Defaults to `false`. IsAutoDelete bool `json:"is_auto_delete,omitempty" toon:"is_auto_delete,omitempty"` // When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule. IsDirectlyDiscard bool `json:"is_directly_discard,omitempty" toon:"is_directly_discard,omitempty"` // Rule name, 1 to 39 characters. RuleName string `json:"rule_name" toon:"rule_name"` - // One-off time window defined by unix seconds. - TimeFilter CreateSilenceRuleRequestTimeFilter `json:"time_filter,omitzero" toon:"time_filter,omitempty"` - // Recurring time windows during which silencing applies. Mutually exclusive with `time_filter`. - TimeFilters []CreateSilenceRuleRequestTimeFiltersItem `json:"time_filters,omitempty" toon:"time_filters,omitempty"` + // One-off silence window. Set exactly one of `time_filter` or `time_filters`. + TimeFilter OnceTimeFilter `json:"time_filter,omitzero" toon:"time_filter,omitempty"` + // Recurring silence windows. Set exactly one of `time_filters` or `time_filter`. + TimeFilters []TimeFilter `json:"time_filters,omitempty" toon:"time_filters,omitempty"` } // CreateStatusPageChangeRequest is generated from the Flashduty OpenAPI schema. type CreateStatusPageChangeRequest struct { // Maintenance only: automatically advance the status based on the scheduled window. AutoUpdateBySchedule bool `json:"auto_update_by_schedule,omitempty" toon:"auto_update_by_schedule,omitempty"` - // Event close time in Unix seconds. Must be greater than or equal to the first update's `at_seconds`. For retrospective events this is the time the event ended; for maintenances with `auto_update_by_schedule` it schedules the automatic transition to `completed` and must be within 30 days from now. + // Event close time in Unix seconds; must be greater than or equal to the first update's `at_seconds`. For maintenances this is the scheduled end; with `auto_update_by_schedule` the event switches to `completed` at this time, which must be within 30 days from now. For a retrospective event in a terminal status, omitting it uses the latest update's time. CloseAtSeconds int64 `json:"close_at_seconds,omitempty" toon:"close_at_seconds,omitempty"` // Event description (Markdown). Must not be empty. Description string `json:"description" toon:"description"` - // Mark this event as a retrospective (historical) one. + // ID of a draft created by `POST /status-page/draft/create` to publish with this event. The draft must be pending, target this `page_id` and `type`, and have no `change_id`; it is marked published once the event is created. Omit when not publishing a draft. + DraftID string `json:"draft_id,omitempty" toon:"draft_id,omitempty"` + // Mark the event as retrospective (a past event recorded afterwards). Requires at least 2 entries in `updates`. IsRetrospective bool `json:"is_retrospective,omitempty" toon:"is_retrospective,omitempty"` // Linked change IDs (related incidents, deployments, etc.). LinkedChanges []string `json:"linked_changes,omitempty" toon:"linked_changes,omitempty"` - // Notify subscribers about this event and all its updates. + // Notify subscribers about this event. On creation one notification is sent for the last update; later timeline entries also notify while this is `true`. NotifySubscribers bool `json:"notify_subscribers,omitempty" toon:"notify_subscribers,omitempty"` // Status page ID; obtain it from `GET /status-page/list`. PageID int64 `json:"page_id" toon:"page_id"` // Member IDs responsible for the event. Responders []int64 `json:"responders,omitempty" toon:"responders,omitempty"` - // Event start time in Unix seconds. The stored start time is always derived from the first update's `at_seconds` (which defaults to the current time when omitted); for maintenances with `auto_update_by_schedule`, this value schedules the automatic transition to `ongoing`. + // Event start time in Unix seconds. Maintenances store this value as the scheduled start (with `auto_update_by_schedule`, the time the event switches to `ongoing`); when it is omitted or 0, and always for incidents, the start time is the first update's `at_seconds`. StartAtSeconds int64 `json:"start_at_seconds,omitempty" toon:"start_at_seconds,omitempty"` // Initial event status. `investigating`/`identified`/`monitoring`/`resolved` apply to incidents; `scheduled`/`ongoing`/`completed` apply to maintenances. Status string `json:"status" toon:"status"` @@ -2359,13 +2424,13 @@ type CreateStatusPageChangeRequest struct { Title string `json:"title" toon:"title"` // Change type: `incident` unplanned incident, `maintenance` planned maintenance. Type string `json:"type" toon:"type"` - // Timeline updates. At least one update is required, and at least one of them must contain `component_changes`. Immediate events normally pass one update; retrospective events must pass all historical updates. + // Timeline updates in non-decreasing `at_seconds` order. At least one update is required, and at least one of them must contain `component_changes`. Immediate events normally pass one update; retrospective events must pass at least 2. Updates []CreateStatusPageChangeRequestUpdatesItem `json:"updates" toon:"updates"` } // CreateStatusPageChangeTimelineRequest is generated from the Flashduty OpenAPI schema. type CreateStatusPageChangeTimelineRequest struct { - // Update timestamp in Unix seconds. Defaults to the current time when omitted or 0. + // Update time in Unix seconds; must not be earlier than the event's latest timeline entry. Defaults to the current time when omitted or 0. AtSeconds int64 `json:"at_seconds,omitempty" toon:"at_seconds,omitempty"` // Target change ID; obtain it from `GET /status-page/change/list`. ChangeID int64 `json:"change_id" toon:"change_id"` @@ -2373,9 +2438,11 @@ type CreateStatusPageChangeTimelineRequest struct { ComponentChanges []CreateStatusPageChangeTimelineRequestComponentChangesItem `json:"component_changes,omitempty" toon:"component_changes,omitempty"` // Update description (Markdown). Must not be empty. Description string `json:"description" toon:"description"` + // ID of a pending draft created by `POST /status-page/draft/create` whose `change_id` is this event; it is marked published when the update is stored. Omit when not publishing a draft. + DraftID string `json:"draft_id,omitempty" toon:"draft_id,omitempty"` // Status page ID; obtain it from `GET /status-page/list`. PageID int64 `json:"page_id" toon:"page_id"` - // Change status after this update; must be valid for the change type. When transitioning to `resolved` or `completed`, all affected components must be back to `operational`. + // Event status after this update; must be valid for the event type. Pass the current status to post an update without a status change. When moving to `resolved` or `completed`, all affected components must be back to `operational`. // | Value | Meaning | // |---|---| // | `investigating` | Investigating (incident). | @@ -2390,9 +2457,9 @@ type CreateStatusPageChangeTimelineRequest struct { // CreateStatusPageDraftRequest is generated from the Flashduty OpenAPI schema. type CreateStatusPageDraftRequest struct { - // Draft payload, stored verbatim, up to 64 KB serialized. Validated fields: `page_id`, `type` (`incident` or `maintenance`), `name`, `message`; optional `change_id` (append an update to an existing event when > 0), `status`, `affected_components`, and `start_time`/`end_time` (Unix epoch seconds, new maintenance only). - Draft map[string]any `json:"draft" toon:"draft"` - // Opaque marker of the drafting origin, e.g. `ai_sre:sess_xxx`. Up to 64 characters. + // Draft payload, stored verbatim (at most 64 KB serialized). The server validates the fields below and keeps any other fields unchanged for the console. + Draft CreateStatusPageDraftRequestDraft `json:"draft" toon:"draft"` + // Free-form text recording where the draft came from, such as an AI session reference; stored and shown with the draft, not interpreted. Up to 64 characters. Source string `json:"source,omitempty" toon:"source,omitempty"` } @@ -2400,7 +2467,7 @@ type CreateStatusPageDraftRequest struct { type CreateStatusPageRequest struct { // Get-in-touch contact, such as a mailto or website URL. ContactInfo string `json:"contact_info,omitempty" toon:"contact_info,omitempty"` - // Custom domain for a public status page. + // Custom domain; allowed only for public pages and must not be used by another status page. CustomDomain string `json:"custom_domain,omitempty" toon:"custom_domain,omitempty"` // Custom navigation links shown on the status page. CustomLinks []map[string]string `json:"custom_links,omitempty" toon:"custom_links,omitempty"` @@ -2414,13 +2481,13 @@ type CreateStatusPageRequest struct { PageFooter string `json:"page_footer,omitempty" toon:"page_footer,omitempty"` // Header content shown on the status page. PageHeader string `json:"page_header,omitempty" toon:"page_header,omitempty"` - // Browser title shown for the status page. + // Accepted for compatibility but not stored; it has no effect. PageTitle string `json:"page_title,omitempty" toon:"page_title,omitempty"` - // Subscription channel toggles. + // Subscription channel toggles; both default to `false`. A public page can enable only `email` and an internal page only `im`. Subscription StatusPageSubscriptionItem `json:"subscription,omitzero" toon:"subscription,omitempty"` // Visibility type: `public` accessible to anyone, `internal` restricted to logged-in members of this account. Type string `json:"type" toon:"type"` - // URL-safe slug, unique per account and page type. + // URL-safe slug; normalized to lowercase with non-alphanumeric characters replaced by hyphens, and must be unique among the account's pages of the same type. URLName string `json:"url_name" toon:"url_name"` } @@ -2436,13 +2503,13 @@ type CreateStatusPageResponse struct { // CreateWarRoomRequest is generated from the Flashduty OpenAPI schema. type CreateWarRoomRequest struct { - // When true, also add historical responders of the incident as observers. + // When true, also invite members who were assigned or added as responders earlier but are no longer current responders. AddObservers bool `json:"add_observers,omitempty" toon:"add_observers,omitempty"` // Incident ID (MongoDB ObjectID). IncidentID string `json:"incident_id" toon:"incident_id"` - // IM integration ID. Must have war room enabled; Feishu, DingTalk, WeCom (self-built), Slack and Teams are supported. + // IM integration ID with war room enabled; obtain it from `POST /datasource/im/war-room-enabled/list`. Feishu, DingTalk, WeCom (self-built app only), and Slack are supported. IntegrationID int64 `json:"integration_id" toon:"integration_id"` - // Additional member IDs to add to the war room. + // Member IDs to invite into the group; every ID must be a valid member of the account. MemberIDs []int64 `json:"member_ids,omitempty" toon:"member_ids,omitempty"` } @@ -2458,15 +2525,17 @@ type CreateWorkItemRequest struct { IdempotencyKey string `json:"idempotency_key" toon:"idempotency_key"` // Incident ID (MongoDB ObjectID) the item is anchored to. IncidentID string `json:"incident_id" toon:"incident_id"` - // `action` anchors to an active incident and must not set `post_mortem_id`; `follow_up` requires `post_mortem_id`. + // Work item type. + // - `action`: a to-do on an incident that is not closed yet; must not set `post_mortem_id`. + // - `follow_up`: a post-mortem follow-up on a closed incident; `post_mortem_id` is optional. ItemType string `json:"item_type" toon:"item_type"` - // Post-mortem ID (32-character hex string). Required for `follow_up`, forbidden for `action`. The post-mortem must be linked to `incident_id`. + // Post-mortem ID (32-character hex string). Forbidden for `action`. Optional for `follow_up`: when set, the incident must be linked to that report; when omitted, the incident's post-mortem is used if it exists. PostMortemID string `json:"post_mortem_id,omitempty" toon:"post_mortem_id,omitempty"` - // Optional client-defined priority (max 64 characters). + // Optional free-form priority, at most 64 characters. The console uses `high`, `medium` and `low`; any other string is stored as-is. Priority string `json:"priority,omitempty" toon:"priority,omitempty"` // Initial status. One of `open`, `in_progress`, `done`, `cancelled`; defaults to `open` when omitted or blank. Status string `json:"status,omitempty" toon:"status,omitempty"` - // Item title (max 512 characters). + // Item title, at most 512 characters; leading and trailing spaces are trimmed and it must not be blank. Title string `json:"title" toon:"title"` } @@ -2516,7 +2585,7 @@ type DsElasticSearchConfig struct { CertificateFingerprint string `json:"certificate_fingerprint,omitempty" toon:"certificate_fingerprint,omitempty"` // Elastic Cloud deployment ID. Only for `cloud` deployment. CloudID string `json:"cloud_id,omitempty" toon:"cloud_id,omitempty"` - // Deployment type. `cloud` uses Elastic Cloud; `self-managed` uses a self-hosted cluster. + // Deployment type; required. `cloud` uses Elastic Cloud (`address` is not needed); `self-managed` uses a self-hosted cluster (`address` is required). Deployment string `json:"deployment,omitempty" toon:"deployment,omitempty"` // Custom HTTP headers added to every request, each entry formatted as `Key: Value`. Headers []string `json:"headers,omitempty" toon:"headers,omitempty"` @@ -2534,7 +2603,7 @@ type DsElasticSearchConfig struct { // DsKafkaConfig is generated from the Flashduty OpenAPI schema. type DsKafkaConfig struct { - // Authentication password; supports ${env:NAME}. Omit on update to preserve; explicitly send an empty string to clear. Literal passwords are omitted from responses. + // Authentication password; supports ${env:NAME}. Required with `username` for SASL authentication and must be empty when `sasl_mechanism` is `none`. On update, omit to keep the stored password; explicitly send an empty string to clear. Literal passwords are omitted from responses. Password *string `json:"password,omitempty" toon:"password,omitempty"` // SASL mechanism: none (default, no credentials), plain, scram-sha-256, scram-sha-512 (require username and password). SaslMechanism string `json:"sasl_mechanism,omitempty" toon:"sasl_mechanism,omitempty"` @@ -2544,7 +2613,7 @@ type DsKafkaConfig struct { TlsCa string `json:"tls_ca,omitempty" toon:"tls_ca,omitempty"` // PEM client certificate or ${env:NAME}; configure both tls_cert and tls_key. TlsCert string `json:"tls_cert,omitempty" toon:"tls_cert,omitempty"` - // Whether TLS is enabled; defaults to false. + // Whether TLS is enabled; defaults to false. When false, all `tls_*` fields are cleared on save. TlsEnabled bool `json:"tls_enabled,omitempty" toon:"tls_enabled,omitempty"` // PEM client private key or ${env:NAME}; configure both tls_cert and tls_key. Omit on update to preserve; an empty string clears it. Literal keys are omitted from responses. TlsKey *string `json:"tls_key,omitempty" toon:"tls_key,omitempty"` @@ -2556,7 +2625,7 @@ type DsKafkaConfig struct { TlsServerName string `json:"tls_server_name,omitempty" toon:"tls_server_name,omitempty"` // Skip server certificate verification when TLS is enabled. TlsSkipVerify bool `json:"tls_skip_verify,omitempty" toon:"tls_skip_verify,omitempty"` - // Authentication username; an ${env:NAME} reference is supported. + // Authentication username; an ${env:NAME} reference is supported. Required when `sasl_mechanism` is `plain`, `scram-sha-256` or `scram-sha-512`; must be empty when it is `none`. Username string `json:"username,omitempty" toon:"username,omitempty"` } @@ -2598,7 +2667,7 @@ type DsMongoDBConfig struct { TimeoutMs int64 `json:"timeout_ms,omitempty" toon:"timeout_ms,omitempty"` // PEM CA certificates or an ${env:NAME} reference. TlsCa string `json:"tls_ca,omitempty" toon:"tls_ca,omitempty"` - // Whether TLS is enabled; defaults to false. + // Whether TLS is enabled; defaults to false. When false, all `tls_*` fields are cleared on save. TlsEnabled bool `json:"tls_enabled,omitempty" toon:"tls_enabled,omitempty"` // Maximum TLS version: 1.2 or 1.3; empty means no constraint. Must not be below the minimum. TlsMaxVersion string `json:"tls_max_version,omitempty" toon:"tls_max_version,omitempty"` @@ -2608,7 +2677,7 @@ type DsMongoDBConfig struct { TlsServerName string `json:"tls_server_name,omitempty" toon:"tls_server_name,omitempty"` // Skip server certificate verification when TLS is enabled. TlsSkipVerify bool `json:"tls_skip_verify,omitempty" toon:"tls_skip_verify,omitempty"` - // Authentication username; an ${env:NAME} reference is supported. + // Authentication username; an ${env:NAME} reference is supported. Must be configured together with `password`. Username string `json:"username,omitempty" toon:"username,omitempty"` } @@ -2664,21 +2733,35 @@ type DsOracleConfig struct { // DsPayload is generated from the Flashduty OpenAPI schema. type DsPayload struct { - Clickhouse DsClickHouseConfig `json:"clickhouse,omitzero" toon:"clickhouse,omitempty"` - Elasticsearch DsElasticSearchConfig `json:"elasticsearch,omitzero" toon:"elasticsearch,omitempty"` - Kafka *DsKafkaConfig `json:"kafka,omitempty" toon:"kafka,omitempty"` - Loki DsLokiConfig `json:"loki,omitzero" toon:"loki,omitempty"` - MongodbMongod *DsMongoDBConfig `json:"mongodb_mongod,omitempty" toon:"mongodb_mongod,omitempty"` - MongodbMongos *DsMongoDBConfig `json:"mongodb_mongos,omitempty" toon:"mongodb_mongos,omitempty"` - Mysql DsMySqlConfig `json:"mysql,omitzero" toon:"mysql,omitempty"` - Oracle DsOracleConfig `json:"oracle,omitzero" toon:"oracle,omitempty"` - Postgres DsPostgresConfig `json:"postgres,omitzero" toon:"postgres,omitempty"` - Prometheus DsPrometheusConfig `json:"prometheus,omitzero" toon:"prometheus,omitempty"` - RedisNode *DsRedisNodeConfig `json:"redis_node,omitempty" toon:"redis_node,omitempty"` + // Settings for `type_ident` `clickhouse`. + Clickhouse DsClickHouseConfig `json:"clickhouse,omitzero" toon:"clickhouse,omitempty"` + // Settings for `type_ident` `elasticsearch`. + Elasticsearch DsElasticSearchConfig `json:"elasticsearch,omitzero" toon:"elasticsearch,omitempty"` + // Settings for `type_ident` `kafka` (diagnostic-only). + Kafka *DsKafkaConfig `json:"kafka,omitempty" toon:"kafka,omitempty"` + // Settings for `type_ident` `loki`. + Loki DsLokiConfig `json:"loki,omitzero" toon:"loki,omitempty"` + // Settings for `type_ident` `mongodb_mongod` (diagnostic-only); same fields as `mongodb_mongos`. + MongodbMongod *DsMongoDBConfig `json:"mongodb_mongod,omitempty" toon:"mongodb_mongod,omitempty"` + // Settings for `type_ident` `mongodb_mongos` (diagnostic-only); same fields as `mongodb_mongod`. + MongodbMongos *DsMongoDBConfig `json:"mongodb_mongos,omitempty" toon:"mongodb_mongos,omitempty"` + // Settings for `type_ident` `mysql`. + Mysql DsMySqlConfig `json:"mysql,omitzero" toon:"mysql,omitempty"` + // Settings for `type_ident` `oracle`. + Oracle DsOracleConfig `json:"oracle,omitzero" toon:"oracle,omitempty"` + // Settings for `type_ident` `postgres`. + Postgres DsPostgresConfig `json:"postgres,omitzero" toon:"postgres,omitempty"` + // Settings for `type_ident` `prometheus`. + Prometheus DsPrometheusConfig `json:"prometheus,omitzero" toon:"prometheus,omitempty"` + // Settings for `type_ident` `redis_node` (diagnostic-only). + RedisNode *DsRedisNodeConfig `json:"redis_node,omitempty" toon:"redis_node,omitempty"` + // Settings for `type_ident` `redis_sentinel` (diagnostic-only). RedisSentinel *DsRedisSentinelConfig `json:"redis_sentinel,omitempty" toon:"redis_sentinel,omitempty"` - SLS DsslsConfig `json:"sls,omitzero" toon:"sls,omitempty"` + // Settings for `type_ident` `sls`. + SLS DsslsConfig `json:"sls,omitzero" toon:"sls,omitempty"` // Tencent CLS credentials. Required when `type_ident` is `tencent_cls`. - TencentCls DsTencentClsConfig `json:"tencent_cls,omitzero" toon:"tencent_cls,omitempty"` + TencentCls DsTencentClsConfig `json:"tencent_cls,omitzero" toon:"tencent_cls,omitempty"` + // Settings for `type_ident` `victorialogs`. Victorialogs DsVictoriaLogsConfig `json:"victorialogs,omitzero" toon:"victorialogs,omitempty"` } @@ -2710,9 +2793,9 @@ type DsPostgresConfig struct { type DsPrometheusConfig struct { // Enable HTTP Basic Auth. BasicAuthEnabled bool `json:"basic_auth_enabled,omitempty" toon:"basic_auth_enabled,omitempty"` - // Basic auth password. + // Basic Auth password, effective when `basic_auth_enabled` is `true`. Returned as stored in create, update and info responses. BasicAuthPassword string `json:"basic_auth_password,omitempty" toon:"basic_auth_password,omitempty"` - // Basic auth username. + // Basic Auth username, effective when `basic_auth_enabled` is `true`. BasicAuthUsername string `json:"basic_auth_username,omitempty" toon:"basic_auth_username,omitempty"` // Custom HTTP headers in `Key: Value` format. Headers []string `json:"headers,omitempty" toon:"headers,omitempty"` @@ -2742,7 +2825,7 @@ type DsRedisNodeConfig struct { Password *string `json:"password,omitempty" toon:"password,omitempty"` // Connection timeout in milliseconds; defaults to 3000 when omitted. TimeoutMs int64 `json:"timeout_ms,omitempty" toon:"timeout_ms,omitempty"` - // Authentication username; an ${env:NAME} reference is supported. + // Authentication username; an ${env:NAME} reference is supported. When set, `password` is required (on update, omit `password` to keep the stored one). Username string `json:"username,omitempty" toon:"username,omitempty"` } @@ -2752,7 +2835,7 @@ type DsRedisSentinelConfig struct { Password *string `json:"password,omitempty" toon:"password,omitempty"` // Connection timeout in milliseconds; defaults to 3000 when omitted. TimeoutMs int64 `json:"timeout_ms,omitempty" toon:"timeout_ms,omitempty"` - // Authentication username; an ${env:NAME} reference is supported. + // Authentication username; an ${env:NAME} reference is supported. When set, `password` is required (on update, omit `password` to keep the stored one). Username string `json:"username,omitempty" toon:"username,omitempty"` } @@ -2804,35 +2887,35 @@ type DsVictoriaLogsConfig struct { // DashboardAbsoluteTimeRange is generated from the Flashduty OpenAPI schema. type DashboardAbsoluteTimeRange struct { - // Unix timestamp in milliseconds. + // Start of the window as a Unix timestamp in milliseconds. Must be 0 or greater and less than `to_ms`. FromMs int64 `json:"from_ms" toon:"from_ms"` - // Unix timestamp in milliseconds. + // End of the window as a Unix timestamp in milliseconds. Must be greater than `from_ms`; `instant` queries are evaluated at this time. ToMs int64 `json:"to_ms" toon:"to_ms"` } // DashboardActor is generated from the Flashduty OpenAPI schema. type DashboardActor struct { - // Member ID. + // Member ID of the person who performed the action. ID uint64 `json:"id" toon:"id"` - // Member display name. + // Member display name, recorded at the time of the action. Name string `json:"name" toon:"name"` } // DashboardBarViz is generated from the Flashduty OpenAPI schema. type DashboardBarViz struct { - // Field supplying the category axis. + // Result field supplying the category axis; required, at most 1024 Unicode code points, not `frame_index` or `field_index`. CategoryField string `json:"category_field" toon:"category_field"` DataLink DashboardDataLink `json:"data_link,omitzero" toon:"data_link,omitempty"` - // Fixed decimal places; omit or send null to let the renderer decide. + // Fixed number of decimal places, 0–15; omit or send null to let the console decide. Decimals *int64 `json:"decimals,omitempty" toon:"decimals,omitempty"` // Visualization kind discriminator; always `bar`. Kind string `json:"kind" toon:"kind"` // Open options object for the chosen visualization kind; the only part of the definition that round-trips losslessly. Missing or null normalizes to `{}`. Options map[string]any `json:"options" toon:"options"` Threshold DashboardThreshold `json:"threshold,omitzero" toon:"threshold,omitempty"` - // Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. + // Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. Defaults to `unitless` when omitted. Unit string `json:"unit,omitempty" toon:"unit,omitempty"` - // Fields supplying the bar values. + // Result fields supplying the bar values; at least one, each listed once. Names must not be `frame_index` or `field_index`. ValueFields []string `json:"value_fields" toon:"value_fields"` } @@ -2854,7 +2937,7 @@ type DashboardColumnOption struct { Threshold DashboardThreshold `json:"threshold,omitzero" toon:"threshold,omitempty"` // How the threshold is painted: `text` = colours the cell text; `background` = colours the cell background. ThresholdDisplay string `json:"threshold_display,omitempty" toon:"threshold_display,omitempty"` - // Unit override for the column: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. + // Unit override for the column: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. Defaults to `unitless` when omitted. Unit string `json:"unit,omitempty" toon:"unit,omitempty"` // Column width in pixels, 80–1200. WidthPx *int64 `json:"width_px,omitempty" toon:"width_px,omitempty"` @@ -2862,10 +2945,10 @@ type DashboardColumnOption struct { // DashboardCreateRequest is generated from the Flashduty OpenAPI schema. type DashboardCreateRequest struct { - // Canonical UUIDv7 of the dashboard. + // Lowercase canonical UUIDv7 generated by the caller; it becomes the dashboard's permanent ID. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` Definition DashboardDefinition `json:"definition" toon:"definition"` - // Folder the dashboard is created in. Must be a folder the caller can write. + // Folder to create the dashboard in; must exist and be accessible to the `app_key` owner, otherwise `FolderNotFound`. FolderID uint64 `json:"folder_id" toon:"folder_id"` // Wire schema version; only `dashboard.v1` is accepted. SchemaVersion string `json:"schema_version" toon:"schema_version"` @@ -2878,7 +2961,7 @@ type DashboardCustomVariable struct { Kind string `json:"kind" toon:"kind"` // Optional display label; falls back to `name`. Label string `json:"label,omitempty" toon:"label,omitempty"` - // Variable name used in `{{ }}` templates, at most 64 characters. Names starting with `__` are reserved for built-in time variables. + // Variable name, unique within the definition. Queries reference it as `${name}` (or `$name` inside Prometheus and Loki expressions). Names starting with `__` are reserved for the built-in variables `__interval`, `__rate_interval`, `__range` and `__auto`. Name string `json:"name" toon:"name"` // Candidate list, 1–1000 entries. Values must be non-empty, unique and must not be `$__all`. Options []DashboardCandidate `json:"options" toon:"options"` @@ -2887,13 +2970,13 @@ type DashboardCustomVariable struct { // DashboardDataLink is generated from the Flashduty OpenAPI schema. type DashboardDataLink struct { - // Target dashboard ID. + // ID of the dashboard to open; must be a canonical UUIDv7. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` // When true the current time range is forwarded to the target. PassTime bool `json:"pass_time" toon:"pass_time"` // Optional tab, section or panel ID to focus in the target dashboard. TargetID string `json:"target_id,omitempty" toon:"target_id,omitempty"` - // Maps target variable names to a source value such as a column or a source variable. + // Values to set in the target dashboard, keyed by target variable name (must match `^[A-Za-z_][A-Za-z0-9_]{0,63}$`); each entry says where the value comes from. Send `{}` for none. VariableMappings map[string]DashboardLinkMapping `json:"variable_mappings" toon:"variable_mappings"` } @@ -2901,17 +2984,17 @@ type DashboardDataLink struct { type DashboardDatasourceRef struct { // Datasource ID. Required when `kind` is `fixed`, forbidden when `kind` is `variable`. DatasourceID uint64 `json:"datasource_id,omitempty" toon:"datasource_id,omitempty"` - // Datasource type identifier, e.g. `prometheus` or `victorialogs`. + // Datasource type identifier: lowercase letters, digits and underscores, starting with a letter. The set is open, so saving accepts any such value, but the dashboard runtime only runs `prometheus`, `mysql` and `loki` datasources; panels on other types fail when run. With `kind` = `variable` it must equal the referenced datasource variable's `datasource_type`. DatasourceType string `json:"datasource_type" toon:"datasource_type"` // `fixed` uses `datasource_id`; `variable` resolves `name` against a datasource variable. Kind string `json:"kind" toon:"kind"` - // Datasource variable name. Required when `kind` is `variable`, forbidden when `kind` is `fixed`. + // Name of a `datasource` variable in the same definition. Required when `kind` is `variable`, forbidden when `kind` is `fixed`. Name string `json:"name,omitempty" toon:"name,omitempty"` } // DashboardDatasourceVariable is generated from the Flashduty OpenAPI schema. type DashboardDatasourceVariable struct { - // Datasource type the candidates are drawn from. + // Type of datasource offered as candidates; candidates are the account's enabled datasources of this type. The set is open, so saving accepts any such value, but the dashboard runtime only runs `prometheus`, `mysql` and `loki` datasources; panels on other types fail when run. DatasourceType string `json:"datasource_type" toon:"datasource_type"` // Default datasource ID. Without a usable default the runtime picks the first candidate by name, then ID. DefaultDatasourceID uint64 `json:"default_datasource_id,omitempty" toon:"default_datasource_id,omitempty"` @@ -2919,7 +3002,7 @@ type DashboardDatasourceVariable struct { Kind string `json:"kind" toon:"kind"` // Optional display label; falls back to `name`. Label string `json:"label,omitempty" toon:"label,omitempty"` - // Variable name used in `{{ }}` templates, at most 64 characters. Names starting with `__` are reserved for built-in time variables. + // Variable name, unique within the definition. Queries reference it as `${name}` (or `$name` inside Prometheus and Loki expressions). Names starting with `__` are reserved for the built-in variables `__interval`, `__rate_interval`, `__range` and `__auto`. Name string `json:"name" toon:"name"` // Wildcard patterns narrowing the candidates; empty means every datasource of the type. NamePatterns []string `json:"name_patterns,omitempty" toon:"name_patterns,omitempty"` @@ -2932,19 +3015,19 @@ type DashboardDefinition struct { Description string `json:"description,omitempty" toon:"description,omitempty"` // Auto-refresh cadence applied by the console: `off` disables auto-refresh; `30s` = every 30 seconds; `1m` = every minute; `5m` = every 5 minutes. RefreshInterval string `json:"refresh_interval" toon:"refresh_interval"` - // Tabs, 1–10. Every tab title is unique and every tab or section ID must be a canonical UUIDv7 used only once across the definition. + // Tabs, 1–10. Every tab, section and panel `id` must be a canonical UUIDv7 used only once across the definition. Tab titles do not need to be unique. Tabs []DashboardTab `json:"tabs" toon:"tabs"` // Dashboard title, 1–189 Unicode code points after trimming. Title string `json:"title" toon:"title"` - // Dashboard variables, at most 20. Names must be unique within the definition and match the variable-name pattern. + // Dashboard variables, at most 20, with unique names. Variables may reference other variables but not in a cycle. Variables []DashboardVariable `json:"variables" toon:"variables"` } // DashboardDeleteOutput is generated from the Flashduty OpenAPI schema. type DashboardDeleteOutput struct { - // Dashboard ID. + // ID of the dashboard moved to the trash. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` - // Revision recorded for the deletion. + // Revision after the deletion; send it as `expected_revision` to restore. Revision uint64 `json:"revision" toon:"revision"` } @@ -2958,9 +3041,9 @@ type DashboardDeleteRequest struct { // DashboardDraftContext is generated from the Flashduty OpenAPI schema. type DashboardDraftContext struct { - // Required for `existing`, forbidden for `new`. + // Required for `existing`, forbidden for `new`. The caller must have access to the dashboard's folder. DashboardID string `json:"dashboard_id,omitempty" toon:"dashboard_id,omitempty"` - // Required for `new`, forbidden for `existing`. + // Required for `new`, forbidden for `existing`. Must be a folder the caller can access, otherwise the call returns `FolderNotFound` (HTTP 404). FolderID uint64 `json:"folder_id,omitempty" toon:"folder_id,omitempty"` // Draft context kind: `existing` = targets a stored dashboard (`dashboard_id` required); `new` = a folder that does not contain one yet (`folder_id` required). Kind string `json:"kind" toon:"kind"` @@ -2970,13 +3053,13 @@ type DashboardDraftContext struct { type DashboardFieldSort struct { // Sort direction: `asc` = ascending; `desc` = descending. Direction string `json:"direction" toon:"direction"` - // Field name to sort by. + // Result field name to sort by; at most 1024 Unicode code points, not `frame_index` or `field_index`. Field string `json:"field" toon:"field"` } // DashboardGaugeViz is generated from the Flashduty OpenAPI schema. type DashboardGaugeViz struct { - // Fixed decimal places; omit or send null to let the renderer decide. + // Fixed number of decimal places, 0–15; omit or send null to let the console decide. Decimals *int64 `json:"decimals,omitempty" toon:"decimals,omitempty"` // Visualization kind discriminator; always `gauge`. Kind string `json:"kind" toon:"kind"` @@ -2989,9 +3072,9 @@ type DashboardGaugeViz struct { // Reduction applied across the returned rows: `last_non_null` = most recent non-null value; `min` = minimum; `max` = maximum; `mean` = average; `sum` = sum. Reducer string `json:"reducer" toon:"reducer"` Threshold DashboardThreshold `json:"threshold,omitzero" toon:"threshold,omitempty"` - // Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. + // Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. Defaults to `unitless` when omitted. Unit string `json:"unit,omitempty" toon:"unit,omitempty"` - // Fields reduced to the gauge value. + // Result fields reduced to the gauge value; at least one, each listed once. Names are matched exactly and must not be `frame_index` or `field_index`. ValueFields []string `json:"value_fields" toon:"value_fields"` } @@ -3025,33 +3108,33 @@ type DashboardInvestigationTarget struct { // DashboardLabelFilter is generated from the Flashduty OpenAPI schema. type DashboardLabelFilter struct { - // Label name. + // Prometheus label name to match, e.g. `job`; letters, digits, `_`, `:`, `.` and `-`, starting with a letter or `_`. Label string `json:"label" toon:"label"` // Matcher operator: `=` = equals; `!=` = not equals; `=~` = regex match; `!~` = regex does-not-match. Op string `json:"op" toon:"op"` - // Matcher value; may reference other variables through `{{ }}`. + // Matcher value; may reference other variables as `${name}`. A multi-value or `all` variable needs `=~` or `!~`. Value string `json:"value" toon:"value"` } // DashboardLinkMapping is generated from the Flashduty OpenAPI schema. type DashboardLinkMapping struct { - // Source column name; required when `source` is `row_column`. + // Table column (result field) to read; required when `source` is `row_column` and forbidden otherwise. Column string `json:"column,omitempty" toon:"column,omitempty"` - // Source dashboard variable name; required when `source` is `variable`. + // Variable of the source dashboard to read; required when `source` is `variable` and must exist in the same definition; forbidden for other sources. Name string `json:"name,omitempty" toon:"name,omitempty"` - // Where the value comes from: `variable` = a dashboard variable; `row_column` = a table column (requires `column`); `category` = the bar category; `series` = the series name; `value` = the value itself. `category`, `series` and `value` are only valid for bar panels. + // Where the value comes from: `variable` = the current value of a variable of the source dashboard (requires `name`), allowed on table and bar panels; `row_column` = the clicked row's value in a table column (requires `column`), table panels only; `category` = the clicked bar's category, `series` = its series name, `value` = its value — these three are bar panels only and take no extra fields. Source string `json:"source" toon:"source"` } // DashboardListItem is generated from the Flashduty OpenAPI schema. type DashboardListItem struct { - // Dashboard ID. + // Dashboard ID; pass it to `POST /monit/dashboard/get` for the full definition. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` - // Dashboard description; empty when unset. + // Dashboard description; omitted when unset. Description string `json:"description" toon:"description"` // Folder path from the root. FolderBreadcrumb []string `json:"folder_breadcrumb" toon:"folder_breadcrumb"` - // Folder ID. + // ID of the folder the dashboard is stored in. FolderID uint64 `json:"folder_id" toon:"folder_id"` // Current revision number. Revision uint64 `json:"revision" toon:"revision"` @@ -3073,9 +3156,9 @@ type DashboardListOutput struct { // DashboardListRequest is generated from the Flashduty OpenAPI schema. type DashboardListRequest struct { ListOptions - // Folder whose dashboards are listed. + // Folder whose directly contained dashboards are listed; subfolders are not included. FolderID uint64 `json:"folder_id" toon:"folder_id"` - // Optional space-separated search words matched against title and description; at most 128 Unicode code points. + // Optional search words separated by whitespace, at most 128 Unicode code points. A dashboard matches when every word appears in its title or description. Query string `json:"query,omitempty" toon:"query,omitempty"` // Sort keys; defaults to `updated_at` descending. Sort []DashboardSort `json:"sort,omitempty" toon:"sort,omitempty"` @@ -3085,7 +3168,7 @@ type DashboardListRequest struct { type DashboardLogsVariableQuery struct { // Named query arguments; defaults to an empty object. Must be empty for a Loki datasource. Args map[string]string `json:"args" toon:"args"` - // Logs query expression; may reference other variables through `{{ }}`. May be empty for a Loki datasource, which then lists the field's values across all streams. + // Logs query expression; may reference other variables as `${name}`. Logs variable queries run only on Loki datasources, where `expr` may be empty to list the field's values across all streams. Expr string `json:"expr" toon:"expr"` // Log field whose values become candidates. For a Loki datasource it must be a bare stream label name (letters, digits and underscores). Field string `json:"field" toon:"field"` @@ -3109,7 +3192,7 @@ type DashboardMoveRequest struct { DashboardID string `json:"dashboard_id" toon:"dashboard_id"` // Revision the caller last read. The write fails with `DashboardRevisionConflict` unless it still matches the stored revision. ExpectedRevision uint64 `json:"expected_revision" toon:"expected_revision"` - // Destination folder ID. + // Destination folder ID; must exist and be accessible to the caller, otherwise `FolderNotFound`. FolderID uint64 `json:"folder_id" toon:"folder_id"` } @@ -3127,15 +3210,15 @@ type DashboardOutline struct { type DashboardOutlineFolder struct { // Folder names from the root. Breadcrumb []string `json:"breadcrumb" toon:"breadcrumb"` - // Folder ID. + // ID of the folder the dashboard is stored in. FolderID uint64 `json:"folder_id" toon:"folder_id"` } // DashboardOutlineInfo is generated from the Flashduty OpenAPI schema. type DashboardOutlineInfo struct { - // Dashboard ID. + // Dashboard ID, as passed in the request. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` - // Dashboard description; empty when unset. + // Dashboard description; omitted when unset. Description string `json:"description" toon:"description"` // Current revision number. Revision uint64 `json:"revision" toon:"revision"` @@ -3149,11 +3232,11 @@ type DashboardOutlineInfo struct { type DashboardOutlinePanel struct { // Full path of titles from the dashboard down to the panel. Breadcrumb []string `json:"breadcrumb" toon:"breadcrumb"` - // Datasource type the panel queries; empty when the panel has no datasource (text panels). + // Datasource type from the panel's `datasource_ref`, such as `prometheus`, `mysql` or `loki`; omitted for text panels, which have no datasource. The set is open: it echoes whatever type was saved. DatasourceType string `json:"datasource_type" toon:"datasource_type"` - // Panel description; empty when unset. + // Panel description; omitted when unset. Description string `json:"description" toon:"description"` - // Panel ID. + // Panel ID; use it as `panel_id` for `POST /monit/dashboard/panel/run` or as `target_id` here. ID string `json:"id" toon:"id"` // Panel title. Title string `json:"title" toon:"title"` @@ -3172,9 +3255,9 @@ type DashboardOutlineRequest struct { type DashboardOutlineSection struct { // Dashboard, tab and section titles. Breadcrumb []string `json:"breadcrumb" toon:"breadcrumb"` - // Section description; empty when unset. + // Section description; omitted when unset. Description string `json:"description" toon:"description"` - // Section ID. + // Section ID; pass it as `target_id` to narrow the outline to this section. ID string `json:"id" toon:"id"` // Panels in the section. Panels []DashboardOutlinePanel `json:"panels" toon:"panels"` @@ -3186,13 +3269,13 @@ type DashboardOutlineSection struct { type DashboardOutlineTab struct { // Dashboard title followed by the tab title. Breadcrumb []string `json:"breadcrumb" toon:"breadcrumb"` - // Tab description; empty when unset. + // Tab description; omitted when unset. Description string `json:"description" toon:"description"` - // Tab ID. + // Tab ID; pass it as `target_id` to narrow the outline to this tab. ID string `json:"id" toon:"id"` // Sections on the tab. Sections []DashboardOutlineSection `json:"sections" toon:"sections"` - // Tab title. + // Tab title as stored in the definition. Title string `json:"title" toon:"title"` // Panels placed directly on the tab. TopPanels []DashboardOutlinePanel `json:"top_panels" toon:"top_panels"` @@ -3202,7 +3285,7 @@ type DashboardOutlineTab struct { type DashboardOutlineVariable struct { // Variable kind: `datasource` = selects a datasource; `custom` = fixed inline list; `query` = resolved by running a query. Kind string `json:"kind" toon:"kind"` - // Display label; empty when unset. + // Display label; omitted when unset. Label string `json:"label" toon:"label"` // Variable name. Name string `json:"name" toon:"name"` @@ -3233,13 +3316,13 @@ type DashboardPanel struct { // DashboardPanelPreviewRequest is generated from the Flashduty OpenAPI schema. type DashboardPanelPreviewRequest struct { Context DashboardDraftContext `json:"context" toon:"context"` - // Downsampling target, 2–5000 points. + // Target maximum number of points per series for `range` queries; the server derives the query step from it. 2–5000; omit or send null for the default of 100. MaxDataPoints *int64 `json:"max_data_points,omitempty" toon:"max_data_points,omitempty"` Panel DashboardPanel `json:"panel" toon:"panel"` - // Selections keyed by variable name. - Selections map[string]DashboardSelection `json:"selections" toon:"selections"` + // Selections keyed by variable name, at most 20 entries. Variables without an entry fall back to their draft default. + Selections map[string]DashboardSelection `json:"selections,omitempty" toon:"selections,omitempty"` Time DashboardAbsoluteTimeRange `json:"time" toon:"time"` - // Draft variables the panel may reference. + // Draft variables the panel may reference, at most 20. Required; the panel's queries can only use variables listed here. Variables []DashboardVariable `json:"variables" toon:"variables"` } @@ -3247,20 +3330,20 @@ type DashboardPanelPreviewRequest struct { type DashboardPanelPreviewResponse struct { Budget DashboardPanelRunBudget `json:"budget" toon:"budget"` Display DashboardVizConfig `json:"display" toon:"display"` - // Panel ID. + // ID of the draft panel, echoing `panel.id` from the request. PanelID string `json:"panel_id" toon:"panel_id"` - // One entry per query in the panel. + // One entry per query of the panel, in the panel's query order. A query that failed to resolve appears with `state` `error`. Refs []DashboardPanelRunRef `json:"refs" toon:"refs"` - // Aggregate state of the run: `success` = all queries succeeded; `partial` = some succeeded; `incompatible` = at least one query is incompatible with its datasource; `cancelled` = the run was cancelled; `error` = all queries failed. + // Aggregate state of the run: `success` = every query succeeded; `partial` = at least one query succeeded and at least one did not; `cancelled` = no query succeeded and the client cancelled the request; `incompatible` = no query succeeded and at least one query ran but returned a result that does not fit the panel's visualization; `error` = no query succeeded and none is `incompatible` (also when the panel has no queries). RunState string `json:"run_state" toon:"run_state"` Time DashboardAbsoluteTimeRange `json:"time" toon:"time"` - // Selections that resolved successfully. + // Effective selections of the variables that resolved successfully, keyed by variable name; variables that failed to resolve are left out. Variables map[string]DashboardSelection `json:"variables" toon:"variables"` } // DashboardPanelQuery is generated from the Flashduty OpenAPI schema. type DashboardPanelQuery struct { - // Optional legend label; supports the same variable templates as `expr`. + // Optional legend label, at most 1024 Unicode code points. The console replaces `{{label}}` with that series label's value (for example `{{env}} requests`); dashboard variables are not substituted here. LegendAlias string `json:"legend_alias,omitempty" toon:"legend_alias,omitempty"` Query DashboardQuery `json:"query" toon:"query"` // Single uppercase letter (A–Z) naming the query inside its panel. @@ -3269,22 +3352,22 @@ type DashboardPanelQuery struct { // DashboardPanelRunBudget is generated from the Flashduty OpenAPI schema. type DashboardPanelRunBudget struct { - // Number of queries launched. + // Number of queries that resolved successfully and were dispatched for execution; queries that failed to resolve are not counted. ExecutionCount int64 `json:"execution_count" toon:"execution_count"` - // Concurrency cap applied to the panel's queries. + // Maximum number of the panel's queries executed at the same time; fixed at 6. MaxConcurrency int64 `json:"max_concurrency" toon:"max_concurrency"` } // DashboardPanelRunRef is generated from the Flashduty OpenAPI schema. type DashboardPanelRunRef struct { - // Request ID of the underlying datasource execution; use it when tracing a single query. + // Request ID of the underlying datasource execution; use it when tracing a single query. Absent when the query never reached the datasource. ChildRequestID string `json:"child_request_id" toon:"child_request_id"` Error DashboardRuntimeError `json:"error" toon:"error"` - // Datasource-specific execution payload, passed through unmodified. + // Datasource-specific execution result, passed through unmodified. Present when `state` is `success` or `incompatible`; absent when `state` is `error`. Execution map[string]any `json:"execution" toon:"execution"` - // Panel-local query reference. + // Query reference within the panel: a single letter `A`–`Z`, as set in the panel's `queries`. RefID string `json:"ref_id" toon:"ref_id"` - // Per-query execution state: `success` = the query executed; `error` = the query failed; `incompatible` = the datasource accepted the call but the query mode or field selection does not fit the datasource type. + // Per-query state: `success` = the query ran and `execution` is present; `error` = the query could not be resolved or executed, or the run was cancelled or timed out, and `error` explains why; `incompatible` = the query ran, but its result does not fit the panel's visualization (for example a configured field is missing or not numeric), so `execution` is still present and `error` explains the mismatch. State string `json:"state" toon:"state"` } @@ -3292,33 +3375,33 @@ type DashboardPanelRunRef struct { type DashboardPanelRunRequest struct { // Canonical UUIDv7 of the dashboard. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` - // Downsampling target, 2–5000 points; omit or send null for the server default of 100. + // Target maximum number of points per series for `range` queries; the server derives the query step from it. 2–5000; omit or send null for the default of 100. MaxDataPoints *int64 `json:"max_data_points,omitempty" toon:"max_data_points,omitempty"` - // Panel to execute. + // ID of the panel to execute. It must belong to the dashboard, otherwise the call returns `TargetNotFound` (HTTP 404). PanelID string `json:"panel_id" toon:"panel_id"` - // Revision guard; when set it must equal the current revision. + // Revision guard. When set (non-zero) it must equal the dashboard's current revision, otherwise the call fails with `DashboardRevisionConflict` (HTTP 409). Omit or send 0 to skip the check. Revision uint64 `json:"revision,omitempty" toon:"revision,omitempty"` Time DashboardAbsoluteTimeRange `json:"time" toon:"time"` - // Selections keyed by variable name, at most 20 entries. - Variables map[string]DashboardSelection `json:"variables" toon:"variables"` + // Selections keyed by variable name, at most 20 entries. Variables without an entry fall back to their stored defaults; a name the dashboard does not define fails the call with HTTP 400. + Variables map[string]DashboardSelection `json:"variables,omitempty" toon:"variables,omitempty"` } // DashboardPanelRunResponse is generated from the Flashduty OpenAPI schema. type DashboardPanelRunResponse struct { Budget DashboardPanelRunBudget `json:"budget" toon:"budget"` - // Dashboard ID. + // ID of the dashboard that was run, echoing the request. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` Display DashboardVizConfig `json:"display" toon:"display"` - // Panel ID. + // ID of the panel that was run, echoing the request. PanelID string `json:"panel_id" toon:"panel_id"` - // One entry per query in the panel. + // One entry per query of the panel, in the panel's query order. A query that failed to resolve appears with `state` `error`. Refs []DashboardPanelRunRef `json:"refs" toon:"refs"` // Revision the run executed against. Revision uint64 `json:"revision" toon:"revision"` - // Aggregate state of the run: `success` = all queries succeeded; `partial` = some succeeded; `incompatible` = at least one query is incompatible with its datasource; `cancelled` = the run was cancelled; `error` = all queries failed. + // Aggregate state of the run: `success` = every query succeeded; `partial` = at least one query succeeded and at least one did not; `cancelled` = no query succeeded and the client cancelled the request; `incompatible` = no query succeeded and at least one query ran but returned a result that does not fit the panel's visualization; `error` = no query succeeded and none is `incompatible` (also when the panel has no queries). RunState string `json:"run_state" toon:"run_state"` Time DashboardAbsoluteTimeRange `json:"time" toon:"time"` - // Selections that resolved successfully. + // Effective selections of the variables that resolved successfully, keyed by variable name; variables that failed to resolve are left out. Variables map[string]DashboardSelection `json:"variables" toon:"variables"` } @@ -3330,7 +3413,7 @@ type DashboardPrometheusVariableQuery struct { Label string `json:"label" toon:"label"` // Optional matchers narrowing the series before label values are read. LabelFilters []DashboardLabelFilter `json:"label_filters,omitempty" toon:"label_filters,omitempty"` - // Optional metric used to restrict the series considered. + // Optional metric selector that restricts the series considered; may reference other variables as `${name}` or `$name`. Metric string `json:"metric,omitempty" toon:"metric,omitempty"` } @@ -3338,39 +3421,39 @@ type DashboardPrometheusVariableQuery struct { type DashboardQueriesResolveRequest struct { // Canonical UUIDv7 of the dashboard. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` - // Downsampling target used to compute the step and render the built-in time variables, 2–5000 points; omit or send null for the server default of 100. + // Target maximum number of points per series, used to compute the step and render the built-in time variables. 2–5000; omit or send null for the default of 100. MaxDataPoints *int64 `json:"max_data_points,omitempty" toon:"max_data_points,omitempty"` // Panels to resolve, 1–100 unique IDs. A panel that does not exist yields an `error` arm rather than failing the call. PanelIDs []string `json:"panel_ids" toon:"panel_ids"` // Keep built-in time variables verbatim in the resolved expressions so a caller with its own execution window can render them; user variables are still resolved. PreserveBuiltinVariables bool `json:"preserve_builtin_variables,omitempty" toon:"preserve_builtin_variables,omitempty"` Time DashboardAbsoluteTimeRange `json:"time" toon:"time"` - // Selections keyed by variable name, at most 20 entries. - Variables map[string]DashboardSelection `json:"variables" toon:"variables"` + // Selections keyed by variable name, at most 20 entries. Variables without an entry fall back to their stored defaults; a name the dashboard does not define fails the call with HTTP 400. + Variables map[string]DashboardSelection `json:"variables,omitempty" toon:"variables,omitempty"` } // DashboardQueriesResolveResponse is generated from the Flashduty OpenAPI schema. type DashboardQueriesResolveResponse struct { - // Dashboard ID. + // ID of the dashboard the queries were resolved against, echoing the request. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` - // Per-panel results. + // One entry per requested panel, in request order. Panels []DashboardResolvedPanelQueries `json:"panels" toon:"panels"` // Revision the resolution ran against. Revision uint64 `json:"revision" toon:"revision"` Time DashboardAbsoluteTimeRange `json:"time" toon:"time"` - // Selections that resolved successfully. + // Effective selections of the variables that resolved successfully, keyed by variable name; variables that failed to resolve are left out. Variables map[string]DashboardSelection `json:"variables" toon:"variables"` } // DashboardQuery is generated from the Flashduty OpenAPI schema. type DashboardQuery struct { - // Named query arguments; defaults to an empty object. Values are passed through verbatim and must not contain `{{ }}` templates. + // Named query arguments; defaults to an empty object. In dashboard panels values may use `${name}` templates except for Loki and MySQL datasources. In drill-down entries keys and values must not contain `{{ }}` templates. Args map[string]string `json:"args" toon:"args"` - // Query expression in the target data source's language. May reference event labels through `{{ }}` templates. + // Query expression in the datasource's language. In dashboard panels it may reference variables as `${name}`, `${name:raw}` (one value inserted as is) or `${name:regex}` (values joined as a regex alternation), or as `$name` in Prometheus and Loki; write `$${...}` for a literal. Without a formatter, multi-value or `all` variables and values inside `=~`/`!~` are inserted in regex form, so they cannot be used with `=` or `!=`. MySQL queries do not support variables. In drill-down entries the expression may reference event labels through `{{ }}` templates. Expr string `json:"expr" toon:"expr"` - // Minimum step, in seconds. Only accepted when `mode` is `range`, and must be greater than zero; omit or pass null to let the server decide. + // Minimum step, in seconds; must be greater than zero. In drill-down entries it is only accepted when `mode` is `range`. Omit or pass null to let the server decide. MinStepSeconds *int64 `json:"min_step_seconds,omitempty" toon:"min_step_seconds,omitempty"` - // Evaluation mode: `instant` evaluates at a single timestamp, `range` evaluates a stepped series, `window` returns raw rows inside a time window. + // Evaluation mode: `instant` = evaluate at a single timestamp; `range` = evaluate a stepped series over the time range; `window` = return raw rows inside the time range. Dashboard panels on Prometheus and Loki accept `instant` or `range` (Loki `logs` panels need `range`); MySQL panels need `window`. Mode string `json:"mode" toon:"mode"` } @@ -3382,7 +3465,7 @@ type DashboardQueryVariable struct { Kind string `json:"kind" toon:"kind"` // Optional display label; falls back to `name`. Label string `json:"label,omitempty" toon:"label,omitempty"` - // Variable name used in `{{ }}` templates, at most 64 characters. Names starting with `__` are reserved for built-in time variables. + // Variable name, unique within the definition. Queries reference it as `${name}` (or `$name` inside Prometheus and Loki expressions). Names starting with `__` are reserved for the built-in variables `__interval`, `__rate_interval`, `__range` and `__auto`. Name string `json:"name" toon:"name"` // When the candidates are recomputed: `on_dashboard_load` = once when the dashboard loads; `on_time_range_change` = every time the time range changes. Refresh string `json:"refresh" toon:"refresh"` @@ -3401,38 +3484,38 @@ type DashboardRelativeTimeRange struct { // DashboardResolvedPanelQueries is generated from the Flashduty OpenAPI schema. type DashboardResolvedPanelQueries struct { Error DashboardRuntimeError `json:"error" toon:"error"` - // Panel ID. + // ID of the panel, echoing an entry of `panel_ids`. PanelID string `json:"panel_id" toon:"panel_id"` - // Successfully resolved queries. + // Queries that resolved successfully, in the panel's query order. Queries that failed are left out; empty array when none resolved. Queries []DashboardResolvedQuery `json:"queries" toon:"queries"` - // Aggregate state of the panel's queries: `success` = every query resolved; `partial` = some resolved; `error` = none resolved. + // Resolution state of the panel's queries: `success` = every query resolved; `partial` = some resolved and some failed; `error` = none resolved, including a panel that does not exist. State string `json:"state" toon:"state"` } // DashboardResolvedQuery is generated from the Flashduty OpenAPI schema. type DashboardResolvedQuery struct { - // Query arguments; empty object when none. + // Query arguments; an empty object when none. Only Loki queries carry arguments: `loki.limit` (a decimal integer from 1 to 1000, the maximum number of log entries) and `loki.direction` (`latest` or `earliest`). Args map[string]string `json:"args" toon:"args"` Datasource DashboardRuntimeDatasource `json:"datasource" toon:"datasource"` - // Expression with variable templates substituted. + // Expression with variable templates substituted. Built-in time variables stay verbatim when the request set `preserve_builtin_variables` to `true`. Expr string `json:"expr" toon:"expr"` - // Minimum step in seconds; null when unset. + // Minimum step in seconds from the panel query; omitted when unset. MinStepSeconds int64 `json:"min_step_seconds" toon:"min_step_seconds"` - // Evaluation mode: `range` = a stepped time series; `instant` = a single point in time; `window` = raw rows inside a bounded time window. + // Evaluation mode: `range` = a stepped time series; `instant` = a single point in time; `window` = rows inside a bounded time window. Prometheus and Loki queries use `range` or `instant`; MySQL queries use `window`. Mode string `json:"mode" toon:"mode"` - // Panel-local query reference. + // Query reference within the panel: a single letter `A`–`Z`. RefID string `json:"ref_id" toon:"ref_id"` } // DashboardResolvedVariable is generated from the Flashduty OpenAPI schema. type DashboardResolvedVariable struct { - // Resolved candidates, at most 1000. + // Selectable options, at most 1000; an empty array when there are none or resolution failed. Order: `custom` keeps the definition order, `datasource` is sorted by name then ID, `query` is sorted by value. Candidates []DashboardCandidate `json:"candidates" toon:"candidates"` Datasource DashboardRuntimeDatasource `json:"datasource" toon:"datasource"` Error DashboardRuntimeError `json:"error" toon:"error"` // Variable kind: `datasource` = selects a datasource; `custom` = fixed inline list; `query` = resolved by running a query. Kind string `json:"kind" toon:"kind"` - // Variable name. + // Variable name, as defined in the dashboard or draft. Name string `json:"name" toon:"name"` Selection DashboardSelection `json:"selection" toon:"selection"` } @@ -3462,9 +3545,9 @@ type DashboardResource struct { type DashboardRestoreRequest struct { // Canonical UUIDv7 of the dashboard. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` - // Revision the caller last read. The write fails with `DashboardRevisionConflict` unless it still matches the stored revision. + // Current revision of the trashed dashboard, as returned by the delete call or listed in the trash. The restore fails with `DashboardRevisionConflict` if it does not match. ExpectedRevision uint64 `json:"expected_revision" toon:"expected_revision"` - // Destination folder. Omit to restore to the original folder; when the original folder is no longer writable the call fails with `RestoreFolderRequired` and you must pass one. + // Destination folder. Omit or send null to restore into the original folder; if that folder no longer exists the call fails with `RestoreFolderRequired` and a destination must be passed. FolderID *uint64 `json:"folder_id,omitempty" toon:"folder_id,omitempty"` } @@ -3481,11 +3564,11 @@ type DashboardRevisionItem struct { Actor DashboardActor `json:"actor" toon:"actor"` // Unix timestamp in seconds. CreatedAt Timestamp `json:"created_at" toon:"created_at"` - // Dashboard ID. + // ID of the dashboard this revision belongs to. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` // Folder the dashboard sat in at that revision. FolderID uint64 `json:"folder_id" toon:"folder_id"` - // Optional commit message; at most 1024 Unicode code points. + // Message passed to `POST /monit/dashboard/update`; omitted when none was given and on revisions written by create, move, delete and restore. Message string `json:"message" toon:"message"` // Revision number. Revision uint64 `json:"revision" toon:"revision"` @@ -3502,12 +3585,12 @@ type DashboardRevisionResource struct { Actor DashboardActor `json:"actor" toon:"actor"` // Unix timestamp in seconds. CreatedAt Timestamp `json:"created_at" toon:"created_at"` - // Dashboard ID. + // ID of the dashboard this revision belongs to. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` Definition DashboardDefinition `json:"definition" toon:"definition"` // Folder the dashboard sat in at that revision. FolderID uint64 `json:"folder_id" toon:"folder_id"` - // Optional commit message. + // Message passed to `POST /monit/dashboard/update`; omitted when none was given. Message string `json:"message" toon:"message"` // Revision number. Revision uint64 `json:"revision" toon:"revision"` @@ -3517,19 +3600,30 @@ type DashboardRevisionResource struct { // DashboardRuntimeDatasource is generated from the Flashduty OpenAPI schema. type DashboardRuntimeDatasource struct { - // Datasource ID. + // Datasource ID, as listed by the datasource list endpoint. ID uint64 `json:"id" toon:"id"` // Datasource name. Name string `json:"name" toon:"name"` - // Datasource type identifier. + // Datasource type identifier. Resolved queries and `query` variables only use `prometheus`, `mysql` or `loki`; the datasource chosen by a `datasource` variable can be any type identifier the variable was configured with. Type string `json:"type" toon:"type"` } // DashboardRuntimeError is generated from the Flashduty OpenAPI schema. type DashboardRuntimeError struct { - // Human-readable detail for the failure. + // Human-readable detail for display or troubleshooting; its wording is not stable, so do not parse it. Message string `json:"message" toon:"message"` - // Machine-readable failure reason. Observed values include `invalid_request`, `variable_invalid`, `panel_missing`, `field_missing`, `datasource_permission_denied`, `timeout`, `panel_deadline`, `panel_canceled`, `canceled`, `overloaded`, `source_too_large`, `edge_unavailable`, `edge_upgrade_required`, `edge_version_unknown`, `mixed_edge_versions` and `internal`. + // Machine-readable failure reason. The set is open; current values: + // - `invalid_request`: the query or datasource setup is rejected (unsupported datasource type or query mode, non-empty `args` where none are allowed, a malformed argument). + // - `variable_invalid`: a variable could not be used (no selection and no default, a selection outside the candidates, an unresolved dependency, a bad substitution, or an unusable candidate list). + // - `panel_missing`: the panel is not in the dashboard (queries resolve only). + // - `datasource_permission_denied`: the datasource is missing, disabled, not accessible to the caller, or no accessible datasource matches the variable. + // - `field_missing`, `value_not_scalar`, `empty_field_name`, `duplicate_field_name`, `field_type_changed`: the result does not fit the panel's visualization, or a SQL variable query returned unusable columns. + // - `timeout`: the datasource call timed out; `panel_deadline`: the run hit the overall 35-second deadline. + // - `canceled`, `panel_canceled`: the call was cancelled. + // - `overloaded`: the datasource side is rate limiting. + // - `too_many_rows`, `result_too_large`, `source_too_large`: a row, size or candidate-count limit was exceeded. + // - `edge_unavailable`, `no_active_edge`, `edge_upgrade_required`, `edge_version_unknown`, `mixed_edge_versions`: the Edge cluster of the datasource is not connected, too old, of unknown version, or mixed. + // - `internal`: an unexpected server-side error. Reason string `json:"reason" toon:"reason"` } @@ -3537,7 +3631,7 @@ type DashboardRuntimeError struct { type DashboardSqlVariableQuery struct { // Named query arguments; defaults to an empty object. Args map[string]string `json:"args" toon:"args"` - // SQL statement; may reference other variables through `{{ }}`. + // SQL statement whose result supplies the candidates. SQL variable queries run only on MySQL datasources, and MySQL queries do not support variable references. Expr string `json:"expr" toon:"expr"` // Query kind discriminator; always `sql`, a SQL query returning one column of candidates. Kind string `json:"kind" toon:"kind"` @@ -3550,7 +3644,7 @@ type DashboardSqlVariableQuery struct { // DashboardSearchRequest is generated from the Flashduty OpenAPI schema. type DashboardSearchRequest struct { ListOptions - // Space-separated search words; at least one word and at most 128 Unicode code points. + // Search words separated by whitespace; at least one word and at most 128 Unicode code points. A dashboard matches when every word appears in its title or description. Query string `json:"query" toon:"query"` // Sort keys; defaults to `updated_at` descending. Sort []DashboardSort `json:"sort,omitempty" toon:"sort,omitempty"` @@ -3564,7 +3658,7 @@ type DashboardSection struct { Description string `json:"description,omitempty" toon:"description,omitempty"` // Canonical UUIDv7 identifying the section; unique across the definition. ID string `json:"id" toon:"id"` - // Panels in the section, at most 30. + // Panels in the section; they count toward the tab's 30-panel limit. Panels []DashboardPanel `json:"panels" toon:"panels"` // Section title. Title string `json:"title" toon:"title"` @@ -3596,7 +3690,7 @@ type DashboardSort struct { // DashboardStatViz is generated from the Flashduty OpenAPI schema. type DashboardStatViz struct { - // Fixed decimal places; omit or send null to let the renderer decide. + // Fixed number of decimal places, 0–15; omit or send null to let the console decide. Decimals *int64 `json:"decimals,omitempty" toon:"decimals,omitempty"` // Visualization kind discriminator; always `stat`. Kind string `json:"kind" toon:"kind"` @@ -3605,9 +3699,9 @@ type DashboardStatViz struct { // Reduction applied across the returned rows: `last_non_null` = most recent non-null value; `min` = minimum; `max` = maximum; `mean` = average; `sum` = sum. Reducer string `json:"reducer" toon:"reducer"` Threshold DashboardThreshold `json:"threshold,omitzero" toon:"threshold,omitempty"` - // Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. + // Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. Defaults to `unitless` when omitted. Unit string `json:"unit,omitempty" toon:"unit,omitempty"` - // Fields reduced to the displayed values. + // Result fields reduced to the displayed values; at least one, each listed once. Names are matched exactly and must not be `frame_index` or `field_index`. ValueFields []string `json:"value_fields" toon:"value_fields"` } @@ -3619,15 +3713,15 @@ type DashboardTab struct { ID string `json:"id" toon:"id"` // Sections on the tab, at most 10. Sections []DashboardSection `json:"sections" toon:"sections"` - // Tab title, 1–189 Unicode code points. Unique among tabs. + // Tab title, 1–189 Unicode code points after trimming. Title string `json:"title" toon:"title"` - // Panels placed directly on the tab, at most 30. + // Panels placed directly on the tab. A tab holds at most 30 panels in total, counting top panels and section panels, and at most 100 queries. TopPanels []DashboardPanel `json:"top_panels" toon:"top_panels"` } // DashboardTableViz is generated from the Flashduty OpenAPI schema. type DashboardTableViz struct { - // Per-column display overrides keyed by field name, at most 100 entries. + // Per-column display overrides keyed by result field name, at most 100 entries. Keys must be non-empty, at most 1024 Unicode code points and not `frame_index` or `field_index`. ColumnOptions map[string]DashboardColumnOption `json:"column_options,omitempty" toon:"column_options,omitempty"` // Visualization kind discriminator; always `table`. Kind string `json:"kind" toon:"kind"` @@ -3635,7 +3729,7 @@ type DashboardTableViz struct { LinkColumns []DashboardDataLink `json:"link_columns,omitempty" toon:"link_columns,omitempty"` // Open options object for the chosen visualization kind; the only part of the definition that round-trips losslessly. Missing or null normalizes to `{}`. Options map[string]any `json:"options" toon:"options"` - // Initial sort keys; fields must be unique. + // Initial sort keys, applied in order; each field may appear once. Sort []DashboardFieldSort `json:"sort,omitempty" toon:"sort,omitempty"` } @@ -3643,7 +3737,7 @@ type DashboardTableViz struct { type DashboardTextViz struct { // Visualization kind discriminator; always `text`. Kind string `json:"kind" toon:"kind"` - // Markdown body, at most 64 KiB. Only a restricted node set (headings, lists, tables, links, code) survives validation. + // Markdown body, at most 64 KiB. Allowed: paragraphs, headings, lists, block quotes, code blocks and spans, emphasis, tables, horizontal rules and links. Links must be `https://` URLs or site-relative paths starting with `/`. Images, raw HTML and `${` templates are rejected with `InvalidParameter`, not stripped. Markdown string `json:"markdown" toon:"markdown"` // Open options object for the chosen visualization kind; the only part of the definition that round-trips losslessly. Missing or null normalizes to `{}`. Options map[string]any `json:"options" toon:"options"` @@ -3661,31 +3755,31 @@ type DashboardThreshold struct { // DashboardTimeSeriesViz is generated from the Flashduty OpenAPI schema. type DashboardTimeSeriesViz struct { - // Fixed decimal places; omit or send null to let the renderer decide. + // Fixed number of decimal places, 0–15; omit or send null to let the console decide. Decimals *int64 `json:"decimals,omitempty" toon:"decimals,omitempty"` // Visualization kind discriminator; always `time_series`. Kind string `json:"kind" toon:"kind"` // Open options object for the chosen visualization kind; the only part of the definition that round-trips losslessly. Missing or null normalizes to `{}`. Options map[string]any `json:"options" toon:"options"` Threshold DashboardThreshold `json:"threshold,omitzero" toon:"threshold,omitempty"` - // Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. + // Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. Defaults to `unitless` when omitted. Unit string `json:"unit,omitempty" toon:"unit,omitempty"` } // DashboardTrashItem is generated from the Flashduty OpenAPI schema. type DashboardTrashItem struct { - // Dashboard ID. + // ID of the trashed dashboard; pass it to `POST /monit/dashboard/restore`. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` // Unix timestamp in seconds. DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` DeletedBy DashboardActor `json:"deleted_by" toon:"deleted_by"` - // Dashboard description; empty when unset. + // Dashboard description; omitted when unset. Description string `json:"description" toon:"description"` // Folder path from the root. FolderBreadcrumb []string `json:"folder_breadcrumb" toon:"folder_breadcrumb"` // Folder the dashboard sat in when deleted. FolderID uint64 `json:"folder_id" toon:"folder_id"` - // Revision the dashboard had when deleted. + // Current revision of the trashed dashboard (the deletion bumped it); send it as `expected_revision` to restore. Revision uint64 `json:"revision" toon:"revision"` // Dashboard title. Title string `json:"title" toon:"title"` @@ -3695,7 +3789,7 @@ type DashboardTrashItem struct { type DashboardTrashListOutput struct { // Deleted dashboards in this page. Items []DashboardTrashItem `json:"items" toon:"items"` - // Total number of deleted dashboards. + // Total number of trashed dashboards visible to the caller, across all pages. Total int64 `json:"total" toon:"total"` } @@ -3708,7 +3802,7 @@ type DashboardTrashListRequest struct { // DashboardUpdateOutput is generated from the Flashduty OpenAPI schema. type DashboardUpdateOutput struct { - // Whether the stored dashboard actually changed. + // Whether the dashboard was written and its `revision` incremented. Changed bool `json:"changed" toon:"changed"` Resource DashboardResource `json:"resource" toon:"resource"` } @@ -3729,7 +3823,7 @@ type DashboardUpdateRequest struct { // DashboardVariable is generated from the Flashduty OpenAPI schema. type DashboardVariable struct { DatasourceRef DashboardDatasourceRef `json:"datasource_ref,omitzero" toon:"datasource_ref,omitempty"` - // Datasource type the candidates are drawn from. + // Type of datasource offered as candidates; candidates are the account's enabled datasources of this type. The set is open, so saving accepts any such value, but the dashboard runtime only runs `prometheus`, `mysql` and `loki` datasources; panels on other types fail when run. DatasourceType string `json:"datasource_type,omitempty" toon:"datasource_type,omitempty"` Default DashboardSelection `json:"default,omitzero" toon:"default,omitempty"` // Default datasource ID. Without a usable default the runtime picks the first candidate by name, then ID. @@ -3738,7 +3832,7 @@ type DashboardVariable struct { Kind string `json:"kind" toon:"kind"` // Optional display label; falls back to `name`. Label string `json:"label,omitempty" toon:"label,omitempty"` - // Variable name used in `{{ }}` templates, at most 64 characters. Names starting with `__` are reserved for built-in time variables. + // Variable name, unique within the definition. Queries reference it as `${name}` (or `$name` inside Prometheus and Loki expressions). Names starting with `__` are reserved for the built-in variables `__interval`, `__rate_interval`, `__range` and `__auto`. Name string `json:"name" toon:"name"` // Wildcard patterns narrowing the candidates; empty means every datasource of the type. NamePatterns []string `json:"name_patterns,omitempty" toon:"name_patterns,omitempty"` @@ -3754,7 +3848,7 @@ type DashboardVariable struct { type DashboardVariableQuery struct { // Named query arguments; defaults to an empty object. Must be empty for a Loki datasource. Args map[string]string `json:"args,omitempty" toon:"args,omitempty"` - // Logs query expression; may reference other variables through `{{ }}`. May be empty for a Loki datasource, which then lists the field's values across all streams. + // Logs query expression; may reference other variables as `${name}`. Logs variable queries run only on Loki datasources, where `expr` may be empty to list the field's values across all streams. Expr string `json:"expr,omitempty" toon:"expr,omitempty"` // Log field whose values become candidates. For a Loki datasource it must be a bare stream label name (letters, digits and underscores). Field string `json:"field,omitempty" toon:"field,omitempty"` @@ -3764,7 +3858,7 @@ type DashboardVariableQuery struct { Label string `json:"label,omitempty" toon:"label,omitempty"` // Optional matchers narrowing the series before label values are read. LabelFilters []DashboardLabelFilter `json:"label_filters,omitempty" toon:"label_filters,omitempty"` - // Optional metric used to restrict the series considered. + // Optional metric selector that restricts the series considered; may reference other variables as `${name}` or `$name`. Metric string `json:"metric,omitempty" toon:"metric,omitempty"` // Column used as the candidate label; defaults to the value column. TextField string `json:"text_field,omitempty" toon:"text_field,omitempty"` @@ -3775,18 +3869,18 @@ type DashboardVariableQuery struct { // DashboardVariablesPreviewRequest is generated from the Flashduty OpenAPI schema. type DashboardVariablesPreviewRequest struct { Context DashboardDraftContext `json:"context" toon:"context"` - // Selections keyed by variable name, at most 20 entries. - Selections map[string]DashboardSelection `json:"selections" toon:"selections"` + // Selections keyed by variable name, at most 20 entries. Variables without an entry fall back to their draft default; a name that is not in `variables` fails the call with HTTP 400. + Selections map[string]DashboardSelection `json:"selections,omitempty" toon:"selections,omitempty"` Time DashboardAbsoluteTimeRange `json:"time" toon:"time"` - // Draft variables, at most 20. + // Draft variables, at most 20. They are validated like a stored definition (names, dependencies, option limits) and must stay within 1 MiB. Variables []DashboardVariable `json:"variables" toon:"variables"` } // DashboardVariablesPreviewResponse is generated from the Flashduty OpenAPI schema. type DashboardVariablesPreviewResponse struct { - // Effective selections keyed by variable name. + // Effective selections keyed by variable name; only variables that resolved successfully appear. Selections map[string]DashboardSelection `json:"selections" toon:"selections"` - // Resolved variables. + // Resolved variables, in the order of the draft `variables`. Variables []DashboardResolvedVariable `json:"variables" toon:"variables"` } @@ -3795,13 +3889,13 @@ type DashboardVariablesResolveRequest struct { // Canonical UUIDv7 of the dashboard. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` Time DashboardAbsoluteTimeRange `json:"time" toon:"time"` - // Selections already made, keyed by variable name, at most 20 entries. Variables omitted here fall back to their stored defaults. - Variables map[string]DashboardSelection `json:"variables" toon:"variables"` + // Selections already made, keyed by variable name, at most 20 entries. Variables without an entry fall back to their stored defaults; a name the dashboard does not define fails the call with HTTP 400. + Variables map[string]DashboardSelection `json:"variables,omitempty" toon:"variables,omitempty"` } // DashboardVariablesResolveResponse is generated from the Flashduty OpenAPI schema. type DashboardVariablesResolveResponse struct { - // Dashboard ID. + // ID of the dashboard the variables were resolved for, echoing the request. DashboardID string `json:"dashboard_id" toon:"dashboard_id"` // Revision the resolution ran against. Revision uint64 `json:"revision" toon:"revision"` @@ -3813,12 +3907,12 @@ type DashboardVariablesResolveResponse struct { // DashboardVizConfig is generated from the Flashduty OpenAPI schema. type DashboardVizConfig struct { - // Field supplying the category axis. + // Result field supplying the category axis; required, at most 1024 Unicode code points, not `frame_index` or `field_index`. CategoryField string `json:"category_field,omitempty" toon:"category_field,omitempty"` - // Per-column display overrides keyed by field name, at most 100 entries. + // Per-column display overrides keyed by result field name, at most 100 entries. Keys must be non-empty, at most 1024 Unicode code points and not `frame_index` or `field_index`. ColumnOptions map[string]DashboardColumnOption `json:"column_options,omitempty" toon:"column_options,omitempty"` DataLink DashboardDataLink `json:"data_link,omitzero" toon:"data_link,omitempty"` - // Fixed decimal places; omit or send null to let the renderer decide. + // Fixed number of decimal places, 0–15; omit or send null to let the console decide. Decimals *int64 `json:"decimals,omitempty" toon:"decimals,omitempty"` // Log fields rendered for each row. DisplayFields []string `json:"display_fields,omitempty" toon:"display_fields,omitempty"` @@ -3826,7 +3920,7 @@ type DashboardVizConfig struct { Kind string `json:"kind" toon:"kind"` // Drill-down links rendered as table columns. Together with per-column links a table allows at most 5. LinkColumns []DashboardDataLink `json:"link_columns,omitempty" toon:"link_columns,omitempty"` - // Markdown body, at most 64 KiB. Only a restricted node set (headings, lists, tables, links, code) survives validation. + // Markdown body, at most 64 KiB. Allowed: paragraphs, headings, lists, block quotes, code blocks and spans, emphasis, tables, horizontal rules and links. Links must be `https://` URLs or site-relative paths starting with `/`. Images, raw HTML and `${` templates are rejected with `InvalidParameter`, not stripped. Markdown string `json:"markdown,omitempty" toon:"markdown,omitempty"` // Scale upper bound; must exceed `min` when both are set. Max *float64 `json:"max,omitempty" toon:"max,omitempty"` @@ -3836,36 +3930,67 @@ type DashboardVizConfig struct { Options map[string]any `json:"options" toon:"options"` // Reduction applied across the returned rows: `last_non_null` = most recent non-null value; `min` = minimum; `max` = maximum; `mean` = average; `sum` = sum. Reducer string `json:"reducer,omitempty" toon:"reducer,omitempty"` - // Initial sort keys; fields must be unique. + // Initial sort keys, applied in order; each field may appear once. Sort []DashboardFieldSort `json:"sort,omitempty" toon:"sort,omitempty"` Threshold DashboardThreshold `json:"threshold,omitzero" toon:"threshold,omitempty"` - // Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. + // Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. Defaults to `unitless` when omitted. Unit string `json:"unit,omitempty" toon:"unit,omitempty"` - // Fields reduced to the gauge value. + // Result fields reduced to the gauge value; at least one, each listed once. Names are matched exactly and must not be `frame_index` or `field_index`. ValueFields []string `json:"value_fields,omitempty" toon:"value_fields,omitempty"` } // DataSourceItem is generated from the Flashduty OpenAPI schema. type DataSourceItem struct { - // Account ID. + // ID of the account that owns the datasource; always the caller's account. AccountID uint64 `json:"account_id" toon:"account_id"` - // Connection address. For Prometheus/Loki/VictoriaLogs: HTTP URL. For MySQL/Oracle/Postgres/ClickHouse: `host:port`. For SLS: endpoint without http/https prefix. Redis/MongoDB diagnostic types: one host:port, bracket IPv6; no URI, userinfo or query. Kafka: 1–32 unique comma-separated host:port bootstrap addresses; payload has no broker list. At most 4096 characters after normalization. + // Connection address as stored, after normalization. The format depends on `type_ident`; see the `address` field of the create request for each type. At most 4096 characters. Address string `json:"address" toon:"address"` // Whether alert evaluation is allowed. Alerting also requires enabled=true and an alerting-capable type. Always false for diagnostic-only types; false does not block non-alerting queries or tools. AlertingEnabled bool `json:"alerting_enabled" toon:"alerting_enabled"` + // ID of the member who created the datasource; `null` when not recorded. The creator can always manage the datasource. + CreatorID uint64 `json:"creator_id" toon:"creator_id"` // Monitors edge cluster name responsible for evaluating rules using this datasource. EdgeClusterName string `json:"edge_cluster_name" toon:"edge_cluster_name"` // Whether business execution is enabled. Disabled datasources reject business queries and tools; enabling does not change alerting_enabled. Enabled bool `json:"enabled" toon:"enabled"` - // Unique datasource ID. + // Unique datasource ID. Pass it as `id` to update, delete and info, and as `datasource_id` to tool invocation. ID uint64 `json:"id" toon:"id"` - // Datasource display name. + // ID of the managing team. Its members can edit, delete, enable or disable the datasource and view its full configuration. `null` means no managing team: any caller with the Datasources Manage permission can manage it. The creator, the account owner and Admin members can always manage. + ManageTeamID uint64 `json:"manage_team_id" toon:"manage_team_id"` + // The caller's access level on this datasource. Only present in list responses. + // - `manage`: can edit, delete, enable or disable the datasource, view its configuration and query it. + // - `readonly`: can query and reference the datasource but not change it or read its configuration. + MyPerm string `json:"my_perm" toon:"my_perm"` + // Datasource name, unique within the account across all types. Name string `json:"name" toon:"name"` - // Optional description. + // Free-text note; an empty string when not set. Note string `json:"note" toon:"note"` // Type-specific configuration block; must contain the key matching `type_ident`. Always `null` in `/monit/datasource/list` responses (the list query does not read the payload column); populated in create/update/info responses. For `tencent_cls`, `secret_key` is masked to an empty string unless it is an `${env:...}` reference. For diagnostic types, password and Kafka tls_key are omitted from responses unless they are ${env:...} references. On update, omit those fields to preserve stored secrets; explicitly send an empty string to clear. Other configuration fields retain their existing behavior. Payload any `json:"payload" toon:"payload"` - // Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。 + // IDs of the teams allowed to query and reference the datasource, in addition to the managing team, the creator, the account owner and Admin members. `null` or an empty array means every member of the account can query it. + ReadonlyTeamIDs []uint64 `json:"readonly_team_ids" toon:"readonly_team_ids"` + // Datasource type. + // + // Alerting types (can evaluate alert rules): + // - `prometheus`: Prometheus-compatible metrics. + // - `loki`: Grafana Loki logs. + // - `mysql`: MySQL. + // - `oracle`: Oracle Database. + // - `postgres`: PostgreSQL. + // - `clickhouse`: ClickHouse. + // - `elasticsearch`: Elasticsearch. + // - `sls`: Alibaba Cloud Simple Log Service. + // - `tencent_cls`: Tencent Cloud Log Service (CLS). + // - `victorialogs`: VictoriaLogs. + // + // Diagnostic-only types (cannot evaluate alerts, `alerting_enabled` is always `false`): + // - `redis_node`: a single Redis node. + // - `redis_sentinel`: Redis Sentinel. + // - `mongodb_mongod`: a MongoDB mongod instance. + // - `mongodb_mongos`: a MongoDB mongos router. + // - `kafka`: a Kafka cluster. + // + // The `payload` key that holds the type-specific settings has the same name as the type. TypeIdent string `json:"type_ident" toon:"type_ident"` // Last update timestamp, Unix epoch seconds. UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` @@ -3873,29 +3998,83 @@ type DataSourceItem struct { // DataSourceListRequest is generated from the Flashduty OpenAPI schema. type DataSourceListRequest struct { - // Datasource type identifier. Omit to return all types. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。 + // Return only the datasource whose name equals this value exactly (names are unique within the account, so at most one item). Omit or leave empty for no name filter. + Name string `json:"name,omitempty" toon:"name,omitempty"` + // Return only datasources of this type; omit or leave empty to return all types. An unrecognized value matches nothing and returns an empty array. + // + // Alerting types (can evaluate alert rules): + // - `prometheus`: Prometheus-compatible metrics. + // - `loki`: Grafana Loki logs. + // - `mysql`: MySQL. + // - `oracle`: Oracle Database. + // - `postgres`: PostgreSQL. + // - `clickhouse`: ClickHouse. + // - `elasticsearch`: Elasticsearch. + // - `sls`: Alibaba Cloud Simple Log Service. + // - `tencent_cls`: Tencent Cloud Log Service (CLS). + // - `victorialogs`: VictoriaLogs. + // + // Diagnostic-only types (cannot evaluate alerts, `alerting_enabled` is always `false`): + // - `redis_node`: a single Redis node. + // - `redis_sentinel`: Redis Sentinel. + // - `mongodb_mongod`: a MongoDB mongod instance. + // - `mongodb_mongos`: a MongoDB mongos router. + // - `kafka`: a Kafka cluster. Type string `json:"type,omitempty" toon:"type,omitempty"` } // DataSourceUpsertRequest is generated from the Flashduty OpenAPI schema. type DataSourceUpsertRequest struct { - // Connection address. Required for every type except `elasticsearch` with `deployment: cloud`. Prometheus/Loki/VictoriaLogs: HTTP URL; MySQL/Oracle/Postgres/ClickHouse: `host:port`; SLS: endpoint without the `http(s)://` prefix; `tencent_cls`: must be `cls.tencentcloudapi.com` or `cls.internal.tencentcloudapi.com` (requires Monitors edge >= v0.66.0). Redis/MongoDB diagnostic types: one host:port, bracket IPv6; no URI, userinfo or query. Kafka: 1–32 unique comma-separated host:port bootstrap addresses; payload has no broker list. At most 4096 characters after normalization. + // Connection address, required for every type except `elasticsearch` with `deployment: cloud`. At most 4096 characters after normalization. Format by type: + // - `prometheus`, `loki`, `victorialogs`: HTTP URL; `http://` is prepended when the value does not start with `http`. + // - `mysql`, `oracle`, `postgres`: `host:port`. + // - `clickhouse`: one or more comma-separated `host:port` endpoints; duplicates are rejected. + // - `elasticsearch` with `self-managed`: one or more comma-separated HTTP(S) URLs (scheme defaults to `http://`) that share identical query parameters; duplicates are rejected. Not needed for `cloud`. + // - `sls`: endpoint without the `http://` or `https://` prefix. + // - `tencent_cls`: exactly `cls.tencentcloudapi.com` or `cls.internal.tencentcloudapi.com` (requires Monitors edge >= v0.66.0). + // - `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`: a single `host:port` (bracket IPv6) with no URI, userinfo or query. + // - `kafka`: 1-32 unique comma-separated `host:port` bootstrap addresses (the payload has no broker list). Address string `json:"address,omitempty" toon:"address,omitempty"` // Whether this datasource may evaluate alerts. Omitted on create: true for alerting types, false for diagnostic-only types; omitted on update: preserve current value. null is invalid. redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka reject true. Disabling is rejected with conflict when enabled rules reference the datasource. AlertingEnabled *bool `json:"alerting_enabled,omitempty" toon:"alerting_enabled,omitempty"` - // Monitors edge cluster name responsible for evaluating rules using this datasource. + // Name of the Monitors edge cluster that evaluates rules and runs queries for this datasource. It must be an existing edge cluster of the account, otherwise the call fails with `InvalidParameter`. Changing it on update closes open alerts of rules that use this datasource. EdgeClusterName string `json:"edge_cluster_name" toon:"edge_cluster_name"` // Whether business execution is enabled. Omitted on create: true; omitted on update: preserve the current value. Explicit false disables execution; null is invalid. Does not change alerting_enabled. Enabled *bool `json:"enabled,omitempty" toon:"enabled,omitempty"` - // Datasource ID. Required for update; omit for create. + // Datasource ID. Required for update (an unknown ID, or one in another account, fails with `ResourceNotFound`); ignored on create. ID uint64 `json:"id,omitempty" toon:"id,omitempty"` - // Datasource display name. This is the name referenced as `ds_name` in query APIs. + // ID of the managing team (see the response field of the same name). On create, omitted means no managing team. On update, omitted keeps the current value, while `null` or `0` clears it. Required whenever `readonly_team_ids` is non-empty. + ManageTeamID *uint64 `json:"manage_team_id,omitempty" toon:"manage_team_id,omitempty"` + // Datasource name; required and unique within the account across all types. This is the name referenced as `ds_name` in query APIs. Duplicates fail with `InvalidParameter`. Name string `json:"name" toon:"name"` - // Optional description. + // Free-text note. On update, an omitted or empty value clears the stored note. Note string `json:"note,omitempty" toon:"note,omitempty"` - // Type-specific configuration block. Must include the key matching `type_ident`. For diagnostic types, password and Kafka tls_key are omitted from responses unless they are ${env:...} references. On update, omit those fields to preserve stored secrets; explicitly send an empty string to clear. Other configuration fields retain their existing behavior. + // Type-specific configuration block; must include the key named by `type_ident`. An update replaces the whole payload, so resend every setting you want to keep (including credentials of non-diagnostic types, which the info endpoint returns). Exceptions: for the diagnostic types, omit the password (and the Kafka `tls_key`) to keep the stored value or send an empty string to clear it; for `tencent_cls`, an omitted or empty `secret_key` keeps the stored key. Stored secrets are not carried over when `type_ident` changes. Payload DsPayload `json:"payload" toon:"payload"` - // Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。 + // IDs of the teams allowed to query and reference the datasource (see the response field of the same name). On create, omitted means unrestricted. On update, omitted keeps the current value, while `null` or an empty array clears it (everyone can query). Duplicates and `0` are dropped. Requires `manage_team_id`: a non-empty list without a managing team fails with `InvalidParameter`. + ReadonlyTeamIDs []uint64 `json:"readonly_team_ids,omitzero" toon:"readonly_team_ids,omitempty"` + // Datasource type. + // + // Alerting types (can evaluate alert rules): + // - `prometheus`: Prometheus-compatible metrics. + // - `loki`: Grafana Loki logs. + // - `mysql`: MySQL. + // - `oracle`: Oracle Database. + // - `postgres`: PostgreSQL. + // - `clickhouse`: ClickHouse. + // - `elasticsearch`: Elasticsearch. + // - `sls`: Alibaba Cloud Simple Log Service. + // - `tencent_cls`: Tencent Cloud Log Service (CLS). + // - `victorialogs`: VictoriaLogs. + // + // Diagnostic-only types (cannot evaluate alerts, `alerting_enabled` is always `false`): + // - `redis_node`: a single Redis node. + // - `redis_sentinel`: Redis Sentinel. + // - `mongodb_mongod`: a MongoDB mongod instance. + // - `mongodb_mongos`: a MongoDB mongos router. + // - `kafka`: a Kafka cluster. + // + // The `payload` key that holds the type-specific settings has the same name as the type. TypeIdent string `json:"type_ident" toon:"type_ident"` } @@ -3903,7 +4082,7 @@ type DataSourceUpsertRequest struct { type DatasourceToolInvokeRequest struct { // Optional consistency check; must equal the authenticated account. AccountID uint64 `json:"account_id,omitempty" toon:"account_id,omitempty"` - // Datasource ID from /monit/datasource/list. + // ID of the datasource to run the tool against, from `/monit/datasource/list`. The caller needs query access to it. For query tools (`.query`) the ID must not exceed 9007199254740991. DatasourceID uint64 `json:"datasource_id" toon:"datasource_id"` // Tool-specific JSON parameters; omitted means {}. Explicit null is invalid. Query tools (`.query`) use the per-datasource params schemas named in the `tool` description. Params json.RawMessage `json:"params,omitempty" toon:"params,omitempty"` @@ -3926,7 +4105,7 @@ type DatasourceToolResult struct { // DatasourceToolTruncation is generated from the Flashduty OpenAPI schema. type DatasourceToolTruncation struct { - // Why the result was truncated. Presence of this object indicates truncation. + // Why the result was truncated, as reported by the executing Edge; treat it as an opaque string. The object is present only when the result was truncated. Reason string `json:"reason" toon:"reason"` } @@ -3950,7 +4129,7 @@ type DeletePostMortemRequest struct { // DeletePostMortemTemplateRequest is generated from the Flashduty OpenAPI schema. type DeletePostMortemTemplateRequest struct { - // Template ID; obtain it from `POST /incident/post-mortem/template/list`. + // ID of the custom template to delete; obtain it from `POST /incident/post-mortem/template/list`. TemplateID string `json:"template_id" toon:"template_id"` } @@ -4006,15 +4185,19 @@ type DeleteStatusPageTemplateRequest struct { // DeleteWarRoomRequest is generated from the Flashduty OpenAPI schema. type DeleteWarRoomRequest struct { + // Chat ID of the war room to unlink, from `POST /incident/war-room/list`. Required when `unlink_only` is `true` and must match the current war room; ignored otherwise. + ChatID string `json:"chat_id,omitempty" toon:"chat_id,omitempty"` // Incident ID (MongoDB ObjectID). IncidentID string `json:"incident_id" toon:"incident_id"` // IM integration ID; obtain it from `POST /datasource/im/war-room-enabled/list`. IntegrationID int64 `json:"integration_id" toon:"integration_id"` + // When true, only remove the link between the incident and the war room without dissolving the group. Allowed only for account owners and admins, only when the IM integration is disabled or deleted, and requires `chat_id`. + UnlinkOnly bool `json:"unlink_only,omitempty" toon:"unlink_only,omitempty"` } // DeleteWorkItemRequest is generated from the Flashduty OpenAPI schema. type DeleteWorkItemRequest struct { - // Current item version for optimistic locking. Must match the stored version. + // The item's current `version` (≥ 1) for optimistic locking. Version int64 `json:"version" toon:"version"` // Work item ID (opaque string, max 128 characters). WorkItemID string `json:"work_item_id" toon:"work_item_id"` @@ -4040,7 +4223,7 @@ type DimensionInsightItem struct { ResponderID int64 `json:"responder_id" toon:"responder_id"` // Responder name, returned when aggregating by responder; omitted when the name cannot be resolved. ResponderName string `json:"responder_name" toon:"responder_name"` - // Team ID, returned only when aggregating by team (`/insight/team`). + // Team ID, returned only by `/insight/team`. Omitted on the row that aggregates incidents without a team. TeamID int64 `json:"team_id" toon:"team_id"` // Team name, returned when aggregating by team; omitted when the name cannot be resolved (e.g. team deleted). TeamName string `json:"team_name" toon:"team_name"` @@ -4078,13 +4261,13 @@ type DimensionInsightItem struct { TotalSecondsToAck int64 `json:"total_seconds_to_ack" toon:"total_seconds_to_ack"` // Total time to close in seconds. TotalSecondsToClose int64 `json:"total_seconds_to_close" toon:"total_seconds_to_close"` - // Start of the aggregation bucket, Unix epoch seconds. Equals `start_time` when no `aggregate_unit` is given. + // Start of the time bucket, Unix seconds. Equals `start_time` when `aggregate_unit` is not set. TS Timestamp `json:"ts" toon:"ts"` } // DimensionInsightResponse is generated from the Flashduty OpenAPI schema. type DimensionInsightResponse struct { - // Insight metric rows aggregated by the endpoint's dimension (account/team/channel); further split by hour bucket or time bucket when `split_hours` or `aggregate_unit` is enabled. + // Metric rows, newest bucket first. Buckets or dimension values without incidents produce no row; an empty array means no incidents matched. Items []DimensionInsightItem `json:"items" toon:"items"` } @@ -4104,7 +4287,7 @@ type DoIncidentCustomActionRequest struct { // DoIncidentCustomActionResponse is generated from the Flashduty OpenAPI schema. type DoIncidentCustomActionResponse struct { - // Error message if the action's HTTP call failed; omitted on success. + // Error returned by the HTTP request to the action's URL (for example, a timeout after 2 seconds). Message string `json:"message" toon:"message"` } @@ -4119,21 +4302,23 @@ type EmptyResponse struct{} // EnabledTime is generated from the Flashduty OpenAPI schema. type EnabledTime struct { - // Days of week, 0 = Sunday. + // Days of week the window applies to, `0` = Sunday through `6` = Saturday; non-empty, no duplicates. Days []int64 `json:"days,omitempty" toon:"days,omitempty"` - // End time, e.g. `18:00`. + // End time in 24-hour `HH:MM` format, e.g. `18:00`. Etime string `json:"etime,omitempty" toon:"etime,omitempty"` - // Start time, e.g. `09:00`. + // Start time in 24-hour `HH:MM` format, e.g. `09:00`. Stime string `json:"stime,omitempty" toon:"stime,omitempty"` } // EnrichFilter is generated from the Flashduty OpenAPI schema. type EnrichFilter struct { - // Event key to match on (e.g. `labels.severity`, `title`). Must be non-empty. + // Event key to match on: `title`, `description`, `labels.` or another alert/change event key. A `labels.` key must use a valid label name. Key string `json:"key" toon:"key"` - // Match operator. `IN` matches when any value matches; `NOTIN` matches when none of the values match. + // Match operator. + // - `IN`: matches when the key's value matches any of `vals`. A key missing from the event never matches. + // - `NOTIN`: matches when the value matches none of `vals`. A key missing from the event always matches. Oper string `json:"oper" toon:"oper"` - // Values to match against. Must contain at least one value. + // Values to match (at least one). Each value is one of: an exact string; `/regex/` for a regular expression; a wildcard pattern with `*` and `?`; `cidr:` (e.g. `cidr:203.0.113.0/24`) for an IP range; `num:lt:`, `num:le:`, `num:gt:` or `num:ge:` for a numeric comparison. Vals []string `json:"vals" toon:"vals"` } @@ -4167,9 +4352,9 @@ type EnrichmentItem struct { CreatorID int64 `json:"creator_id" toon:"creator_id"` // Deletion time, Unix seconds. Omitted when the rule set is not deleted; read endpoints never return soft-deleted rule sets, so this is effectively always omitted. DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` - // Integration ID. + // ID of the integration this rule set belongs to; one integration has at most one rule set. IntegrationID int64 `json:"integration_id" toon:"integration_id"` - // Ordered enrichment rules. + // Rules in execution order; each rule sees the labels written by the rules before it. Rules []EnrichRule `json:"rules" toon:"rules"` // Rule set status: `enabled` (active) or `deleted` (soft-deleted). Read endpoints exclude soft-deleted rule sets, so responses always carry `enabled`. Status string `json:"status" toon:"status"` @@ -4195,7 +4380,7 @@ type EnrichmentListResponse struct { type EnrichmentUpsertRequest struct { // Integration ID to configure enrichment rules for. IntegrationID int64 `json:"integration_id" toon:"integration_id"` - // Ordered list of enrichment rules. Replaces all existing rules. + // Ordered rule list that replaces the integration's whole rule set; send `[]` to remove all rules. Rules run in this order. Rules []EnrichRule `json:"rules" toon:"rules"` } @@ -4207,13 +4392,28 @@ type EnvironmentBinding struct { Kind string `json:"kind" toon:"kind"` // Human-readable environment name; empty for cloud bindings using the default allowlist. Name string `json:"name" toon:"name"` - // Live binding health, namespaced by kind: BYOC uses online/pending/offline/deleted; cloud uses available/rebuilding/expired. + // Live health of the binding. Omitted when unknown. + // + // For `byoc`: + // - `online`: runner connected and ready + // - `degraded`: runner connected but its executor is unhealthy; messages are still accepted + // - `pending`: runner has never connected + // - `offline`: runner heartbeat lost; messages cannot be served + // - `deleted`: the environment no longer exists; choose another + // + // For `cloud`: + // - `available`: the sandbox can serve the next message (paused or starting sandboxes resume automatically) + // - `rebuilding`: the sandbox is being resumed or recreated + // - `expired`: the sandbox failed permanently and cannot recover by itself + // - `deleted`: the selected cloud environment template was deleted Status string `json:"status" toon:"status"` + // Team that owns the bound environment; 0 for account-scope environments. + TeamID int64 `json:"team_id" toon:"team_id"` } // ErsComposition is generated from the Flashduty OpenAPI schema. type ErsComposition struct { - // When `true`, overwrite the label if it already exists. Defaults to `false`. + // When `false` (default) the rule is skipped if `result_label` already exists on the event; when `true` the existing value is overwritten. Override bool `json:"override,omitempty" toon:"override,omitempty"` // Destination label key the composed value is written to. Must match `^[a-zA-Z_][a-zA-Z0-9_]*$`. ResultLabel string `json:"result_label" toon:"result_label"` @@ -4223,17 +4423,17 @@ type ErsComposition struct { // ErsDrop is generated from the Flashduty OpenAPI schema. type ErsDrop struct { - // List of label keys to remove from the alert. + // Label names to remove from the event (at least one), given without the `labels.` prefix. DropLabels []string `json:"drop_labels" toon:"drop_labels"` } // ErsExtraction is generated from the Flashduty OpenAPI schema. type ErsExtraction struct { - // GJson path expression used to extract a value from a JSON-encoded field. Mutually exclusive with `pattern`. + // GJSON path (a leading `$.` is ignored) used when the source value is a JSON string, e.g. `host.name`. If the source value is not valid JSON the rule is skipped; if the path does not exist an empty string is written. Exactly one of `pattern` and `g_json` must be set. GJSON string `json:"g_json,omitempty" toon:"g_json,omitempty"` - // When `true`, overwrite the label if it already exists. Defaults to `false`. + // When `false` (default) the rule is skipped if `result_label` already exists on the event; when `true` the existing value is overwritten. Override bool `json:"override,omitempty" toon:"override,omitempty"` - // RE2 regular expression applied to the source value. Must contain at least one capture group; the captured groups are joined with a space and written to `result_label`. Mutually exclusive with `g_json`. + // Regular expression (RE2) applied to the source value; may be wrapped in `/.../`. All capture groups are joined with a space and written to `result_label`. Nothing is written when the expression does not match, has no capture group, or the first group is empty. Exactly one of `pattern` and `g_json` must be set. Pattern string `json:"pattern,omitempty" toon:"pattern,omitempty"` // Destination label key the extracted value is written to. Must match `^[a-zA-Z_][a-zA-Z0-9_]*$`. ResultLabel string `json:"result_label" toon:"result_label"` @@ -4245,11 +4445,13 @@ type ErsExtraction struct { type ErsMapping struct { // Mapping API ID (MongoDB ObjectID hex). Required when `mapping_type` is `api`. APIID string `json:"api_id,omitempty" toon:"api_id,omitempty"` - // Mapping source type. `schema` uses a mapping schema table; `api` calls an external HTTP API. + // Lookup source. + // - `schema` (default): look up a row in the mapping schema `schema_id` using the event's values of the schema's `source_labels`; the rule does nothing if any source label is missing or no row matches. + // - `api`: call the mapping API `api_id` with the event; runs for alert events only. MappingType string `json:"mapping_type,omitempty" toon:"mapping_type,omitempty"` - // When `true`, overwrite labels that already exist. Defaults to `false`. + // When `false` (default) the rule is skipped if every label in `result_labels` already exists, and otherwise only the missing labels are filled. When `true` all `result_labels` are overwritten with the lookup result. Override bool `json:"override,omitempty" toon:"override,omitempty"` - // Label keys to populate from the mapping lookup result. Each must match `^[a-zA-Z_][a-zA-Z0-9_]*$`. + // Label keys to fill from the lookup result (at least one). For `schema` they are normally the schema's `result_labels`; for `api` they are sent to the API as `result_label_keys`. ResultLabels []string `json:"result_labels" toon:"result_labels"` // Mapping schema ID (MongoDB ObjectID hex). Required when `mapping_type` is `schema`. SchemaID string `json:"schema_id,omitempty" toon:"schema_id,omitempty"` @@ -4257,13 +4459,13 @@ type ErsMapping struct { // EscalateLayer is generated from the Flashduty OpenAPI schema. type EscalateLayer struct { - // Wait before moving to the next level, in minutes. + // Minutes to wait after this level's first notification before escalating to the next level, 0–720. Ignored on the last level. EscalateWindow int64 `json:"escalate_window,omitempty" toon:"escalate_window,omitempty"` - // When true, always escalate regardless of acknowledgement. + // When true, escalate even after the incident has been acknowledged (`Processing`). When false, escalation stops once the incident is acknowledged. Closed or snoozed incidents never escalate. ForceEscalate bool `json:"force_escalate,omitempty" toon:"force_escalate,omitempty"` - // Max repeat notifications within the level. + // Total notifications sent in this level, including the first, 0–6; `0` and `1` both notify once. MaxTimes int64 `json:"max_times,omitempty" toon:"max_times,omitempty"` - // Repeat interval in minutes. + // Minutes between repeat notifications in this level, 0.5–120, kept to one decimal place. Used only when `max_times` is greater than 1. NotifyStep float64 `json:"notify_step,omitempty" toon:"notify_step,omitempty"` Target EscalateTarget `json:"target" toon:"target"` } @@ -4272,33 +4474,31 @@ type EscalateLayer struct { type EscalateRuleItem struct { // Owning account ID. AccountID int64 `json:"account_id" toon:"account_id"` - // Delay window in seconds. + // Delay in seconds, 0–3600, before the first notification for a newly assigned incident is sent; `0` notifies immediately. AggrWindow int64 `json:"aggr_window" toon:"aggr_window"` // Channel the rule belongs to. ChannelID int64 `json:"channel_id" toon:"channel_id"` - // Channel name, populated for cross-channel listing responses. - ChannelName string `json:"channel_name" toon:"channel_name"` // Creation time, Unix timestamp in seconds. CreatedAt Timestamp `json:"created_at" toon:"created_at"` // Deletion time, Unix timestamp in seconds. Omitted unless the rule is soft-deleted; deleted rules are excluded from list responses. DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` // Rule description. Description string `json:"description" toon:"description"` - // Incident-level match conditions (OR-of-AND tree): the rule is matched against the incident the alert was grouped into, not against the alert itself. Omit or leave empty to apply the rule to all incidents in the channel. + // Incident conditions (OR of AND groups), matched against the incident the alert was grouped into. Empty means the rule matches every incident in the channel. Filters FilterGroup `json:"filters" toon:"filters"` // Escalation levels in order. Layers []EscalateLayer `json:"layers" toon:"layers"` - // Evaluation priority. Lower runs first. + // Evaluation order from `0` to `200`: lower values are evaluated first, ties broken by creation time. The first enabled rule whose time windows and filters match a new incident takes it. Priority int64 `json:"priority" toon:"priority"` // Escalation rule ID (MongoDB ObjectID). RuleID string `json:"rule_id" toon:"rule_id"` - // Rule name. + // Rule name, 1–39 characters. RuleName string `json:"rule_name" toon:"rule_name"` // Rule status: `enabled` means active, `disabled` means paused, `deleted` is soft-deleted (possible only from the detail endpoint; lists never return deleted rules). Status string `json:"status" toon:"status"` - // Notification template ID (MongoDB ObjectID). + // Notification template ID (24-character hex); see `POST /template/list`. TemplateID string `json:"template_id" toon:"template_id"` - // Recurring time windows during which the rule applies. + // Recurring time windows during which the rule can match; empty means at any time. TimeFilters []TimeFilter `json:"time_filters" toon:"time_filters"` // Last update time, Unix timestamp in seconds. UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` @@ -4308,25 +4508,25 @@ type EscalateRuleItem struct { // EscalateTarget is generated from the Flashduty OpenAPI schema. type EscalateTarget struct { - // Per-severity personal notification channels. Required unless `webhooks` is provided. - By EscalateTargetBy `json:"by,omitzero" toon:"by,omitempty"` - // Email addresses to notify (push-only scenarios). + // Personal notification channels for the people in this target, per incident severity. Required unless `webhooks` is set; returned as `null` when not set. + By *EscalateTargetBy `json:"by,omitempty" toon:"by,omitempty"` + // Email addresses of account members; each address is resolved to the member who owns it when the level fires. Emails []string `json:"emails,omitempty" toon:"emails,omitempty"` - // Member IDs to notify directly. + // Member IDs to notify directly; obtain them from `POST /member/list`. Every ID must exist. PersonIDs []int64 `json:"person_ids,omitempty" toon:"person_ids,omitempty"` - // Map of schedule ID to the role IDs on that schedule to notify. + // Notify whoever is on call: keys are schedule IDs (from `POST /schedule/list`) written as strings, values are the role IDs on that schedule. Each value must be non-empty. ScheduleToRoleIDs map[string][]int64 `json:"schedule_to_role_ids,omitempty" toon:"schedule_to_role_ids,omitempty"` - // Team IDs to notify. + // Team IDs whose members are notified; obtain them from `POST /team/list`. Each team must have at least one member. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` - // Group chat / webhook targets. Required unless `by` is provided. + // Group chats to notify through robots or IM apps. Required unless `by` is set; returned as `null` when not set. Webhooks []EscalateTargetWebhooksItem `json:"webhooks,omitempty" toon:"webhooks,omitempty"` } // EventGroup is generated from the Flashduty OpenAPI schema. type EventGroup struct { - // When true, repeated events merge into the existing alert; when false, every event creates a separate alert. Defaults to true. + // 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. IsEnabled bool `json:"is_enabled,omitempty" toon:"is_enabled,omitempty"` - // Merge window in minutes, 1-1440 (24 h); accounts with the extended limit may use up to 10080 (7 days). Defaults to 1440. + // 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. TimeWindow int64 `json:"time_window,omitempty" toon:"time_window,omitempty"` } @@ -4342,16 +4542,24 @@ type EventItem struct { Content map[string]any `json:"content" toon:"content"` // Unix timestamp in milliseconds when the event was written. CreatedAt TimestampMilli `json:"created_at" toon:"created_at"` + // Delivery mode negotiated for the IM request that produced this event. `reply_only`: the IM client shows only explicit replies, not the agent's final text. Omitted for normal delivery. + DeliveryMode string `json:"delivery_mode" toon:"delivery_mode"` // Error code when the event represents a failure. ErrorCode string `json:"error_code" toon:"error_code"` // Human-readable error message, when present. ErrorMessage string `json:"error_message" toon:"error_message"` // Event identifier. EventID string `json:"event_id" toon:"event_id"` - // ADK invocation id grouping a turn. + // ID of the invocation (one agent turn) that wrote this event. Omitted when empty. InvocationID string `json:"invocation_id" toon:"invocation_id"` + // True when this is an assistant event recording a runtime failure whose message is safe to show to users. Omitted when false. + IsError bool `json:"is_error" toon:"is_error"` // True for a streaming partial chunk. Partial bool `json:"partial" toon:"partial"` + // Member ID of the person who sent this user message. Omitted on assistant and tool events and when no member is recorded (automation runs, some IM turns). + PersonID int64 `json:"person_id" toon:"person_id"` + // Invocation ID of the top-level user turn this event belongs to, linking events written by nested subagent invocations back to it. Omitted when empty. + RootInvocationID string `json:"root_invocation_id" toon:"root_invocation_id"` // Owning session id. SessionID string `json:"session_id" toon:"session_id"` // Event status. One of: `normal` (a live event included in the context fed to the model), `compressed` (folded into a compaction summary boundary event; no longer loaded for the model, kept as history only). @@ -4386,7 +4594,7 @@ type ExploreField struct { type ExploreFrame struct { // Columns of the frame. Fields []ExploreField `json:"fields" toon:"fields"` - // Frame shape. `table` is an unlabeled table, while `time_series` carries exactly one time field and one float field. + // Frame shape. `table` is an unlabeled table. `time_series` carries exactly one time field and one float field; its time values are strictly increasing and never null. Kind string `json:"kind" toon:"kind"` } @@ -4408,11 +4616,11 @@ type ExploreResponseExecution struct { // ExploreResult is generated from the Flashduty OpenAPI schema. type ExploreResult struct { - // Entry limit applied to a logs result; at most 1000. + // Entry limit applied to a logs result: 1 to 1000 (1 to 100 for `sls` data sources). Present only when `kind` is `logs`. AppliedLimit int64 `json:"applied_limit" toon:"applied_limit"` // Log entries. Present when `kind` is `logs`; never longer than `applied_limit`. Entries []ExploreLogEntry `json:"entries" toon:"entries"` - // Columnar frames. Present when `kind` is `frames`; at most 1,000 frames. + // Columnar frames. Present when `kind` is `frames`; at most 1,000 frames, 1,000 table rows in total, and 100,000 values in total. Frames []ExploreFrame `json:"frames" toon:"frames"` // Whether a logs result was truncated by `applied_limit`. HasMore bool `json:"has_more" toon:"has_more"` @@ -4442,7 +4650,7 @@ type ExportStatusPageSubscribersRequest struct { type ExportedStatusPageSubscriberItem struct { // Whether the subscriber is subscribed to all components. All bool `json:"all" toon:"all"` - // Components this subscriber has subscribed to. + // Components the subscriber follows; each item carries only `component_id` and `name`. Empty when `all` is `true`. Components []StatusPageComponentItem `json:"components" toon:"components"` // Preferred locale for notifications. Omitted when empty. Locale string `json:"locale" toon:"locale"` @@ -4537,7 +4745,7 @@ type FeedDetailIncidentAck struct { Comment string `json:"comment" toon:"comment"` // Images from the acknowledgement form, recorded on the timeline entry only. Omitted when none were submitted. Images []Image `json:"images" toon:"images"` - // Progress note entered at acknowledgement. + // `Processing` when this acknowledgement moved the incident from `Triggered` to `Processing`; omitted when the incident was already `Processing`. Progress string `json:"progress" toon:"progress"` } @@ -4549,17 +4757,19 @@ type FeedDetailIncidentAddRspd struct { // FeedDetailIncidentAssign is generated from the Flashduty OpenAPI schema. type FeedDetailIncidentAssign struct { - // Unix timestamp (seconds) when the assignment was made. + // Unix timestamp (seconds) when the assignment was made; set by the server. AssignedAt Timestamp `json:"assigned_at" toon:"assigned_at"` - // Email recipients, used by integrations such as ServiceNow. + // Member IDs that actually received the assignment: `person_ids` plus the members of the selected escalation level, deduplicated and sorted. Set by the server; omitted when empty. + EffectivePersonIDs []int64 `json:"effective_person_ids" toon:"effective_person_ids"` + // Member emails; each is resolved to a member ID and merged into `person_ids`. Emails without a matching member are ignored. Emails []string `json:"emails" toon:"emails"` // Escalation rule ID (MongoDB ObjectID) to drive assignment. EscalateRuleID string `json:"escalate_rule_id" toon:"escalate_rule_id"` - // Escalation rule display name, filled by the server. + // Escalation rule name, filled by the server in responses; ignored in requests. EscalateRuleName string `json:"escalate_rule_name" toon:"escalate_rule_name"` - // Opaque assignment ID generated by the server. + // Assignment ID generated by the server for each assignment; set by the server. ID string `json:"id" toon:"id"` - // Current level index within the escalation rule. + // Zero-based escalation level within `escalate_rule_id` (`0` = first level). Responders are taken from this level. LayerIdx int64 `json:"layer_idx" toon:"layer_idx"` // Override the notification channels used for this assignment. Notify FeedDetailIncidentAssignNotify `json:"notify" toon:"notify"` @@ -4567,7 +4777,7 @@ type FeedDetailIncidentAssign struct { PersonIDs []int64 `json:"person_ids" toon:"person_ids"` // Member IDs that received the assignment. To []int64 `json:"to" toon:"to"` - // Assignment type: `assign` direct assignment, `reassign` reassignment, `escalate` escalation-rule driven, `reopen` automatic reassignment on reopen. + // How the assignment happened: `assign` first assignment; `reassign` reassignment of an already assigned incident; `escalate` moved by the escalation flow; `reopen` reassignment after the incident was reopened; empty string in responses when the incident was never assigned. Omit it in requests and the server derives it. Type string `json:"type" toon:"type"` } @@ -4577,7 +4787,8 @@ type FeedDetailIncidentAutoRefreshCard struct{} // FeedDetailIncidentComment is generated from the Flashduty OpenAPI schema. type FeedDetailIncidentComment struct { // Comment body. - Comment string `json:"comment" toon:"comment"` + Comment string `json:"comment" toon:"comment"` + // Name and color of the attached comment type, resolved at read time; omitted when no comment type is attached or it no longer exists. CommentType IncidentCommentTypeDisplay `json:"comment_type" toon:"comment_type"` // ObjectID of the account-level comment type attached to the comment. CommentTypeID string `json:"comment_type_id" toon:"comment_type_id"` @@ -4597,16 +4808,17 @@ type FeedDetailIncidentCustomAction struct { type FeedDetailIncidentMerge struct { // Merge comment. Comment string `json:"comment" toon:"comment"` - // Member ID that performed the merge. + // Not set by incident merges, which never change the owner; present only on older entries. OwnerID int64 `json:"owner_id" toon:"owner_id"` - // True if the source incidents were removed after merging. + // `true` when the source incidents were permanently deleted after the merge. RemoveSourceIncidents bool `json:"remove_source_incidents" toon:"remove_source_incidents"` - // Source incidents that were merged. + // Incidents merged into the target; present on the target incident's entry. SourceIncidents []IncidentShort `json:"source_incidents" toon:"source_incidents"` - // Responder member IDs carried over from the source incidents. - SourceResponders []int64 `json:"source_responders" toon:"source_responders"` - TargetIncident IncidentShort `json:"target_incident" toon:"target_incident"` - // Resulting incident title. + // Member IDs that were responders on the source incidents, for reference; they are not added to the target's responders. + SourceResponders []int64 `json:"source_responders" toon:"source_responders"` + // Incident this incident was merged into; present on each source incident's entry. + TargetIncident IncidentShort `json:"target_incident" toon:"target_incident"` + // New title the merge set on the target incident; present only on the target's entry and only when the title changed. Title string `json:"title" toon:"title"` } @@ -4626,8 +4838,9 @@ type FeedDetailIncidentMuteReply struct{} // FeedDetailIncidentNew is generated from the Flashduty OpenAPI schema. type FeedDetailIncidentNew struct { // Email of the reporter when the incident was created externally. - ReporterEmail string `json:"reporter_email" toon:"reporter_email"` - Severity FeedSeverity `json:"severity" toon:"severity"` + ReporterEmail string `json:"reporter_email" toon:"reporter_email"` + // Severity of the incident when it was created. + Severity FeedSeverity `json:"severity" toon:"severity"` // Initial incident title. Title string `json:"title" toon:"title"` } @@ -4658,7 +4871,7 @@ type FeedDetailIncidentNotify struct { // FeedDetailIncidentReopen is generated from the Flashduty OpenAPI schema. type FeedDetailIncidentReopen struct { - // Reason why the incident was reopened. + // Free-text reason passed as `reason` to `POST /incident/reopen`; omitted when none was given. Reason string `json:"reason" toon:"reason"` } @@ -4684,15 +4897,17 @@ type FeedDetailIncidentResetRootCause struct{} // FeedDetailIncidentResetSeverity is generated from the Flashduty OpenAPI schema. type FeedDetailIncidentResetSeverity struct { + // Severity before the change. From FeedSeverity `json:"from" toon:"from"` - To FeedSeverity `json:"to" toon:"to"` + // Severity after the change. + To FeedSeverity `json:"to" toon:"to"` } // FeedDetailIncidentResetTitle is generated from the Flashduty OpenAPI schema. type FeedDetailIncidentResetTitle struct { - // Previous title. + // Title before the change. From string `json:"from" toon:"from"` - // New title. + // Title after the change. To string `json:"to" toon:"to"` } @@ -4730,13 +4945,13 @@ type FeedDetailIncidentStorm struct { // FeedDetailIncidentUnack is generated from the Flashduty OpenAPI schema. type FeedDetailIncidentUnack struct { - // Progress note entered when acknowledgement was removed. + // `Triggered` when removing this acknowledgement returned the incident to `Triggered` (no responder still acknowledged); omitted otherwise. Progress string `json:"progress" toon:"progress"` } // FeedDetailIncidentWake is generated from the Flashduty OpenAPI schema. type FeedDetailIncidentWake struct { - // Unix timestamp at which the prior snooze was scheduled to end. + // Unix timestamp (seconds) at which the cancelled snooze would have ended. SnoozedBefore Timestamp `json:"snoozedBefore" toon:"snoozedBefore"` } @@ -4750,7 +4965,7 @@ type FeedDetailIncidentWarRoomCreate struct { IntegrationID int64 `json:"integration_id" toon:"integration_id"` // Integration display name. IntegrationName string `json:"integration_name" toon:"integration_name"` - // Chat integration plugin type. + // Plugin type of the IM integration: `feishu_app` (Feishu), `dingtalk_app` (DingTalk), `wecom_app` (WeCom), or `slack_app` (Slack). PluginType string `json:"plugin_type" toon:"plugin_type"` // Shareable join link for the war room. ShareLink string `json:"share_link" toon:"share_link"` @@ -4766,8 +4981,10 @@ type FeedDetailIncidentWarRoomDelete struct { IntegrationID int64 `json:"integration_id" toon:"integration_id"` // Integration display name. IntegrationName string `json:"integration_name" toon:"integration_name"` - // Chat integration plugin type. + // Plugin type of the IM integration: `feishu_app` (Feishu), `dingtalk_app` (DingTalk), `wecom_app` (WeCom), or `slack_app` (Slack). PluginType string `json:"plugin_type" toon:"plugin_type"` + // `true` when the war room was only unlinked from the incident (`unlink_only` request) and the group was not dissolved. Omitted otherwise. + UnlinkOnly bool `json:"unlink_only" toon:"unlink_only"` } // FeedDetailWorkItemAssigneesChanged is generated from the Flashduty OpenAPI schema. @@ -4788,7 +5005,7 @@ type FeedDetailWorkItemAssigneesChanged struct { RemovedAssignees []WorkItemAssignee `json:"removed_assignees" toon:"removed_assignees"` // Work item title. Title string `json:"title" toon:"title"` - // Work item ID. + // Work item ID (`wi_` followed by a random string); use it with the `/incident/work-item/*` endpoints. WorkItemID string `json:"work_item_id" toon:"work_item_id"` } @@ -4800,13 +5017,13 @@ type FeedDetailWorkItemBound struct { PostMortemID string `json:"post_mortem_id" toon:"post_mortem_id"` // Work item title. Title string `json:"title" toon:"title"` - // Work item ID. + // Work item ID (`wi_` followed by a random string); use it with the `/incident/work-item/*` endpoints. WorkItemID string `json:"work_item_id" toon:"work_item_id"` } // FeedDetailWorkItemCompleted is generated from the Flashduty OpenAPI schema. type FeedDetailWorkItemCompleted struct { - // Status label before completion. + // Status before completion, usually `open` or `in_progress`; items created before these statuses existed may carry other text. FromStatus string `json:"from_status" toon:"from_status"` // Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem. ItemType string `json:"item_type" toon:"item_type"` @@ -4814,9 +5031,9 @@ type FeedDetailWorkItemCompleted struct { PostMortemID string `json:"post_mortem_id" toon:"post_mortem_id"` // Work item title. Title string `json:"title" toon:"title"` - // Status label after completion. + // Status after completion; always `done`. ToStatus string `json:"to_status" toon:"to_status"` - // Work item ID. + // Work item ID (`wi_` followed by a random string); use it with the `/incident/work-item/*` endpoints. WorkItemID string `json:"work_item_id" toon:"work_item_id"` } @@ -4826,13 +5043,13 @@ type FeedDetailWorkItemConverted struct { FromType string `json:"from_type" toon:"from_type"` // ID of the post-mortem the work item is bound to. PostMortemID string `json:"post_mortem_id" toon:"post_mortem_id"` - // Work item status label after the conversion. + // Work item status after the conversion, usually `open` or `in_progress` (conversion keeps the status). Status string `json:"status" toon:"status"` // Work item title. Title string `json:"title" toon:"title"` // Work item type after the conversion. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem. Conversion currently only supports `action` → `follow_up`, so `to_type` is always `follow_up` in this event, and a successful conversion immediately tries to bind the incident's post-mortem. ToType string `json:"to_type" toon:"to_type"` - // Work item ID. + // Work item ID (`wi_` followed by a random string); use it with the `/incident/work-item/*` endpoints. WorkItemID string `json:"work_item_id" toon:"work_item_id"` } @@ -4846,11 +5063,11 @@ type FeedDetailWorkItemCreated struct { ItemType string `json:"item_type" toon:"item_type"` // ID of the post-mortem the work item is bound to. PostMortemID string `json:"post_mortem_id" toon:"post_mortem_id"` - // Work item status label (e.g. `open`, `done`). + // Work item status at creation: `open` not started; `in_progress` being worked on; `done` completed; `cancelled` no longer needed. Status string `json:"status" toon:"status"` // Work item title. Title string `json:"title" toon:"title"` - // Work item ID. + // Work item ID (`wi_` followed by a random string); use it with the `/incident/work-item/*` endpoints. WorkItemID string `json:"work_item_id" toon:"work_item_id"` } @@ -4862,7 +5079,7 @@ type FeedDetailWorkItemDeleted struct { PostMortemID string `json:"post_mortem_id" toon:"post_mortem_id"` // Work item title. Title string `json:"title" toon:"title"` - // Work item ID. + // Work item ID (`wi_` followed by a random string); use it with the `/incident/work-item/*` endpoints. WorkItemID string `json:"work_item_id" toon:"work_item_id"` } @@ -4870,9 +5087,9 @@ type FeedDetailWorkItemDeleted struct { type FeedDetailWorkItemUpdated struct { // Description before the update. FromDescription string `json:"from_description" toon:"from_description"` - // Priority label before the update. + // Priority before the update. Free-text priority label defined by the client (up to 64 characters); present only when the priority changed. FromPriority string `json:"from_priority" toon:"from_priority"` - // Status label before the update. + // Status before the update; present only when the status changed. Usually one of `open`, `in_progress`, `done`, `cancelled`; items created before these statuses existed may carry other text. FromStatus string `json:"from_status" toon:"from_status"` // Title before the update. FromTitle string `json:"from_title" toon:"from_title"` @@ -4882,17 +5099,17 @@ type FeedDetailWorkItemUpdated struct { Title string `json:"title" toon:"title"` // Description after the update. ToDescription string `json:"to_description" toon:"to_description"` - // Priority label after the update. + // Priority after the update. Free-text priority label defined by the client (up to 64 characters); present only when the priority changed. ToPriority string `json:"to_priority" toon:"to_priority"` - // Status label after the update. + // Status after the update; present only when the status changed. `open` not started; `in_progress` being worked on; `done` completed; `cancelled` no longer needed. ToStatus string `json:"to_status" toon:"to_status"` - // Work item ID. + // Work item ID (`wi_` followed by a random string); use it with the `/incident/work-item/*` endpoints. WorkItemID string `json:"work_item_id" toon:"work_item_id"` } // FeedItem is generated from the Flashduty OpenAPI schema. type FeedItem struct { - // Account ID. + // ID of the account that owns the alert. AccountID int64 `json:"account_id" toon:"account_id"` // AI SRE session that produced the entry. Omitted when no agent wrote it. AgentSessionID string `json:"agent_session_id" toon:"agent_session_id"` @@ -4998,11 +5215,11 @@ type FieldListResponse struct { // FilterCondition is generated from the Flashduty OpenAPI schema. type FilterCondition struct { - // Field name to filter on. Use plain names for built-in alert fields (e.g. `alert_severity`, `alert_key`, `check`, `resource`, `service`, `cluster`) or the `labels.` prefix for custom alert labels (e.g. `labels.env`, `labels.region`). + // Field to match. Which built-in keys are allowed depends on the rule type and is listed on the field that holds the conditions; any `labels.` key (for example `labels.env`) is always accepted. An unknown key returns `InvalidParameter`. When the alert or incident has no value for the key, `IN` does not match and `NOTIN` matches. Key string `json:"key" toon:"key"` - // Filter operator. `IN` — value must match one of `vals`; `NOTIN` — value must not match any of `vals`. Supports regex patterns wrapped in `/pattern/`. + // Match operator, case-sensitive. `IN`: matches when the field value matches any entry in `vals`. `NOTIN`: matches when it matches none of them. Oper string `json:"oper" toon:"oper"` - // List of values to match against. Each entry is a plain string or a `/regex/` pattern. + // Values to compare, at least one. Each entry is matched as: an exact string; a wildcard pattern when it contains `*` or `?` (must match the whole value); a regular expression when wrapped in slashes, such as `/^db-/` (may match anywhere in the value); an IP range written `cidr:`, such as `cidr:203.0.113.0/24`; or a numeric comparison `num::` with `lt`, `le`, `gt` or `ge`, such as `num:gt:90`. Vals []string `json:"vals" toon:"vals"` } @@ -5010,9 +5227,9 @@ type FilterCondition struct { type Flapping struct { // Observation window in minutes. InMins int64 `json:"in_mins,omitempty" toon:"in_mins,omitempty"` - // Disable flapping detection. + // When true, flapping detection is turned off. IsDisabled bool `json:"is_disabled,omitempty" toon:"is_disabled,omitempty"` - // Max state changes allowed within `in_mins`. + // Max state changes allowed within `in_mins`, 2–100. When omitted or `0`, all three values fall back to the defaults: 4 changes, `in_mins` 60, `mute_mins` 120. MaxChanges int64 `json:"max_changes,omitempty" toon:"max_changes,omitempty"` // Mute duration in minutes after flapping is detected. MuteMins int64 `json:"mute_mins,omitempty" toon:"mute_mins,omitempty"` @@ -5020,33 +5237,33 @@ type Flapping struct { // FolderCreateRequest is generated from the Flashduty OpenAPI schema. type FolderCreateRequest struct { - // Folder name; cannot contain a period, slash, or comma. + // Folder name; required, and must not contain a period (`.`), slash (`/`), or comma (`,`). Name string `json:"name" toon:"name"` - // Free-form note; omitted or empty clears the note on update. + // Free-form note. Empty when omitted. Note string `json:"note,omitempty" toon:"note,omitempty"` - // Parent folder ID; 0 or omitted creates a root folder. + // ID of the parent folder; 0 or omitted creates a root folder. The caller must be allowed to modify the parent. ParentID uint64 `json:"parent_id,omitempty" toon:"parent_id,omitempty"` - // Team ID; 0 means account-wide. Omitted on update resets to 0. + // ID of the team the folder belongs to; 0 or omitted means no team. Members of the team can see and modify the folder and everything below it. TeamID uint64 `json:"team_id,omitempty" toon:"team_id,omitempty"` } // FolderDeleteRequest is generated from the Flashduty OpenAPI schema. type FolderDeleteRequest struct { - // Folder ID. + // ID of the folder to delete, from `/monit/folder/list`. The folder must be empty. ID uint64 `json:"id" toon:"id"` } // FolderHealthItem is generated from the Flashduty OpenAPI schema. type FolderHealthItem struct { - // Folder ID. + // ID of the folder this entry describes; matches `id` in `/monit/folder/list`. FolderID uint64 `json:"folder_id" toon:"folder_id"` - // Whether this folder or a visible descendant has active alerts or rule runtime issues. + // `true` when a rule in this folder or in any descendant has an active alert or a runtime problem (`runtime_state` of `offline`, `abnormal`, `stale`, or `no_datasource`). Rules in folders the caller cannot read are not counted. HasIssue bool `json:"has_issue" toon:"has_issue"` } // FolderHealthOutput is generated from the Flashduty OpenAPI schema. type FolderHealthOutput struct { - // Folder health summaries. + // One health entry per folder visible to the caller, sorted by `folder_id`. Items []FolderHealthItem `json:"items" toon:"items"` } @@ -5054,13 +5271,13 @@ type FolderHealthOutput struct { type FolderItem struct { // Owning account ID. AccountID uint64 `json:"account_id" toon:"account_id"` - // Unix timestamp in seconds. + // Creation time as a Unix timestamp in seconds. CreatedAt Timestamp `json:"created_at" toon:"created_at"` - // Member ID of the creator. + // Member ID of the creator; the creator can always see and modify the folder. CreatorID uint64 `json:"creator_id" toon:"creator_id"` // Name of the creator. CreatorName string `json:"creator_name" toon:"creator_name"` - // Folder ID. + // Folder ID. Pass it as `id` to update, move, or delete the folder, as `parent_id` or `dest_parent_id` to nest folders under it, and as `folder_id` on alert rules and dashboards. ID uint64 `json:"id" toon:"id"` // Folder name. Name string `json:"name" toon:"name"` @@ -5070,11 +5287,11 @@ type FolderItem struct { ParentID uint64 `json:"parent_id" toon:"parent_id"` // Comma-separated ancestor IDs from the root, excluding this folder; empty at the root. ParentPath string `json:"parent_path" toon:"parent_path"` - // Team the folder is scoped to; 0 when account-wide. + // ID of the team the folder belongs to; 0 when it has no team. Members of the team can see and modify the folder. TeamID uint64 `json:"team_id" toon:"team_id"` - // Unix timestamp in seconds. + // Time of the last update or move as a Unix timestamp in seconds. UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` - // Member ID of the last updater. + // Member ID of the last updater. Updates and moves both set it. UpdaterID uint64 `json:"updater_id" toon:"updater_id"` // Name of the last updater. UpdaterName string `json:"updater_name" toon:"updater_name"` @@ -5082,39 +5299,40 @@ type FolderItem struct { // FolderMoveRequest is generated from the Flashduty OpenAPI schema. type FolderMoveRequest struct { - // Destination parent folder ID; required even when 0 to move to the root. + // ID of the new parent folder; send 0 to move to the root. The field cannot be omitted. Must differ from `id` and must not be a descendant of the folder. DestParentID uint64 `json:"dest_parent_id" toon:"dest_parent_id"` - // Folder ID. + // ID of the folder to move, from `/monit/folder/list`. ID uint64 `json:"id" toon:"id"` } // FolderUpdateRequest is generated from the Flashduty OpenAPI schema. type FolderUpdateRequest struct { - // Folder ID. + // ID of the folder to update, from `/monit/folder/list` or the create response. ID uint64 `json:"id" toon:"id"` - // Folder name; cannot contain a period, slash, or comma. + // New folder name; required, and must not contain a period (`.`), slash (`/`), or comma (`,`). Name string `json:"name" toon:"name"` - // Free-form note; omitted or empty clears the note on update. + // New note. Omitted or empty clears the note. Note string `json:"note,omitempty" toon:"note,omitempty"` - // Team ID; 0 means account-wide. Omitted on update resets to 0. + // New team ID; 0 or omitted removes the team assignment. TeamID uint64 `json:"team_id,omitempty" toon:"team_id,omitempty"` } // GetIntegrationRequest is generated from the Flashduty OpenAPI schema. type GetIntegrationRequest struct { - // Integration ID. + // ID of a public integration, returned by `POST /integration/list`. An unknown ID or a channel-owned integration returns `ResourceNotFound`. IntegrationID int64 `json:"integration_id" toon:"integration_id"` } // GetRemoteConfigRequest is generated from the Flashduty OpenAPI schema. type GetRemoteConfigRequest struct { - // RUM application ID. + // RUM application ID. Get application IDs via `POST /rum/application/list`. ApplicationID string `json:"application_id" toon:"application_id"` } // GetRemoteConfigResponse is generated from the Flashduty OpenAPI schema. type GetRemoteConfigResponse struct { - Config RemoteConfig `json:"config" toon:"config"` + // The live configuration (the newest published version). `null` when the application has never been configured. + Config any `json:"config" toon:"config"` // Unix timestamp in milliseconds - when the current version was published. 0 when never configured. UpdatedAt TimestampMilli `json:"updated_at" toon:"updated_at"` // Version the live configuration is stored under. 0 means the application has never been configured. @@ -5123,13 +5341,13 @@ type GetRemoteConfigResponse struct { // GetWarRoomDefaultObserversRequest is generated from the Flashduty OpenAPI schema. type GetWarRoomDefaultObserversRequest struct { - // Incident ID, a MongoDB ObjectID hex string. + // Incident ID (MongoDB ObjectID). IncidentID string `json:"incident_id" toon:"incident_id"` } // GetWarRoomDefaultObserversResponse is generated from the Flashduty OpenAPI schema. type GetWarRoomDefaultObserversResponse struct { - // Historical responders suggested as default war-room observers. + // Suggested observers, in timeline order. Empty array when there are none. Observers []WarRoomPersonItem `json:"observers" toon:"observers"` } @@ -5143,7 +5361,7 @@ type GetWarRoomDetailRequest struct { // GetWebhookHistoryDetailRequest is generated from the Flashduty OpenAPI schema. type GetWebhookHistoryDetailRequest struct { - // Event ID returned by `ListWebhookHistory`. + // `event_id` of a record returned by `POST /webhook/history/list`. It starts with the delivery date (`YYYYMMDD`); an ID without that prefix fails the request. EventID string `json:"event_id" toon:"event_id"` // Integration ID the event belongs to; available in the items returned by `POST /webhook/history/list`. IntegrationID int64 `json:"integration_id" toon:"integration_id"` @@ -5151,21 +5369,24 @@ type GetWebhookHistoryDetailRequest struct { // Group is generated from the Flashduty OpenAPI schema. type Group struct { - // When true, all listed keys must be present for grouping. + // When true, a key set matches only if every key in it is present on the alert. When false, missing keys compare as empty, but at least one key of the set must be present. AllEqualsRequired bool `json:"all_equals_required,omitempty" toon:"all_equals_required,omitempty"` // Per-filter grouping overrides. Cases []GroupCasesItem `json:"cases,omitempty" toon:"cases,omitempty"` - // Groups of label keys whose equality defines a bucket. + // Key sets for rule-based (`p`) grouping, up to 5 sets. A new alert joins an active incident when every key of any one set has the same value on both. Keys: `title`, `description`, `severity`, or `labels.`; each set must be non-empty. With `p`, at least one of `equals` or `cases` is required. Equals [][]string `json:"equals,omitempty" toon:"equals,omitempty"` - // Label keys used for intelligent grouping embeddings. + // Fields used by intelligent (`i`) grouping, up to 10: `title`, `description`, `severity`, or `labels.`. Empty uses `title`, `description`, `labels.service` and `labels.resource`. IKeys []string `json:"i_keys,omitempty" toon:"i_keys,omitempty"` - // Intelligent grouping similarity threshold. + // Minimum similarity, 0.5–1, for intelligent grouping to merge an alert into an existing incident. Omitted or `0` uses 0.9. IScoreThreshold float64 `json:"i_score_threshold,omitempty" toon:"i_score_threshold,omitempty"` - // Grouping method: `i` intelligent, `p` pattern, `n` none. + // Grouping method: + // - `n`: no grouping; every new alert opens its own incident. + // - `p`: rule-based grouping by the keys in `equals` and `cases`; requires the Standard license or higher. + // - `i`: intelligent grouping by content similarity (see `i_keys`, `i_score_threshold`); requires the Pro license. Method string `json:"method" toon:"method"` - // Alert storm threshold. + // Legacy single storm threshold; used only when `storm_thresholds` is empty and the value is greater than 1. `0` disables it. StormThreshold int64 `json:"storm_threshold,omitempty" toon:"storm_threshold,omitempty"` - // Multi-level storm thresholds. + // Alert counts at which an incident storm event fires: when the number of alerts merged into one incident reaches a threshold, a storm notification is sent. Up to 5 values, each at least 2; duplicates are removed and values are sorted. StormThresholds []int64 `json:"storm_thresholds,omitempty" toon:"storm_thresholds,omitempty"` // Grouping time window in minutes. Default max is 1440 minutes (24 h); extended accounts may allow up to 43200 minutes (30 days). TimeWindow int64 `json:"time_window,omitempty" toon:"time_window,omitempty"` @@ -5181,7 +5402,7 @@ type IDRequest struct { // Image is generated from the Flashduty OpenAPI schema. type Image struct { - // Alt text. + // Alternative text shown when the image cannot be displayed; empty when not set. Alt string `json:"alt" toon:"alt"` // Optional link the image points to. Href string `json:"href" toon:"href"` @@ -5191,7 +5412,7 @@ type Image struct { // ImportStatusPageSubscriberItem is generated from the Flashduty OpenAPI schema. type ImportStatusPageSubscriberItem struct { - // When true, the subscriber receives notifications for all components. Must be true when `component_ids` and `change_ids` are both empty. + // When `true`, the subscriber receives notifications for all components and events, and `component_ids`/`change_ids` are ignored. Must be `true` when both lists are empty. All bool `json:"all,omitempty" toon:"all,omitempty"` // Specific event IDs the subscriber should receive notifications for. ChangeIDs []int64 `json:"change_ids,omitempty" toon:"change_ids,omitempty"` @@ -5209,15 +5430,15 @@ type ImportStatusPageSubscribersRequest struct { Method string `json:"method" toon:"method"` // Target status page ID; obtain it from `GET /status-page/list`. PageID int64 `json:"page_id" toon:"page_id"` - // Subscribers to import. + // Subscribers to import. Each recipient's existing subscriptions on this page are replaced; an empty or omitted list does nothing. Subscribers []ImportStatusPageSubscriberItem `json:"subscribers,omitempty" toon:"subscribers,omitempty"` } // IncProgressCnts is generated from the Flashduty OpenAPI schema. type IncProgressCnts struct { - // Count of processing incidents in the last 30 days. + // Incidents started in the last 30 days that are `Processing` (acknowledged, not yet closed). Processing int64 `json:"Processing" toon:"Processing"` - // Count of triggered incidents in the last 30 days. + // Incidents started in the last 30 days that are still `Triggered` (not yet acknowledged). Triggered int64 `json:"Triggered" toon:"Triggered"` } @@ -5265,8 +5486,10 @@ type IncidentCommentTypeItem struct { // IncidentFeedItem is generated from the Flashduty OpenAPI schema. type IncidentFeedItem struct { - // Account ID. + // ID of the account that owns this record; the same for every record returned to one `app_key`. AccountID int64 `json:"account_id" toon:"account_id"` + // ID of the AI SRE session that performed the action; present only when `via` is `ai_sre` and a session was recorded. + AgentSessionID string `json:"agent_session_id" toon:"agent_session_id"` // Creation timestamp in milliseconds. CreatedAt TimestampMilli `json:"created_at" toon:"created_at"` // User ID of the actor. `0` means system-generated. @@ -5275,22 +5498,24 @@ type IncidentFeedItem struct { DeletedAt TimestampMilli `json:"deleted_at" toon:"deleted_at"` // Type-specific payload. The concrete shape is determined by `type`; `null` when the entry has no structured detail. Detail any `json:"detail" toon:"detail"` - // ObjectID of the source alert or incident this entry references. + // ID of the incident the entry belongs to; equals the requested `incident_id`. RefID string `json:"ref_id" toon:"ref_id"` Type IncidentFeedType `json:"type" toon:"type"` // Last update timestamp in milliseconds. UpdatedAt TimestampMilli `json:"updated_at" toon:"updated_at"` + // `ai_sre` when AI SRE performed the action on behalf of `creator_id`; omitted for direct actions. + Via string `json:"via" toon:"via"` } // IncidentInfo is generated from the Flashduty OpenAPI schema. type IncidentInfo struct { // Account ID that owns the incident. AccountID int64 `json:"account_id" toon:"account_id"` - // Account locale. + // Always an empty string in API responses; filled only when the incident is rendered for notifications. AccountLocale string `json:"account_locale" toon:"account_locale"` - // Account name. + // Always an empty string in API responses; filled only when the incident is rendered for notifications. AccountName string `json:"account_name" toon:"account_name"` - // Account time zone. + // Always an empty string in API responses; filled only when the incident is rendered for notifications. AccountTimeZone string `json:"account_time_zone" toon:"account_time_zone"` // Unix timestamp (seconds) when the incident was first acknowledged. 0 if unacknowledged. AckTime Timestamp `json:"ack_time" toon:"ack_time"` @@ -5302,15 +5527,15 @@ type IncidentInfo struct { AlertCnt int64 `json:"alert_cnt" toon:"alert_cnt"` // Total raw alert event count across all merged alerts. AlertEventCnt int64 `json:"alert_event_cnt" toon:"alert_event_cnt"` - // Embedded alerts, only populated for notification templates and custom actions. + // Not returned by the incident endpoints; present only in notification template and custom action payloads. Alerts []AlertInfo `json:"alerts" toon:"alerts"` - // Current assignment target for the incident. + // Current assignment target. Always present; for an incident that was never assigned, `type` and `id` are empty and `assigned_at` is `0`. AssignedTo AssignedTo `json:"assigned_to" toon:"assigned_to"` // Channel ID. 0 for standalone incidents. ChannelID int64 `json:"channel_id" toon:"channel_id"` // Channel display name. ChannelName string `json:"channel_name" toon:"channel_name"` - // Channel status. + // Status of the channel: `enabled`, `disabled`, or `deleted`. Empty string when the record has no channel or the channel no longer exists. ChannelStatus string `json:"channel_status" toon:"channel_status"` // Unix timestamp (seconds) when the incident was closed. 0 if still open. CloseTime Timestamp `json:"close_time" toon:"close_time"` @@ -5328,7 +5553,7 @@ type IncidentInfo struct { DataSourceID int64 `json:"data_source_id" toon:"data_source_id"` // Deprecated. Use `integration_ids` instead. DataSourceIDs []int64 `json:"data_source_ids" toon:"data_source_ids"` - // Deprecated. Use `integration_type` instead. + // Deprecated; same value as `integration_type`. DataSourceType string `json:"data_source_type" toon:"data_source_type"` // Deprecated. Use `integration_types` instead. DataSourceTypes []string `json:"data_source_types" toon:"data_source_types"` @@ -5352,7 +5577,9 @@ type IncidentInfo struct { Frequency string `json:"frequency" toon:"frequency"` // Alert grouping method: `i` intelligent, `p` pattern, `n` none. GroupMethod string `json:"group_method" toon:"group_method"` - // Attached images. + // `true` when the incident still has at least one action item or follow-up that is neither `done` nor `cancelled`. + HasUnfinishedWorkItem bool `json:"has_unfinished_work_item" toon:"has_unfinished_work_item"` + // Images attached to the incident; `null` when there are none. Tokens starting with `img_` are returned as download URLs. Images []Image `json:"images" toon:"images"` // Impact description. Impact string `json:"impact" toon:"impact"` @@ -5364,11 +5591,11 @@ type IncidentInfo struct { IncidentStatus string `json:"incident_status" toon:"incident_status"` // First integration associated with the incident. IntegrationID int64 `json:"integration_id" toon:"integration_id"` - // All integration IDs contributing alerts to this incident. + // IDs of all integrations contributing alerts to this incident; `null` for incidents without integrations, such as manually created ones. IntegrationIDs []int64 `json:"integration_ids" toon:"integration_ids"` - // First alert's integration type string, used by the detail page for label mappings. + // Plugin type of the incident's first integration (see `integration_types` for all). Open set, for example `prometheus.alert` or `monit.alert`; `POST /integration/type/list` returns the full list. Omitted when the incident has no integration or the endpoint does not fill it. IntegrationType string `json:"integration_type" toon:"integration_type"` - // Integration type strings for all contributing integrations. + // Plugin types of all contributing integrations (see `integration_type`); `null` when there are none. IntegrationTypes []string `json:"integration_types" toon:"integration_types"` // Labels propagated from alerts. Labels map[string]string `json:"labels" toon:"labels"` @@ -5376,7 +5603,7 @@ type IncidentInfo struct { LastTime Timestamp `json:"last_time" toon:"last_time"` // Channel-level link integrations rendered for this incident. Links []LinkItem `json:"links" toon:"links"` - // Fields that were manually overridden after auto-population. + // Fields edited manually and therefore no longer overwritten by merged alerts: `title`, `description`, `incident_severity`. `null` when none. ManualOverrides []string `json:"manual_overrides" toon:"manual_overrides"` // Short display identifier; not guaranteed unique. Num string `json:"num" toon:"num"` @@ -5420,13 +5647,13 @@ type IncidentInfoRequest struct { // IncidentListResponse is generated from the Flashduty OpenAPI schema. type IncidentListResponse struct { - // True when more results are available beyond this page. + // Whether another page exists. Reflects the real data with both `p`/`limit` and `search_after_ctx` paging, including past the 1,000 cap of `total`. Always `false` for `POST /incident/list-by-ids`. HasNextPage bool `json:"has_next_page" toon:"has_next_page"` // Incident list for the current page. Items []IncidentInfo `json:"items" toon:"items"` - // Opaque cursor to pass as `search_after_ctx` on the next request. + // Cursor pointing at the last item of this page; pass it as `search_after_ctx` on the next request to continue past the 1,000-item page limit. Returned for every non-empty page in `p`/`limit` mode, and in cursor mode only when `has_next_page` is `true`. Omitted by `POST /incident/list-by-ids`. SearchAfterCtx string `json:"search_after_ctx" toon:"search_after_ctx"` - // Total number of matching incidents. + // Number of matching incidents, capped at 1,000. For `POST /incident/list-by-ids`, the number of incidents found. Total int64 `json:"total" toon:"total"` } @@ -5516,7 +5743,7 @@ type IncidentRawItem struct { type IncidentShort struct { // Incident ID (ObjectID hex string). IncidentID string `json:"incident_id" toon:"incident_id"` - // Incident progress — one of `Triggered`, `Processing`, `Closed`. + // Incident progress: `Triggered` not yet acknowledged; `Processing` acknowledged and being handled; `Closed` resolved. Progress string `json:"progress" toon:"progress"` // Incident title. Title string `json:"title" toon:"title"` @@ -5534,19 +5761,19 @@ type InhibitRuleItem struct { DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` // Rule description. Description string `json:"description" toon:"description"` - // Field keys whose values must be equal between the source (inhibiting) alert and the target (suppressed) alert, e.g. `data_source_id` or `labels.cluster`. + // Keys whose values must be equal on the source alert and the incoming event. Only `title`, `severity` and `labels.` take effect; with any other key the rule never fires. Equals []string `json:"equals" toon:"equals"` // When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule. IsDirectlyDiscard bool `json:"is_directly_discard" toon:"is_directly_discard"` // Rule ID (MongoDB ObjectID). RuleID string `json:"rule_id" toon:"rule_id"` - // Rule name. + // Inhibit rule name, 1–39 characters. RuleName string `json:"rule_name" toon:"rule_name"` // Conditions the source alert must match, evaluated against stored active alerts. Supported keys: `status`, `incident_status`, `alert_status`, `severity`, `incident_severity`, `alert_severity`, `title`, `description`, or any `labels.`. Empty makes the rule inert. SourceFilters FilterGroup `json:"source_filters" toon:"source_filters"` // Rule status: `enabled` or `disabled`; deleted rules never appear in the list. Status string `json:"status" toon:"status"` - // Conditions the incoming target alert event must match to be suppressed; empty means every event is a target. + // Conditions the incoming target alert event must match to be inhibited; empty means every incoming event is a target. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`. TargetFilters FilterGroup `json:"target_filters" toon:"target_filters"` // Last update time, Unix timestamp in seconds. UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` @@ -5556,9 +5783,9 @@ type InhibitRuleItem struct { // InitPostMortemRequest is generated from the Flashduty OpenAPI schema. type InitPostMortemRequest struct { - // Incident IDs to link to the report. 1-10 incidents. + // Incident IDs (MongoDB ObjectIDs) to link to the report, 1–10. All must exist in the account. The same set always maps to the same report. IncidentIDs []string `json:"incident_ids" toon:"incident_ids"` - // Template ID used to initialize the report. + // Template ID from `POST /incident/post-mortem/template/list`, e.g. the built-in `post_mortem_default_tmpl_en-us` or `post_mortem_default_tmpl_zh-cn`, or a custom template ID. TemplateID string `json:"template_id" toon:"template_id"` } @@ -5582,7 +5809,7 @@ type InsightAlertByLabelResponse struct { // InsightFilter is generated from the Flashduty OpenAPI schema. type InsightFilter struct { - // Sort ascending when `true`, descending otherwise. Only used by `/insight/incident/list`. + // Sort ascending when `true`, descending (default) otherwise. Used by the incident list and export; `/insight/alert/topk-by-label` has its own `asc`. Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` // Filter by channel IDs. At most 100 entries. ChannelIDs []int64 `json:"channel_ids,omitempty" toon:"channel_ids,omitempty"` @@ -5594,19 +5821,19 @@ type InsightFilter struct { ExportFields []string `json:"export_fields,omitempty" toon:"export_fields,omitempty"` // Custom-field filters (exact match). Fields map[string]any `json:"fields,omitempty" toon:"fields,omitempty"` - // Filter by incident IDs (MongoDB ObjectIDs). At most 100 entries. + // Filter by incident IDs (24-character hex). Used only by the incident list and export. At most 100 entries. IncidentIDs []string `json:"incident_ids,omitempty" toon:"incident_ids,omitempty"` // Include incidents that have ever been muted. By default, they are excluded. IncludeEverMuted bool `json:"include_ever_muted,omitempty" toon:"include_ever_muted,omitempty"` - // Restrict results to teams the caller belongs to. When true and the caller has no teams, the result set is empty. + // Restrict results to the caller's teams (intersected with `team_ids` when both are set). When that intersection is empty, or the caller belongs to no team, the result is empty. IsMyTeam bool `json:"is_my_team,omitempty" toon:"is_my_team,omitempty"` // Label filters (exact match). Labels map[string]string `json:"labels,omitempty" toon:"labels,omitempty"` - // Sort field of the incident list; only `created_at` (incident creation time) is supported. Used by `/insight/incident/list` only. + // Sort field of the incident list; only `created_at` (incident creation time, the default). Used by `/insight/incident/list` and `/insight/incident/export`. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` // Substring match on the incident title (SQL `LIKE %query%`). Query string `json:"query,omitempty" toon:"query,omitempty"` - // Filter by responder person IDs. At most 100 entries. + // Filter by responder member IDs. Used by `/insight/responder` (which responders to return) and the incident list/export (incidents any of them responded to); ignored by the account/team/channel and top-K endpoints. At most 100 entries. ResponderIDs []int64 `json:"responder_ids,omitempty" toon:"responder_ids,omitempty"` // Lower bound (inclusive) on time-to-acknowledge, in seconds. SecondsToAckFrom int64 `json:"seconds_to_ack_from,omitempty" toon:"seconds_to_ack_from,omitempty"` @@ -5616,20 +5843,20 @@ type InsightFilter struct { SecondsToCloseFrom int64 `json:"seconds_to_close_from,omitempty" toon:"seconds_to_close_from,omitempty"` // Upper bound (exclusive) on time-to-close, in seconds. Must be greater than `seconds_to_close_from` when both are set. SecondsToCloseTo int64 `json:"seconds_to_close_to,omitempty" toon:"seconds_to_close_to,omitempty"` - // Filter by severity. At most 3 entries. + // Filter by severity: `Critical`, `Warning`, `Info`, or `Ok`. At most 3 entries. Severities []string `json:"severities,omitempty" toon:"severities,omitempty"` // Start time, Unix seconds. Must be greater than 0. StartTime int64 `json:"start_time" toon:"start_time"` // Filter by team IDs. At most 100 entries. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` - // IANA time zone name used to cut day/week/month buckets (e.g. `Asia/Shanghai`). Optional; defaults to UTC, except that `/insight/incident/export` falls back to the account time zone and then `Asia/Shanghai`. + // IANA time zone (for example `Asia/Shanghai` or `UTC`) used to cut `aggregate_unit` buckets; abbreviations such as `EST` and `Etc/GMT±N` are rejected. Defaults to UTC. `/insight/incident/export` uses it to render times, falling back to the account time zone and then `Asia/Shanghai`. TimeZone string `json:"time_zone,omitempty" toon:"time_zone,omitempty"` } // InsightIncidentListRequest is generated from the Flashduty OpenAPI schema. type InsightIncidentListRequest struct { ListOptions - // Sort ascending when `true`, descending otherwise. Only used by `/insight/incident/list`. + // Sort ascending when `true`, descending (default) otherwise. Used by the incident list and export; `/insight/alert/topk-by-label` has its own `asc`. Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` // Filter by channel IDs. At most 100 entries. ChannelIDs []int64 `json:"channel_ids,omitempty" toon:"channel_ids,omitempty"` @@ -5641,19 +5868,19 @@ type InsightIncidentListRequest struct { ExportFields []string `json:"export_fields,omitempty" toon:"export_fields,omitempty"` // Custom-field filters (exact match). Fields map[string]any `json:"fields,omitempty" toon:"fields,omitempty"` - // Filter by incident IDs (MongoDB ObjectIDs). At most 100 entries. + // Filter by incident IDs (24-character hex). Used only by the incident list and export. At most 100 entries. IncidentIDs []string `json:"incident_ids,omitempty" toon:"incident_ids,omitempty"` // Include incidents that have ever been muted. By default, they are excluded. IncludeEverMuted bool `json:"include_ever_muted,omitempty" toon:"include_ever_muted,omitempty"` - // Restrict results to teams the caller belongs to. When true and the caller has no teams, the result set is empty. + // Restrict results to the caller's teams (intersected with `team_ids` when both are set). When that intersection is empty, or the caller belongs to no team, the result is empty. IsMyTeam bool `json:"is_my_team,omitempty" toon:"is_my_team,omitempty"` // Label filters (exact match). Labels map[string]string `json:"labels,omitempty" toon:"labels,omitempty"` - // Sort field of the incident list; only `created_at` (incident creation time) is supported. Used by `/insight/incident/list` only. + // Sort field of the incident list; only `created_at` (incident creation time, the default). Used by `/insight/incident/list` and `/insight/incident/export`. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` // Substring match on the incident title (SQL `LIKE %query%`). Query string `json:"query,omitempty" toon:"query,omitempty"` - // Filter by responder person IDs. At most 100 entries. + // Filter by responder member IDs. Used by `/insight/responder` (which responders to return) and the incident list/export (incidents any of them responded to); ignored by the account/team/channel and top-K endpoints. At most 100 entries. ResponderIDs []int64 `json:"responder_ids,omitempty" toon:"responder_ids,omitempty"` // Lower bound (inclusive) on time-to-acknowledge, in seconds. SecondsToAckFrom int64 `json:"seconds_to_ack_from,omitempty" toon:"seconds_to_ack_from,omitempty"` @@ -5663,13 +5890,13 @@ type InsightIncidentListRequest struct { SecondsToCloseFrom int64 `json:"seconds_to_close_from,omitempty" toon:"seconds_to_close_from,omitempty"` // Upper bound (exclusive) on time-to-close, in seconds. Must be greater than `seconds_to_close_from` when both are set. SecondsToCloseTo int64 `json:"seconds_to_close_to,omitempty" toon:"seconds_to_close_to,omitempty"` - // Filter by severity. At most 3 entries. + // Filter by severity: `Critical`, `Warning`, `Info`, or `Ok`. At most 3 entries. Severities []string `json:"severities,omitempty" toon:"severities,omitempty"` // Start time, Unix seconds. Must be greater than 0. StartTime int64 `json:"start_time" toon:"start_time"` // Filter by team IDs. At most 100 entries. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` - // IANA time zone name used to cut day/week/month buckets (e.g. `Asia/Shanghai`). Optional; defaults to UTC, except that `/insight/incident/export` falls back to the account time zone and then `Asia/Shanghai`. + // IANA time zone (for example `Asia/Shanghai` or `UTC`) used to cut `aggregate_unit` buckets; abbreviations such as `EST` and `Etc/GMT±N` are rejected. Defaults to UTC. `/insight/incident/export` uses it to render times, falling back to the account time zone and then `Asia/Shanghai`. TimeZone string `json:"time_zone,omitempty" toon:"time_zone,omitempty"` } @@ -5677,19 +5904,22 @@ type InsightIncidentListRequest struct { type InsightIncidentListResponse struct { // Whether another page of results is available. HasNextPage bool `json:"has_next_page" toon:"has_next_page"` - // Incident items. + // Incidents on this page; an empty array when none match. Items []IncidentRawItem `json:"items" toon:"items"` // Cursor token to fetch the next page — the incident ID of the last row on this page. Present only when `has_next_page` is true. SearchAfterCtx string `json:"search_after_ctx" toon:"search_after_ctx"` - // Total matching incidents. + // Number of matching incidents. When the request carried `search_after_ctx`, only incidents after the cursor are counted. Total int64 `json:"total" toon:"total"` } // InsightQueryRequest is generated from the Flashduty OpenAPI schema. type InsightQueryRequest struct { - // Aggregates metrics by time granularity. When set, the time range must be at least 24 hours; with `day` granularity the range must not exceed 31 days. `day` buckets by calendar day, `week` by calendar week, and `month` by calendar month, with boundaries aligned to `time_zone`. + // Split the range into time buckets; omit for a single bucket covering the whole range. Requires a range of at least 24 hours, and `day` allows at most 31 days. + // - `day`: calendar days in `time_zone` (the first bucket runs from `start_time` to the next midnight). + // - `week`: consecutive 7-day buckets starting at `start_time` (not aligned to Monday). + // - `month`: calendar months in `time_zone` (the first bucket runs from `start_time` to the 1st of the next month). AggregateUnit string `json:"aggregate_unit,omitempty" toon:"aggregate_unit,omitempty"` - // Sort ascending when `true`, descending otherwise. Only used by `/insight/incident/list`. + // Sort ascending when `true`, descending (default) otherwise. Used by the incident list and export; `/insight/alert/topk-by-label` has its own `asc`. Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` // Filter by channel IDs. At most 100 entries. ChannelIDs []int64 `json:"channel_ids,omitempty" toon:"channel_ids,omitempty"` @@ -5701,19 +5931,19 @@ type InsightQueryRequest struct { ExportFields []string `json:"export_fields,omitempty" toon:"export_fields,omitempty"` // Custom-field filters (exact match). Fields map[string]any `json:"fields,omitempty" toon:"fields,omitempty"` - // Filter by incident IDs (MongoDB ObjectIDs). At most 100 entries. + // Filter by incident IDs (24-character hex). Used only by the incident list and export. At most 100 entries. IncidentIDs []string `json:"incident_ids,omitempty" toon:"incident_ids,omitempty"` // Include incidents that have ever been muted. By default, they are excluded. IncludeEverMuted bool `json:"include_ever_muted,omitempty" toon:"include_ever_muted,omitempty"` - // Restrict results to teams the caller belongs to. When true and the caller has no teams, the result set is empty. + // Restrict results to the caller's teams (intersected with `team_ids` when both are set). When that intersection is empty, or the caller belongs to no team, the result is empty. IsMyTeam bool `json:"is_my_team,omitempty" toon:"is_my_team,omitempty"` // Label filters (exact match). Labels map[string]string `json:"labels,omitempty" toon:"labels,omitempty"` - // Sort field of the incident list; only `created_at` (incident creation time) is supported. Used by `/insight/incident/list` only. + // Sort field of the incident list; only `created_at` (incident creation time, the default). Used by `/insight/incident/list` and `/insight/incident/export`. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` // Substring match on the incident title (SQL `LIKE %query%`). Query string `json:"query,omitempty" toon:"query,omitempty"` - // Filter by responder person IDs. At most 100 entries. + // Filter by responder member IDs. Used by `/insight/responder` (which responders to return) and the incident list/export (incidents any of them responded to); ignored by the account/team/channel and top-K endpoints. At most 100 entries. ResponderIDs []int64 `json:"responder_ids,omitempty" toon:"responder_ids,omitempty"` // Lower bound (inclusive) on time-to-acknowledge, in seconds. SecondsToAckFrom int64 `json:"seconds_to_ack_from,omitempty" toon:"seconds_to_ack_from,omitempty"` @@ -5723,21 +5953,24 @@ type InsightQueryRequest struct { SecondsToCloseFrom int64 `json:"seconds_to_close_from,omitempty" toon:"seconds_to_close_from,omitempty"` // Upper bound (exclusive) on time-to-close, in seconds. Must be greater than `seconds_to_close_from` when both are set. SecondsToCloseTo int64 `json:"seconds_to_close_to,omitempty" toon:"seconds_to_close_to,omitempty"` - // Filter by severity. At most 3 entries. + // Filter by severity: `Critical`, `Warning`, `Info`, or `Ok`. At most 3 entries. Severities []string `json:"severities,omitempty" toon:"severities,omitempty"` - // When true, metrics are split into `work`/`sleep`/`off` hour buckets. + // When `true`, each bucket is further split into `work`, `sleep` and `off` hours, returned as separate rows with `hours` set. SplitHours bool `json:"split_hours,omitempty" toon:"split_hours,omitempty"` // Start time, Unix seconds. Must be greater than 0. StartTime int64 `json:"start_time" toon:"start_time"` // Filter by team IDs. At most 100 entries. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` - // IANA time zone name used to cut day/week/month buckets (e.g. `Asia/Shanghai`). Optional; defaults to UTC, except that `/insight/incident/export` falls back to the account time zone and then `Asia/Shanghai`. + // IANA time zone (for example `Asia/Shanghai` or `UTC`) used to cut `aggregate_unit` buckets; abbreviations such as `EST` and `Etc/GMT±N` are rejected. Defaults to UTC. `/insight/incident/export` uses it to render times, falling back to the account time zone and then `Asia/Shanghai`. TimeZone string `json:"time_zone,omitempty" toon:"time_zone,omitempty"` } // InsightTopkAlertByLabelRequest is generated from the Flashduty OpenAPI schema. type InsightTopkAlertByLabelRequest struct { - // Aggregates metrics by time granularity. When set, the time range must be at least 24 hours; with `day` granularity the range must not exceed 31 days. `day` buckets by calendar day, `week` by calendar week, and `month` by calendar month, with boundaries aligned to `time_zone`. + // Split the range into time buckets; omit for a single bucket covering the whole range. Requires a range of at least 24 hours, and `day` allows at most 31 days. + // - `day`: calendar days in `time_zone` (the first bucket runs from `start_time` to the next midnight). + // - `week`: consecutive 7-day buckets starting at `start_time` (not aligned to Monday). + // - `month`: calendar months in `time_zone` (the first bucket runs from `start_time` to the 1st of the next month). AggregateUnit string `json:"aggregate_unit,omitempty" toon:"aggregate_unit,omitempty"` // Sort ascending when `true`, descending otherwise. Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` @@ -5751,13 +5984,13 @@ type InsightTopkAlertByLabelRequest struct { ExportFields []string `json:"export_fields,omitempty" toon:"export_fields,omitempty"` // Custom-field filters (exact match). Fields map[string]any `json:"fields,omitempty" toon:"fields,omitempty"` - // Filter by incident IDs (MongoDB ObjectIDs). At most 100 entries. + // Filter by incident IDs (24-character hex). Used only by the incident list and export. At most 100 entries. IncidentIDs []string `json:"incident_ids,omitempty" toon:"incident_ids,omitempty"` // Include incidents that have ever been muted. By default, they are excluded. IncludeEverMuted bool `json:"include_ever_muted,omitempty" toon:"include_ever_muted,omitempty"` - // Restrict results to teams the caller belongs to. When true and the caller has no teams, the result set is empty. + // Restrict results to the caller's teams (intersected with `team_ids` when both are set). When that intersection is empty, or the caller belongs to no team, the result is empty. IsMyTeam bool `json:"is_my_team,omitempty" toon:"is_my_team,omitempty"` - // Number of top entries to return, between 1 and 100. Defaults to 20. + // Number of label values to return, between 1 and 100 (default 20). With `split_hours`, applied per hour bucket. K int64 `json:"k,omitempty" toon:"k,omitempty"` // Aggregation dimension. `check` aggregates by the event's `labels.check` label (monitoring check); `resource` aggregates by the `labels.resource` label (monitored resource identifier). Label string `json:"label" toon:"label"` @@ -5767,7 +6000,7 @@ type InsightTopkAlertByLabelRequest struct { Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` // Substring match on the incident title (SQL `LIKE %query%`). Query string `json:"query,omitempty" toon:"query,omitempty"` - // Filter by responder person IDs. At most 100 entries. + // Filter by responder member IDs. Used by `/insight/responder` (which responders to return) and the incident list/export (incidents any of them responded to); ignored by the account/team/channel and top-K endpoints. At most 100 entries. ResponderIDs []int64 `json:"responder_ids,omitempty" toon:"responder_ids,omitempty"` // Lower bound (inclusive) on time-to-acknowledge, in seconds. SecondsToAckFrom int64 `json:"seconds_to_ack_from,omitempty" toon:"seconds_to_ack_from,omitempty"` @@ -5777,15 +6010,15 @@ type InsightTopkAlertByLabelRequest struct { SecondsToCloseFrom int64 `json:"seconds_to_close_from,omitempty" toon:"seconds_to_close_from,omitempty"` // Upper bound (exclusive) on time-to-close, in seconds. Must be greater than `seconds_to_close_from` when both are set. SecondsToCloseTo int64 `json:"seconds_to_close_to,omitempty" toon:"seconds_to_close_to,omitempty"` - // Filter by severity. At most 3 entries. + // Filter by severity: `Critical`, `Warning`, `Info`, or `Ok`. At most 3 entries. Severities []string `json:"severities,omitempty" toon:"severities,omitempty"` - // When true, metrics are split into `work`/`sleep`/`off` hour buckets. + // When `true`, each bucket is further split into `work`, `sleep` and `off` hours, returned as separate rows with `hours` set. SplitHours bool `json:"split_hours,omitempty" toon:"split_hours,omitempty"` // Start time, Unix seconds. Must be greater than 0. StartTime int64 `json:"start_time" toon:"start_time"` // Filter by team IDs. At most 100 entries. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` - // IANA time zone name used to cut day/week/month buckets (e.g. `Asia/Shanghai`). Optional; defaults to UTC, except that `/insight/incident/export` falls back to the account time zone and then `Asia/Shanghai`. + // IANA time zone (for example `Asia/Shanghai` or `UTC`) used to cut `aggregate_unit` buckets; abbreviations such as `EST` and `Etc/GMT±N` are rejected. Defaults to UTC. `/insight/incident/export` uses it to render times, falling back to the account time zone and then `Asia/Shanghai`. TimeZone string `json:"time_zone,omitempty" toon:"time_zone,omitempty"` } @@ -5801,7 +6034,7 @@ type IntegrationDetail struct { Description string `json:"description" toon:"description"` // Whether the current caller passes the integration object-permission check; write calls also require Integrations Manage. Editable bool `json:"editable" toon:"editable"` - // Integration ID. + // Integration ID; pass it as `integration_id` to the other `/integration/*` endpoints. IntegrationID int64 `json:"integration_id" toon:"integration_id"` // Decrypted integration key for inbound pushes. Empty when no key is stored; distinct from the account `app_key`. IntegrationKey string `json:"integration_key" toon:"integration_key"` @@ -5851,7 +6084,7 @@ type IntegrationItem struct { Editable bool `json:"editable" toon:"editable"` // Legacy compatibility field; `0` for items returned by this public-integration list. ExclusiveDataSourceID int64 `json:"exclusive_data_source_id" toon:"exclusive_data_source_id"` - // Integration ID. + // Integration ID; pass it as `integration_id` to the other `/integration/*` endpoints. IntegrationID int64 `json:"integration_id" toon:"integration_id"` // Decrypted integration key for inbound pushes. Empty when no key is stored; distinct from the account `app_key`. IntegrationKey string `json:"integration_key" toon:"integration_key"` @@ -5883,7 +6116,7 @@ type IntegrationItem struct { // IntegrationLifecycleRequest is generated from the Flashduty OpenAPI schema. type IntegrationLifecycleRequest struct { - // Integration ID. + // ID of a public integration, returned by `POST /integration/list`. An unknown ID or a channel-owned integration returns `ResourceNotFound`. IntegrationID int64 `json:"integration_id" toon:"integration_id"` } @@ -5891,13 +6124,13 @@ type IntegrationLifecycleRequest struct { type IntegrationTypeItem struct { // Category the type belongs to: `event.alert` alert events, `event.change` change events, `im` IM bots, `webhook` custom webhooks. Category string `json:"category" toon:"category"` - // Type identifier to pass as `plugin_type` when creating an integration. + // 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. PluginType string `json:"plugin_type" toon:"plugin_type"` // Logo URL of the type. PluginTypeLogoURL string `json:"plugin_type_logo_url" toon:"plugin_type_logo_url"` // Display name of the type. PluginTypeName string `json:"plugin_type_name" toon:"plugin_type_name"` - // Platform status of the type. + // 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. Status string `json:"status" toon:"status"` // Whether `POST /integration/create` accepts this type. SupportsAPICreate bool `json:"supports_api_create" toon:"supports_api_create"` @@ -5908,7 +6141,7 @@ type IntegrationTypeListRequest struct { ListOptions // Sort ascending when `true` (the default); descending when `false`. Asc *bool `json:"asc,omitempty" toon:"asc,omitempty"` - // Filter by category. Accepts a comma-separated list, for example `event.alert,event.change`. + // 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. Category string `json:"category,omitempty" toon:"category,omitempty"` // Sort field. When omitted, types are returned in console ranking order. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` @@ -5940,35 +6173,45 @@ type InvestigationTimeRange struct { type InviteMemberItem struct { // ISO 3166-1 alpha-2 region code for `phone` (e.g. "CN"). Validated and normalized to upper case before storage; invalid values are rejected with a 400. Also the parsing hint when `phone` has no "+" prefix (defaults to "CN"). CountryCode string `json:"country_code,omitempty" toon:"country_code,omitempty"` - // Email address. Required when `phone` is not provided. + // Email address, stored in lower case. Required when `phone` is not provided. Email string `json:"email,omitempty" toon:"email,omitempty"` - // Locale. One of: `zh-CN` (Simplified Chinese), `en-US` (English); other values are rejected with a 400. + // Locale: `zh-CN` (Simplified Chinese) or `en-US` (English); other values are rejected with a 400. Defaults to the account's locale when omitted. Locale string `json:"locale,omitempty" toon:"locale,omitempty"` // Display name, 2–39 characters. Required when `email` is not provided; derived from the email prefix when omitted. MemberName string `json:"member_name,omitempty" toon:"member_name,omitempty"` // Phone number. Required when `email` is not provided. Phone string `json:"phone,omitempty" toon:"phone,omitempty"` - // External reference ID + // External reference ID (for example an employee ID in an HR system), usable later as a lookup key in `POST /member/delete` and `POST /member/info/reset`. RefID string `json:"ref_id,omitempty" toon:"ref_id,omitempty"` - // Role IDs to assign + // Role IDs to assign: built-in `2` (Admin), `6` (Responder), `8` (Viewer), or custom role IDs from `POST /role/list`. Defaults to Viewer (`8`) when omitted; an ID that does not exist returns `400`. RoleIDs []uint64 `json:"role_ids,omitempty" toon:"role_ids,omitempty"` - // Time zone + // IANA time zone name such as `Asia/Shanghai`. Omit it to have the member follow the account's time zone; an invalid name returns `400`. TimeZone string `json:"time_zone,omitempty" toon:"time_zone,omitempty"` } // KnowledgeFileDeleteRequest is generated from the Flashduty OpenAPI schema. type KnowledgeFileDeleteRequest struct { + // Optimistic-concurrency guard. `0` or omitted: delete unconditionally. A positive value: delete only if the knowledge's current `version` equals it; otherwise nothing is deleted and the call returns HTTP 200 with `status` = `conflict` and the current `version`. + ExpectedVersion int64 `json:"expected_version,omitempty" toon:"expected_version,omitempty"` // Delete even when other knowledge files reference this file; the referrers are then returned as warnings instead of blocking the delete. Force bool `json:"force,omitempty" toon:"force,omitempty"` // Knowledge ID; defaults to the caller's account-scope knowledge. PackID string `json:"pack_id,omitempty" toon:"pack_id,omitempty"` - // Path of the file relative to the knowledge root. + // Path of the file relative to the knowledge root. Same path rules as `POST /safari/knowledge/file/put`. RelPath string `json:"rel_path" toon:"rel_path"` } // KnowledgeFileDeleteResponse is generated from the Flashduty OpenAPI schema. type KnowledgeFileDeleteResponse struct { - // Non-blocking warnings after deletion; `code=still_referenced_by` means the (force-)deleted file is still @ref-referenced by other files in the knowledge (`refs` lists the referrers). Absent when there are no warnings (omitempty). + // Explanation of the conflict. Present only when `status` is `conflict`. + Message string `json:"message" toon:"message"` + // Outcome of the delete. + // - `ok`: the file was deleted, or did not exist. + // - `conflict`: `expected_version` did not match the current knowledge version, so nothing was deleted. + Status string `json:"status" toon:"status"` + // Knowledge `version` after the delete (unchanged if the file did not exist). When the file did not exist and `expected_version` was not sent, this is `0`. On `conflict`, the current version. + Version int64 `json:"version" toon:"version"` + // Non-blocking warnings; `still_referenced_by` means `force` deleted a file that other files still reference (`refs` lists them). Omitted when there are no warnings. Warnings []KnowledgeWarning `json:"warnings" toon:"warnings"` } @@ -5976,28 +6219,31 @@ type KnowledgeFileDeleteResponse struct { type KnowledgeFileGetRequest struct { // Knowledge ID; defaults to the caller's account-scope knowledge. PackID string `json:"pack_id,omitempty" toon:"pack_id,omitempty"` - // Path of the file relative to the knowledge root. + // Path of the file relative to the knowledge root. If no file exists at this path, the call still succeeds with `file` set to `null` and an empty `content_b64`. RelPath string `json:"rel_path" toon:"rel_path"` } // KnowledgeFileGetResponse is generated from the Flashduty OpenAPI schema. type KnowledgeFileGetResponse struct { - // Base64-encoded file content; decodes to UTF-8 text. - ContentB64 string `json:"content_b64" toon:"content_b64"` - File KnowledgeFileItem `json:"file" toon:"file"` + // Base64-encoded file content. Empty string when the file does not exist (or is empty). + ContentB64 string `json:"content_b64" toon:"content_b64"` + // Metadata of the file; `null` when no file exists at `rel_path`. + File any `json:"file" toon:"file"` + // Current `version` of the knowledge. Pass it as `expected_version` to `POST /safari/knowledge/file/put` or `POST /safari/knowledge/file/delete` to reject the write if someone else changed the knowledge in between. + Version int64 `json:"version" toon:"version"` } // KnowledgeFileItem is generated from the Flashduty OpenAPI schema. type KnowledgeFileItem struct { // SHA-256 hex digest of the file content. Checksum string `json:"checksum" toon:"checksum"` - // MIME type; inferred from the file extension when not set on upload. + // MIME type stored with the file. Open set: when `content_type` is omitted on write it is derived from the extension of `rel_path` — `.md` → `text/markdown`, `.yaml`/`.yml` → `text/yaml`, `.json` → `application/json`, `.sh` → `text/x-sh`, anything else → `text/plain`; a value passed explicitly is stored as given. ContentType string `json:"content_type" toon:"content_type"` // File ID (`kfl_` prefix). FileID string `json:"file_id" toon:"file_id"` // ID of the knowledge that contains the file. PackID string `json:"pack_id" toon:"pack_id"` - // Path relative to the knowledge root, e.g. `runbooks/restart.md`. + // Path relative to the knowledge root, using `/` separators, e.g. `runbooks/restart.md`. Unique within the knowledge. RelPath string `json:"rel_path" toon:"rel_path"` // File size in bytes. SizeBytes int64 `json:"size_bytes" toon:"size_bytes"` @@ -6018,26 +6264,39 @@ type KnowledgeFileListRequest struct { type KnowledgeFileListResponse struct { // Array of files in the specified knowledge; empty array when it has no files. Files []KnowledgeFileItem `json:"files" toon:"files"` - // Total number of files in the knowledge. + // Number of files in `files` — always the full file count of the knowledge, since this endpoint does not paginate. Total int64 `json:"total" toon:"total"` + // Current `version` of the knowledge; usable as `expected_version` for file writes. + Version int64 `json:"version" toon:"version"` } // KnowledgeFilePutRequest is generated from the Flashduty OpenAPI schema. type KnowledgeFilePutRequest struct { - // Base64-encoded file content; must decode to valid UTF-8 text (binary is rejected). Per-file limit 1 MiB. + // Base64-encoded (standard alphabet) file content. The decoded bytes must be UTF-8 text with no NUL bytes and at most 1 MiB (`DUTY.md`: at most 32 KiB). Omit or send an empty string to write an empty file. ContentB64 string `json:"content_b64,omitempty" toon:"content_b64,omitempty"` - // MIME type; inferred from the file extension when omitted. + // MIME type to store with the file. Optional: when omitted it is derived from the extension of `rel_path` (`.md` → `text/markdown`, `.yaml`/`.yml` → `text/yaml`, `.json` → `application/json`, `.sh` → `text/x-sh`, otherwise `text/plain`). Any value passed is stored as given. ContentType string `json:"content_type,omitempty" toon:"content_type,omitempty"` + // Optimistic-concurrency guard. `0` or omitted: write unconditionally. A positive value: write only if the knowledge's current `version` equals it; otherwise nothing is written and the call returns HTTP 200 with `status` = `conflict` and the current `version`. + ExpectedVersion int64 `json:"expected_version,omitempty" toon:"expected_version,omitempty"` // Knowledge ID; defaults to the caller's account-scope knowledge. PackID string `json:"pack_id,omitempty" toon:"pack_id,omitempty"` - // Destination path relative to the knowledge root; existing files are overwritten. + // Destination path relative to the knowledge root; an existing file at this path is overwritten. Must use `/` separators, must not start with `/`, must already be in normalized form, and no segment may be empty, `.`, `..`, or start with `.` (dotfiles are rejected). RelPath string `json:"rel_path" toon:"rel_path"` } // KnowledgeFilePutResponse is generated from the Flashduty OpenAPI schema. type KnowledgeFilePutResponse struct { + // The file as stored after the write. Omitted when `status` is `conflict`. File KnowledgeFileItem `json:"file" toon:"file"` - // Non-blocking warnings after a successful write; `code=unresolved_reference` means an @ref in the file content points to a file that does not exist in the knowledge. Absent when there are no warnings (omitempty). + // Explanation of the conflict (`this knowledge was updated by someone else`). Present only when `status` is `conflict`. + Message string `json:"message" toon:"message"` + // Outcome of the write. + // - `ok`: the change was committed. + // - `conflict`: `expected_version` did not match the current knowledge version, so nothing was changed; re-read the file and retry with the returned `version`. + Status string `json:"status" toon:"status"` + // Knowledge `version` produced by this write when `status` is `ok`; the current version when `status` is `conflict`. Use it as `expected_version` for the next write. + Version int64 `json:"version" toon:"version"` + // Non-blocking warnings; `unresolved_reference` means an @ref in the written content points to a path that does not exist in the knowledge. Omitted when there are no warnings. Warnings []KnowledgeWarning `json:"warnings" toon:"warnings"` } @@ -6059,15 +6318,17 @@ type KnowledgePackDeleteRequest struct { // KnowledgePackDeleteResponse is generated from the Flashduty OpenAPI schema. type KnowledgePackDeleteResponse struct { - // True when the knowledge was deleted. + // Always `true` on success; a failed delete returns an error instead. OK bool `json:"ok" toon:"ok"` } // KnowledgePackEnsureRequest is generated from the Flashduty OpenAPI schema. type KnowledgePackEnsureRequest struct { - // Scope of the knowledge to ensure. One of: `account` (account-level knowledge; scope_id is forced to the caller's account ID and only account admins may create it; first creation seeds a default DUTY.md), `team` (team-level knowledge; the `scope_id` team ID is required and the caller must belong to that team). + // Scope of the knowledge to ensure. + // - `account`: the account knowledge. `scope_id` is replaced by the caller's account ID; only the account owner and admins may call this, even when the knowledge already exists. If the knowledge has no `DUTY.md`, a default one is written. + // - `team`: the knowledge of the team in `scope_id`. `scope_id` is required and the caller must be a member of that team. Scope string `json:"scope" toon:"scope"` - // Team ID; required for `team` scope, ignored for `account` scope. + // Team ID. Required (non-zero) for `team` scope, otherwise the request fails with `InvalidParameter`; ignored for `account` scope. ScopeID int64 `json:"scope_id,omitempty" toon:"scope_id,omitempty"` } @@ -6075,42 +6336,48 @@ type KnowledgePackEnsureRequest struct { type KnowledgePackItem struct { // Account that owns the knowledge. AccountID int64 `json:"account_id" toon:"account_id"` - // Whether the caller can edit this knowledge. + // Whether the caller can change this knowledge and its files: for `account` scope, `true` only for the account owner and admins; for `team` scope, `true` only when the caller is a member of that team (owners and admins are not exempt). CanEdit bool `json:"can_edit" toon:"can_edit"` // Unix timestamp in milliseconds when the knowledge was created. CreatedAtMs TimestampMilli `json:"created_at_ms" toon:"created_at_ms"` - // Person ID of the member who created the knowledge. + // Person ID of the member whose request created the knowledge. Account knowledge is created automatically by the first request that needs it, so this can be any member of the account. CreatedBy int64 `json:"created_by" toon:"created_by"` - // Knowledge version at which DUTY.md was last authored or re-affirmed. When `version` is greater, DUTY.md no longer reflects every file in the knowledge. + // The `version` at which `DUTY.md` was last written. Writing `DUTY.md` sets it to the new `version`; when `version` is greater, files were added, changed or deleted after `DUTY.md` was last updated, so `DUTY.md` may no longer index every file. DutyVersion int64 `json:"duty_version" toon:"duty_version"` - // Number of files in the knowledge. + // Number of files currently in the knowledge. FileCount int64 `json:"file_count" toon:"file_count"` // Knowledge ID (`kpk_` prefix). PackID string `json:"pack_id" toon:"pack_id"` - // Knowledge scope. `channel` is a legacy scope; new knowledge is `account` or `team` scope. + // Knowledge scope. + // - `account`: account-level knowledge shared by the whole account; `scope_id` is the account ID. + // - `team`: knowledge owned by one team; `scope_id` is the team ID. + // - `channel`: legacy scope. It cannot be created or moved into through this API and is never returned by `POST /safari/knowledge/pack/list`; it can only appear when such knowledge is addressed directly by `pack_id`. Scope string `json:"scope" toon:"scope"` // Scope owner: the account ID for `account` scope, the team ID for `team` scope. ScopeID int64 `json:"scope_id" toon:"scope_id"` // Display name of the owning team (team scope only). Omitted when empty (account scope, or the team name could not be resolved). TeamName string `json:"team_name" toon:"team_name"` - // Total size of all files in bytes. + // Total size of all files in bytes. Capped at 5 MiB per knowledge. TotalBytes int64 `json:"total_bytes" toon:"total_bytes"` // Unix timestamp in milliseconds when the knowledge was last modified. UpdatedAtMs TimestampMilli `json:"updated_at_ms" toon:"updated_at_ms"` - // Knowledge version, incremented on every file change. + // Knowledge version. Starts at 0 and increases by 1 on every file write or file deletion. Moving the knowledge to another scope does not change it. Version int64 `json:"version" toon:"version"` } // KnowledgePackListRequest is generated from the Flashduty OpenAPI schema. type KnowledgePackListRequest struct { ListOptions - // Include the account-scope knowledge; defaults to true. + // Whether to include the account knowledge when `scope` is `all` or omitted. Defaults to `true`. IncludeAccount *bool `json:"include_account,omitempty" toon:"include_account,omitempty"` - // Case-insensitive substring filter over knowledge ID, scope, scope ID/account ID, and team name. + // Case-insensitive substring filter over knowledge ID, scope, scope ID, account ID and team name. Account knowledge also matches `账户`/`账号` and team knowledge also matches `团队`. Leading and trailing spaces are ignored. Query string `json:"query,omitempty" toon:"query,omitempty"` - // Restrict to one scope; `all` (default) overrides `include_account`. One of: `all` (account scope plus visible team scopes), `account` (account-level knowledge only), `team` (team-level knowledge only, can be combined with `team_ids`). + // Which scopes to return: + // - `all` (default): account knowledge (unless `include_account` is `false`) plus the visible team knowledge. + // - `account`: only the account knowledge; `include_account` and `team_ids` are ignored. + // - `team`: only team knowledge, optionally narrowed by `team_ids`; `include_account` is ignored. Scope string `json:"scope,omitempty" toon:"scope,omitempty"` - // Restrict to these team IDs; for non-admins the list is intersected with their own teams. + // Restrict team knowledge to these team IDs. IDs of teams the caller does not belong to are silently dropped — this applies to every caller, including owners and admins. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` } @@ -6126,9 +6393,12 @@ type KnowledgePackListResponse struct { type KnowledgePackUpdateRequest struct { // Knowledge ID to update. PackID string `json:"pack_id" toon:"pack_id"` - // Destination scope; omit for a no-op that returns the current knowledge. + // Destination scope. Omit to leave the knowledge unchanged and get it back. + // - `account`: make it the account knowledge (only the account owner and admins). + // - `team`: move it to the team in `scope_id` (the caller must be a member of that team). + // Any other value returns `InvalidParameter`. If the destination already has knowledge, the request fails with `ReferenceExist`. Scope *string `json:"scope,omitempty" toon:"scope,omitempty"` - // Destination team ID; required when `scope` is `team`, set automatically for `account`. + // Destination team ID. Required (non-zero) when `scope` is `team`; ignored when `scope` is `account` (the account ID is used). ScopeID *int64 `json:"scope_id,omitempty" toon:"scope_id,omitempty"` } @@ -6136,9 +6406,9 @@ type KnowledgePackUpdateRequest struct { type KnowledgeWarning struct { // Warning code. One of: `unresolved_reference` (an @ref in the written file's content points to a file that does not exist in the knowledge; `ref` carries it), `still_referenced_by` (the deleted file is still @ref-referenced by other files in the knowledge; `refs` lists the referrers). Code string `json:"code" toon:"code"` - // Single reference related to the warning. + // Set only for `unresolved_reference`: the referenced path that does not exist in the knowledge. Ref string `json:"ref" toon:"ref"` - // Multiple references related to the warning. + // Set only for `still_referenced_by`: `rel_path` of every other file that still references the deleted file. Refs []string `json:"refs" toon:"refs"` } @@ -6189,8 +6459,8 @@ type ListChangeRequest struct { DataSourceID int64 `json:"data_source_id,omitempty" toon:"data_source_id,omitempty"` // Deprecated: use `integration_ids` instead. At least 1 entry when provided. DataSourceIDs []int64 `json:"data_source_ids,omitempty" toon:"data_source_ids,omitempty"` - // End of the query window, Unix epoch seconds. See `start_time` for defaults and constraints. - EndTime int64 `json:"end_time,omitempty" toon:"end_time,omitempty"` + // End of the query window, Unix seconds. Required in practice; see `start_time`. + EndTime int64 `json:"end_time" toon:"end_time"` // Structured filters ANDed onto the query (e.g. on labels). Keys prefixed with `incident` are ignored. Filters []FilterCondition `json:"filters,omitempty" toon:"filters,omitempty"` // Include the underlying change events for each change when true. @@ -6203,8 +6473,8 @@ type ListChangeRequest struct { Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` // Case-insensitive substring or regular-expression match over the change title, change_key, and description. An invalid regular expression falls back to a literal match. Query string `json:"query,omitempty" toon:"query,omitempty"` - // Start of the query window, Unix epoch seconds. Optional — when both `start_time` and `end_time` are omitted or 0, the window defaults to the last hour. Must be less than `end_time`, with a span of at most 31 days. A change matches when its [start_time, last_time] window overlaps the query window. - StartTime int64 `json:"start_time,omitempty" toon:"start_time,omitempty"` + // Start of the query window, Unix seconds. Required in practice: it must be less than `end_time`, and the window can span at most 31 days. A change matches when its [start_time, last_time] range overlaps the window. + StartTime int64 `json:"start_time" toon:"start_time"` } // ListChangeResponse is generated from the Flashduty OpenAPI schema. @@ -6226,29 +6496,29 @@ type ListChannelsRequest struct { ChannelIDs []int64 `json:"channel_ids,omitempty" toon:"channel_ids,omitempty"` // Exact-match filter on channel name. Takes priority over `query` for name filtering. Must be valid UTF-8 — invalid byte sequences are rejected with `InvalidParameter`. ChannelName string `json:"channel_name,omitempty" toon:"channel_name,omitempty"` - // When true, return only `channel_id`, `channel_name`, `description` and `status`, and return all matches without pagination. + // When true, return only `channel_id`, `channel_name`, `description`, `status` and `is_starred` for each channel, with all matches in one page. IsBrief bool `json:"is_brief,omitempty" toon:"is_brief,omitempty"` - // When true, return only channels the caller manages. + // When true, return only channels owned by one of the caller's teams or created by the caller. Takes precedence over `is_my_team` and `is_my_starred`. IsMyManaged bool `json:"is_my_managed,omitempty" toon:"is_my_managed,omitempty"` - // When true, return only channels the caller has starred. Mutually exclusive with `is_my_team`. + // When true, return only channels the caller has starred. Cannot be combined with `is_my_team`. IsMyStarred bool `json:"is_my_starred,omitempty" toon:"is_my_starred,omitempty"` - // When true, return channels owned by the caller's teams. Mutually exclusive with `is_my_starred`. + // When true, return only channels whose owning team is one of the caller's teams. Cannot be combined with `is_my_starred`. IsMyTeam bool `json:"is_my_team,omitempty" toon:"is_my_team,omitempty"` - // Field used to order results. Defaults to `created_at`. + // Sort field, default `created_at`. `ranking` uses the caller's own channel order saved in the console and falls back to creation order when none is saved; `channel_name` sorts case-insensitively. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` // Case-insensitive regular expression matched against channel name and description; invalid regex syntax falls back to a literal match. Must be valid UTF-8 — invalid byte sequences are rejected with `InvalidParameter`. Query string `json:"query,omitempty" toon:"query,omitempty"` - // Filter by team IDs. + // Return only channels owned by these teams. Ignored when `is_my_managed` or `is_my_team` is true. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` } // ListChannelsResponse is generated from the Flashduty OpenAPI schema. type ListChannelsResponse struct { - // Whether more pages are available. + // Whether more pages follow. Reliable only when `p` is passed. HasNextPage bool `json:"has_next_page" toon:"has_next_page"` // Channels on the current page. Items []ChannelItem `json:"items" toon:"items"` - // Total matching channels. + // Total number of matching channels across all pages. Total int64 `json:"total" toon:"total"` } @@ -6260,7 +6530,7 @@ type ListDropRulesResponse struct { // ListEscalationRulesResponse is generated from the Flashduty OpenAPI schema. type ListEscalationRulesResponse struct { - // All escalation rules of the channel, excluding deleted ones, ordered by priority ascending. + // Escalation rules of the channel, excluding deleted ones, in evaluation order: ascending `priority`, then creation time. Items []EscalateRuleItem `json:"items" toon:"items"` } @@ -6277,7 +6547,7 @@ type ListIncidentAlertsRequest struct { // ListIncidentAlertsResponse is generated from the Flashduty OpenAPI schema. type ListIncidentAlertsResponse struct { - // Alert list. + // Alerts on the requested page; an empty array when no alert matches. Items []AlertInfo `json:"items" toon:"items"` // Total matching alerts. Total int64 `json:"total" toon:"total"` @@ -6299,7 +6569,7 @@ type ListIncidentFeedRequest struct { Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` // Incident ID (MongoDB ObjectID). IncidentID string `json:"incident_id" toon:"incident_id"` - // Optional filter restricting the returned entries to specific types. + // Return only entries of these types; omit to return all types. Types []IncidentFeedType `json:"types,omitempty" toon:"types,omitempty"` } @@ -6334,9 +6604,11 @@ type ListIncidentsRequest struct { EndTime int64 `json:"end_time" toon:"end_time"` // When true, include only incidents that were ever silenced. EverMuted bool `json:"ever_muted,omitempty" toon:"ever_muted,omitempty"` + // When true, include only incidents that still have an action item or follow-up that is neither `done` nor `cancelled`. `false` applies no filter. + HasUnfinishedWorkItem bool `json:"has_unfinished_work_item,omitempty" toon:"has_unfinished_work_item,omitempty"` // Restrict to the given incident IDs. IncidentIDs []string `json:"incident_ids,omitempty" toon:"incident_ids,omitempty"` - // Comma-separated list of severities (`Critical,Warning,Info`). + // Comma-separated severities to match, for example `Critical,Warning`. Values: `Critical` most severe, `Warning`, `Info` least severe. IncidentSeverity string `json:"incident_severity,omitempty" toon:"incident_severity,omitempty"` // When true, restrict to incidents in channels the user personally owns. IsMyChannel bool `json:"is_my_channel,omitempty" toon:"is_my_channel,omitempty"` @@ -6348,7 +6620,7 @@ type ListIncidentsRequest struct { IsSnoozed bool `json:"is_snoozed,omitempty" toon:"is_snoozed,omitempty"` // Filter by incident short numbers (the numbers shown before incident titles in the console). Nums []string `json:"nums,omitempty" toon:"nums,omitempty"` - // Comma-separated list of progress states to match (e.g. `Triggered,Processing`). + // Comma-separated progress states to match, for example `Triggered,Processing`. Values: `Triggered` not yet acknowledged; `Processing` acknowledged and being handled; `Closed` resolved. Omit to match every state. Progress string `json:"progress,omitempty" toon:"progress,omitempty"` // Full-text search query. Query string `json:"query,omitempty" toon:"query,omitempty"` @@ -6380,23 +6652,23 @@ type ListIntegrationsRequest struct { ListOptions // Sort ascending when true, descending when false. Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` - // Filter by category. Accepts a comma-separated list. + // 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. Category string `json:"category,omitempty" toon:"category,omitempty"` // Limit the result to integrations owned by your teams. IsMyTeam bool `json:"is_my_team,omitempty" toon:"is_my_team,omitempty"` - // Filter by integration name. + // Filter by integration name; matches any name that contains this text. Name string `json:"name,omitempty" toon:"name,omitempty"` // Sort field. Defaults to `created_at`; `plugin_type` is sorted by the underlying plugin. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` - // Filter by integration type. Accepts a comma-separated list. + // Comma-separated integration type keys, for example `standard.alert,prometheus.alert`; the keys are the `plugin_type` values from `POST /integration/type/list`. PluginType string `json:"plugin_type,omitempty" toon:"plugin_type,omitempty"` // Filter by source reference IDs. Each value must start with `c_` (channel), `a_` (account) or `w_`. RefIDs []string `json:"ref_ids,omitempty" toon:"ref_ids,omitempty"` - // Filter by status. Accepts a comma-separated list. + // Comma-separated status filter: `enabled` (accepting events) and/or `disabled` (paused). Status string `json:"status,omitempty" toon:"status,omitempty"` // Filter by team IDs. With `is_my_team`, the values narrow that set further. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` - // Deprecated. Merged into `plugin_type` when both are set. + // Deprecated alias of `plugin_type` (comma-separated type keys such as `prometheus.alert`, `zabbix.alert`). Ignored when `plugin_type` is also set. Type string `json:"type,omitempty" toon:"type,omitempty"` } @@ -6426,9 +6698,9 @@ type ListPastIncidentsResponse struct { // ListPostMortemTemplatesRequest is generated from the Flashduty OpenAPI schema. type ListPostMortemTemplatesRequest struct { ListOptions - // Ascending order when true. + // Sort custom templates in ascending order when true; default false (newest first). Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` - // Field used to order results. + // Sort field for custom templates. Only `created_at_seconds` is supported, which is also the default. OrderBy string `json:"order_by,omitempty" toon:"order_by,omitempty"` } @@ -6436,11 +6708,9 @@ type ListPostMortemTemplatesRequest struct { type ListPostMortemTemplatesResponse struct { // True when another page is available. HasNextPage bool `json:"has_next_page" toon:"has_next_page"` - // Templates in the current page. + // Templates on this page; the built-in template is first on page 1. Items []PostMortemTemplate `json:"items" toon:"items"` - // Cursor for forward pagination. - SearchAfterCtx string `json:"search_after_ctx" toon:"search_after_ctx"` - // Total matching templates. + // Total number of templates, including the built-in one. Total int64 `json:"total" toon:"total"` } @@ -6455,7 +6725,7 @@ type ListPostMortemsRequest struct { CreatedAtEndSeconds int64 `json:"created_at_end_seconds,omitempty" toon:"created_at_end_seconds,omitempty"` // Lower bound of post-mortem creation time (Unix timestamp in seconds). CreatedAtStartSeconds int64 `json:"created_at_start_seconds,omitempty" toon:"created_at_start_seconds,omitempty"` - // Field used to order results. + // Sort field: `created_at_seconds` creation time, `updated_at_seconds` last update time. OrderBy string `json:"order_by,omitempty" toon:"order_by,omitempty"` // Optional status filter: `drafting` returns only drafts, `published` returns only published post-mortems. When omitted, post-mortems in all statuses are returned. Status string `json:"status,omitempty" toon:"status,omitempty"` @@ -6478,27 +6748,32 @@ type ListPostMortemsResponse struct { // ListRemoteConfigHistoryRequest is generated from the Flashduty OpenAPI schema. type ListRemoteConfigHistoryRequest struct { ListOptions - // RUM application ID. + // RUM application ID. Get application IDs via `POST /rum/application/list`. ApplicationID string `json:"application_id" toon:"application_id"` // Ascending order. Default: false (descending). Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` - // Sort field. Default: `updated_at`. + // Sort field: + // + // - `updated_at`: publish time (default). + // - `version`: version number. + // + // Any other value falls back to `updated_at`. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` } // ListRemoteConfigHistoryResponse is generated from the Flashduty OpenAPI schema. type ListRemoteConfigHistoryResponse struct { - // Whether more pages remain. + // `true` when more versions remain after this page. HasNextPage bool `json:"has_next_page" toon:"has_next_page"` - // Version items, newest first by default. + // Versions on this page, newest first by default. Empty array when the application has never been configured. Items []RemoteConfigHistoryItem `json:"items" toon:"items"` - // Total number of versions. + // Number of retained versions (at most 50). Total int64 `json:"total" toon:"total"` } // ListRoutesRequest is generated from the Flashduty OpenAPI schema. type ListRoutesRequest struct { - // Integration IDs to fetch routing rules for. + // Shared integration IDs to fetch routing rules for, at least one; obtain them from `POST /integration/list`. IntegrationIDs []int64 `json:"integration_ids" toon:"integration_ids"` } @@ -6554,9 +6829,9 @@ type ListWebhookHistoryRequest struct { EndTime int64 `json:"end_time" toon:"end_time"` // Filter by event type codes (e.g. `i_new` incident created, `a_new` alert triggered). EventTypes []string `json:"event_types,omitempty" toon:"event_types,omitempty"` - // Filter by webhook integration ID. + // Filter by webhook integration ID; `0` or omitted returns all integrations. IntegrationID int64 `json:"integration_id,omitempty" toon:"integration_id,omitempty"` - // Page size. + // Number of records per page, 1–100. Limit int64 `json:"limit" toon:"limit"` // Sort field. Currently only `event_time` is supported. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` @@ -6576,23 +6851,23 @@ type ListWebhookHistoryResponse struct { Items []WebhookHistoryItem `json:"items" toon:"items"` // Cursor to pass as `search_after_ctx` to fetch the next page. Empty when no further pages are available. SearchAfterCtx string `json:"search_after_ctx" toon:"search_after_ctx"` - // Total number of matching records. + // Total number of records matching the filters, not capped. Total int64 `json:"total" toon:"total"` } // ListWorkItemRequest is generated from the Flashduty OpenAPI schema. type ListWorkItemRequest struct { - // Restrict results to items assigned to this member ID. Listing by assignee alone requires being that assignee or an account admin. Ignored when `assignee_type` is `ai_sre`. + // Restrict results to items assigned to this member ID. Listing by assignee alone requires being that member or an account owner or admin. Ignored when `assignee_type` is `ai_sre`. AssigneeID int64 `json:"assignee_id,omitempty" toon:"assignee_id,omitempty"` // Filter by assignee type: `person` or `ai_sre`. `ai_sre` returns items assigned to AI SRE (an AI caller uses this to list its own tasks) and does not require `assignee_id`. `person` together with `assignee_id` restricts results to that member. Omitted with a positive `assignee_id` means `person`. AssigneeType string `json:"assignee_type,omitempty" toon:"assignee_type,omitempty"` - // Pagination cursor from a previous response's `next_cursor`. + // Opaque cursor from a previous response's `next_cursor`. An invalid cursor returns `InvalidParameter`. Cursor string `json:"cursor,omitempty" toon:"cursor,omitempty"` // Incident ID (MongoDB ObjectID). Also returns follow-ups anchored on the incident's post-mortem. IncidentID string `json:"incident_id,omitempty" toon:"incident_id,omitempty"` // Filter by work item type: `action` action item, `follow_up` post-mortem follow-up. ItemType string `json:"item_type,omitempty" toon:"item_type,omitempty"` - // Page size, at most 200. Defaults to 50. + // Page size. 0, negative or omitted means 50; values above 200 are treated as 200. Limit int64 `json:"limit,omitempty" toon:"limit,omitempty"` // Post-mortem ID (32-character hex string). Returns follow-ups bound to this post-mortem. PostMortemID string `json:"post_mortem_id,omitempty" toon:"post_mortem_id,omitempty"` @@ -6606,33 +6881,38 @@ type McpServerCreateRequest struct { AllowInsecureTlsSkipVerify bool `json:"allow_insecure_tls_skip_verify,omitempty" toon:"allow_insecure_tls_skip_verify,omitempty"` // Command arguments (stdio transport). Args []string `json:"args,omitempty" toon:"args,omitempty"` - // Authentication mode: shared (default), per_user_secret, or per_user_oauth. + // Who supplies the credential: + // - `shared` (default; an empty value behaves the same): one credential stored on the server (`env` / `headers`) is used for every caller. + // - `per_user_secret`: each user stores their own secret, sent in the header named by `secret_schema.header_name`. + // - `per_user_oauth`: each user completes their own OAuth authorization; discovery and client registration run on first use. + // + // `per_user_secret` requires `secret_schema` with a non-empty `header_name`; any other value returns `InvalidParameter`. AuthMode string `json:"auth_mode,omitempty" toon:"auth_mode,omitempty"` - // Tool-call timeout in seconds. 0 = default (60s). + // Tool-call timeout in seconds. Omitted or `0` is stored as `0` and means the 60-second default. CallTimeout int64 `json:"call_timeout,omitempty" toon:"call_timeout,omitempty"` // Executable command (stdio transport). Command string `json:"command,omitempty" toon:"command,omitempty"` - // Connection timeout in seconds. 0 = default (10s). + // Connection timeout in seconds. Omitted or `0` is stored as `0` and means the 10-second default. ConnectTimeout int64 `json:"connect_timeout,omitempty" toon:"connect_timeout,omitempty"` // Server description. Description string `json:"description" toon:"description"` - // Environment variables (stdio transport). + // Environment variables (`stdio` transport). Values under credential-looking names (containing `KEY`, `SECRET`, `TOKEN`, `PASSWORD`, …) are encrypted at rest and masked in responses. Env map[string]string `json:"env,omitempty" toon:"env,omitempty"` // Execution environments this server is callable from: `cloud` and/or BYOC runner environment IDs. Omitted or empty means all environments. Environments []string `json:"environments,omitempty" toon:"environments,omitempty"` - // HTTP headers (sse / streamable-http). + // HTTP headers (`sse` / `streamable-http` transport). Values under credential-looking names (containing `KEY`, `TOKEN`, `AUTHORIZATION`, …) are encrypted at rest and masked in responses. Headers map[string]string `json:"headers,omitempty" toon:"headers,omitempty"` // JSON OAuth metadata; reserved for per_user_oauth. OauthMetadata string `json:"oauth_metadata,omitempty" toon:"oauth_metadata,omitempty"` // JSON secret schema; required when auth_mode=per_user_secret. SecretSchema string `json:"secret_schema,omitempty" toon:"secret_schema,omitempty"` - // MCP server name: must start with a letter and contain only letters, digits, `-`, or `_` (`@` is reserved); unique within its scope (account-wide or one team), case-insensitive. + // MCP server name: must start with a letter and contain only letters, digits, `-`, or `_` (`@` is reserved); unique within its scope (account-wide or one team). ServerName string `json:"server_name" toon:"server_name"` - // Marketplace template name when created from a connector template. + // Name of the marketplace template to install. When set, the template must exist, the server is created at account scope, and the connection fields must match the template except for its declared parameter values. Cannot be changed later. SourceTemplateName string `json:"source_template_name,omitempty" toon:"source_template_name,omitempty"` // Initial status: `enabled` (default) or `disabled` (created but kept off). Status string `json:"status,omitempty" toon:"status,omitempty"` - // Team scope: 0 = account-wide; >0 = team. + // Team scope: `0` = account-wide (account owner or admin only); `>0` = a team the caller belongs to. Ignored when `source_template_name` is set — marketplace installs are always account-wide. TeamID int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` // Transport protocol: `stdio` launches a local process via `command`/`args`/`env`, `sse` / `streamable-http` connects to a remote service via `url`/`headers`. Transport string `json:"transport" toon:"transport"` @@ -6664,15 +6944,18 @@ type McpServerItem struct { AllowInsecureTlsSkipVerify bool `json:"allow_insecure_tls_skip_verify" toon:"allow_insecure_tls_skip_verify"` // Command arguments (stdio transport). Args []string `json:"args" toon:"args"` - // Authentication mode. One of: `shared` (a single static credential saved on the resource and shared by all callers in the account; the default — an empty value behaves the same), `per_user_secret` (each user stores their own secret per `secret_schema`, injected per user at runtime), `per_user_oauth` (each user completes their own OAuth grant; discovery and registration run lazily on first use). + // Who supplies the credential; omitted when empty, which behaves like `shared`: + // - `shared`: one credential stored on the server (`env` / `headers`) is used for every caller. + // - `per_user_secret`: each user stores their own secret, sent in the header named by `secret_schema.header_name`. + // - `per_user_oauth`: each user completes their own OAuth authorization; discovery and client registration run on first use. AuthMode string `json:"auth_mode" toon:"auth_mode"` - // Tool-call timeout in seconds (0 = server default, 60s). + // Tool-call timeout in seconds as stored; `0` means the 60-second default is used. CallTimeout int64 `json:"call_timeout" toon:"call_timeout"` - // Whether the caller may edit this server. + // Whether the caller may update, enable, disable, or delete this server: `true` for an account-scoped server only for the account owner or an admin, for a team server only for members of that team. Create and update responses always return `true`. CanEdit bool `json:"can_edit" toon:"can_edit"` // Executable command (stdio transport only). Command string `json:"command" toon:"command"` - // Connection timeout in seconds (0 = server default, 10s). + // Connection timeout in seconds as stored; `0` means the 10-second default is used. ConnectTimeout int64 `json:"connect_timeout" toon:"connect_timeout"` // Creation time. Unix timestamp in milliseconds. CreatedAt TimestampMilli `json:"created_at" toon:"created_at"` @@ -6680,28 +6963,34 @@ type McpServerItem struct { CreatedBy int64 `json:"created_by" toon:"created_by"` // Server description. Description string `json:"description" toon:"description"` - // Environment variables (stdio transport). Secret values are masked. + // Environment variables (`stdio` transport). Values under credential-looking names, or encrypted at rest, are masked: longer than 8 characters shows the first and last 4 characters around `****`, otherwise `****`. Omitted when empty. Env map[string]string `json:"env" toon:"env"` // Execution environments this server is callable from (`cloud` and/or BYOC runner environment IDs). Always present; `[]` means all environments (also the value on legacy rows created before this field). Environments []string `json:"environments" toon:"environments"` - // HTTP headers (sse / streamable-http). Secret values are masked. + // HTTP headers (`sse` / `streamable-http` transport), masked by the same rule as `env`. Omitted when empty. Headers map[string]string `json:"headers" toon:"headers"` // JSON-encoded OAuth metadata (per_user_oauth mode). OauthMetadata string `json:"oauth_metadata" toon:"oauth_metadata"` - // Outbound proxy URL used to reach the server. + // Outbound proxy URL used to reach the server. Not settable through the public API; omitted when empty. ProxyURL string `json:"proxy_url" toon:"proxy_url"` // JSON-encoded secret schema (per_user_secret mode). SecretSchema string `json:"secret_schema" toon:"secret_schema"` // Unique MCP server ID (prefix `mcp_`). ServerID string `json:"server_id" toon:"server_id"` - // MCP server name, unique within its scope (account-wide or one team), case-insensitive. + // MCP server name, unique within its scope (account-wide or one team). ServerName string `json:"server_name" toon:"server_name"` - // Marketplace template this connector was installed from; empty for user-authored. + // Marketplace template this server was installed from; omitted for servers created by hand. SourceTemplateName string `json:"source_template_name" toon:"source_template_name"` - // Server status. + // Whether the server's tools are offered to AI SRE sessions: + // - `enabled`: available (default on create). + // - `disabled`: kept but not offered; re-enable with `POST /safari/mcp/server/enable`. Status string `json:"status" toon:"status"` // Team scope: 0 = account-wide; >0 = the owning team. TeamID int64 `json:"team_id" toon:"team_id"` + // Error message from the last connection test; omitted when the last test succeeded or the server was never tested. + TestError string `json:"test_error" toon:"test_error"` + // Time of the last connection test, Unix timestamp in milliseconds; omitted if the server was never tested. + TestedAt TimestampMilli `json:"tested_at" toon:"tested_at"` // Transport protocol. One of: `stdio` (standard I/O to a local subprocess), `sse` (standalone SSE, the legacy MCP transport), `streamable-http` (the newer HTTP streaming transport). Transport string `json:"transport" toon:"transport"` // Last update time. Unix timestamp in milliseconds. @@ -6713,13 +7002,13 @@ type McpServerItem struct { // McpServerListRequest is generated from the Flashduty OpenAPI schema. type McpServerListRequest struct { ListOptions - // Include account-scoped (team_id=0) rows. Defaults to true. + // Include account-scoped (`team_id=0`) rows. Defaults to `true`; ignored when `scope` is `account` (always included) or `team` (never included). IncludeAccount *bool `json:"include_account,omitempty" toon:"include_account,omitempty"` // Case-insensitive substring search across name, description, AI-generated description, server ID, transport, URL, command, and source template name. Query string `json:"query,omitempty" toon:"query,omitempty"` // Restrict results to a scope: `account` for account-wide rows only, `team` for the caller's own visible team rows only, or omit (defaults to `all`) for both, subject to team_ids/include_account. Scope string `json:"scope,omitempty" toon:"scope,omitempty"` - // Filter to these team IDs; empty = the caller's visible set. + // Restrict to these team IDs. IDs of teams the caller does not belong to are ignored; empty means all of the caller's teams. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` } @@ -6745,35 +7034,40 @@ type McpServerUpdateRequest struct { AllowInsecureTlsSkipVerify *bool `json:"allow_insecure_tls_skip_verify,omitempty" toon:"allow_insecure_tls_skip_verify,omitempty"` // Command arguments (`stdio` transport); replaces the whole list — pass `[]` to clear, omit to leave unchanged. Args []string `json:"args,omitempty" toon:"args,omitempty"` - // Authentication mode: shared (default), per_user_secret, or per_user_oauth. + // New auth mode; omitted or empty leaves it unchanged. Who supplies the credential: + // - `shared` (default; an empty value behaves the same): one credential stored on the server (`env` / `headers`) is used for every caller. + // - `per_user_secret`: each user stores their own secret, sent in the header named by `secret_schema.header_name`. + // - `per_user_oauth`: each user completes their own OAuth authorization; discovery and client registration run on first use. + // + // `per_user_secret` requires `secret_schema` with a non-empty `header_name`; any other value returns `InvalidParameter`. AuthMode string `json:"auth_mode,omitempty" toon:"auth_mode,omitempty"` - // Tool-call timeout in seconds. 0 = default (60s). + // New tool-call timeout in seconds; omitted or `0` leaves it unchanged (a stored `0` means the 60-second default). CallTimeout int64 `json:"call_timeout,omitempty" toon:"call_timeout,omitempty"` - // Executable command (stdio transport). + // New executable command (`stdio` transport); omitted or empty leaves it unchanged. Command string `json:"command,omitempty" toon:"command,omitempty"` - // Connection timeout in seconds. 0 = default (10s). + // New connection timeout in seconds; omitted or `0` leaves it unchanged (a stored `0` means the 10-second default). ConnectTimeout int64 `json:"connect_timeout,omitempty" toon:"connect_timeout,omitempty"` // New description; omitted or empty leaves it unchanged. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Environment variables (`stdio` transport); replaces the whole map, but a sensitive key sent back masked or as an empty string keeps its stored value; omit to leave unchanged. + // Environment variables (`stdio` transport); replaces the whole map, so keys left out are removed. For a protected key (see the masking rule on get), sending the masked value or an empty string keeps the stored value. Omit to leave unchanged. Env map[string]string `json:"env,omitempty" toon:"env,omitempty"` // Execution environments this server is callable from: `cloud` and/or BYOC runner environment IDs. Omit (null) to leave unchanged; send a list to set it — an empty list clears the restriction back to all environments. Environments []string `json:"environments,omitempty" toon:"environments,omitempty"` // HTTP headers (`sse` / `streamable-http` transport); replaces the whole map, with the same masked/empty-value preservation as `env`; omit to leave unchanged. Headers map[string]string `json:"headers,omitempty" toon:"headers,omitempty"` - // JSON OAuth metadata; reserved for per_user_oauth. + // New JSON OAuth metadata. A non-empty value is stored as sent. When omitted or empty, the stored value is kept unless `auth_mode` or `url` changes, in which case it is cleared. OauthMetadata string `json:"oauth_metadata,omitempty" toon:"oauth_metadata,omitempty"` - // JSON secret schema; required when auth_mode=per_user_secret. + // New JSON secret schema, e.g. `{"header_name":"X-Api-Key"}`. Applied only together with a non-empty `auth_mode`; sent alone it is ignored. SecretSchema string `json:"secret_schema,omitempty" toon:"secret_schema,omitempty"` // Target MCP server ID, from the list returned by `POST /safari/mcp/server/list`. ServerID string `json:"server_id" toon:"server_id"` // New name; omitted or empty leaves it unchanged. ServerName string `json:"server_name,omitempty" toon:"server_name,omitempty"` - // Reassign team scope: 0 = account-wide; >0 = team. Omit to leave unchanged. + // Reassign team scope: `0` = account-wide (account owner or admin only); `>0` = a team the caller belongs to. Servers installed from the marketplace can only move to `0`. Omit to leave unchanged. TeamID *int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` // Transport protocol; when switching, also supply the matching fields (`command`/`args`/`env` for `stdio`, `url`/`headers` for `sse` / `streamable-http`); omitted or empty leaves it unchanged. Transport string `json:"transport,omitempty" toon:"transport,omitempty"` - // Server URL (sse / streamable-http transport). + // New server URL (`sse` / `streamable-http` transport); omitted or empty leaves it unchanged. A real change also clears `oauth_metadata` unless a new one is sent. URL string `json:"url,omitempty" toon:"url,omitempty"` } @@ -6789,7 +7083,7 @@ type ManualRunRuleResult struct { // MappingAPICreateRequest is generated from the Flashduty OpenAPI schema. type MappingAPICreateRequest struct { - // Unique API name (max 199 chars). + // Name of the mapping API, unique among non-deleted mapping APIs (max 199 characters). APIName string `json:"api_name" toon:"api_name"` // Optional description. Values longer than 500 characters are silently truncated. Description string `json:"description,omitempty" toon:"description,omitempty"` @@ -6797,13 +7091,13 @@ type MappingAPICreateRequest struct { Headers map[string]string `json:"headers,omitempty" toon:"headers,omitempty"` // Skip TLS certificate verification. Default `false`. InsecureSkipVerify bool `json:"insecure_skip_verify,omitempty" toon:"insecure_skip_verify,omitempty"` - // Number of retries on failure (0–1). Default 0. + // Number of retries after a failed call (0–1). Defaults to 0. RetryCount int64 `json:"retry_count,omitempty" toon:"retry_count,omitempty"` - // Owning team ID; obtain it from `POST /team/list`. + // Owning team ID; obtain it from `POST /team/list`. `0` or omitted means no team. A non-zero ID must be an existing team. TeamID int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` - // Request timeout in seconds (1–3). Default 2. + // Timeout of the whole request in seconds (1–3). Defaults to 2 when omitted or 0. Timeout int64 `json:"timeout,omitempty" toon:"timeout,omitempty"` - // HTTP/HTTPS endpoint URL (max 500 chars). + // Endpoint called with `POST`. Must be an `http` or `https` URL of at most 500 characters; in SaaS the host must not resolve to an internal IP address. URL string `json:"url" toon:"url"` } @@ -6811,7 +7105,7 @@ type MappingAPICreateRequest struct { type MappingAPICreateResponse struct { // Created API ID (MongoDB ObjectID hex). APIID string `json:"api_id" toon:"api_id"` - // API name. + // Name of the created mapping API, as sent in the request. APIName string `json:"api_name" toon:"api_name"` } @@ -6825,7 +7119,7 @@ type MappingApiidRequest struct { type MappingAPIItem struct { // API ID (MongoDB ObjectID hex). APIID string `json:"api_id" toon:"api_id"` - // API name. + // Name of the mapping API, unique among non-deleted mapping APIs. APIName string `json:"api_name" toon:"api_name"` // Creation time, Unix seconds. Omitted when 0 (legacy records). CreatedAt Timestamp `json:"created_at" toon:"created_at"` @@ -6833,19 +7127,19 @@ type MappingAPIItem struct { CreatorID int64 `json:"creator_id" toon:"creator_id"` // Deletion time, Unix seconds. Omitted when the API has not been soft-deleted. DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` - // Description. + // Free-text description (at most 500 characters); an empty string when none was given. Description string `json:"description" toon:"description"` - // Custom request headers. `null` when none are configured. + // Request headers sent with every call, returned in plain text to callers who can edit the API (the account owner or an admin, the API's creator, or a member of its team). `null` when none are configured or the caller cannot edit the API. Headers map[string]string `json:"headers" toon:"headers"` // Whether TLS verification is skipped. InsecureSkipVerify bool `json:"insecure_skip_verify" toon:"insecure_skip_verify"` - // Retry count. + // Number of retries after a failed call: `0` or `1`. RetryCount int64 `json:"retry_count" toon:"retry_count"` // API status: `enabled` or `deleted` (soft-deleted). The list endpoint excludes `deleted` items; the info endpoint may return them. Status string `json:"status" toon:"status"` // Owning team ID. TeamID int64 `json:"team_id" toon:"team_id"` - // Request timeout in seconds. + // Timeout of the whole request in seconds (1–3). Timeout int64 `json:"timeout" toon:"timeout"` // Last update time, Unix seconds. Omitted when 0 (legacy records). UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` @@ -6859,7 +7153,7 @@ type MappingAPIItem struct { type MappingAPIListResponse struct { // Mapping APIs. Items []MappingAPIItem `json:"items" toon:"items"` - // Total API count. + // Number of items returned; the list is not paginated. Total int64 `json:"total" toon:"total"` } @@ -6867,27 +7161,27 @@ type MappingAPIListResponse struct { type MappingAPIUpdateRequest struct { // Mapping API ID (MongoDB ObjectID hex). APIID string `json:"api_id" toon:"api_id"` - // New API name (max 199 chars). + // New name, unique among non-deleted mapping APIs (max 199 characters). Omit to keep. APIName *string `json:"api_name,omitempty" toon:"api_name,omitempty"` - // New description. + // New description; longer than 500 characters is truncated. Omit to keep, send `""` to clear. Description *string `json:"description,omitempty" toon:"description,omitempty"` - // Custom HTTP request headers. In SaaS mode, security-sensitive names (`authorization`, `cookie`, `x-forwarded-for`, etc.) are rejected; keys must be RFC 7230 token characters (max 1024 chars) and values max 4096 chars. + // Replaces the whole header map when sent; send `{}` to remove all headers. Omit to keep. In SaaS, sensitive header names (see `/enrichment/mapping/api/create`) are rejected; keys are at most 1,024 characters and values at most 4,096. Headers map[string]string `json:"headers,omitempty" toon:"headers,omitempty"` - // New TLS skip-verify setting. + // New TLS skip-verify setting. Omit to keep. InsecureSkipVerify *bool `json:"insecure_skip_verify,omitempty" toon:"insecure_skip_verify,omitempty"` - // New retry count. + // New retry count (0–1). Omit to keep. RetryCount *int64 `json:"retry_count,omitempty" toon:"retry_count,omitempty"` - // New owning team ID; obtain it from `POST /team/list`. + // New owning team ID from `POST /team/list`; `0` removes the team. Omit to keep. TeamID *int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` - // New timeout in seconds. + // New whole-request timeout in seconds (1–3). Omit to keep. Timeout *int64 `json:"timeout,omitempty" toon:"timeout,omitempty"` - // New endpoint URL (max 500 chars). + // New `http`/`https` endpoint (max 500 characters); in SaaS the host must not resolve to an internal IP. Omit to keep. URL *string `json:"url,omitempty" toon:"url,omitempty"` } // MappingDataDeleteRequest is generated from the Flashduty OpenAPI schema. type MappingDataDeleteRequest struct { - // Keys of rows to delete. + // Row keys to delete (at most 100), as returned in `key` by `/enrichment/mapping/data/list` or in `keys` by `/enrichment/mapping/data/upsert`. Keys that match no row are ignored. Keys []string `json:"keys" toon:"keys"` // Mapping schema ID (MongoDB ObjectID hex). SchemaID string `json:"schema_id" toon:"schema_id"` @@ -6895,7 +7189,7 @@ type MappingDataDeleteRequest struct { // MappingDataItem is generated from the Flashduty OpenAPI schema. type MappingDataItem struct { - // Creation time, Unix seconds. Omitted when 0. + // Time the row was last written, Unix seconds; a replaced row gets a new value. Omitted when 0. CreatedAt Timestamp `json:"created_at" toon:"created_at"` // All label key-value pairs of this row. Omitted when empty. Fields map[string]string `json:"fields" toon:"fields"` @@ -6908,7 +7202,7 @@ type MappingDataItem struct { // MappingDataListRequest is generated from the Flashduty OpenAPI schema. type MappingDataListRequest struct { ListOptions - // Sort ascending when `true`. + // Sort ascending when `true`; defaults to `false` (newest first). Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` // Sort field. Defaults to `updated_at`. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` @@ -6920,19 +7214,21 @@ type MappingDataListRequest struct { // MappingDataListResponse is generated from the Flashduty OpenAPI schema. type MappingDataListResponse struct { - // Whether more pages exist. + // `true` when more rows follow this page. HasNextPage bool `json:"has_next_page" toon:"has_next_page"` - // Data rows. + // Data rows of this page, ordered by `orderby`/`asc`. Empty when nothing matches. Items []MappingDataItem `json:"items" toon:"items"` // Cursor token (ObjectID hex of this page's last row) for fetching the next page. Omitted when there is no next page. SearchAfterCtx string `json:"search_after_ctx" toon:"search_after_ctx"` - // Total matching rows. + // Number of rows matching `query`, counted up to 1,000; a value of 1,000 means at least 1,000. Total int64 `json:"total" toon:"total"` + // Total number of rows stored in the schema, regardless of `query`. Compare it with the schema row limit (10,000 by default). + UsedCnt int64 `json:"used_cnt" toon:"used_cnt"` } // MappingDataUpsertRequest is generated from the Flashduty OpenAPI schema. type MappingDataUpsertRequest struct { - // Rows to insert or update. Each row must include all source and result labels; unknown labels are silently dropped; a value longer than 2048 characters is rejected. + // Rows to insert or replace (at most 1,000). Each row maps label names to values and must include every source and result label; other keys are dropped; a value longer than 2,048 bytes is rejected. A row whose source label values match an existing row replaces it. Docs []map[string]string `json:"docs" toon:"docs"` // Mapping schema ID (MongoDB ObjectID hex). SchemaID string `json:"schema_id" toon:"schema_id"` @@ -6940,7 +7236,7 @@ type MappingDataUpsertRequest struct { // MappingDataUpsertResponse is generated from the Flashduty OpenAPI schema. type MappingDataUpsertResponse struct { - // Composite keys of upserted rows. + // Row keys of the written rows (one per distinct row, in no particular order); use them with `/enrichment/mapping/data/delete`. Keys []string `json:"keys" toon:"keys"` } @@ -6950,11 +7246,11 @@ type MappingSchemaCreateRequest struct { Description string `json:"description,omitempty" toon:"description,omitempty"` // Output label names written on a match (1–10). Each must match `^[a-zA-Z_][a-zA-Z0-9_]*$`; entries must be unique and must not overlap with `source_labels`. ResultLabels []string `json:"result_labels" toon:"result_labels"` - // Unique schema name (max 39 chars). + // Schema name, unique among the account's non-deleted schemas (max 39 characters). SchemaName string `json:"schema_name" toon:"schema_name"` // Lookup key label names (1–3). Each must match `^[a-zA-Z_][a-zA-Z0-9_]*$`; entries must be unique and must not overlap with `result_labels`. SourceLabels []string `json:"source_labels" toon:"source_labels"` - // Owning team ID. `0` means no team. + // Owning team ID from `POST /team/list`. `0` or omitted means no team; a non-zero ID must be an existing team. TeamID int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` } @@ -6962,7 +7258,7 @@ type MappingSchemaCreateRequest struct { type MappingSchemaCreateResponse struct { // Created schema ID (MongoDB ObjectID hex). SchemaID string `json:"schema_id" toon:"schema_id"` - // Schema name. + // Name of the created schema, as sent in the request. SchemaName string `json:"schema_name" toon:"schema_name"` } @@ -6982,17 +7278,17 @@ type MappingSchemaItem struct { DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` // Schema description. Description string `json:"description" toon:"description"` - // Output label names. + // Label names written to the event when a row matches (1–10); fixed at creation. ResultLabels []string `json:"result_labels" toon:"result_labels"` // Schema ID (MongoDB ObjectID hex). SchemaID string `json:"schema_id" toon:"schema_id"` - // Schema name. + // Schema name, unique among the account's non-deleted schemas. SchemaName string `json:"schema_name" toon:"schema_name"` - // Lookup key label names. + // Label names whose values form the lookup key of a data row (1–3); fixed at creation. SourceLabels []string `json:"source_labels" toon:"source_labels"` // Schema status: `enabled` or `deleted` (soft-deleted). The list endpoint excludes `deleted` items; the info endpoint may return them. Status string `json:"status" toon:"status"` - // Owning team ID. + // Owning team ID; `0` when the schema belongs to no team. TeamID int64 `json:"team_id" toon:"team_id"` // Last update time, Unix seconds. Omitted when 0 (legacy records). UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` @@ -7004,19 +7300,19 @@ type MappingSchemaItem struct { type MappingSchemaListResponse struct { // Mapping schemas. Items []MappingSchemaItem `json:"items" toon:"items"` - // Total schema count. + // Number of items returned; the list is not paginated. Total int64 `json:"total" toon:"total"` } // MappingSchemaUpdateRequest is generated from the Flashduty OpenAPI schema. type MappingSchemaUpdateRequest struct { - // New description (max 500 chars). + // New description (max 500 characters). Omit to keep, send `""` to clear. Description *string `json:"description,omitempty" toon:"description,omitempty"` // Schema ID (MongoDB ObjectID hex). SchemaID string `json:"schema_id" toon:"schema_id"` - // New schema name (max 39 chars). + // New name, unique among non-deleted schemas (max 39 characters). Omit to keep. SchemaName *string `json:"schema_name,omitempty" toon:"schema_name,omitempty"` - // New owning team ID. `0` removes the team association. + // New owning team ID from `POST /team/list`; `0` removes the team. Omit to keep. TeamID *int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` } @@ -7026,7 +7322,7 @@ type MemberDeleteRequest struct { CountryCode string `json:"country_code,omitempty" toon:"country_code,omitempty"` // Email address. Only used when neither `member_id` nor `member_name` is provided Email string `json:"email,omitempty" toon:"email,omitempty"` - // Force delete. Defaults to false, which checks for references from escalation rules, schedules, etc. Set to true to skip the reference check and delete immediately + // Skip the reference check. When false (default), the call fails with `ReferenceExist` if the member belongs to a team, is targeted by an escalation rule, or is in a schedule. A forced delete does not remove those references. IsForce bool `json:"is_force,omitempty" toon:"is_force,omitempty"` // Member ID. When several lookup fields are provided, the first non-empty one wins in the order `member_id` > `member_name` > `email` > `phone` > `ref_id` MemberID uint64 `json:"member_id,omitempty" toon:"member_id,omitempty"` @@ -7048,17 +7344,17 @@ type MemberInfoRequest struct{} type MemberInfoResponse struct { // Account avatar URL AccountAvatar string `json:"account_avatar" toon:"account_avatar"` - // Account email + // Contact email of the account owner. AccountEmail string `json:"account_email" toon:"account_email"` - // Account ID + // ID of the account the member belongs to. AccountID uint64 `json:"account_id" toon:"account_id"` // Account-level locale preference (e.g. zh-CN or en-US). Omitted when the account has none set. AccountLocale string `json:"account_locale" toon:"account_locale"` - // Account name + // Name of the account (organization). AccountName string `json:"account_name" toon:"account_name"` - // Assigned role IDs + // IDs of the roles assigned to the member; resolve them with `POST /role/list`. AccountRoleIDs []uint64 `json:"account_role_ids" toon:"account_role_ids"` - // Account-level time zone (e.g. Asia/Shanghai). Omitted when the account has none set. + // The account's IANA time zone setting; empty string when the account has none. Always present. AccountTimeZone string `json:"account_time_zone" toon:"account_time_zone"` // Member avatar URL Avatar string `json:"avatar" toon:"avatar"` @@ -7066,7 +7362,7 @@ type MemberInfoResponse struct { CountryCode string `json:"country_code" toon:"country_code"` // Member creation time, Unix timestamp in seconds. CreatedAt Timestamp `json:"created_at" toon:"created_at"` - // Account domain + // Account domain, the subdomain used to sign in to the console. Domain string `json:"domain" toon:"domain"` // Email address Email string `json:"email" toon:"email"` @@ -7076,19 +7372,21 @@ type MemberInfoResponse struct { IsExternal bool `json:"is_external" toon:"is_external"` // Member's locale preference. Omitted when the member has none set. Locale string `json:"locale" toon:"locale"` - // Member ID + // ID of the calling member. MemberID uint64 `json:"member_id" toon:"member_id"` // Member display name MemberName string `json:"member_name" toon:"member_name"` // Account identifier on the marketplace platform. Omitted together with `mp_plat`. MpAccountID string `json:"mp_account_id" toon:"mp_account_id"` - // Cloud marketplace platform the account was provisioned from. Omitted when the account did not come from a marketplace. + // Cloud marketplace the account was provisioned from: `aws` — AWS Marketplace. Omitted when the account did not come from a marketplace. MpPlat string `json:"mp_plat" toon:"mp_plat"` // Masked phone number Phone string `json:"phone" toon:"phone"` // Whether phone is verified PhoneVerified bool `json:"phone_verified" toon:"phone_verified"` - // Member's IANA time zone. Omitted when the member has none set. + // Effective time zone to render times in: the member's `time_zone` if valid, otherwise the account's, otherwise `Asia/Shanghai`. Always present. + ResolvedTimeZone string `json:"resolved_time_zone" toon:"resolved_time_zone"` + // The member's own IANA time zone setting; empty string when the member follows the account's time zone. Always present. TimeZone string `json:"time_zone" toon:"time_zone"` } @@ -7102,43 +7400,43 @@ type MemberInviteRequest struct { // MemberInviteResponse is generated from the Flashduty OpenAPI schema. type MemberInviteResponse struct { - // Newly created members + // Members created by this call; entries skipped because they already exist are not listed. `null` when no member was created. Items []NewMemberItem `json:"items" toon:"items"` } // MemberItem is generated from the Flashduty OpenAPI schema. type MemberItem struct { - // Account ID + // ID of the account the member belongs to. AccountID uint64 `json:"account_id" toon:"account_id"` - // Role IDs + // IDs of the roles assigned to the member: built-in `2` (Admin), `6` (Responder), `8` (Viewer), or custom role IDs from `POST /role/list`. AccountRoleIDs []uint64 `json:"account_role_ids" toon:"account_role_ids"` - // Avatar URL + // Avatar image URL or path; empty string when unset. Avatar string `json:"avatar" toon:"avatar"` // ISO 3166-1 alpha-2 region code of the member's contact phone (e.g. "CN", "US", "HK"). CountryCode string `json:"country_code" toon:"country_code"` // Creation timestamp (Unix seconds) CreatedAt Timestamp `json:"created_at" toon:"created_at"` - // Email address + // Email address in lower case; empty string when unset. Email string `json:"email" toon:"email"` - // Email verified + // `true` once the member has verified the email address. EmailVerified bool `json:"email_verified" toon:"email_verified"` - // Provisioned via SSO + // `true` when the member was provisioned through SSO rather than invited or registered. IsExternal bool `json:"is_external" toon:"is_external"` - // Member's locale preference (e.g. `zh-CN`). Omitted when empty — the list endpoint does not populate it. + // Locale preference. Not populated by `POST /member/list`, so it is always omitted there. Locale string `json:"locale" toon:"locale"` - // Member ID + // Member ID; the same value is used as the person ID in other APIs (for example `person_ids`). MemberID uint64 `json:"member_id" toon:"member_id"` - // Display name + // Display name, unique in the account. MemberName string `json:"member_name" toon:"member_name"` - // Masked phone number + // Phone number in E.164 form with the middle digits masked (for example `+86151****6519`); empty string when unset. Phone string `json:"phone" toon:"phone"` - // Phone verified + // `true` once the member has verified the phone number. PhoneVerified bool `json:"phone_verified" toon:"phone_verified"` - // External reference ID + // External reference ID (for example an employee ID in an HR system); empty string when unset. RefID string `json:"ref_id" toon:"ref_id"` - // Member status. `enabled` — active member; `pending` — invited but not yet accepted; `deleted` — removed from the organization. + // Member status. `enabled` — active member; `pending` — invited but has not accepted yet. Removed members are not listed. Status string `json:"status" toon:"status"` - // Member's IANA time zone (e.g. `Asia/Shanghai`). Omitted when empty — the list endpoint does not populate it. + // The member's own IANA time zone setting (for example `Asia/Shanghai`). Omitted when unset, which means the member follows the account's time zone; `POST /member/info` returns the effective zone. TimeZone string `json:"time_zone" toon:"time_zone"` // Update timestamp (Unix seconds) UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` @@ -7153,7 +7451,7 @@ type MemberListRequest struct { MemberID uint64 `json:"member_id,omitempty" toon:"member_id,omitempty"` // Sort field. Default: `updated_at` Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` - // Substring match on member name or email; if the keyword parses as a phone number, an exact phone match is also applied + // Keyword. Matches a substring of the member name or email; a numeric keyword also matches an exact member ID, and a keyword that parses as a phone number (without `+`, parsed as a Chinese number) also matches the exact phone. Query string `json:"query,omitempty" toon:"query,omitempty"` // Filter by role ID. Get role IDs from `POST /role/list` (built-in roles: 2=Admin, 6=Responder, 8=Viewer) RoleID uint64 `json:"role_id,omitempty" toon:"role_id,omitempty"` @@ -7162,9 +7460,9 @@ type MemberListRequest struct { // MemberListResponse is generated from the Flashduty OpenAPI schema. type MemberListResponse struct { ListOptions - // Member items + // Members on this page; empty array when none match. Items []MemberItem `json:"items" toon:"items"` - // Total count + // Number of members matching the filters, across all pages. Total int64 `json:"total" toon:"total"` } @@ -7198,7 +7496,7 @@ type MemberNotifyResultItem struct { // MemberOncallInterval is generated from the Flashduty OpenAPI schema. type MemberOncallInterval struct { - // Unix timestamp in seconds - when the shift ends. Absent while the shift is ongoing. + // Unix timestamp in seconds when the shift ends. Present on `current`; omitted on `next`. EndAt Timestamp `json:"end_at" toon:"end_at"` // Owning schedule ID. ScheduleID int64 `json:"schedule_id" toon:"schedule_id"` @@ -7234,25 +7532,25 @@ type MemberResetInfoUpdates struct { Avatar *string `json:"avatar,omitempty" toon:"avatar,omitempty"` // ISO 3166-1 alpha-2 region code (e.g. "CN", "US"). Updated independently — `phone` is not required — and also used as the parsing hint for `phone`. Invalid values are rejected with a 400; an explicit empty string is not allowed. CountryCode *string `json:"country_code,omitempty" toon:"country_code,omitempty"` - // New email address. + // New email address. Must not belong to another member; the new address is marked unverified (see `from`). Email *string `json:"email,omitempty" toon:"email,omitempty"` // New locale preference. One of: `zh-CN` (Simplified Chinese), `en-US` (English); other values are rejected with a 400. Locale *string `json:"locale,omitempty" toon:"locale,omitempty"` - // New display name. + // New display name, 2–39 characters, unique in the account. MemberName *string `json:"member_name,omitempty" toon:"member_name,omitempty"` // New login password in the encrypted format accepted by the backend. Password *string `json:"password,omitempty" toon:"password,omitempty"` - // New phone number. Include country_code when the number is not in E.164 format. + // New phone number; include `country_code` when it is not in E.164 format. Must not belong to another member; the new number is marked unverified (see `from`). Phone *string `json:"phone,omitempty" toon:"phone,omitempty"` - // New external reference ID. + // New external reference ID; an empty string clears it. RefID *string `json:"ref_id,omitempty" toon:"ref_id,omitempty"` - // New IANA time zone name, such as Asia/Shanghai. + // New IANA time zone name such as `Asia/Shanghai`; an empty string clears it so the member follows the account's time zone. An invalid name returns `400`. TimeZone *string `json:"time_zone,omitempty" toon:"time_zone,omitempty"` } // MemberRoleGrantRequest is generated from the Flashduty OpenAPI schema. type MemberRoleGrantRequest struct { - // Member ID + // ID of the member whose roles change (from `POST /member/list`). MemberID uint64 `json:"member_id" toon:"member_id"` // Role IDs to grant; appended to the member's current roles (duplicates are deduplicated). RoleIDs []uint64 `json:"role_ids" toon:"role_ids"` @@ -7260,7 +7558,7 @@ type MemberRoleGrantRequest struct { // MemberRoleRevokeRequest is generated from the Flashduty OpenAPI schema. type MemberRoleRevokeRequest struct { - // Member ID + // ID of the member whose roles change (from `POST /member/list`). MemberID uint64 `json:"member_id" toon:"member_id"` // Role IDs to remove from the member. RoleIDs []uint64 `json:"role_ids" toon:"role_ids"` @@ -7268,17 +7566,17 @@ type MemberRoleRevokeRequest struct { // MemberRoleUpdateRequest is generated from the Flashduty OpenAPI schema. type MemberRoleUpdateRequest struct { - // Member ID + // ID of the member whose roles change (from `POST /member/list`). MemberID uint64 `json:"member_id" toon:"member_id"` - // New role ID set. Replaces the member's existing roles entirely (not additive); get IDs from `POST /role/list`. Leave empty to reset to the built-in Viewer role (ID 8) + // New role ID set; replaces the member's existing roles entirely (not additive). Get IDs from `POST /role/list`. RoleIDs []uint64 `json:"role_ids,omitempty" toon:"role_ids,omitempty"` } // MemberScheduleItem is generated from the Flashduty OpenAPI schema. type MemberScheduleItem struct { - // Schedule ID. + // ID of a schedule the member participates in; pass it to `/schedule/info`. ScheduleID int64 `json:"schedule_id" toon:"schedule_id"` - // Schedule name. + // Name of that schedule. ScheduleName string `json:"schedule_name" toon:"schedule_name"` } @@ -7288,7 +7586,7 @@ type MergeIncidentsRequest struct { Comment string `json:"comment,omitempty" toon:"comment,omitempty"` // Accepted for compatibility but currently ignored by the server; the merge does not change the target incident owner. OwnerID int64 `json:"owner_id,omitempty" toon:"owner_id,omitempty"` - // When true, soft-delete the source incidents after merging instead of closing them. + // When true, permanently delete the source incidents after their alerts move to the target. When false, the sources are closed and kept. RemoveSourceIncidents bool `json:"remove_source_incidents,omitempty" toon:"remove_source_incidents,omitempty"` // Source incident IDs. The target incident is removed from this set automatically. SourceIncidentIDs []string `json:"source_incident_ids" toon:"source_incident_ids"` @@ -7310,11 +7608,11 @@ type MetricsBase struct { ResponderID int64 `json:"responder_id" toon:"responder_id"` // Responder name, returned when aggregating by responder; omitted when the name cannot be resolved. ResponderName string `json:"responder_name" toon:"responder_name"` - // Team ID, returned only when aggregating by team (`/insight/team`). + // Team ID, returned only by `/insight/team`. Omitted on the row that aggregates incidents without a team. TeamID int64 `json:"team_id" toon:"team_id"` // Team name, returned when aggregating by team; omitted when the name cannot be resolved (e.g. team deleted). TeamName string `json:"team_name" toon:"team_name"` - // Start of the aggregation bucket, Unix epoch seconds. Equals `start_time` when no `aggregate_unit` is given. + // Start of the time bucket, Unix seconds. Equals `start_time` when `aggregate_unit` is not set. TS Timestamp `json:"ts" toon:"ts"` } @@ -7322,7 +7620,7 @@ type MetricsBase struct { type MigrateStatusPageEmailSubscribersRequest struct { // Atlassian Statuspage API key with access to the source page. APIKey string `json:"api_key" toon:"api_key"` - // Atlassian Statuspage source page ID. + // Atlassian Statuspage source page ID; only letters, digits, `_`, and `-` are accepted. SourcePageID string `json:"source_page_id" toon:"source_page_id"` // Flashduty target status page ID that will receive the imported subscribers. TargetPageID int64 `json:"target_page_id" toon:"target_page_id"` @@ -7332,7 +7630,7 @@ type MigrateStatusPageEmailSubscribersRequest struct { type MigrateStatusPageStructureRequest struct { // Atlassian Statuspage API key with access to the source page. APIKey string `json:"api_key" toon:"api_key"` - // Atlassian Statuspage source page ID. + // Atlassian Statuspage source page ID; only letters, digits, `_`, and `-` are accepted. SourcePageID string `json:"source_page_id" toon:"source_page_id"` // Target URL name for the new status page, normalized to a URL-safe slug (max 255 characters). Omit or pass null to derive it from the source page name; an explicitly empty string is rejected. URLName *string `json:"url_name,omitempty" toon:"url_name,omitempty"` @@ -7340,17 +7638,17 @@ type MigrateStatusPageStructureRequest struct { // NameMessage is generated from the Flashduty OpenAPI schema. type NameMessage struct { - // Empty on success, error message on failure. + // Outcome for this rule. On success it is empty for `/monit/rule/update/fields` and a localized success text (`Move successfully` / `移动成功`) for `/monit/rule/move`; on failure it carries the error message. Message string `json:"message" toon:"message"` - // Rule name. + // Name of the rule this result belongs to; `id: ` when the rule ID does not exist. Name string `json:"name" toon:"name"` } // NewMemberItem is generated from the Flashduty OpenAPI schema. type NewMemberItem struct { - // Member ID + // ID of the newly created member. MemberID uint64 `json:"member_id" toon:"member_id"` - // Member display name + // Display name stored for the member; derived from the email prefix when `member_name` was omitted. MemberName string `json:"member_name" toon:"member_name"` } @@ -7362,13 +7660,13 @@ type NotifyChat struct { ChatName string `json:"chat_name" toon:"chat_name"` // Integration data source ID used to send the notification. DataSourceID int64 `json:"data_source_id" toon:"data_source_id"` - // Failure reason if delivery did not succeed. + // Localized, human-readable reason the delivery failed, as reported by the delivery channel; omitted when delivery succeeded or no failure was reported. The text is not a fixed code set. FailedReason string `json:"failed_reason" toon:"failed_reason"` } // NotifyPerson is generated from the Flashduty OpenAPI schema. type NotifyPerson struct { - // Failure reason if delivery did not succeed. + // Localized, human-readable reason the delivery failed, as reported by the delivery channel; omitted when delivery succeeded or no failure was reported. The text is not a fixed code set. FailedReason string `json:"failed_reason" toon:"failed_reason"` // Recipient member ID. PersonID int64 `json:"person_id" toon:"person_id"` @@ -7380,7 +7678,7 @@ type NotifyPerson struct { type NotifyRobot struct { // Robot alias. Alias string `json:"alias" toon:"alias"` - // Failure reason if delivery did not succeed. + // Localized, human-readable reason the delivery failed, as reported by the delivery channel; omitted when delivery succeeded or no failure was reported. The text is not a fixed code set. FailedReason string `json:"failed_reason" toon:"failed_reason"` // Robot token or identifier. Token string `json:"token" toon:"token"` @@ -7398,11 +7696,11 @@ type OnceTimeFilter struct { type PastIncidentItem struct { // Account ID that owns the incident. AccountID int64 `json:"account_id" toon:"account_id"` - // Account locale. + // Always an empty string in API responses; filled only when the incident is rendered for notifications. AccountLocale string `json:"account_locale" toon:"account_locale"` - // Account name. + // Always an empty string in API responses; filled only when the incident is rendered for notifications. AccountName string `json:"account_name" toon:"account_name"` - // Account time zone. + // Always an empty string in API responses; filled only when the incident is rendered for notifications. AccountTimeZone string `json:"account_time_zone" toon:"account_time_zone"` // Unix timestamp (seconds) when the incident was first acknowledged. 0 if unacknowledged. AckTime Timestamp `json:"ack_time" toon:"ack_time"` @@ -7414,15 +7712,15 @@ type PastIncidentItem struct { AlertCnt int64 `json:"alert_cnt" toon:"alert_cnt"` // Total raw alert event count across all merged alerts. AlertEventCnt int64 `json:"alert_event_cnt" toon:"alert_event_cnt"` - // Embedded alerts, only populated for notification templates and custom actions. + // Not returned by the incident endpoints; present only in notification template and custom action payloads. Alerts []AlertInfo `json:"alerts" toon:"alerts"` - // Current assignment target for the incident. + // Current assignment target. Always present; for an incident that was never assigned, `type` and `id` are empty and `assigned_at` is `0`. AssignedTo AssignedTo `json:"assigned_to" toon:"assigned_to"` // Channel ID. 0 for standalone incidents. ChannelID int64 `json:"channel_id" toon:"channel_id"` // Channel display name. ChannelName string `json:"channel_name" toon:"channel_name"` - // Channel status. + // Status of the channel: `enabled`, `disabled`, or `deleted`. Empty string when the record has no channel or the channel no longer exists. ChannelStatus string `json:"channel_status" toon:"channel_status"` // Unix timestamp (seconds) when the incident was closed. 0 if still open. CloseTime Timestamp `json:"close_time" toon:"close_time"` @@ -7440,7 +7738,7 @@ type PastIncidentItem struct { DataSourceID int64 `json:"data_source_id" toon:"data_source_id"` // Deprecated. Use `integration_ids` instead. DataSourceIDs []int64 `json:"data_source_ids" toon:"data_source_ids"` - // Deprecated. Use `integration_type` instead. + // Deprecated; same value as `integration_type`. DataSourceType string `json:"data_source_type" toon:"data_source_type"` // Deprecated. Use `integration_types` instead. DataSourceTypes []string `json:"data_source_types" toon:"data_source_types"` @@ -7464,7 +7762,9 @@ type PastIncidentItem struct { Frequency string `json:"frequency" toon:"frequency"` // Alert grouping method: `i` intelligent, `p` pattern, `n` none. GroupMethod string `json:"group_method" toon:"group_method"` - // Attached images. + // `true` when the incident still has at least one action item or follow-up that is neither `done` nor `cancelled`. + HasUnfinishedWorkItem bool `json:"has_unfinished_work_item" toon:"has_unfinished_work_item"` + // Images attached to the incident; `null` when there are none. Tokens starting with `img_` are returned as download URLs. Images []Image `json:"images" toon:"images"` // Impact description. Impact string `json:"impact" toon:"impact"` @@ -7476,11 +7776,11 @@ type PastIncidentItem struct { IncidentStatus string `json:"incident_status" toon:"incident_status"` // First integration associated with the incident. IntegrationID int64 `json:"integration_id" toon:"integration_id"` - // All integration IDs contributing alerts to this incident. + // IDs of all integrations contributing alerts to this incident; `null` for incidents without integrations, such as manually created ones. IntegrationIDs []int64 `json:"integration_ids" toon:"integration_ids"` - // First alert's integration type string, used by the detail page for label mappings. + // Plugin type of the incident's first integration (see `integration_types` for all). Open set, for example `prometheus.alert` or `monit.alert`; `POST /integration/type/list` returns the full list. Omitted when the incident has no integration or the endpoint does not fill it. IntegrationType string `json:"integration_type" toon:"integration_type"` - // Integration type strings for all contributing integrations. + // Plugin types of all contributing integrations (see `integration_type`); `null` when there are none. IntegrationTypes []string `json:"integration_types" toon:"integration_types"` // Labels propagated from alerts. Labels map[string]string `json:"labels" toon:"labels"` @@ -7488,7 +7788,7 @@ type PastIncidentItem struct { LastTime Timestamp `json:"last_time" toon:"last_time"` // Channel-level link integrations rendered for this incident. Links []LinkItem `json:"links" toon:"links"` - // Fields that were manually overridden after auto-population. + // Fields edited manually and therefore no longer overwritten by merged alerts: `title`, `description`, `incident_severity`. `null` when none. ManualOverrides []string `json:"manual_overrides" toon:"manual_overrides"` // Short display identifier; not guaranteed unique. Num string `json:"num" toon:"num"` @@ -7608,7 +7908,7 @@ type PersonInfosResponse struct { // PersonItem is generated from the Flashduty OpenAPI schema. type PersonItem struct { - // Account ID + // ID of the account the person belongs to. AccountID uint64 `json:"account_id" toon:"account_id"` // Principal kind: `account` — the account owner principal; `member` — an organization member. As string `json:"as" toon:"as"` @@ -7616,11 +7916,11 @@ type PersonItem struct { Avatar string `json:"avatar" toon:"avatar"` // Email address. Omitted when empty. Email string `json:"email" toon:"email"` - // Email verified + // `true` when the email address is verified; for the account owner, `true` whenever an email is set. EmailVerified bool `json:"email_verified" toon:"email_verified"` - // Locale. Omitted when empty. + // Locale preference (`zh-CN` or `en-US`). Omitted when unset. Locale string `json:"locale" toon:"locale"` - // Person ID + // Person ID: the account ID for the account owner, otherwise the member ID. PersonID uint64 `json:"person_id" toon:"person_id"` // Display name. Omitted when empty. PersonName string `json:"person_name" toon:"person_name"` @@ -7630,7 +7930,7 @@ type PersonItem struct { PhoneVerified bool `json:"phone_verified" toon:"phone_verified"` // Person status. `enabled` — active; `pending` — invited but not yet accepted; `deleted` — removed. Omitted when empty. Status string `json:"status" toon:"status"` - // Time zone. Omitted when empty. + // IANA time zone setting: the member's own setting, or the account's for the account owner. Omitted when unset (a member without a setting follows the account's time zone). TimeZone string `json:"time_zone" toon:"time_zone"` } @@ -7640,7 +7940,7 @@ type PersonShort struct { As string `json:"as" toon:"as"` // Member email address. Email string `json:"email" toon:"email"` - // Member ID. + // Member ID; the same ID that `POST /member/list` returns. PersonID int64 `json:"person_id" toon:"person_id"` // Member display name. PersonName string `json:"person_name" toon:"person_name"` @@ -7674,13 +7974,15 @@ type PostMortemItem struct { // Post-mortem body; the object holds a single `content` field whose value is a BlockNote JSON string. Content PostMortemItemContent `json:"content" toon:"content"` // Follow-up action items rendered as a single string. - FollowUps string `json:"follow_ups" toon:"follow_ups"` - Meta PostMortemMeta `json:"meta" toon:"meta"` + FollowUps string `json:"follow_ups" toon:"follow_ups"` + // `true` when at least one linked incident is not closed yet; follow-ups stay locked until all are closed. Computed per request. + HasActiveIncident bool `json:"has_active_incident" toon:"has_active_incident"` + Meta PostMortemMeta `json:"meta" toon:"meta"` } // PostMortemMeta is generated from the Flashduty OpenAPI schema. type PostMortemMeta struct { - // Account ID. + // ID of the account that owns this record; the same for every record returned to one `app_key`. AccountID int64 `json:"account_id" toon:"account_id"` // Member IDs that contributed to the report. AuthorIDs []int64 `json:"author_ids" toon:"author_ids"` @@ -7698,7 +8000,7 @@ type PostMortemMeta struct { IsPrivate bool `json:"is_private" toon:"is_private"` // Number of uploaded media files. MediaCount int64 `json:"media_count" toon:"media_count"` - // Deterministic post-mortem ID derived from account and incident IDs. + // Post-mortem ID: a 32-character hex string derived from the account ID and the linked incident IDs. PostMortemID string `json:"post_mortem_id" toon:"post_mortem_id"` // Content revision for optimistic concurrency. Monotonically increases on collaborative saves and full content resets. Revision int64 `json:"revision" toon:"revision"` @@ -7716,23 +8018,23 @@ type PostMortemMeta struct { // PostMortemTemplate is generated from the Flashduty OpenAPI schema. type PostMortemTemplate struct { - // Account ID that owns the template. 0 for built-in templates. + // Account ID that owns the template; 0 for the built-in template. AccountID int64 `json:"account_id" toon:"account_id"` - // BlockNote JSON content used to initialize the report body. + // Template body as BlockNote editor JSON (an array of blocks), serialized as a string. Content string `json:"content" toon:"content"` // Markdown version of the template content, used by AI generation. ContentMarkdown string `json:"content_markdown" toon:"content_markdown"` - // Unix timestamp in seconds when the template was created. + // Creation time, Unix timestamp in seconds; 0 for the built-in template. CreatedAtSeconds Timestamp `json:"created_at_seconds" toon:"created_at_seconds"` // Template description. Description string `json:"description" toon:"description"` // Template name shown in the console. Name string `json:"name" toon:"name"` - // Managing team ID. Built-in templates use 0. + // Managing team ID; 0 for the built-in template. TeamID int64 `json:"team_id" toon:"team_id"` - // Template ID. Built-in templates use a stable `post_mortem_default_tmpl_*` ID. + // Template ID: `post_mortem_default_tmpl_zh-cn` or `post_mortem_default_tmpl_en-us` for the built-in templates, a server-generated ID for custom ones. TemplateID string `json:"template_id" toon:"template_id"` - // Unix timestamp in seconds when the template was last updated. + // Last update time, Unix timestamp in seconds; 0 for the built-in template. UpdatedAtSeconds Timestamp `json:"updated_at_seconds" toon:"updated_at_seconds"` } @@ -7742,7 +8044,7 @@ type PreflightResult struct { AppName string `json:"app_name" toon:"app_name"` // Names of the readiness checks performed, in order. Current fixed set: rule_loaded, actor_authorized, app_allowed, runtime_scope_resolved, rule_config_valid. Checks []string `json:"checks" toon:"checks"` - // Whether all readiness checks passed. Always true in a response that reaches the caller — a failed preflight returns a 400/403 error instead of a payload with ok=false. + // Whether all readiness checks passed. Always `true` in a 200 response; a failed preflight returns an error instead. OK bool `json:"ok" toon:"ok"` // Rule owner person ID. OwnerID int64 `json:"owner_id" toon:"owner_id"` @@ -7750,70 +8052,71 @@ type PreflightResult struct { Scope string `json:"scope" toon:"scope"` // Rule's scope team ID; 0 means a personal rule. TeamID int64 `json:"team_id" toon:"team_id"` - // Non-fatal warnings surfaced during preflight. Omitted or empty when there are none. + // Non-fatal warnings from preflight. Currently never populated, so the field is omitted. Warnings []string `json:"warnings" toon:"warnings"` } -// PreviewIncidentCardFixedField is generated from the Flashduty OpenAPI schema. -type PreviewIncidentCardFixedField struct { - // Incident-card field name. - // - // | Value | Meaning | - // |---|---| - // | `channel` | Name of the alert channel that produced the incident; returned only when non-empty. | - // | `snoozed_before` | Snooze-until timestamp formatted as `YYYY-MM-DD HH:MM:SS`; returned only while the incident is snoozed. | - // | `severity` | Incident severity label; returned only when non-empty. | - // | `responders` | Names of the current responders, separated by spaces; returned only when the incident has responders. | - // | `aggregate_alert_count` | Number of alerts aggregated into the incident; returned only when greater than 1. | - Field string `json:"field" toon:"field"` - // Rendered display value for the fixed field. - Value string `json:"value" toon:"value"` -} - // PreviewRemoteConfigRequest is generated from the Flashduty OpenAPI schema. type PreviewRemoteConfigRequest struct { - // App version the simulated client reports. + // App version the simulated client reports, compared exactly with rules' `match.app_version` (no range or prefix matching). Omitted = not reported. AppVersion string `json:"app_version,omitempty" toon:"app_version,omitempty"` - // RUM application ID. - ApplicationID string `json:"application_id" toon:"application_id"` - Config RemoteConfig `json:"config,omitzero" toon:"config,omitempty"` - // Environment the simulated client reports. + // RUM application ID. Get application IDs via `POST /rum/application/list`. + ApplicationID string `json:"application_id" toon:"application_id"` + // Draft configuration to evaluate, validated like `POST /rum/application/remote-config/update`. Omit to evaluate the live configuration. + Config RemoteConfig `json:"config,omitzero" toon:"config,omitempty"` + // Environment the simulated client reports, compared exactly with rules' `match.env`. Omitted = not reported, so rules that test `env` cannot match. Env string `json:"env,omitempty" toon:"env,omitempty"` - // SDK name and version the simulated client reports, e.g. `web@2.4.1`. + // SDK identifier the simulated client reports, e.g. `web@2.4.1`, compared exactly with rules' `match.sdk`. Omitted = not reported. Sdk string `json:"sdk,omitempty" toon:"sdk,omitempty"` } // PreviewRemoteConfigResponse is generated from the Flashduty OpenAPI schema. type PreviewRemoteConfigResponse struct { - // 0-based index of the rule that decided the result, or -1 when only the default applied. - HitRuleIndex int64 `json:"hit_rule_index" toon:"hit_rule_index"` - Values RemoteConfigValues `json:"values" toon:"values"` + // 0-based index into `config.rules` of the first rule that matched, or `-1` when no rule matched (only `default` applied) or the configuration is disabled or absent. + HitRuleIndex int64 `json:"hit_rule_index" toon:"hit_rule_index"` + // `default` merged with the matching rule's `set`. Fields set by neither are omitted; an empty object means the client keeps all its init values. + Values RemoteConfigValues `json:"values" toon:"values"` } // PreviewTemplateRequest is generated from the Flashduty OpenAPI schema. type PreviewTemplateRequest struct { - // Template content to render. - Content string `json:"content" toon:"content"` - // Render the preview as a Feishu app card v2 message. - FeishuAppCardV2Enabled bool `json:"feishu_app_card_v2_enabled,omitempty" toon:"feishu_app_card_v2_enabled,omitempty"` + // Template source to render for the channel `type`. Empty or omitted previews the channel's built-in preset content. Ignored for `push`. + Content string `json:"content,omitempty" toon:"content,omitempty"` // Keep blank lines in the body of the Feishu app card v2 preview. FeishuAppCardV2PreserveBlankLines bool `json:"feishu_app_card_v2_preserve_blank_lines,omitempty" toon:"feishu_app_card_v2_preserve_blank_lines,omitempty"` + // Render Markdown tables in `feishu_app` content as native Feishu card tables, as the template setting of the same name does. + FeishuAppCardV2TableEnabled bool `json:"feishu_app_card_v2_table_enabled,omitempty" toon:"feishu_app_card_v2_table_enabled,omitempty"` // Incident card fields to hide per IM app when previewing. IncidentCardHiddenFields IncidentCardHiddenFields `json:"incident_card_hidden_fields,omitempty" toon:"incident_card_hidden_fields,omitempty"` - // Incident ID whose data is used to render the template; mock data is used when omitted. A MongoDB ObjectID hex string. + // Incident whose data is rendered (24-character hex ID from `/incident/list`); must exist in the account, otherwise `InvalidParameter`. When omitted a mock incident is used. IncidentID string `json:"incident_id,omitempty" toon:"incident_id,omitempty"` - // Template channel type that selects the rendering engine. `email` renders as Go html/template; other channels render as text/template. Values match the template channel fields, for example `email`, `sms`, `voice`, `dingtalk`, `wecom`, `feishu`, `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, `teams_app`, `telegram`, `slack`, `zoom`. + // Channel to preview; other values return `InvalidParameter`. + // - `email`: email body (HTML template). + // - `sms`, `voice`: SMS text and voice call script. + // - `push`: mobile app push (fixed content; `content` is ignored). + // - `dingtalk`, `wecom`, `feishu`, `zoom`, `telegram`, `slack`: robot (webhook) messages. + // - `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, `teams_app`: IM app cards. Type string `json:"type" toon:"type"` + // Preview `wecom` content as a `markdown_v2` message, as the template setting of the same name does (size limit 4,096 bytes). + WecomMarkdownV2Enabled bool `json:"wecom_markdown_v2_enabled,omitempty" toon:"wecom_markdown_v2_enabled,omitempty"` } // PreviewTemplateResponse is generated from the Flashduty OpenAPI schema. type PreviewTemplateResponse struct { - // Rendered template output, present when success is true. + // How the recipient's client shows `content`, split into blocks. Omitted for channels that show the text as is. + Blocks []PreviewTemplateResponseBlocksItem `json:"blocks" toon:"blocks"` + // Message frame around the rendered template, in the account language. Returned for `email`, `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app` and `teams_app`; omitted otherwise. + Card PreviewTemplateResponseCard `json:"card" toon:"card"` + // Rendered template output; an empty string when `success` is `false`. Content string `json:"content" toon:"content"` - // Fixed incident-card fields returned for supported IM previews after the requested hiding rules are applied. - FixedFields []PreviewIncidentCardFixedField `json:"fixed_fields" toon:"fixed_fields"` - // Error message describing why rendering failed, present when success is false. + // Why rendering failed, in the caller's language; an empty string when `success` is `true`. Message string `json:"message" toon:"message"` + // Warnings about how the content will be delivered. Omitted when there are none. + Notices []PreviewTemplateResponseNoticesItem `json:"notices" toon:"notices"` + // Size of the rendered content in bytes, measured before any truncation. + SizeBytes int64 `json:"size_bytes" toon:"size_bytes"` + // Size limit the channel applies in bytes: 4,000 for robot channels (and `wecom` without `markdown_v2`), 4,096 for `wecom` with `markdown_v2`, 15,000 for `slack_app`, 30,720 for `feishu_app`; `0` when the channel has no limit. + SizeLimitBytes int64 `json:"size_limit_bytes" toon:"size_limit_bytes"` // Whether the template rendered without errors. Success bool `json:"success" toon:"success"` } @@ -7836,7 +8139,7 @@ type PublishedArtifactItem struct { ArtifactID string `json:"artifact_id" toon:"artifact_id"` // Whether the caller may manage this artifact (rename, transfer, delete, share): the creator, any member of the owning team, or a manager of the source session. CanEdit bool `json:"can_edit" toon:"can_edit"` - // MIME type of the file. + // MIME type, derived from the file-name extension when the file was produced: `text/html` (.html/.htm), `text/markdown` (.md), `text/plain` (.txt/.log), `text/csv`, `text/yaml` (.yaml/.yml), `text/x-python`, `text/x-go`, `text/x-sh`, `application/json`, `application/xml`, `application/pdf`, `image/png`, `image/jpeg`, `image/gif`, `image/svg+xml`, `image/webp`, `application/zip`, `application/gzip` (.tar/.gz/.tgz); any other extension is `application/octet-stream`. Empty when the underlying file record is missing. ContentType string `json:"content_type" toon:"content_type"` // Unix timestamp in milliseconds when the artifact was published. CreatedAt TimestampMilli `json:"created_at" toon:"created_at"` @@ -7844,12 +8147,14 @@ type PublishedArtifactItem struct { CreatorName string `json:"creator_name" toon:"creator_name"` // Presented-file ID (`pf_` prefix) currently holding the artifact's bytes. Changes on every republish. FileID string `json:"file_id" toon:"file_id"` - // Whether the caller is the creator. + // `true` when the caller (for an `app_key` call, the key owner) is the creator, i.e. `person_id` equals the caller's person ID. IsMine bool `json:"is_mine" toon:"is_mine"` - // Underlying file name including extension. + // Underlying file name including extension. Empty when the underlying file record is missing. Name string `json:"name" toon:"name"` - // Person (member) ID of the creator. + // Person ID of the artifact's creator: the owner of the source session at first publish. It never changes on republish or scope transfer. PersonID int64 `json:"person_id" toon:"person_id"` + // Unix timestamp in milliseconds when the caller pinned this artifact in the console gallery. Pins are per member; omitted when the caller has not pinned it. Pinned artifacts are listed first by `/safari/artifact/gallery/list`. + PinnedAt TimestampMilli `json:"pinned_at" toon:"pinned_at"` // Anonymous public link — a console `/share/artifact/` page served entirely from CDN. Present only while shared; anyone with the link can view it, no login required. PublicURL string `json:"public_url" toon:"public_url"` // Source session ID (`sess_` prefix) that produced the file. @@ -7862,33 +8167,55 @@ type PublishedArtifactItem struct { ShareFileID string `json:"share_file_id" toon:"share_file_id"` // Unix timestamp in milliseconds of the last share enable or snapshot sync. Present only while shared. SharedAt TimestampMilli `json:"shared_at" toon:"shared_at"` - // Person ID of the member who enabled sharing. Present only while shared. + // Person ID of the member who enabled sharing; a later snapshot sync does not change it. Present only while shared. SharedBy int64 `json:"shared_by" toon:"shared_by"` // File size in bytes. Size int64 `json:"size" toon:"size"` - // Owning team ID. `0` means a personal artifact (creator-only management); a positive value means team-owned. + // Owning scope. `0` means a personal artifact: it appears only in its creator's list, and can be managed by the creator or by anyone who can manage the source session. A positive value is the owning team ID: the artifact appears in that team's members' lists and any team member can manage it. Set from the source session at first publish; change it with `/safari/artifact/gallery/update`. TeamID int64 `json:"team_id" toon:"team_id"` // Owning team's display name. Omitted for personal artifacts. TeamName string `json:"team_name" toon:"team_name"` // Display title in the gallery. Title string `json:"title" toon:"title"` - // Unix timestamp in milliseconds when the artifact was last updated (rename, transfer, or republish). + // Unix timestamp in milliseconds of the last change to the artifact row (rename, transfer, republish, or share state change). UpdatedAt TimestampMilli `json:"updated_at" toon:"updated_at"` } // QueryDataRequest is generated from the Flashduty OpenAPI schema. type QueryDataRequest struct { - // Optional consistency check. Must equal the authenticated account when supplied; mismatched values are rejected. Business execution always uses the authenticated account. + // Optional consistency check. When supplied it must equal the authenticated account, otherwise the request fails with `AccessDenied`. The query always runs as the authenticated account. AccountID int64 `json:"account_id,omitempty" toon:"account_id,omitempty"` - // Polymorphic key/value extension parameters forwarded verbatim to monit-edge. All values must be strings, and keys are always namespaced by source (e.g. `sls.project`, `loki.type`). Validation depends on `ds_type`: SLS requires `sls.project` + `sls.logstore`. Elasticsearch accepts `es.type` of `sql`, or omitted — any other value is rejected. Loki and VictoriaLogs accept `.type` of `stats`, `raw`, or omitted; `raw` additionally requires a time range, either `.start` + `.end` or `.timespan.value` + `.timespan.unit` (unit one of `s`, `m`, `h`, `d`). Prometheus and the remaining SQL sources ignore `args` entirely. + // Extra query parameters as string key/value pairs; keys are namespaced by data source (for example `sls.project`, `loki.type`). At most 128 entries, keys up to 256 bytes, values up to 64 KiB, and 128 KiB in total. What is accepted depends on `ds_type`: + // + // - `prometheus`: optional `prometheus.time`, the evaluation time as Unix seconds, not in the future. + // - `loki`, `victorialogs`: `.type` is `stats` (default) or `raw`. `stats` accepts an optional `.time` (Unix seconds, not in the future). `raw` requires a time range, either `.start` + `.end` (Unix seconds) or `.timespan.value` + `.timespan.unit` (`s`, `m`, `h`, or `d`), spanning at most 6 hours, and accepts `.limit` from 1 to 1001. + // - `sls`: `sls.project` and `sls.logstore` are required. Optional: `sls.lines` (1 to 100), `sls.offset` (0 or more), and a time range of at most 6 hours given as `sls.from` + `sls.to` (Unix seconds) or `sls.timespan.value` + `sls.timespan.unit`. + // - `tencent_cls`: `tencent_cls.region`, `tencent_cls.topic_id`, `tencent_cls.query_mode` (`raw` or `analysis`), and `tencent_cls.syntax` (`cql` or `lucene`) are required. Optional: `tencent_cls.limit` (1 to 100, `raw` mode only, needs monit-edge v0.67.0 or later) and a time range given as `tencent_cls.from` + `tencent_cls.to` (Unix seconds) or `tencent_cls.timespan.value` + `tencent_cls.timespan.unit`, at most 6 hours in `raw` mode and 24 hours in `analysis` mode. Any other key is rejected. + // - `elasticsearch`: `es.type` may be `sql` or omitted; any other value is rejected. + // - `mysql`, `postgres`, `oracle`, `clickhouse`: no arguments are defined. + // + // An absolute `.time` is only valid for its own data source type. Edges older than v0.74.0 approximate it with a look-back offset and accept only times within the last 86,400 seconds. Args map[string]string `json:"args,omitempty" toon:"args,omitempty"` - // Look-back offset in seconds applied to point-in-time queries (Prometheus, Loki stats, VictoriaLogs stats). Ignored for raw / detail queries. + // Look-back offset in seconds, from 0 to 86400. Applied to point-in-time queries (Prometheus, Loki stats, VictoriaLogs stats); ignored for raw and detail queries. When `args` carries an absolute `.time` and the Edge is v0.74.0 or later, the absolute time takes precedence and this offset is not applied. DelaySeconds int64 `json:"delay_seconds,omitempty" toon:"delay_seconds,omitempty"` - // Data source name; must match a configured data source under the tenant. + // Data source name, as returned by `/monit/datasource/list`. The data source must be enabled; a name that matches no data source of the account returns HTTP 400. DsName string `json:"ds_name" toon:"ds_name"` - // Data source type; must match a configured data source under the tenant. Examples: `prometheus`, `loki`, `victorialogs`, `sls`, `elasticsearch`, `mysql`, `postgres`, `oracle`, `clickhouse`. + // Data source type. Together with `ds_name` it must match an enabled data source of the account. + // + // - `prometheus`: Prometheus-compatible data source; `expr` is PromQL. + // - `loki`: Grafana Loki; `expr` is LogQL. + // - `victorialogs`: VictoriaLogs. + // - `sls`: Alibaba Cloud Log Service (SLS). + // - `tencent_cls`: Tencent Cloud Log Service (CLS); requires monit-edge v0.66.0 or later. + // - `elasticsearch`: Elasticsearch. + // - `mysql`: MySQL; `expr` is SQL. + // - `postgres`: PostgreSQL; `expr` is SQL. + // - `oracle`: Oracle Database; `expr` is SQL. + // - `clickhouse`: ClickHouse; `expr` is SQL. + // + // Other data source types (for example MongoDB, Redis, or Kafka) are rejected. DsType string `json:"ds_type" toon:"ds_type"` - // Query expression. Syntax depends on `ds_type` and is interpreted by the corresponding monit-edge client (PromQL for Prometheus, LogQL for Loki, SQL for SQL sources, etc.). + // Query expression in the language of `ds_type` (PromQL for `prometheus`, LogQL for `loki`, SQL for SQL sources, and so on). Required, at most 64 KiB (12 KiB for `tencent_cls`). Loki's `$__auto` is not supported here; use a fixed duration such as `[5m]`. Prometheus expressions are syntax-checked before dispatch. Expr string `json:"expr" toon:"expr"` } @@ -7901,15 +8228,19 @@ type QueryDataResponse struct { // QueryExploreExecution is generated from the Flashduty OpenAPI schema. type QueryExploreExecution struct { - // Unix timestamp in milliseconds for the start of the range. Required for `range` and `window`; optional for `instant`. + // Start of the interval as a Unix timestamp in milliseconds; non-negative and less than `to_ms`. Required for `range` and `window`; optional for `instant`. FromMs int64 `json:"from_ms,omitempty" toon:"from_ms,omitempty"` - // Execution kind. `instant` evaluates at a single point in time, `range` evaluates a series over a range, and `window` returns raw rows inside a time window. + // Execution kind. + // + // - `instant`: evaluate at a single point in time. + // - `range`: evaluate a series over `from_ms` to `to_ms`, with a step derived from `max_data_points` and `min_step_seconds`. + // - `window`: query the interval from `from_ms` to `to_ms` with no step. Kind string `json:"kind" toon:"kind"` // Maximum number of points to return. Required for `range` and rejected for `instant` and `window`. MaxDataPoints int64 `json:"max_data_points,omitempty" toon:"max_data_points,omitempty"` // Lower bound, in seconds, for the step derived from `max_data_points`. Optional and only accepted for `range`. MinStepSeconds int64 `json:"min_step_seconds,omitempty" toon:"min_step_seconds,omitempty"` - // Unix timestamp in milliseconds for the end of the range. Required for every execution kind. + // End of the interval (or the evaluation time for `instant`) as a Unix timestamp in milliseconds; non-negative. Required for every execution kind. ToMs int64 `json:"to_ms,omitempty" toon:"to_ms,omitempty"` } @@ -7917,10 +8248,10 @@ type QueryExploreExecution struct { type QueryExploreRequest struct { // Macro substitutions keyed by variable name, used for Grafana-style variables. Keys are at most 256 bytes, values at most 64 KiB, with a 128 KiB total budget. Args map[string]string `json:"args" toon:"args"` - // Data source ID from `/monit/datasource/list`. Must be a positive JavaScript-safe integer and belong to the authenticated account. + // Data source ID from `/monit/datasource/list`. Must be a positive JavaScript-safe integer for an enabled data source of the authenticated account that the caller may query. DatasourceID int64 `json:"datasource_id" toon:"datasource_id"` Execution QueryExploreExecution `json:"execution" toon:"execution"` - // Query expression in the data source's native language (PromQL, LogsQL, SQL, and so on). Non-empty UTF-8 of at most 64 KiB; some data source types enforce a lower limit. + // Query expression in the data source's native language (PromQL, LogsQL, SQL, and so on). Non-empty UTF-8 of at most 64 KiB; `mysql` allows at most 16 KiB and `tencent_cls` at most 12 KiB. Expr string `json:"expr" toon:"expr"` } @@ -7982,17 +8313,39 @@ type QueryResult struct { // QueryRowsRequest is generated from the Flashduty OpenAPI schema. type QueryRowsRequest struct { - // Optional consistency check. Must equal the authenticated account when supplied; mismatched values are rejected. Business execution always uses the authenticated account. + // Optional consistency check. When supplied it must equal the authenticated account, otherwise the request fails with `AccessDenied`. The query always runs as the authenticated account. AccountID int64 `json:"account_id,omitempty" toon:"account_id,omitempty"` - // Polymorphic key/value extension parameters forwarded verbatim to monit-edge. All values must be strings, and keys are always namespaced by source (e.g. `sls.project`, `loki.type`). Validation depends on `ds_type`: SLS requires `sls.project` + `sls.logstore`. Elasticsearch accepts `es.type` of `sql`, or omitted — any other value is rejected. Loki and VictoriaLogs accept `.type` of `stats`, `raw`, or omitted; `raw` additionally requires a time range, either `.start` + `.end` or `.timespan.value` + `.timespan.unit` (unit one of `s`, `m`, `h`, `d`). Prometheus and the remaining SQL sources ignore `args` entirely. + // Extra query parameters as string key/value pairs; keys are namespaced by data source (for example `sls.project`, `loki.type`). At most 128 entries, keys up to 256 bytes, values up to 64 KiB, and 128 KiB in total. What is accepted depends on `ds_type`: + // + // - `prometheus`: optional `prometheus.time`, the evaluation time as Unix seconds, not in the future. + // - `loki`, `victorialogs`: `.type` is `stats` (default) or `raw`. `stats` accepts an optional `.time` (Unix seconds, not in the future). `raw` requires a time range, either `.start` + `.end` (Unix seconds) or `.timespan.value` + `.timespan.unit` (`s`, `m`, `h`, or `d`), spanning at most 6 hours, and accepts `.limit` from 1 to 1001. + // - `sls`: `sls.project` and `sls.logstore` are required. Optional: `sls.lines` (1 to 100), `sls.offset` (0 or more), and a time range of at most 6 hours given as `sls.from` + `sls.to` (Unix seconds) or `sls.timespan.value` + `sls.timespan.unit`. + // - `tencent_cls`: `tencent_cls.region`, `tencent_cls.topic_id`, `tencent_cls.query_mode` (`raw` or `analysis`), and `tencent_cls.syntax` (`cql` or `lucene`) are required. Optional: `tencent_cls.limit` (1 to 100, `raw` mode only, needs monit-edge v0.67.0 or later) and a time range given as `tencent_cls.from` + `tencent_cls.to` (Unix seconds) or `tencent_cls.timespan.value` + `tencent_cls.timespan.unit`, at most 6 hours in `raw` mode and 24 hours in `analysis` mode. Any other key is rejected. + // - `elasticsearch`: `es.type` may be `sql` or omitted; any other value is rejected. + // - `mysql`, `postgres`, `oracle`, `clickhouse`: no arguments are defined. + // + // An absolute `.time` is only valid for its own data source type. Edges older than v0.74.0 approximate it with a look-back offset and accept only times within the last 86,400 seconds. Args map[string]string `json:"args,omitempty" toon:"args,omitempty"` - // Look-back offset in seconds applied to point-in-time queries (Prometheus, Loki stats, VictoriaLogs stats). Ignored for raw / detail queries. + // Look-back offset in seconds, from 0 to 86400. Applied to point-in-time queries (Prometheus, Loki stats, VictoriaLogs stats); ignored for raw and detail queries. When `args` carries an absolute `.time` and the Edge is v0.74.0 or later, the absolute time takes precedence and this offset is not applied. DelaySeconds int64 `json:"delay_seconds,omitempty" toon:"delay_seconds,omitempty"` - // Data source name; must match a configured data source under the tenant. + // Data source name, as returned by `/monit/datasource/list`. The data source must be enabled; a name that matches no data source of the account returns HTTP 400. DsName string `json:"ds_name" toon:"ds_name"` - // Data source type; must match a configured data source under the tenant. Examples: `prometheus`, `loki`, `victorialogs`, `sls`, `elasticsearch`, `mysql`, `postgres`, `oracle`, `clickhouse`. + // Data source type. Together with `ds_name` it must match an enabled data source of the account. + // + // - `prometheus`: Prometheus-compatible data source; `expr` is PromQL. + // - `loki`: Grafana Loki; `expr` is LogQL. + // - `victorialogs`: VictoriaLogs. + // - `sls`: Alibaba Cloud Log Service (SLS). + // - `tencent_cls`: Tencent Cloud Log Service (CLS); requires monit-edge v0.66.0 or later. + // - `elasticsearch`: Elasticsearch. + // - `mysql`: MySQL; `expr` is SQL. + // - `postgres`: PostgreSQL; `expr` is SQL. + // - `oracle`: Oracle Database; `expr` is SQL. + // - `clickhouse`: ClickHouse; `expr` is SQL. + // + // Other data source types (for example MongoDB, Redis, or Kafka) are rejected. DsType string `json:"ds_type" toon:"ds_type"` - // Query expression. Syntax depends on `ds_type` and is interpreted by the corresponding monit-edge client (PromQL for Prometheus, LogQL for Loki, SQL for SQL sources, etc.). + // Query expression in the language of `ds_type` (PromQL for `prometheus`, LogQL for `loki`, SQL for SQL sources, and so on). Required, at most 64 KiB (12 KiB for `tencent_cls`). Loki's `$__auto` is not supported here; use a fixed duration such as `[5m]`. Prometheus expressions are syntax-checked before dispatch. Expr string `json:"expr" toon:"expr"` } @@ -8016,31 +8369,33 @@ type QuerySamplesResult struct { type RemoteConfig struct { // How a change lands on a client that is already running: `next_session` (the default, and what an empty value means) leaves running sessions untouched and applies the change to new sessions; `immediate` ends the running session as soon as the change arrives so a new session starts under the new configuration. Activation string `json:"activation,omitempty" toon:"activation,omitempty"` - // Application-defined pass-through values handed to the host app verbatim. At most 5 keys, each key up to 64 bytes, each value up to 4 KB of JSON nested at most 3 levels, 16 KB in total. Anyone holding the public client token can read it. - Custom map[string]any `json:"custom,omitempty" toon:"custom,omitempty"` + // Free-form key/value map that SDKs hand to the host app verbatim; the platform does not interpret it. At most 5 keys, each key 1–64 bytes, each value valid JSON of at most 4 KB nested at most 3 levels, 16 KB in total. Anyone holding the public client token can read it. Omitted from responses when empty. + Custom map[string]any `json:"custom,omitempty" toon:"custom,omitempty"` + // Values every client receives unless a matching rule overrides them. Default RemoteConfigValues `json:"default,omitzero" toon:"default,omitempty"` - // Kill switch. When false the engine reports no values at all and SDKs fall back to their init values. + // Kill switch. When `false` the SDK config endpoint returns no values and SDKs fall back to their init values; `default` and `rules` are kept. Treated as `false` when omitted. Enabled bool `json:"enabled,omitempty" toon:"enabled,omitempty"` - // Let clients re-check the configuration when they return to the foreground instead of waiting for the next poll. + // If `true`, clients re-check the configuration when they return to the foreground instead of waiting for the next poll. Default `false`; omitted from responses when `false`. RefreshOnForeground bool `json:"refresh_on_foreground,omitempty" toon:"refresh_on_foreground,omitempty"` - // Targeting rules, evaluated in order; at most 20 per application. + // Targeting rules, evaluated in order; the first match wins. At most 20. Can be `null` when the configuration was saved without rules. Rules []RemoteConfigRule `json:"rules,omitempty" toon:"rules,omitempty"` } // RemoteConfigHistoryItem is generated from the Flashduty OpenAPI schema. type RemoteConfigHistoryItem struct { + // The configuration content that went live under this version. Config RemoteConfig `json:"config" toon:"config"` - // Hash of the configuration content; lets the console identify versions with identical content. + // Fingerprint of the stored configuration: the first 16 hex characters of its SHA-256. Versions with equal hashes have identical content. Can be empty for older versions. ContentHash string `json:"content_hash" toon:"content_hash"` - // Earliest version carrying the same content, when that is not this version itself. + // Earliest retained version with the same `content_hash`, e.g. the version a revert restored. Omitted when this version is itself the earliest. EquivalentTo int64 `json:"equivalent_to" toon:"equivalent_to"` - // Operator's note left when the version was published. Empty when none was given. + // Free-text note (not an enum) sent as `reason` when the version was published or reverted; `""` when none was given. Reason string `json:"reason" toon:"reason"` // Unix timestamp in milliseconds - when the version was published. UpdatedAt TimestampMilli `json:"updated_at" toon:"updated_at"` // ID of the member who published the version. UpdatedBy int64 `json:"updated_by" toon:"updated_by"` - // Name of the member who published the version. + // Name of the member who published the version at publish time, truncated to 128 characters. UpdatedByName string `json:"updated_by_name" toon:"updated_by_name"` // Version number, unique within the application. Version int64 `json:"version" toon:"version"` @@ -8048,24 +8403,28 @@ type RemoteConfigHistoryItem struct { // RemoteConfigRule is generated from the Flashduty OpenAPI schema. type RemoteConfigRule struct { - // Key/value conditions the SDK's config request must equal. Keys are limited to `env`, `app_version` and `sdk`; values are at most 256 bytes. + // Conditions on what the SDK reports in its config request, combined with AND and compared as exact strings. Keys are limited to `env`, `app_version` and `sdk`; values are 1–256 bytes. A key the SDK does not report never matches. Match map[string]string `json:"match" toon:"match"` Set RemoteConfigValues `json:"set" toon:"set"` } // RemoteConfigValues is generated from the Flashduty OpenAPI schema. type RemoteConfigValues struct { - // How Session Replay masks a page by default. + // How Session Replay masks a page by default: + // + // - `mask`: replaces text and hides input values. + // - `mask-user-input`: keeps page text but hides what users type. + // - `allow`: records the page as it is; content already uploaded cannot be masked later. DefaultPrivacyLevel *string `json:"defaultPrivacyLevel,omitempty" toon:"defaultPrivacyLevel,omitempty"` // Keep sessions the session sample rate did not draw when they report an error; applies only to sessions that rate missed, so it does nothing alongside a rate of 100. SessionOnError *bool `json:"sessionOnError,omitempty" toon:"sessionOnError,omitempty"` // The same switch for Session Replay: un-sampled sessions still record and upload their recording only when the session errors. SessionReplayOnError *bool `json:"sessionReplayOnError,omitempty" toon:"sessionReplayOnError,omitempty"` - // Session Replay sampling rate (0-100). + // Percentage of sessions that record Session Replay (0–100). SessionReplaySampleRate *int64 `json:"sessionReplaySampleRate,omitempty" toon:"sessionReplaySampleRate,omitempty"` - // Session sampling rate (0-100). + // Percentage of sessions collected (0–100). SessionSampleRate *int64 `json:"sessionSampleRate,omitempty" toon:"sessionSampleRate,omitempty"` - // Trace sampling rate (0-100): which sessions inject trace headers into their requests. + // Percentage of sessions that inject trace headers into their requests (0–100). Decided per session: a session traces all of its requests or none. TraceSampleRate *int64 `json:"traceSampleRate,omitempty" toon:"traceSampleRate,omitempty"` } @@ -8079,7 +8438,7 @@ type RemoveIncidentRequest struct { type ReopenIncidentRequest struct { // Incident IDs to reopen. At most 100 per call. IncidentIDs []string `json:"incident_ids" toon:"incident_ids"` - // Optional reason recorded on the timeline. + // Optional free-text reason, recorded on the `i_reopen` timeline entry. At most 1,024 characters. Reason string `json:"reason,omitempty" toon:"reason,omitempty"` } @@ -8091,9 +8450,9 @@ type ReorderIncidentCommentTypesRequest struct { // ResetIncidentFieldRequest is generated from the Flashduty OpenAPI schema. type ResetIncidentFieldRequest struct { - // Custom field name; must match a field defined on the account. + // Custom field name (the field's `field_name`, not its display name). The field must exist and be enabled; list fields with `POST /field/list`. FieldName string `json:"field_name" toon:"field_name"` - // New field value. Type must match the field definition. + // New value. Its type must match the field: `checkbox` takes a boolean, `single_select` one of the options, `multi_select` an array of options, `text` a string. Omit it or send `null` to clear the field. FieldValue any `json:"field_value,omitempty" toon:"field_value,omitempty"` // Incident ID (MongoDB ObjectID). IncidentID string `json:"incident_id" toon:"incident_id"` @@ -8103,15 +8462,19 @@ type ResetIncidentFieldRequest struct { type ResetPostMortemBasicsRequest struct { // Unix timestamp in seconds for the earliest linked incident start time. IncidentsEarliestStartSeconds int64 `json:"incidents_earliest_start_seconds" toon:"incidents_earliest_start_seconds"` - // Highest severity among linked incidents: `Critical`, `Warning`, `Info`, or `Ok`. + // Highest severity among the linked incidents. + // - `Critical`: critical. + // - `Warning`: warning. + // - `Info`: informational. + // - `Ok`: recovered. IncidentsHighestSeverity string `json:"incidents_highest_severity" toon:"incidents_highest_severity"` - // Unix timestamp in seconds for the latest linked incident close time. 0 when still open. + // Latest close time among the linked incidents, Unix timestamp in seconds. 0 (also when omitted) means still open. IncidentsLatestCloseSeconds int64 `json:"incidents_latest_close_seconds,omitempty" toon:"incidents_latest_close_seconds,omitempty"` - // Total incident duration in seconds. + // Total incident duration in seconds; 0 when omitted. IncidentsTotalDurationSeconds int64 `json:"incidents_total_duration_seconds,omitempty" toon:"incidents_total_duration_seconds,omitempty"` // Post-mortem ID; obtain it from `POST /incident/post-mortem/list`. PostMortemID string `json:"post_mortem_id" toon:"post_mortem_id"` - // Responder member IDs to store on the report. + // Member IDs to store as the report's responders. Replaces the stored list; omit or send `[]` to clear it. IDs that do not resolve to a person are dropped. ResponderIDs []int64 `json:"responder_ids,omitempty" toon:"responder_ids,omitempty"` } @@ -8129,7 +8492,7 @@ type ResetPostMortemContentRequest struct { // ResetPostMortemFollowUpsRequest is generated from the Flashduty OpenAPI schema. type ResetPostMortemFollowUpsRequest struct { - // Follow-up action items as free text. + // Follow-ups as free text, replacing the stored string. A JSON array in the console's follow-up format (objects with `title`, `status`, `priority`, `assignee_ids`, …) is also synced into structured follow-up work items. FollowUps string `json:"follow_ups,omitempty" toon:"follow_ups,omitempty"` // Post-mortem ID; obtain it from `POST /incident/post-mortem/list`. PostMortemID string `json:"post_mortem_id" toon:"post_mortem_id"` @@ -8139,7 +8502,9 @@ type ResetPostMortemFollowUpsRequest struct { type ResetPostMortemStatusRequest struct { // Post-mortem ID; obtain it from `POST /incident/post-mortem/list`. PostMortemID string `json:"post_mortem_id" toon:"post_mortem_id"` - // Target report status: `drafting` draft, `published` published. + // Target report status. + // - `drafting`: being edited; the body can still be replaced with a content reset. + // - `published`: published; media files no longer referenced by the body are deleted. Status string `json:"status" toon:"status"` } @@ -8147,7 +8512,7 @@ type ResetPostMortemStatusRequest struct { type ResetPostMortemTitleRequest struct { // Post-mortem ID; obtain it from `POST /incident/post-mortem/list`. PostMortemID string `json:"post_mortem_id" toon:"post_mortem_id"` - // New report title. + // New report title, at most 256 characters. Title string `json:"title" toon:"title"` } @@ -8157,7 +8522,7 @@ type ResetWorkItemAssigneesRequest struct { AssigneeIDs []int64 `json:"assignee_ids,omitempty" toon:"assignee_ids,omitempty"` // Replacement assignee set. Each entry is `{type, id?}`. `type` is `person` or `ai_sre`; an `ai_sre` entry omits `id`. Mutually exclusive with `assignee_ids`: sending both returns an error. `assignee_ids` is the legacy alias and is equivalent to an all-`person` list. At most 20 entries. An empty array clears all assignees. Assignees []WorkItemAssignee `json:"assignees,omitempty" toon:"assignees,omitempty"` - // Current item version for optimistic locking. Must match the stored version. + // The item's current `version` (≥ 1) for optimistic locking. Version int64 `json:"version" toon:"version"` // Work item ID (opaque string, max 128 characters). WorkItemID string `json:"work_item_id" toon:"work_item_id"` @@ -8213,7 +8578,7 @@ type ResponderInsightItem struct { ResponderID int64 `json:"responder_id" toon:"responder_id"` // Responder name, returned when aggregating by responder; omitted when the name cannot be resolved. ResponderName string `json:"responder_name" toon:"responder_name"` - // Team ID, returned only when aggregating by team (`/insight/team`). + // Team ID, returned only by `/insight/team`. Omitted on the row that aggregates incidents without a team. TeamID int64 `json:"team_id" toon:"team_id"` // Team name, returned when aggregating by team; omitted when the name cannot be resolved (e.g. team deleted). TeamName string `json:"team_name" toon:"team_name"` @@ -8237,19 +8602,19 @@ type ResponderInsightItem struct { TotalNotifications int64 `json:"total_notifications" toon:"total_notifications"` // This responder's total time to acknowledgement in seconds: each incident contributes acknowledgement time minus assignment time. TotalSecondsToAck int64 `json:"total_seconds_to_ack" toon:"total_seconds_to_ack"` - // Start of the aggregation bucket, Unix epoch seconds. Equals `start_time` when no `aggregate_unit` is given. + // Start of the time bucket, Unix seconds. Equals `start_time` when `aggregate_unit` is not set. TS Timestamp `json:"ts" toon:"ts"` } // ResponderInsightResponse is generated from the Flashduty OpenAPI schema. type ResponderInsightResponse struct { - // Incident response metric rows aggregated by responder; further split by hour bucket or time bucket when `split_hours` or `aggregate_unit` is enabled. + // Per-responder metric rows, newest bucket first. Responders without incidents in a bucket produce no row. Items []ResponderInsightItem `json:"items" toon:"items"` } // ResponseEnvelope is generated from the Flashduty OpenAPI schema. type ResponseEnvelope struct { - // Endpoint-specific payload. See each operation's 200 response schema. + // Operation-specific payload, documented in each operation's 200 response. Operations without a payload return `{}` or omit `data` entirely. Data any `json:"data" toon:"data"` Error any `json:"error" toon:"error"` // Unique ID for this request. Mirrored in the Flashcat-Request-Id header. Include it when reporting issues. @@ -8258,23 +8623,23 @@ type ResponseEnvelope struct { // RevertRemoteConfigRequest is generated from the Flashduty OpenAPI schema. type RevertRemoteConfigRequest struct { - // RUM application ID. + // RUM application ID. Get application IDs via `POST /rum/application/list`. ApplicationID string `json:"application_id" toon:"application_id"` - // Operator's note. The console fills in `rolled back to vN` when left empty. + // Optional free-text note (not an enum), at most 255 characters, stored verbatim and returned as `reason` by `POST /rum/application/remote-config/history/list`. The server does not fill it in when omitted. Reason string `json:"reason,omitempty" toon:"reason,omitempty"` - // History version to republish. + // Version to restore. Must be one of the retained versions listed by `POST /rum/application/remote-config/history/list`. Version int64 `json:"version" toon:"version"` } // RevertRemoteConfigResponse is generated from the Flashduty OpenAPI schema. type RevertRemoteConfigResponse struct { - // New version number created by the revert. + // New version number created by the revert (previous highest version + 1). Version int64 `json:"version" toon:"version"` } // RoleDeleteRequest is generated from the Flashduty OpenAPI schema. type RoleDeleteRequest struct { - // When false (default), deletion fails with a `ReferenceExist` error listing the members that still hold the role in `data.refs`. When true, the role is first revoked from all holders and then deleted. + // When false (default), deletion fails with `ReferenceExist` while members still hold the role, listing them in `data.refs`. When true, the role is first revoked from all holders and then deleted. Does not bypass the SSO default-role check. IsForce bool `json:"is_force,omitempty" toon:"is_force,omitempty"` // Role ID to delete. Get IDs from `POST /role/list` (built-in roles: 2=Admin, 6=Responder, 8=Viewer). RoleID uint64 `json:"role_id" toon:"role_id"` @@ -8282,7 +8647,7 @@ type RoleDeleteRequest struct { // RoleGrantRequest is generated from the Flashduty OpenAPI schema. type RoleGrantRequest struct { - // Member IDs to grant/revoke the role. + // IDs of the members to grant the role to or revoke it from (from `POST /member/list`). All must be members of the account; duplicates are rejected. MemberIDs []uint64 `json:"member_ids" toon:"member_ids"` // Role ID to grant or revoke. Get IDs from `POST /role/list`. RoleID uint64 `json:"role_id" toon:"role_id"` @@ -8302,19 +8667,19 @@ type RoleInfoRequest struct { // RoleItem is generated from the Flashduty OpenAPI schema. type RoleItem struct { - // Unix epoch seconds the role was created. + // Time the role was created, Unix timestamp in seconds. Built-in roles carry a fixed timestamp. CreatedAt Timestamp `json:"created_at" toon:"created_at"` - // Role description. + // Role description. For built-in roles it is localized by the request language. Description string `json:"description" toon:"description"` - // False for built-in roles which cannot be modified. + // `false` for the built-in roles (Admin, Responder, Viewer); `true` for custom roles. Editable bool `json:"editable" toon:"editable"` - // IDs of permissions granted by this role. + // IDs of the permissions the role grants, in ascending order; resolve them with `POST /role/permission/list`. Empty array when none. PermissionIDs []uint64 `json:"permission_ids" toon:"permission_ids"` - // Unique role ID. + // Role ID. Built-in roles use the fixed IDs `2` (Admin), `6` (Responder), and `8` (Viewer). RoleID uint64 `json:"role_id" toon:"role_id"` - // Role display name. + // Role name, unique in the account. The built-in roles are named `Admin`, `Responder`, and `Viewer` in every language. RoleName string `json:"role_name" toon:"role_name"` - // Role status. + // Role status. `enabled` — active; `disabled` — turned off with `POST /role/disable`; it grants no permissions to the members who hold it. Built-in roles are always `enabled`; deleted roles are never returned. Status string `json:"status" toon:"status"` // Unix epoch seconds the role was last updated. UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` @@ -8334,15 +8699,15 @@ type RoleListRequest struct { type RoleListResponse struct { // Array of roles; includes account roles plus built-in global roles unless `no_global=true`; empty array when no results. Items []RoleItem `json:"items" toon:"items"` - // Total role count. + // Number of roles returned: custom roles plus the 3 built-in roles unless `no_global` is true. Total int64 `json:"total" toon:"total"` } // RolePermissionListRequest is generated from the Flashduty OpenAPI schema. type RolePermissionListRequest struct { - // Filter to permissions granted to these roles. + // Role IDs (built-in or custom) whose granted permissions to return or mark. IDs that do not exist are ignored. RoleIDs []uint64 `json:"role_ids,omitempty" toon:"role_ids,omitempty"` - // If true, return all permissions with is_granted set to indicate which are granted. + // When true, return every permission and use `is_granted` to mark the ones granted by `role_ids`. When false (default), return only the granted permissions. WithAll bool `json:"with_all,omitempty" toon:"with_all,omitempty"` } @@ -8354,11 +8719,11 @@ type RolePermissionListResponse struct { // RoleUpsertRequest is generated from the Flashduty OpenAPI schema. type RoleUpsertRequest struct { - // Role description. + // Role description, up to 499 characters. Omitting it on update clears the stored description. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Permission IDs to grant. Replaces the existing set. + // IDs of the permissions the role grants (from `POST /role/permission/list`). Replaces the existing set; omitting it or sending an empty array leaves the role with no permissions. PermissionIDs []uint64 `json:"permission_ids,omitempty" toon:"permission_ids,omitempty"` - // Role ID. Omit or set to 0 to create. + // ID of the custom role to update. Omit or set to 0 to create a new role. Do not pass the built-in role IDs `2`, `6`, or `8`. RoleID uint64 `json:"role_id,omitempty" toon:"role_id,omitempty"` // Role display name. 1–39 characters. RoleName string `json:"role_name" toon:"role_name"` @@ -8382,25 +8747,25 @@ type RotateIntegrationKeyResponse struct { type RouteCase struct { // Target channel IDs. Required when `routing_mode` is `standard` (or empty); returned as `null` for `name_mapping`. ChannelIDs []int64 `json:"channel_ids,omitempty" toon:"channel_ids,omitempty"` - // If `true`, evaluation continues to the next case after this one matches; otherwise matching stops at the first hit. + // When `true`, evaluation continues with the next case after this one matches and the channels of all matched cases are combined; when `false`, evaluation stops at this case. Fallthrough bool `json:"fallthrough,omitempty" toon:"fallthrough,omitempty"` - // List of match conditions that are AND-ed together. + // Conditions joined with AND; an empty list matches every event. Required. If []RouteMatchCondition `json:"if" toon:"if"` - // Label key whose value is used as the target channel name. Required when `routing_mode` is `name_mapping`. + // Event field whose value is used as the target channel name, for example `labels.service`. Required when `routing_mode` is `name_mapping`; if no enabled channel has that name, the case adds no channel. NameMappingLabel string `json:"name_mapping_label,omitempty" toon:"name_mapping_label,omitempty"` - // Routing mode. `standard` (default, also used when left empty) routes to the fixed channel IDs; `name_mapping` resolves channels by reading a label value from the alert event. + // Routing mode. `standard` routes to the fixed `channel_ids`; `name_mapping` routes to the enabled channel whose name equals the value of `name_mapping_label` on the event. An empty value is treated as `standard` and is omitted in responses. RoutingMode string `json:"routing_mode,omitempty" toon:"routing_mode,omitempty"` } // RouteDefault is generated from the Flashduty OpenAPI schema. type RouteDefault struct { - // Channel IDs to fall back to. + // Channels used when no case yields a channel. An empty list is treated as no default branch. ChannelIDs []int64 `json:"channel_ids,omitempty" toon:"channel_ids,omitempty"` } // RouteInfoRequest is generated from the Flashduty OpenAPI schema. type RouteInfoRequest struct { - // Integration ID. Must be greater than 0. + // Shared integration ID, greater than 0; obtain it from `POST /integration/list`. IntegrationID int64 `json:"integration_id" toon:"integration_id"` } @@ -8413,29 +8778,29 @@ type RouteItem struct { // ID of the person who created the rule. CreatorID int64 `json:"creator_id" toon:"creator_id"` Default RouteDefault `json:"default" toon:"default"` - // Soft-delete timestamp, Unix seconds. Omitted when the rule is active. + // Soft-delete time, Unix timestamp in seconds. Not returned by these endpoints, which return only active rules. DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` // Integration the rule belongs to. IntegrationID int64 `json:"integration_id" toon:"integration_id"` // Optional sections that visually group cases. Sections []RouteSection `json:"sections" toon:"sections"` - // Route status. `enabled` means active; `deleted` means removed, visible only in historical versions. + // Rule status. These endpoints return only `enabled` rules; `deleted` rules (for example of a deleted integration) are not returned. Status string `json:"status" toon:"status"` // Last update time, Unix timestamp in seconds. UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` // ID of the person who performed the last update. UpdatedBy int64 `json:"updated_by" toon:"updated_by"` - // Monotonic version number, incremented on each update. Use it for optimistic concurrency control. + // Version number, increased on every `POST /route/upsert`. The server does not use it for concurrency checks. Version int64 `json:"version" toon:"version"` } // RouteMatchCondition is generated from the Flashduty OpenAPI schema. type RouteMatchCondition struct { - // Field key to match against the alert event (e.g. `alert_severity`, `labels.service`). + // Alert or change event field to match: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `change_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`. An unknown key returns `InvalidParameter`. Key string `json:"key" toon:"key"` - // Match operator. `IN` matches when the field value is one of `vals`; `NOTIN` matches when it is not. + // Match operator. `IN` matches when the field value matches any entry in `vals`; `NOTIN` matches when it matches none. A missing field never matches `IN` and always matches `NOTIN`. Oper string `json:"oper" toon:"oper"` - // Values to compare against. Each value may be a literal string, a wildcard (`*`, `?`), a regular expression wrapped in slashes (`/pattern/`), a CIDR (`cidr:10.0.0.0/8`), or a numeric comparison (`num:lt:100`). + // Values to compare, at least one. Each entry is matched as: an exact string; a wildcard pattern when it contains `*` or `?` (must match the whole value); a regular expression when wrapped in slashes, such as `/^db-/` (may match anywhere in the value); an IP range written `cidr:`, such as `cidr:203.0.113.0/24`; or a numeric comparison `num::` with `lt`, `le`, `gt` or `ge`, such as `num:gt:90`. Vals []string `json:"vals" toon:"vals"` } @@ -8477,9 +8842,9 @@ type RuleEmptyResponse struct{} // RuleFieldsUpdateRequest is generated from the Flashduty OpenAPI schema. type RuleFieldsUpdateRequest struct { - // Annotation key-value pairs delivered with alert events; keys must not start with `$` (reserved for query fields). Effective only when `fields` includes `annotations`. + // Annotation key-value pairs delivered with alert events; replaces existing annotations as a whole, and keys must not start with `$` (reserved for query fields). Effective only when `fields` includes `annotations`; cannot be sent together with `annotations_patch`. Annotations map[string]string `json:"annotations,omitempty" toon:"annotations,omitempty"` - // Partial annotation update. Effective only when `fields` includes `annotations`; takes precedence over `annotations` when both are sent. + // Partial annotation update that keeps unmentioned annotations. Requires `annotations` in `fields` and cannot be sent together with `annotations`; otherwise the call returns `InvalidParameter`. AnnotationsPatch StringMapPatch `json:"annotations_patch,omitzero" toon:"annotations_patch,omitempty"` // IDs of the collaboration spaces alerts are sent to; may be empty. Effective only when `fields` includes `channel_ids`. ChannelIDs []uint64 `json:"channel_ids,omitempty" toon:"channel_ids,omitempty"` @@ -8489,31 +8854,31 @@ type RuleFieldsUpdateRequest struct { DebugLogEnabled bool `json:"debug_log_enabled,omitempty" toon:"debug_log_enabled,omitempty"` // Seconds to shift the evaluation query window backward, compensating for data ingestion latency. Effective only when `fields` includes `delay_seconds`. DelaySeconds int64 `json:"delay_seconds,omitempty" toon:"delay_seconds,omitempty"` - // Rule description (Markdown). Effective only when `fields` includes `description`. + // Rule description, rendered according to the rule's existing `description_type` (which this endpoint cannot change). Effective only when `fields` includes `description`. Description string `json:"description,omitempty" toon:"description,omitempty"` // Datasource IDs, merged with `ds_list` to decide which datasources the rule monitors; IDs survive datasource renames. Effective only when `fields` includes `ds_ids`. DsIDs []uint64 `json:"ds_ids,omitempty" toon:"ds_ids,omitempty"` // Datasource name match patterns; wildcards supported. Effective only when `fields` includes `ds_list`. DsList []string `json:"ds_list,omitempty" toon:"ds_list,omitempty"` - // Datasource type identifier. Effective only when `fields` includes `ds_type`. + // Datasource type identifier. Enabled rules must use a type that supports alerting: `prometheus`, `elasticsearch`, `loki`, `clickhouse`, `mysql`, `oracle`, `postgres`, `sls`, `tencent_cls`, `victorialogs`. Effective only when `fields` includes `ds_type`. DsType string `json:"ds_type,omitempty" toon:"ds_type,omitempty"` // Whether the rule is enabled. Setting it to `false` makes the server clean up the rule's active alerts. Effective only when `fields` includes `enabled`. Enabled bool `json:"enabled,omitempty" toon:"enabled,omitempty"` // Time windows during which the rule is in effect; element structure see `EnabledTime`. Effective only when `fields` includes `enabled_times`. EnabledTimes []EnabledTime `json:"enabled_times,omitempty" toon:"enabled_times,omitempty"` - // Field names to update. Only listed fields are updated, taking new values from the same-named request fields; values for unlisted fields are silently ignored. + // Names of the fields to update. Each listed field takes the value of the same-named request field, and is set to its zero value when that value is omitted; values sent for unlisted fields are ignored. An unknown name fails the whole call with `InvalidParameter`. Fields []string `json:"fields" toon:"fields"` - // Rule IDs to update. + // IDs of the rules to update; must contain at least one ID. IDs []uint64 `json:"ids" toon:"ids"` - // Custom label key-value pairs; replaces existing labels as a whole. Effective only when `fields` includes `labels`. + // Custom label key-value pairs; replaces existing labels as a whole. Effective only when `fields` includes `labels`; cannot be sent together with `labels_patch`. Labels map[string]string `json:"labels,omitempty" toon:"labels,omitempty"` - // Partial label update. Effective only when `fields` includes `labels`; takes precedence over `labels` when both are sent. + // Partial label update that keeps unmentioned labels. Requires `labels` in `fields` and cannot be sent together with `labels`; otherwise the call returns `InvalidParameter`. LabelsPatch StringMapPatch `json:"labels_patch,omitzero" toon:"labels_patch,omitempty"` - // Interval in seconds between repeated alert notifications. Effective only when `fields` includes `repeat_interval`. + // Interval in seconds between repeated alert notifications; values below 1 fall back to 3600, maximum 2147483647. Effective only when `fields` includes `repeat_interval`. RepeatInterval int64 `json:"repeat_interval,omitempty" toon:"repeat_interval,omitempty"` - // Maximum number of repeated notifications. Effective only when `fields` includes `repeat_total`. + // Maximum number of repeated notifications; values below 1 fall back to 3, maximum 2147483647. Effective only when `fields` includes `repeat_total`. RepeatTotal int64 `json:"repeat_total,omitempty" toon:"repeat_total,omitempty"` - // Timezone in which the rule executes. IANA timezone name; defaults to `Asia/Shanghai`. + // Timezone the rule runs in, as an IANA name (e.g. `Asia/Shanghai`, `UTC`); empty falls back to `Asia/Shanghai`. Effective only when `fields` includes `timezone`. Timezone string `json:"timezone,omitempty" toon:"timezone,omitempty"` } @@ -8525,41 +8890,41 @@ type RuleIDRequest struct { // RuleIDsRequest is generated from the Flashduty OpenAPI schema. type RuleIDsRequest struct { - // Rule IDs. + // IDs of the alert rules to delete; must contain at least one ID. Get them from `POST /monit/rule/list/basic`. IDs []uint64 `json:"ids" toon:"ids"` } // RuleListRequest is generated from the Flashduty OpenAPI schema. type RuleListRequest struct { - // Folder ID. Must be an existing folder; `0` is rejected with a `folder_not_found` error. + // ID of the folder to list. Must be an existing folder the caller can manage; `0` or an unknown ID returns `InvalidParameter`. FolderID uint64 `json:"folder_id,omitempty" toon:"folder_id,omitempty"` - // Also include rules from all descendant folders. When `true`, each returned item carries only `id`, `folder_id` and `name`; combine with `query` / `limit` for rule-picker scenarios. + // Also search all descendant folders. When `true`, results are sorted by name, capped by `limit`, and each item fills only `id`, `folder_id` and `name` (other fields carry zero values); combine with `query` for rule-picker scenarios. IncludeDescendants bool `json:"include_descendants,omitempty" toon:"include_descendants,omitempty"` // Max number of rules returned; only effective when `include_descendants` is `true`. Defaults to 50, capped at 100. Limit int64 `json:"limit,omitempty" toon:"limit,omitempty"` - // Rule name fuzzy filter; only effective when `include_descendants` is `true`. + // Filter by rule name substring; a numeric value also matches the rule with that ID. Only effective when `include_descendants` is `true`. Query string `json:"query,omitempty" toon:"query,omitempty"` } // RuleMoveRequest is generated from the Flashduty OpenAPI schema. type RuleMoveRequest struct { - // Destination folder ID. Obtainable via `POST /monit/folder/list`. + // Destination folder ID, from `POST /monit/folder/list`. Must be non-zero; a folder that does not exist or that the caller cannot manage fails the whole call with `AccessDenied`. DestFolderID uint64 `json:"dest_folder_id" toon:"dest_folder_id"` - // Rule IDs to move. + // IDs of the rules to move; must contain at least one ID. IDs []uint64 `json:"ids" toon:"ids"` } // RUMApplicationAlerting is generated from the Flashduty OpenAPI schema. type RUMApplicationAlerting struct { - // Channel IDs to send alerts to. Used only when `delivery_mode` is `oncall`. + // On-call channel IDs that receive the alerts; used only when `delivery_mode` is `oncall`. Kept as a draft in `webhook` mode. Can be `null` when never set. ChannelIDs []int64 `json:"channel_ids,omitempty" toon:"channel_ids,omitempty"` // Alert delivery channel: `oncall` routes alert events through Flashduty On-call, `webhook` POSTs them directly to `webhook_url`. An empty value is treated as `oncall`, and on create/update it is persisted as the deployment default (`webhook` on RUM-only on-premises deployments, `oncall` otherwise). Omitted when empty (legacy rows). DeliveryMode string `json:"delivery_mode,omitempty" toon:"delivery_mode,omitempty"` - // Whether alerting is enabled. + // Whether alerting is on. `false` turns alerting off; with `false`, `webhook_url` is not checked. Enabled bool `json:"enabled" toon:"enabled"` // Associated on-call integration ID (read-only, auto-assigned on save when `delivery_mode` is `oncall`). IntegrationID int64 `json:"integration_id,omitempty" toon:"integration_id,omitempty"` - // URL that receives alert events when `delivery_mode` is `webhook`; required in that mode, ignored otherwise. Omitted when empty. + // URL that receives alert events when `delivery_mode` is `webhook`. Required in that mode while `enabled` is `true`; must use `http` or `https`, and on Flashduty cloud must not resolve to a private, loopback, link-local or reserved address. Ignored in `oncall` mode. Omitted from responses when empty. WebhookURL string `json:"webhook_url,omitempty" toon:"webhook_url,omitempty"` } @@ -8569,19 +8934,19 @@ type RUMApplicationCreateRequest struct { Alerting RUMApplicationAlerting `json:"alerting,omitzero" toon:"alerting,omitempty"` // Application name. 1–40 characters. ApplicationName string `json:"application_name" toon:"application_name"` - // Restrict access to team members only. + // If `true`, only the account owner, account admins, the creator and members of the owning team can see or edit the application. Default `false`. IsPrivate bool `json:"is_private,omitempty" toon:"is_private,omitempty"` // Optional external-link integration configuration. Links RUMApplicationLinks `json:"links,omitzero" toon:"links,omitempty"` - // Do not infer geographic location. + // If `true`, geographic location is not inferred from the client IP. Default `false`. NoGeo bool `json:"no_geo,omitempty" toon:"no_geo,omitempty"` - // Do not collect IP addresses. + // If `true`, client IP addresses are not collected. Default `false`. NoIP bool `json:"no_ip,omitempty" toon:"no_ip,omitempty"` // Source code repositories to link, in order; the first entry is the primary repository. At most 10 entries. Repositories []RUMApplicationRepository `json:"repositories,omitempty" toon:"repositories,omitempty"` // Owning team ID. Get team IDs via `POST /team/list`. TeamID int64 `json:"team_id" toon:"team_id"` - // Optional APM tracing integration configuration. + // Optional APM tracing integration configuration. Stored as empty (`enabled: false`, empty `open_type` and `endpoint`) when omitted. Tracing RUMApplicationTracing `json:"tracing,omitzero" toon:"tracing,omitempty"` // Platform identifier: // @@ -8603,11 +8968,11 @@ type RUMApplicationCreateRequest struct { // RUMApplicationCreateResponse is generated from the Flashduty OpenAPI schema. type RUMApplicationCreateResponse struct { - // Auto-generated unique application ID. + // Server-generated application ID (22-character short UUID); pass it as `application_id` to the other application operations. ApplicationID string `json:"application_id" toon:"application_id"` // Application display name. ApplicationName string `json:"application_name" toon:"application_name"` - // Token for RUM SDK initialization. + // Token used to initialize the RUM SDK. Also returned by `POST /rum/application/info`. ClientToken string `json:"client_token" toon:"client_token"` } @@ -8619,21 +8984,21 @@ type RUMApplicationIDRequest struct { // RUMApplicationInfosRequest is generated from the Flashduty OpenAPI schema. type RUMApplicationInfosRequest struct { - // Up to 200 application IDs. Get IDs via `POST /rum/application/list`. + // Up to 200 application IDs. Duplicates are collapsed, and unknown or deleted IDs are skipped. Get IDs via `POST /rum/application/list`. ApplicationIDs []string `json:"application_ids" toon:"application_ids"` } // RUMApplicationInfosResponse is generated from the Flashduty OpenAPI schema. type RUMApplicationInfosResponse struct { - // Application info items matching the requested `application_ids` (max 200, deduplicated). + // Applications found among the requested `application_ids`, in no guaranteed order. Empty array when none match. Items []RUMApplicationItem `json:"items" toon:"items"` } // RUMApplicationItem is generated from the Flashduty OpenAPI schema. type RUMApplicationItem struct { - // Account ID. + // ID of the Flashduty account that owns the application. AccountID int64 `json:"account_id" toon:"account_id"` - // Alerting configuration of the application. + // Alerting configuration of the application. Always an object. Alerting RUMApplicationAlerting `json:"alerting" toon:"alerting"` // Unique application ID. ApplicationID string `json:"application_id" toon:"application_id"` @@ -8643,23 +9008,27 @@ type RUMApplicationItem struct { ClientToken string `json:"client_token" toon:"client_token"` // Creation timestamp, Unix epoch milliseconds. CreatedAt TimestampMilli `json:"created_at" toon:"created_at"` - // Creator member ID. + // Member ID of the creator. The creator can always edit the application. CreatedBy int64 `json:"created_by" toon:"created_by"` - // If `true`, the application is only accessible to team members. + // If `true`, only the account owner, account admins, the creator and members of the owning team can see or edit the application. IsPrivate bool `json:"is_private" toon:"is_private"` - // External-link integration configuration. + // External-link integration configuration. Always an object; `systems` can be `null` when no system was ever saved. Links RUMApplicationLinks `json:"links" toon:"links"` // If `true`, geographic location is not inferred from IP. NoGeo bool `json:"no_geo" toon:"no_geo"` // If `true`, IP addresses are not collected. NoIP bool `json:"no_ip" toon:"no_ip"` - // Linked source code repositories, in order; the first entry is the primary repository. Linking grants no access by itself: AI sessions can only read repositories granted to the account's GitHub App installations. + // Linked source code repositories, in order; the first entry is the primary repository. Empty array when none are linked. Linking grants no access by itself: AI sessions can only read repositories granted to the account's GitHub App installations. Repositories []RUMApplicationRepository `json:"repositories" toon:"repositories"` - // Application status. One of `enabled` (active, receiving data), `disabled` (deactivated), `deleted` (soft-delete marker; every query filters it out, so it never actually appears in responses). + // Application status: + // + // - `enabled`: the SDK `client_token` is accepted and data is collected. Every application created through the API starts in this state. + // - `disabled`: the `client_token` is rejected, so no new data is collected. No public operation sets this status. + // - `deleted`: soft-delete marker; deleted applications are filtered out of every response, so this value is never returned. Status string `json:"status" toon:"status"` - // Owning team ID. + // Owning team ID. Members of this team can edit the application and, when it is private, see it. TeamID int64 `json:"team_id" toon:"team_id"` - // APM tracing integration configuration. + // APM tracing integration configuration. Always an object; when tracing was never configured it is `enabled: false` with empty `open_type` and `endpoint`. Tracing RUMApplicationTracing `json:"tracing" toon:"tracing"` // Platform identifier: // @@ -8685,7 +9054,7 @@ type RUMApplicationItem struct { // RUMApplicationLink is generated from the Flashduty OpenAPI schema. type RUMApplicationLink struct { - // Whether this external system link is enabled. + // Whether this external system link is shown. Treated as `false` when omitted. Enabled bool `json:"enabled" toon:"enabled"` // RUM event types where this external system link is shown; at least one is required. // @@ -8699,11 +9068,11 @@ type RUMApplicationLink struct { // | `session` | Session events | // | `all` | All event types | EventTypes []string `json:"event_types" toon:"event_types"` - // Display color for the link icon. + // Display color for the link icon, e.g. `#0F766E`. Omitted from responses when empty. IconColor string `json:"icon_color,omitempty" toon:"icon_color,omitempty"` - // Short text shown in the link icon. + // Short text shown in the link icon, e.g. `S3`. Omitted from responses when empty. IconText string `json:"icon_text,omitempty" toon:"icon_text,omitempty"` - // Stable client-side identifier for this external system. + // Client-chosen identifier for this external system, kept as sent; the server does not validate it. ID string `json:"id,omitempty" toon:"id,omitempty"` // Display name of the external system. Name string `json:"name" toon:"name"` @@ -8713,7 +9082,7 @@ type RUMApplicationLink struct { // RUMApplicationLinks is generated from the Flashduty OpenAPI schema. type RUMApplicationLinks struct { - // Whether external link integration is enabled. + // Master switch for the external-link integration. Treated as `false` when omitted. Enabled bool `json:"enabled" toon:"enabled"` // External systems whose URL templates can be opened from matching RUM events. Systems []RUMApplicationLink `json:"systems,omitempty" toon:"systems,omitempty"` @@ -8722,13 +9091,13 @@ type RUMApplicationLinks struct { // RUMApplicationListRequest is generated from the Flashduty OpenAPI schema. type RUMApplicationListRequest struct { ListOptions - // Sort ascending if `true`. + // Sort ascending if `true`; default `false` (descending). Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` - // If `true`, return only applications belonging to the current user's teams. + // If `true`, return only applications owned by teams the caller belongs to. When the caller belongs to no team, the list is empty. IsMyTeam bool `json:"is_my_team,omitempty" toon:"is_my_team,omitempty"` // Sort field: `created_at` (creation time) or `updated_at` (last update time); defaults to `updated_at` when omitted. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` - // Substring match on the application name. + // Substring match on the application name (SQL `LIKE`, so `%` and `_` act as wildcards). Query string `json:"query,omitempty" toon:"query,omitempty"` // Filter by team ID. Get team IDs via `POST /team/list`. TeamID int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` @@ -8738,7 +9107,7 @@ type RUMApplicationListRequest struct { type RUMApplicationListResponse struct { // Whether more pages exist; `true` when matching records remain beyond the current page. HasNextPage bool `json:"has_next_page" toon:"has_next_page"` - // RUM applications of the current page. + // RUM applications on the current page. Empty array when nothing matches. Items []RUMApplicationItem `json:"items" toon:"items"` // Total number of applications matching the filter conditions. Total int64 `json:"total" toon:"total"` @@ -8754,25 +9123,29 @@ type RUMApplicationRepository struct { // RUMApplicationTracing is generated from the Flashduty OpenAPI schema. type RUMApplicationTracing struct { - // Whether tracing integration is enabled. + // Whether trace links are shown on RUM events. Enabled bool `json:"enabled" toon:"enabled"` - // Trace endpoint URL (http or https). + // Trace endpoint URL; must start with `http` or `https`. Required whenever `tracing` is sent, even with `enabled: false`. Empty in responses when tracing was never configured. Endpoint string `json:"endpoint" toon:"endpoint"` - // How to open the trace link. One of `popup` (open trace details in a popup) or `tab` (open in a new browser tab). + // How the trace link opens: + // + // - `popup`: open trace details in a popup. + // - `tab`: open them in a new browser tab. + // - `""` (empty): returned only when tracing was never configured; rejected in requests. OpenType string `json:"open_type" toon:"open_type"` } // RUMApplicationUpdateRequest is generated from the Flashduty OpenAPI schema. type RUMApplicationUpdateRequest struct { - // Alerting configuration. Omit to leave unchanged. + // Alerting configuration. When sent, it replaces the stored alerting object (except `integration_id`, which the server manages). Omit to leave unchanged. Alerting *RUMApplicationAlerting `json:"alerting,omitempty" toon:"alerting,omitempty"` // Application ID to update. Get application IDs via `POST /rum/application/list`. ApplicationID string `json:"application_id" toon:"application_id"` // New application name, 1–40 characters. Omit to leave unchanged. ApplicationName *string `json:"application_name,omitempty" toon:"application_name,omitempty"` - // Restrict access to members of the owning team; `false` explicitly makes the application public. Omit to leave unchanged. + // `true` limits access to the account owner, account admins, the creator and members of the owning team; `false` makes the application visible to everyone in the account. Omit to leave unchanged. IsPrivate *bool `json:"is_private,omitempty" toon:"is_private,omitempty"` - // External-link integration configuration. Omit to leave unchanged. + // External-link integration configuration. When sent, it replaces the stored object, including the whole `systems` list. Omit to leave unchanged. Links *RUMApplicationLinks `json:"links,omitempty" toon:"links,omitempty"` // When `true`, stop inferring geographic location from IP; when `false`, resume inferring it. Omit to leave unchanged. NoGeo *bool `json:"no_geo,omitempty" toon:"no_geo,omitempty"` @@ -8780,9 +9153,9 @@ type RUMApplicationUpdateRequest struct { NoIP *bool `json:"no_ip,omitempty" toon:"no_ip,omitempty"` // Replaces the linked source code repositories when present; an empty array removes all links, and omitting the field leaves them unchanged. At most 10 entries. Repositories []RUMApplicationRepository `json:"repositories,omitzero" toon:"repositories,omitempty"` - // Owning team ID. Get team IDs via `POST /team/list`. Omit to leave unchanged. + // New owning team ID. Get team IDs via `POST /team/list`. Omit to leave unchanged. Moving the application to another team changes who can edit it. TeamID *int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` - // APM tracing integration configuration. Omit to leave unchanged. + // APM tracing integration configuration. When sent, it replaces the stored object and must carry a valid `open_type` and `endpoint`. Omit to leave unchanged. Tracing RUMApplicationTracing `json:"tracing,omitzero" toon:"tracing,omitempty"` // Application type. Omit to leave unchanged. Platform identifier: // @@ -8804,33 +9177,33 @@ type RUMApplicationUpdateRequest struct { // RUMDataFieldMeta is generated from the Flashduty OpenAPI schema. type RUMDataFieldMeta struct { - // Column name. + // Column name or alias as written in `sql`; `ts` for the bucket column of `time_series` queries. Name string `json:"name" toon:"name"` - // Whether values in this column may be null. + // Whether values in this column may be `null`. `true` when the driver cannot tell. Nullable bool `json:"nullable" toon:"nullable"` - // Backend database type name for this column. + // Column type name as reported by the database driver, such as `VARCHAR`, `BIGINT`, `DOUBLE` or `DATETIME`. It depends on the selected column or expression, so the set is open; use it as a hint for parsing `values`. Type string `json:"type" toon:"type"` } // RUMDataQueryDefinition is generated from the Flashduty OpenAPI schema. type RUMDataQueryDefinition struct { - // When true, asks the query engine to avoid sampling when possible. + // When `true`, the query always runs on the full data and the response never carries `sampling`. When `false` (default), the server may sample aggregate queries over large time windows. DisableSampling bool `json:"disable_sampling,omitempty" toon:"disable_sampling,omitempty"` - // Optional RUM DQL filter expression used together with SQL validation. + // Optional RUM DQL filter. It is translated and `AND`-ed into the `WHERE` clause of `sql`. A DQL parse error is reported in this query's `error` entry. Dql string `json:"dql,omitempty" toon:"dql,omitempty"` // Output format. `table` returns rows; `time_series` returns bucketed time-series rows. Format string `json:"format" toon:"format"` // Client-supplied query ID. The same value is used as the key in the response object. ID string `json:"id" toon:"id"` - // Time bucket interval in seconds for `time_series` queries. + // Minimum time-bucket width in **milliseconds** for `time_series` queries. Default 3600 (3.6 seconds). The effective width is the smallest step of a fixed ladder that is at least this value and at least the window length divided by `max_points`; it is returned as `interval`. Ignored for `table` queries. Interval int64 `json:"interval,omitempty" toon:"interval,omitempty"` - // Maximum number of points for `time_series` queries. + // Upper bound on the number of buckets for `time_series` queries. Default 1226. The bucket width grows so that the window holds at most this many buckets. Ignored for `table` queries. MaxPoints int64 `json:"max_points,omitempty" toon:"max_points,omitempty"` - // Opaque cursor returned by a previous table query for continuing pagination. + // Cursor from a previous response's `search_after_ctx`, to fetch the next page of the same `table` query. Only used by non-aggregate queries with `ORDER BY` and no `OFFSET`. An invalid value makes this query fail. SearchAfterCtx string `json:"search_after_ctx,omitempty" toon:"search_after_ctx,omitempty"` - // RUM SQL query to execute. + // RUM SQL `SELECT` statement. `FROM` names a scope table (`sessions`, `views`, `actions`, `errors`, `resources`, `long_tasks`, `vitals`, `issues`, `sourcemaps`); columns are `field_key` values from `POST /rum/field/list`. The server adds the account and time-range filters. Sql string `json:"sql" toon:"sql"` - // IANA time zone name used when evaluating time functions, such as `Asia/Shanghai`. + // IANA time zone name, such as `Asia/Shanghai`, used to align `time_series` bucket boundaries to local time. Defaults to UTC alignment. Ignored for `table` queries; an unknown name fails the request with `InvalidParameter`. TimeZone string `json:"time_zone,omitempty" toon:"time_zone,omitempty"` } @@ -8838,7 +9211,7 @@ type RUMDataQueryDefinition struct { type RUMDataQueryOutput struct { // Query result. Omitted when the query failed. Data RUMDataQueryResult `json:"data" toon:"data"` - // Subquery failure details. Omitted when the query succeeded. + // Set when this query failed after request validation (unknown table or column, invalid `dql` or `search_after_ctx`, database error). The code is always `InternalError`. Omitted when the query succeeded. Error any `json:"error" toon:"error"` } @@ -8854,15 +9227,15 @@ type RUMDataQueryRequest struct { // RUMDataQueryResult is generated from the Flashduty OpenAPI schema. type RUMDataQueryResult struct { - // Column metadata for the values matrix. + // Column metadata, one entry per returned column, in the same order as `values`. For `time_series` queries the first column is `ts`. Fields []RUMDataFieldMeta `json:"fields" toon:"fields"` - // Effective time bucket interval in seconds. Omitted for `table`-format queries. + // Effective time-bucket width in **milliseconds** used by a `time_series` query. Omitted for `table` queries. Interval int64 `json:"interval" toon:"interval"` // Sampling metadata. Omitted when the query did not use sampling. Sampling RUMDataSamplingDecision `json:"sampling" toon:"sampling"` - // Opaque cursor for continuing paginated table queries. Omitted when the query is not a cursor-paginated table query or no further pages exist. + // Cursor for the next page of a non-aggregate `table` query with `ORDER BY` and no `OFFSET`. Present only when this page returned as many rows as the `LIMIT`; omitted otherwise. SearchAfterCtx string `json:"search_after_ctx" toon:"search_after_ctx"` - // Rows returned by the query. Each row aligns with `fields` by index. + // Result values in column-major order: `values[i]` is the list of every row's value for column `fields[i]`. A column is `null` when the query returned no rows. Datetime values are returned as RFC 3339 strings. Values [][]any `json:"values" toon:"values"` } @@ -8870,7 +9243,7 @@ type RUMDataQueryResult struct { type RUMDataSamplingDecision struct { // Whether sampling was applied. Always `true` here — the `sampling` object is omitted entirely when sampling was not used. Enabled bool `json:"enabled" toon:"enabled"` - // Multiplier used to scale sampled counts back to estimated full counts. + // Multiplier applied to scale sampled results back to estimated full values. `COUNT`, `SUM` and `COUNT(DISTINCT)` columns in `values` are already multiplied by it; other aggregates are returned as computed on the sample. ScaleFactor float64 `json:"scale_factor" toon:"scale_factor"` } @@ -8878,9 +9251,9 @@ type RUMDataSamplingDecision struct { type RUMErrorIngestionCreateRequest struct { // RUM application ID. Get application IDs via `POST /rum/application/list`. ApplicationID string `json:"application_id" toon:"application_id"` - // Rule description, up to 512 characters. + // Rule description, up to 512 characters. Defaults to an empty string. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Filter conditions (OR-of-ANDs) to match errors; matched errors are dropped and not ingested. + // Conditions (OR-of-ANDs) that select errors. A matched error is still stored but is not grouped into any issue. Filters RUMErrorIngestionOrFilters `json:"filters" toon:"filters"` // Rule name, 1-128 characters. RuleName string `json:"rule_name" toon:"rule_name"` @@ -8899,25 +9272,27 @@ type RUMErrorIngestionEmptyResponse struct{} // RUMErrorIngestionFilterCondition is generated from the Flashduty OpenAPI schema. type RUMErrorIngestionFilterCondition struct { - // Field key. One of `error.usr_id`, `error.usr_email`, `error.error_type`, `error.error_message`, `error.error_stack`, `error.view_url`, `error.env`, `error.version`, `error.service`, `error.browser_name`, `error.browser_version`, `error.fingerprint`, `error.is_crash`, or a `context.`-prefixed custom context path (up to 3 levels deep). + // Field to match. One of `error.usr_id`, `error.usr_email`, `error.error_type`, `error.error_message`, `error.error_stack`, `error.view_url`, `error.env`, `error.version`, `error.service`, `error.browser_name`, `error.browser_version`, `error.fingerprint`, `error.is_crash` (value `true` or `false`), or a `context.`-prefixed path into the error's custom context. Context objects are flattened with dots up to 3 levels (`context.a.b.c`); a deeper object is compared as its JSON text, and array values can't be matched. Key string `json:"key" toon:"key"` - // Match mode: `IN` matches when the field value matches any entry in `vals`; `NOTIN` matches when it matches none. + // Match mode: + // - `IN`: matches when the field value matches any entry in `vals`. A context field the error doesn't carry never matches. + // - `NOTIN`: matches when the field value matches none of `vals`. A context field the error doesn't carry always matches. Oper string `json:"oper" toon:"oper"` - // Values to match against, at least 1 entry. Each entry is an exact string, or a special pattern using wildcards (`*`/`?`), a regexp wrapped in `/`, a `cidr:`-prefixed CIDR match, or a `num:lt|le|gt|ge:`-prefixed numeric comparison. + // Values to match against, at least 1 entry. Each entry is one of: an exact, case-sensitive string; a wildcard pattern using `*`/`?` that must match the whole value; a regexp wrapped in `/` (matches anywhere in the value unless anchored); `cidr:` (the value is parsed as an IP); or `num:lt|le|gt|ge:` (the value is parsed as a number, non-numeric values don't match). Vals []string `json:"vals" toon:"vals"` } // RUMErrorIngestionHistoryItem is generated from the Flashduty OpenAPI schema. type RUMErrorIngestionHistoryItem struct { - // The application's complete rule list as of this version. + // The application's complete non-deleted rule list as it was just before the change that created this version. Empty for the version created by the application's first rule. Rules []RUMErrorIngestionRuleSnapshotItem `json:"rules" toon:"rules"` - // Unix timestamp in milliseconds when this snapshot was recorded. + // Time of the change that created this version, as a Unix timestamp in milliseconds. UpdatedAt TimestampMilli `json:"updated_at" toon:"updated_at"` - // Member ID whose action triggered this snapshot. + // Member ID of the person who made the change that created this version. UpdatedBy int64 `json:"updated_by" toon:"updated_by"` - // Display name of the member whose action triggered this snapshot. + // Display name of that member at the time of the change. UpdatedByName string `json:"updated_by_name" toon:"updated_by_name"` - // History version number, incrementing from 1. + // History version number, starting at 1 and incremented by every write. Pass it to `POST /rum/error-ingestion/rules/history/revert`. Version int64 `json:"version" toon:"version"` } @@ -8926,19 +9301,22 @@ type RUMErrorIngestionHistoryListRequest struct { ListOptions // RUM application ID. Get application IDs via `POST /rum/application/list`. ApplicationID string `json:"application_id" toon:"application_id"` - // Sort ascending instead of the default descending order. + // `true` sorts ascending; `false` (default) sorts descending, newest first. Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` - // Sort column: `updated_at` or `version`. Unrecognized values fall back to `updated_at`. + // Sort column: + // - `updated_at`: time of the change that created the version (default). + // - `version`: version number. + // Any other value falls back to `updated_at`. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` } // RUMErrorIngestionHistoryListResponse is generated from the Flashduty OpenAPI schema. type RUMErrorIngestionHistoryListResponse struct { - // Whether another page of history exists after this one. + // `true` when more versions exist after this page. HasNextPage bool `json:"has_next_page" toon:"has_next_page"` // History snapshots, ordered by `orderby`/`asc`. Items []RUMErrorIngestionHistoryItem `json:"items" toon:"items"` - // Total number of history versions for the application. + // Total number of history versions for the application, across all pages. Total int64 `json:"total" toon:"total"` } @@ -8964,19 +9342,21 @@ type RUMErrorIngestionRevertRequest struct { // RUMErrorIngestionRule is generated from the Flashduty OpenAPI schema. type RUMErrorIngestionRule struct { - // Unix timestamp in milliseconds when the rule was created. + // Unix timestamp in milliseconds when the rule was created; reset to the revert time when the rule is restored by a history revert. CreatedAt TimestampMilli `json:"created_at" toon:"created_at"` - // Rule description, up to 512 characters. + // Rule description, up to 512 characters; empty string when none was given. Description string `json:"description" toon:"description"` - // The rule's filter conditions. + // The rule's conditions. An error that matches them is stored but not grouped into any issue. Filters RUMErrorIngestionOrFilters `json:"filters" toon:"filters"` - // Rule ID. + // Rule ID, generated by the server on `create`. It stays the same across updates and history reverts. RuleID string `json:"rule_id" toon:"rule_id"` // Rule name, 1-128 characters. Not required to be unique within the application. RuleName string `json:"rule_name" toon:"rule_name"` - // Current status of the rule. + // Rule status: + // - `enabled`: the rule is applied to newly ingested errors. + // - `disabled`: the rule is kept but not applied. Status string `json:"status" toon:"status"` - // Unix timestamp in milliseconds when the rule was last updated. + // Unix timestamp in milliseconds of the last update, enable, or disable; reset to the revert time when the rule is restored by a history revert. UpdatedAt TimestampMilli `json:"updated_at" toon:"updated_at"` } @@ -8990,7 +9370,7 @@ type RUMErrorIngestionRuleIDRequest struct { // RUMErrorIngestionRuleSnapshotItem is generated from the Flashduty OpenAPI schema. type RUMErrorIngestionRuleSnapshotItem struct { - // Account ID. + // ID of the account that owns the rule. AccountID int64 `json:"account_id" toon:"account_id"` // RUM application ID the rule belongs to. ApplicationID string `json:"application_id" toon:"application_id"` @@ -8998,23 +9378,25 @@ type RUMErrorIngestionRuleSnapshotItem struct { CreatedAt TimestampMilli `json:"created_at" toon:"created_at"` // Member ID who created the rule. CreatedBy int64 `json:"created_by" toon:"created_by"` - // Unix timestamp in milliseconds when the row was soft-deleted; `0` when not deleted. + // Soft-delete time as a Unix timestamp in milliseconds. Always `0` here, because snapshots contain only non-deleted rules. DeletedAt TimestampMilli `json:"deleted_at" toon:"deleted_at"` - // Rule description. + // Rule description as of this snapshot version; empty string when none was given. Description string `json:"description" toon:"description"` // The rule's filter conditions as of this snapshot version. Filters RUMErrorIngestionOrFilters `json:"filters" toon:"filters"` - // Internal row ID. + // Internal storage row ID. Not accepted by any endpoint; use `rule_id` instead. Changes when the rule is restored by a history revert. ID int64 `json:"id" toon:"id"` - // Rule ID. + // Rule ID, the same value `list` returns for this rule. RuleID string `json:"rule_id" toon:"rule_id"` - // Rule name. + // Rule name as of this snapshot version. RuleName string `json:"rule_name" toon:"rule_name"` - // The rule's status as of this snapshot version. + // The rule's status as of this snapshot version: + // - `enabled`: applied to newly ingested errors. + // - `disabled`: kept but not applied. Status string `json:"status" toon:"status"` // Unix timestamp in milliseconds when the row was last updated. UpdatedAt TimestampMilli `json:"updated_at" toon:"updated_at"` - // Member ID who last updated the rule. + // Member ID who last updated the rule before this snapshot. UpdatedBy int64 `json:"updated_by" toon:"updated_by"` } @@ -9034,13 +9416,13 @@ type RUMErrorIngestionUpdateRequest struct { // RUMFacetCountRequest is generated from the Flashduty OpenAPI schema. type RUMFacetCountRequest struct { - // RUM DQL filter expression applied before counting. + // RUM DQL filter expression applied before counting. Fields in it are validated against the `scope`. Dql string `json:"dql,omitempty" toon:"dql,omitempty"` // End of the time range, Unix epoch milliseconds. Maximum 31-day span. EndTime int64 `json:"end_time" toon:"end_time"` - // Field key whose value distribution to count; must be a registered field of the given `scope`. List available fields via `POST /rum/field/list`. + // Field key whose value distribution to count, such as `error_type`. Must be a facet field of the given `scope` with `show_type: list` and a non-array `value_type`. List candidates with `POST /rum/field/list`. FacetKey string `json:"facet_key" toon:"facet_key"` - // When set, filter events where `facet_key` equals this value before counting. Accepts string, number, or boolean. + // When set, count only events whose `facet_key` equals this value. The JSON type must match the field's `value_type` (string, number or boolean); a mismatch returns `InvalidParameter`. When omitted, events with a `null` value are excluded. FacetValue any `json:"facet_value,omitempty" toon:"facet_value,omitempty"` // Symbol kind, used only when `scope` is `sourcemap` and only meaningful for `android`/`harmony`: `mapping` (default) selects ProGuard/R8 mappings or ArkTS sourcemaps, `native` selects native .so symbols. Kind string `json:"kind,omitempty" toon:"kind,omitempty"` @@ -9060,7 +9442,7 @@ type RUMFacetCountRequest struct { // | `issue` | Aggregated error-tracking issues | // | `sourcemap` | Sourcemap / symbol files | Scope string `json:"scope" toon:"scope"` - // SQL WHERE clause (no SELECT) for additional filtering. + // Bare SQL `WHERE` condition (without the `WHERE` keyword) for extra filtering, such as `env = 'prod'`. Any occurrence of `SELECT` is rejected. Sql string `json:"sql,omitempty" toon:"sql,omitempty"` // Start of the time range, Unix epoch milliseconds. StartTime int64 `json:"start_time" toon:"start_time"` @@ -9099,21 +9481,21 @@ type RUMFieldItem struct { FieldKey string `json:"field_key" toon:"field_key"` // Human-readable field name. FieldName string `json:"field_name" toon:"field_name"` - // Display group for this field. + // Display group used to cluster fields in the console, such as `error`, `action` or `device`. Empty when the field has no group. Group string `json:"group" toon:"group"` // True if value distribution counting is supported for this field. IsFacet bool `json:"is_facet" toon:"is_facet"` // True if this field can be used in DQL/SQL queries. Queryable bool `json:"queryable" toon:"queryable"` - // RUM scopes this field appears in. + // RUM scopes this field appears in, using the same values as the request `scopes` (for example `error`, `issue`). Scopes []string `json:"scopes" toon:"scopes"` // Display type in the analytics UI. One of `list` (shown as an enumerated value list; only this type supports facet counting) or `range` (filtered and shown as a numeric/time range). ShowType string `json:"show_type" toon:"show_type"` - // Field status, e.g. `active`. + // Field status. `enabled`: the field is in use. `disabled`: the field is defined but switched off. Deleted fields are never returned. Status string `json:"status" toon:"status"` - // Measurement unit family, e.g. `time`, `bytes`. Empty for dimensionless fields. + // Measurement unit family. `time`: a duration or timestamp (see `unit_name`). `bytes`: a size in bytes. Empty string for dimensionless fields. UnitFamily string `json:"unit_family" toon:"unit_family"` - // Specific measurement unit, e.g. `millisecond`, `byte`. + // Unit of the stored value. Durations: `nanosecond`, `microsecond`, `millisecond`, `second`. Timestamps: `unix_millisecond`, `unix_second`. Sizes: `byte`. Empty string for dimensionless fields. Most built-in duration fields are in `nanosecond`. UnitName string `json:"unit_name" toon:"unit_name"` // Data type of the field value. One of: // @@ -9163,15 +9545,15 @@ type RUMIssueExportRequest struct { Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` // When `true`, match by time-range overlap: export issues still active within the window (`last_seen_timestamp` >= `start_time`) even if created before it. Default `false` exports only issues created inside the window. ByIntersection bool `json:"by_intersection,omitempty" toon:"by_intersection,omitempty"` - // Console origin used to build the `issue_url` column, e.g. `https://console.flashcat.cloud`. The service cannot infer it (SaaS, on-premises and dev releases answer on different origins). + // Console origin used to build the `issue_url` column, e.g. `https://console.flashcat.cloud`; a trailing `/` is trimmed. The service cannot infer it. When omitted, `issue_url` holds only the path `/rum/error-tracking/issue/`. ConsoleOrigin string `json:"console_origin,omitempty" toon:"console_origin,omitempty"` - // DQL query for advanced filtering. Cannot be used with `sql`. + // DQL query for advanced filtering. Field names must be fields of the `issue` scope (see `POST /rum/field/list` with `scopes: ["issue"]`); a bare full-text term searches the error message. Cannot be used with `sql`. Dql string `json:"dql,omitempty" toon:"dql,omitempty"` // End of the time range, Unix epoch milliseconds. Must be greater than `start_time`; maximum range: 183 days. EndTime int64 `json:"end_time" toon:"end_time"` // If `true`, only export issues with at least one associated error event. ErrorRequired bool `json:"error_required,omitempty" toon:"error_required,omitempty"` - // CSV columns to export, in the order they appear. Unknown keys are rejected with a parameter error; an empty array uses the default column set. + // CSV columns to export, in the order they appear. Unknown keys are rejected with a parameter error and duplicates are dropped. Empty or omitted: every column below except the `sample_first_*` group. // // | Value | Column content | // |---|---| @@ -9192,7 +9574,23 @@ type RUMIssueExportRequest struct { // | `last_seen_version` | Application version at the most recent occurrence | // | `versions` | All affected versions | // | `suspected_cause` | Suspected cause category | - // | `resolved_at` | Resolution time (rendered in `time_zone`) | + // | `resolved_at` | Resolution time (rendered in `time_zone`); empty while unresolved | + // | `sample_time` | Latest error event in the time window: time of the event (rendered in `time_zone`) | + // | `sample_version` | Latest error event in the time window: application version | + // | `sample_view` | Latest error event in the time window: view name, or the view URL when the name is empty | + // | `sample_session_id` | Latest error event in the time window: session ID | + // | `sample_device` | Latest error event in the time window: device brand and model | + // | `sample_os` | Latest error event in the time window: OS name and version | + // | `sample_browser` | Latest error event in the time window: browser name and version | + // | `sample_stack` | Latest error event in the time window: error stack, truncated to the first 20 lines | + // | `sample_first_time` | Earliest error event in the time window: time of the event (rendered in `time_zone`) | + // | `sample_first_version` | Earliest error event in the time window: application version | + // | `sample_first_view` | Earliest error event in the time window: view name, or the view URL when the name is empty | + // | `sample_first_session_id` | Earliest error event in the time window: session ID | + // | `sample_first_device` | Earliest error event in the time window: device brand and model | + // | `sample_first_os` | Earliest error event in the time window: OS name and version | + // | `sample_first_browser` | Earliest error event in the time window: browser name and version | + // | `sample_first_stack` | Earliest error event in the time window: error stack, truncated to the first 20 lines | ExportFields []string `json:"export_fields,omitempty" toon:"export_fields,omitempty"` // Sort field; defaults to `updated_at` when omitted. // @@ -9204,9 +9602,9 @@ type RUMIssueExportRequest struct { // | `error_count` | Error occurrence count | // | `severity` | Severity rank (`Critical` > `Warning` > `Info`) | Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` - // SQL-style query for advanced filtering. Cannot be used with `dql`. + // SQL-style WHERE condition for advanced filtering, without the `WHERE` keyword (for example `error_count > 100`). Field names must be fields of the `issue` scope; any text containing `SELECT` is rejected. Cannot be used with `dql`. Sql string `json:"sql,omitempty" toon:"sql,omitempty"` - // Start of the time range, Unix epoch milliseconds. + // Start of the time range, Unix timestamp in milliseconds (a value that looks like seconds is rejected). Issues are matched by creation time unless `by_intersection` is `true`. StartTime int64 `json:"start_time" toon:"start_time"` // Filter by triage status; any other value is rejected with a parameter error. // @@ -9230,7 +9628,7 @@ type RUMIssueExportRequest struct { SuspectedCauses []string `json:"suspected_causes,omitempty" toon:"suspected_causes,omitempty"` // Filter by team IDs. Get team IDs via `POST /team/list`. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` - // IANA time zone used to render timestamps in the CSV, e.g. `Asia/Shanghai` or `UTC`. Default: `Asia/Shanghai`. + // IANA time zone used to render the CSV time columns and the file name, e.g. `Asia/Shanghai` or `UTC`. Default: `Asia/Shanghai`. An unknown zone name returns `InvalidParameter`. TimeZone string `json:"time_zone,omitempty" toon:"time_zone,omitempty"` } @@ -9262,19 +9660,21 @@ type RUMIssueItem struct { IssueID string `json:"issue_id" toon:"issue_id"` // Information about the issue's most recent occurrence (time and application version). LastSeen RUMIssueItemLastSeen `json:"last_seen" toon:"last_seen"` - // Regression metadata. Present only when a previously resolved issue re-occurred. + // Regression record. Present only after a resolved issue was reopened because its error recurred; cleared when the issue is resolved again. Regression RUMIssueItemRegression `json:"regression" toon:"regression"` - // Time the issue was marked resolved, Unix timestamp in milliseconds; 0 while unresolved. + // How the issue reacts when its error recurs after being resolved: `any` reopens it on any recurrence; `version` reopens it only when the error recurs in an application version the issue has not been seen in (errors without a version always reopen it). New issues and automatic resolution use `version`; resolving through `POST /rum/issue/update` without `resolve_mode` sets `any`. + ResolveMode string `json:"resolve_mode" toon:"resolve_mode"` + // Time the issue was marked resolved (by a user or automatically), Unix timestamp in milliseconds; `0` while unresolved. ResolvedAt TimestampMilli `json:"resolved_at" toon:"resolved_at"` - // Person ID of the user who marked the issue resolved; 0 while unresolved. + // Person ID of the user who marked the issue resolved; `0` while unresolved or when the issue was resolved automatically. ResolvedBy int64 `json:"resolved_by" toon:"resolved_by"` // Name of the service that produced this issue, taken from the error event's `service` field. Service string `json:"service" toon:"service"` // Affected user sessions. SessionCount int64 `json:"session_count" toon:"session_count"` - // Issue severity: `Critical`, `Warning`, or `Info`. Empty string on legacy issues created before severity existed. + // Issue severity, fixed when the issue is created: the first matching enabled preset severity rule (see `POST /rum/issue/preset-severity/rules/list`) decides it, otherwise a built-in rule (crashes are `Critical`; other errors are scored by environment and message keywords). An error only joins an existing issue of equal or higher severity, so the same error can produce separate issues per severity. Empty string on legacy issues created before severity existed. Severity string `json:"severity" toon:"severity"` - // Triage status of the issue; soft-deleted (`deleted`) issues are never returned. + // Triage status of the issue; soft-deleted (`deleted`) issues are never returned. The system resolves an issue automatically when its error has not been seen for 14 days, or when a newer application version reports no such error, and reopens a resolved issue as `for_review` when the error recurs (see `resolve_mode`). // // | Value | Meaning | // |---|---| @@ -9289,7 +9689,7 @@ type RUMIssueItem struct { TeamID int64 `json:"team_id" toon:"team_id"` // Time the issue was last updated, Unix timestamp in milliseconds. UpdatedAt TimestampMilli `json:"updated_at" toon:"updated_at"` - // Deduplicated list of application versions in which this issue has occurred; may contain an empty string for events without version info. + // Deduplicated list of application versions in which this issue has occurred; may contain an empty string for events without version info. `null` on issues that never recorded a version list. Versions []string `json:"versions" toon:"versions"` } @@ -9302,7 +9702,7 @@ type RUMIssueListRequest struct { Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` // When `true`, match by time-range overlap: return issues still active within the window (`last_seen_timestamp` >= `start_time`) even if created before it. Default `false` returns only issues created inside the window. ByIntersection bool `json:"by_intersection,omitempty" toon:"by_intersection,omitempty"` - // DQL query for advanced filtering. Cannot be used with `sql`. + // DQL query for advanced filtering. Field names must be fields of the `issue` scope (see `POST /rum/field/list` with `scopes: ["issue"]`); a bare full-text term searches the error message. Cannot be used with `sql`. Dql string `json:"dql,omitempty" toon:"dql,omitempty"` // End of the time range, Unix epoch milliseconds. Must be greater than `start_time`; maximum range: 183 days. EndTime int64 `json:"end_time" toon:"end_time"` @@ -9318,9 +9718,9 @@ type RUMIssueListRequest struct { // | `error_count` | Error occurrence count | // | `severity` | Severity rank (`Critical` > `Warning` > `Info`) | Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` - // SQL-style query for advanced filtering. Cannot be used with `dql`. + // SQL-style WHERE condition for advanced filtering, without the `WHERE` keyword (for example `error_count > 100`). Field names must be fields of the `issue` scope; any text containing `SELECT` is rejected. Cannot be used with `dql`. Sql string `json:"sql,omitempty" toon:"sql,omitempty"` - // Start of the time range, Unix epoch milliseconds. + // Start of the time range, Unix timestamp in milliseconds (a value that looks like seconds is rejected). Issues are matched by creation time unless `by_intersection` is `true`. StartTime int64 `json:"start_time" toon:"start_time"` // Filter by triage status; any other value is rejected with a parameter error. // @@ -9360,7 +9760,14 @@ type RUMIssueListResponse struct { type RUMIssueUpdateRequest struct { // Issue ID to update. Get issue IDs via `POST /rum/issue/list`. IssueID string `json:"issue_id" toon:"issue_id"` - // New status. Setting `resolved` records the resolution time and operator; switching away from `resolved` clears them. + // How the issue reacts when its error recurs after being resolved. Applied only together with `status: resolved`; defaults to `any` there when omitted, and is ignored with any other status. + // + // | Value | Meaning | + // |---|---| + // | `any` | Reopen the issue on any recurrence | + // | `version` | Reopen only when the error recurs in an application version the issue has not been seen in; errors without a version always reopen it | + ResolveMode string `json:"resolve_mode,omitempty" toon:"resolve_mode,omitempty"` + // New status. Setting `resolved` on an unresolved issue records the resolution time and operator and clears `regression`; switching away from `resolved` clears the resolution time and operator. Omit to keep the current status. // // | Value | Meaning | // |---|---| @@ -9388,7 +9795,7 @@ type RUMPresetSeverityRuleCreateRequest struct { ApplicationID string `json:"application_id" toon:"application_id"` // Optional description, up to 512 characters. Description string `json:"description,omitempty" toon:"description,omitempty"` - // OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches. + // OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches. An empty outer array never matches; an empty inner group matches every error. Filters [][]RUMPresetSeverityRuleFilterCondition `json:"filters" toon:"filters"` // Rule display name, 1-128 characters. RuleName string `json:"rule_name" toon:"rule_name"` @@ -9423,11 +9830,11 @@ type RUMPresetSeverityRuleFilterCondition struct { // | `error.device_type` | Device type | // | `error.os_name` | Operating system name | // | `error.browser_name` | Browser name | - // | `error.is_crash` | Whether the error is a crash (boolean) | + // | `error.is_crash` | Whether the error is a crash, compared as the string `true` or `false` | Key string `json:"key" toon:"key"` - // Match semantics: `IN` matches when the field's value matches any of `vals`; `NOTIN` matches when it matches none of them (and matches when the field is absent). + // Match semantics: `IN` matches when the attribute value matches any of `vals`; `NOTIN` matches when it matches none of them. An attribute the error does not carry is compared as an empty string. Oper string `json:"oper" toon:"oper"` - // Values to match against. Each entry supports exact string match, wildcard (`*`/`?`), regex (wrap in `/.../`), CIDR (`cidr:10.0.0.0/8`) for IP-shaped values, or numeric comparison (`num:gt:100`, `num:le:50`, etc.). + // Values to match against; at least one, none empty. Each entry is one of: an exact, case-sensitive whole-value match; a wildcard pattern with `*`/`?` (whole value); a regular expression wrapped in `/.../` (matches anywhere in the value unless anchored with `^`/`$`); `cidr:` for IP-shaped values, e.g. `cidr:10.0.0.0/8`; or a numeric comparison `num::` with `op` one of `lt`, `le`, `gt`, `ge`, e.g. `num:gt:100`. For `error.is_crash`, use `true` or `false`. Vals []string `json:"vals" toon:"vals"` } @@ -9488,7 +9895,7 @@ type RUMPresetSeverityRuleHistorySnapshotRule struct { DeletedAt TimestampMilli `json:"deleted_at" toon:"deleted_at"` // Rule description. May be empty. Description string `json:"description" toon:"description"` - // OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches. + // OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches. An empty outer array never matches; an empty inner group matches every error. Filters [][]RUMPresetSeverityRuleFilterCondition `json:"filters" toon:"filters"` // Internal auto-increment row ID. Not stable across a history revert — reverting reinserts rows with new IDs. ID int64 `json:"id" toon:"id"` @@ -9522,7 +9929,7 @@ type RUMPresetSeverityRuleItem struct { CreatedAt TimestampMilli `json:"created_at" toon:"created_at"` // Rule description. May be empty. Description string `json:"description" toon:"description"` - // OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches. + // OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches. An empty outer array never matches; an empty inner group matches every error. Filters [][]RUMPresetSeverityRuleFilterCondition `json:"filters" toon:"filters"` // Evaluation order among the application's rules. `1` is evaluated first (highest precedence); the first enabled rule whose filters match wins. Priority int64 `json:"priority" toon:"priority"` @@ -9566,7 +9973,7 @@ type RUMPresetSeverityRuleUpdateRequest struct { ApplicationID string `json:"application_id" toon:"application_id"` // New description, up to 512 characters. Omit to leave unchanged. Description *string `json:"description,omitempty" toon:"description,omitempty"` - // OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches. + // New OR-of-ANDs filter structure; replaces the whole current structure. Omit or pass `null` to leave unchanged. The outer array is OR'd, each inner array is AND'd; an empty outer array never matches, an empty inner group matches every error. Filters [][]RUMPresetSeverityRuleFilterCondition `json:"filters,omitempty" toon:"filters,omitempty"` // Rule ID to update. Get rule IDs via `POST /rum/issue/preset-severity/rules/list`. RuleID string `json:"rule_id" toon:"rule_id"` @@ -9590,21 +9997,21 @@ type RUMReplayDevice struct { // RUMReplayForegroundPeriod is generated from the Flashduty OpenAPI schema. type RUMReplayForegroundPeriod struct { - // Unix timestamp in milliseconds when the foreground period ended. - End TimestampMilli `json:"end" toon:"end"` - // Unix timestamp in milliseconds when the foreground period started. - Start TimestampMilli `json:"start" toon:"start"` + // End of the foreground period, in **nanoseconds** since the start of the view identified by `view_id` (not a Unix timestamp). + End Timestamp `json:"end" toon:"end"` + // Start of the foreground period, in **nanoseconds** since the start of the view identified by `view_id` (not a Unix timestamp). + Start Timestamp `json:"start" toon:"start"` // View ID active during this foreground period. ViewID string `json:"view_id" toon:"view_id"` } // RUMReplaySession is generated from the Flashduty OpenAPI schema. type RUMReplaySession struct { - // Unix timestamp in milliseconds when the session ended (or was last updated, if still active). + // Unix timestamp in milliseconds of the session end: the later of the session's recorded end and the end of its last returned view. End TimestampMilli `json:"end" toon:"end"` // Whether the session was still active as of the last recorded event. IsActive bool `json:"is_active" toon:"is_active"` - // Clock skew in milliseconds between the client and Flashduty's servers, added to client timestamps for correction. + // Always `0`: timestamps are returned as recorded by the client, without clock-skew correction. ServerTimeDelta int64 `json:"server_time_delta" toon:"server_time_delta"` // SDK platform that recorded the session. Platform identifier: // @@ -9628,7 +10035,21 @@ type RUMReplaySession struct { // RUMReplayView is generated from the Flashduty OpenAPI schema. type RUMReplayView struct { - // SDK platform of the container app, when this view is embedded (e.g. a WebView inside a native app). Omitted when the view is not embedded. + // SDK platform of the app that embeds this view (for example a WebView inside a native app). Omitted when the view is not embedded. + // + // | Value | Meaning | + // |---|---| + // | `browser` | Web browser application | + // | `ios` | Apple iOS application | + // | `android` | Android application | + // | `react-native` | React Native application | + // | `flutter` | Flutter application | + // | `kotlin-multiplatform` | Kotlin Multiplatform application | + // | `roku` | Roku channel application | + // | `unity` | Unity application | + // | `miniprogram` | WeChat mini program | + // | `harmony` | HarmonyOS application | + // | `electron` | Electron desktop application | ContainerSource string `json:"container_source" toon:"container_source"` // View ID of the containing view, when this view is embedded. Omitted when the view is not embedded. ContainerViewID string `json:"container_view_id" toon:"container_view_id"` @@ -9636,11 +10057,11 @@ type RUMReplayView struct { End TimestampMilli `json:"end" toon:"end"` // Whether the view was still active as of the last recorded event. IsActive bool `json:"is_active" toon:"is_active"` - // How the view was entered, e.g. `initial_load`, `route_change`. + // How the view was entered, as reported by the SDK. Web: `initial_load`, `route_change`. Mobile: `activity_display`, `activity_redisplay`, `fragment_display`, `fragment_redisplay`, `view_controller_display`, `view_controller_redisplay`. Empty when not reported. LoadingType string `json:"loading_type" toon:"loading_type"` // View name, typically the route or screen name. Name string `json:"name" toon:"name"` - // Clock skew in milliseconds between the client and Flashduty's servers, added to client timestamps for correction. + // Always `0`: timestamps are returned as recorded by the client, without clock-skew correction. ServerTimeDelta int64 `json:"server_time_delta" toon:"server_time_delta"` // SDK platform that recorded the view. Platform identifier: // @@ -9700,17 +10121,17 @@ type RUMResourceItem struct { ResourceName string `json:"resource_name" toon:"resource_name"` // Retention period in days for session data. SessionDays int64 `json:"session.days" toon:"session.days"` - // Free quota for investigate sessions per application, per billing window. + // Free quota of investigate (error tracking) sessions per application, per billing window. A negative value means unlimited. SessionInvestigateFreeCnt int64 `json:"session_investigate.free_cnt" toon:"session_investigate.free_cnt"` // Number of investigate (error tracking) sessions used in the current billing window. SessionInvestigateUsedCnt int64 `json:"session_investigate.used_cnt" toon:"session_investigate.used_cnt"` - // `true` when a `version=free` account has exceeded its combined free session quota across all applications. Always `false` for non-free plans. + // `true` when a `version=free` account's investigate or replay sessions in the current window have reached the per-application free quota multiplied by the number of applications. Always `false` for non-free plans and for accounts without applications. SessionLimitReached bool `json:"session_limit_reached" toon:"session_limit_reached"` - // Free quota for measure sessions per application, per billing window. + // Free quota of measure (performance) sessions per application, per billing window. A negative value means unlimited. SessionMeasureFreeCnt int64 `json:"session_measure.free_cnt" toon:"session_measure.free_cnt"` // Number of measure (performance) sessions used in the current billing window. SessionMeasureUsedCnt int64 `json:"session_measure.used_cnt" toon:"session_measure.used_cnt"` - // Free quota for session-replay sessions per application, per billing window. + // Free quota of session-replay sessions per application, per billing window. A negative value means unlimited. SessionReplayFreeCnt int64 `json:"session_replay.free_cnt" toon:"session_replay.free_cnt"` // Number of session-replay sessions used in the current billing window. SessionReplayUsedCnt int64 `json:"session_replay.used_cnt" toon:"session_replay.used_cnt"` @@ -9734,11 +10155,11 @@ type RUMSessionReplayMetaItem struct { Application RUMReplayApplication `json:"application" toon:"application"` // Device that recorded the session. Device RUMReplayDevice `json:"device" toon:"device"` - // Foreground periods across the session (mobile sessions only; empty for web). + // Periods during which a view was in the foreground (focused), collected from every returned view. Empty when the SDK reported none. ForegroundPeriods []RUMReplayForegroundPeriod `json:"foreground_periods" toon:"foreground_periods"` // Session bounds and state. Session RUMReplaySession `json:"session" toon:"session"` - // Every view recorded during the session, in chronological order. + // Views of the session that carry replay data, ordered by start time. Views []RUMReplayView `json:"views" toon:"views"` } @@ -9746,7 +10167,7 @@ type RUMSessionReplayMetaItem struct { type RUMSessionReplayMetaRequest struct { // RUM session ID (the `session.id` attribute on RUM events). SessionID string `json:"session_id" toon:"session_id"` - // Unix timestamp in milliseconds of the session start time. Optional; disambiguates when a session ID has been reused across different time windows. + // Session start time, Unix milliseconds. Optional. When set, it must match the session's start exactly; use it to pick one session when a `session_id` was reused. TS int64 `json:"ts,omitempty" toon:"ts,omitempty"` } @@ -9758,7 +10179,7 @@ type RUMSessionReplaySegmentsRequest struct { SearchAfterCtx string `json:"search_after_ctx,omitempty" toon:"search_after_ctx,omitempty"` // RUM session ID (the `session.id` attribute on RUM events). SessionID string `json:"session_id" toon:"session_id"` - // Unix timestamp in milliseconds. When set (and `search_after_ctx` is empty), seeks to the most recent full-snapshot segment at or before this time instead of starting from the beginning. + // Unix timestamp in milliseconds. When set and `search_after_ctx` is empty, paging starts at the last full-snapshot segment at or before this time (searching up to 4 hours back); if none is found, paging starts from the beginning. TS int64 `json:"ts,omitempty" toon:"ts,omitempty"` // When `true`, return presigned download URLs as a JSON envelope instead of streaming segment bytes. Defaults to `false`. URLMode bool `json:"url_mode,omitempty" toon:"url_mode,omitempty"` @@ -9768,27 +10189,27 @@ type RUMSessionReplaySegmentsRequest struct { // RUMSessionReplaySegmentsResult is generated from the Flashduty OpenAPI schema. type RUMSessionReplaySegmentsResult struct { - // Presigned, time-limited URLs (valid 1 hour) for downloading each segment's raw compressed bytes. + // Presigned URLs (valid 1 hour) for downloading each segment object. The object body is zlib-compressed; decompress it to get the segment JSON. Items []string `json:"items" toon:"items"` - // Pagination cursor to pass as `search_after_ctx` on the next call. Empty when this page was the last one. + // Cursor to pass as `search_after_ctx` on the next call. Set whenever this page returned `limit` segments (the next page may then be empty); empty string when fewer were returned. SearchAfterCtx string `json:"search_after_ctx" toon:"search_after_ctx"` } // RUMWebhookTestRequest is generated from the Flashduty OpenAPI schema. type RUMWebhookTestRequest struct { - // RUM application ID. Get application IDs via `POST /rum/application/list`. + // RUM application whose name is put in the sample event's `labels.application_name`. The caller must be able to edit it. Get application IDs via `POST /rum/application/list`. ApplicationID string `json:"application_id" toon:"application_id"` - // Webhook URL to receive the sample alert event. + // Webhook URL to receive the sample alert event; must use `http` or `https`. Not saved: use `POST /rum/application/update` with `alerting.webhook_url` to store it. WebhookURL string `json:"webhook_url" toon:"webhook_url"` } // RUMWebhookTestResponse is generated from the Flashduty OpenAPI schema. type RUMWebhookTestResponse struct { - // `ok` on success, otherwise the delivery error message. + // `ok` on success. Otherwise `unexpected status ` when the endpoint answered with an error status, or `request failed: ` when no response was received. Message string `json:"message" toon:"message"` - // Whether the webhook endpoint accepted the sample event. + // `true` when the endpoint answered with a status below 400 (after following redirects); `false` otherwise. OK bool `json:"ok" toon:"ok"` - // HTTP status code returned by the webhook endpoint. 0 when the request did not receive a response. + // HTTP status code of the last delivery attempt. `0` when no response was received (connection error or timeout). StatusCode int64 `json:"status_code" toon:"status_code"` } @@ -9856,19 +10277,21 @@ type ScheduleByPersonRequest struct { // ScheduleByPersonResponse is generated from the Flashduty OpenAPI schema. type ScheduleByPersonResponse struct { - Current MemberOncallInterval `json:"current" toon:"current"` - Next MemberOncallInterval `json:"next" toon:"next"` + // Shift in progress now; `null` when the member is not on call. + Current any `json:"current" toon:"current"` + // Next upcoming shift (without `end_at`); `null` when none within 45 days. + Next any `json:"next" toon:"next"` // All enabled schedules the member participates in. Schedules []MemberScheduleItem `json:"schedules" toon:"schedules"` } // ScheduleCalculatedLayer is generated from the Flashduty OpenAPI schema. type ScheduleCalculatedLayer struct { - // Layer display name. + // Layer name; empty string in `final_schedule`. LayerName string `json:"layer_name" toon:"layer_name"` - // Layer mode: 0 = common rotation, 1 = override. + // Type of the source layer: `0` = rotation layer, `1` = override layer. Always `0` in `final_schedule`. Mode int64 `json:"mode" toon:"mode"` - // Layer internal name. + // Same as `layer_name`. Name string `json:"name" toon:"name"` // Computed shifts; null when the layer produces none. Schedules []ScheduleCalculatedSchedule `json:"schedules" toon:"schedules"` @@ -9878,9 +10301,9 @@ type ScheduleCalculatedLayer struct { type ScheduleCalculatedSchedule struct { // Shift end timestamp (Unix seconds). End Timestamp `json:"end" toon:"end"` - // Oncall group covering the shift; null marks a coverage gap. - Group ScheduleGroup `json:"group" toon:"group"` - // Index inside the rotation. + // Group on call during the shift; `null` marks a gap with nobody on call. + Group any `json:"group" toon:"group"` + // Zero-based position, in the schedule's layer list, of the layer the shift comes from. Index int64 `json:"index" toon:"index"` // Shift start timestamp (Unix seconds). Start Timestamp `json:"start" toon:"start"` @@ -9888,7 +10311,7 @@ type ScheduleCalculatedSchedule struct { // ScheduleDayMask is generated from the Flashduty OpenAPI schema. type ScheduleDayMask struct { - // Weekday numbers (0 = Sunday) included in the rotation. Conflicts with restrict_mode = 2 (week). + // Weekdays on which the layer is on call: `0` = Sunday … `6` = Saturday, in the schedule's time zone. Empty or all seven days means every day. Cannot be combined with `restrict_mode` 2. Repeat []int64 `json:"repeat,omitempty" toon:"repeat,omitempty"` } @@ -9907,7 +10330,7 @@ type ScheduleFixedTimeNotifyInfo struct { // ScheduleGroup is generated from the Flashduty OpenAPI schema. type ScheduleGroup struct { - // Group end timestamp (Unix seconds). + // End of the group's shift (Unix seconds) in computed results; `0` in layer definitions and ignored on input. End int64 `json:"end" toon:"end"` // Group display name. Null when only the legacy name is set. GroupName *string `json:"group_name,omitempty" toon:"group_name,omitempty"` @@ -9915,7 +10338,7 @@ type ScheduleGroup struct { Members []ScheduleMember `json:"members" toon:"members"` // Legacy group name. Name string `json:"name" toon:"name"` - // Group start timestamp (Unix seconds). + // Start of the group's shift (Unix seconds) in computed results; `0` in layer definitions and ignored on input. Start int64 `json:"start" toon:"start"` } @@ -9941,23 +10364,28 @@ type ScheduleIDsRequest struct { type ScheduleImNotify struct { // Webhook channel settings. Settings ScheduleImNotifySettings `json:"settings" toon:"settings"` - // IM provider type (for example feishu_app, dingtalk_app, wecom_app, teams_app, slack_app). + // Where the notification goes: + // - `feishu`, `dingtalk`, `wecom`, `slack`: group robot webhook given by `settings.token`. + // - `telegram`: bot `settings.token` posting to `settings.chat_ids`. + // - `zoom`: Zoom robot with `settings.token` and `settings.verify_token`. + // - `feishu_app`, `dingtalk_app`, `slack_app`, `teams_app`: an IM integration (`settings.data_source_id`) posting to the group chats in `settings.chat_ids`. + // Other values are stored but never sent. Type string `json:"type" toon:"type"` } // ScheduleImNotifySettings is generated from the Flashduty OpenAPI schema. type ScheduleImNotifySettings struct { - // Channel alias. + // Display alias for the entry; not used when sending. Alias string `json:"alias" toon:"alias"` - // Chat IDs. + // Target chat IDs: group chats of the IM integration for `*_app` types, or Telegram chat IDs for `telegram`. ChatIDs []string `json:"chat_ids" toon:"chat_ids"` - // Data source ID. + // ID of the IM integration used by the `*_app` types; `0` for robot types. DataSourceID int64 `json:"data_source_id" toon:"data_source_id"` - // Signature secret. + // Robot signing secret. Stored with the entry. SignSecret string `json:"sign_secret" toon:"sign_secret"` - // Webhook token. + // Robot webhook token for `feishu`, `dingtalk`, `wecom`, `slack`, `telegram` and `zoom`; empty for the `*_app` types. Token string `json:"token" toon:"token"` - // Verification token. + // Verification token, used by the `zoom` type. VerifyToken string `json:"verify_token" toon:"verify_token"` } @@ -9973,50 +10401,50 @@ type ScheduleInfoRequest struct { // ScheduleItem is generated from the Flashduty OpenAPI schema. type ScheduleItem struct { - // Account ID. + // ID of the account that owns the schedule. AccountID int64 `json:"account_id" toon:"account_id"` // Creation timestamp (Unix seconds). CreateAt Timestamp `json:"create_at" toon:"create_at"` // Creator person ID. CreateBy int64 `json:"create_by" toon:"create_by"` - // Current on-call group, or null when nobody is on-call. - CurOncall ScheduleOncallGroup `json:"cur_oncall" toon:"cur_oncall"` + // The shift in progress now; `null` when nobody is on call, or when the endpoint does not compute it (`/schedule/infos`, `/schedule/self`, `/schedule/list` without a window). + CurOncall any `json:"cur_oncall" toon:"cur_oncall"` // Schedule description. null when returned from /schedule/preview. Description string `json:"description" toon:"description"` - // Disabled flag (0 = enabled, 1 = disabled). Deprecated. null when returned from /schedule/preview. + // Whether the schedule is disabled: `0` = enabled, `1` = disabled (disabled schedules send no shift notifications and are skipped by `/schedule/self` and `/schedule/by-person`). Same value as `status`. `null` in `/schedule/preview` unless sent. Disabled int64 `json:"disabled" toon:"disabled"` - // Window end (Unix seconds). Omitted when 0 (no window requested). + // Window end (Unix seconds). Only echoed by `/schedule/preview`; omitted elsewhere. End Timestamp `json:"end" toon:"end"` - // Field name used by the legacy update-field endpoint. - Field string `json:"field" toon:"field"` - // Collapsed final schedule across all layers. + // All layers merged into one timeline for the window: where layers overlap, override layers win over rotation layers and later layers win over earlier ones. In `/schedule/self` it keeps only the caller's shifts. Empty (`schedules` is `null`) when nothing was computed. FinalSchedule ScheduleCalculatedLayer `json:"final_schedule" toon:"final_schedule"` // Legacy team/group ID. null when returned from /schedule/preview. GroupID int64 `json:"group_id" toon:"group_id"` // Schedule ID. null when returned from /schedule/preview. ID int64 `json:"id" toon:"id"` - // Alias of schedule_layers returned for compatibility. Null when not computed. + // Same content as `schedule_layers`, filled by `/schedule/info` and `/schedule/preview` only; `null` elsewhere. LayerSchedules []ScheduleCalculatedLayer `json:"layer_schedules" toon:"layer_schedules"` // Rotation layers defined on the schedule. Null when layers were not loaded (for example by `/schedule/infos`, or by `/schedule/list` without start/end). Layers []ScheduleLayer `json:"layers" toon:"layers"` // Schedule name (legacy field; mirrors schedule_name). null when returned from /schedule/preview. Name string `json:"name" toon:"name"` - // Next on-call group, or null when unknown. - NextOncall ScheduleOncallGroup `json:"next_oncall" toon:"next_oncall"` - // Notification configuration. Null when the schedule has none. - Notify ScheduleNotify `json:"notify" toon:"notify"` + // The next shift with someone on duty after the current one; `null` when none is found within 45 days or the endpoint does not compute it. + NextOncall any `json:"next_oncall" toon:"next_oncall"` + // Shift notification configuration; `null` when the schedule has none. + Notify any `json:"notify" toon:"notify"` // Schedule ID. Null when returned from `/schedule/preview`. ScheduleID int64 `json:"schedule_id" toon:"schedule_id"` - // Computed per-layer schedules for the requested window. Null when not computed. + // Shifts of each visible (non-hidden) layer in the requested window. `null` when no window was computed (`/schedule/infos`, `/schedule/self`, `/schedule/list` without `start`/`end`). ScheduleLayers []ScheduleCalculatedLayer `json:"schedule_layers" toon:"schedule_layers"` // Schedule display name. null when returned from /schedule/preview. ScheduleName string `json:"schedule_name" toon:"schedule_name"` - // Window start (Unix seconds). Omitted when 0 (no window requested). + // Window start (Unix seconds). Only echoed by `/schedule/preview`; omitted elsewhere. Start Timestamp `json:"start" toon:"start"` - // Legacy status flag. Deprecated. null when returned from /schedule/preview. + // Mirror of `disabled`: `0` = enabled, `1` = disabled. Send it on `/schedule/update` to enable or disable a schedule. `null` in `/schedule/preview` unless sent. Status int64 `json:"status" toon:"status"` // Owning team ID. null when returned from /schedule/preview. TeamID int64 `json:"team_id" toon:"team_id"` + // IANA time zone (for example `Asia/Shanghai`) in which the schedule's handoffs, restriction windows, weekdays and fixed-time notifications are evaluated. Set at creation and immutable. An empty string means none was set and the schedule is evaluated in `Asia/Shanghai`. + TimeZone string `json:"time_zone" toon:"time_zone"` // Last update timestamp (Unix seconds). UpdateAt Timestamp `json:"update_at" toon:"update_at"` // Last updater person ID. @@ -10025,47 +10453,59 @@ type ScheduleItem struct { // ScheduleLayer is generated from the Flashduty OpenAPI schema. type ScheduleLayer struct { - // Account ID. + // ID of the account that owns the layer. Set by the server. AccountID int64 `json:"account_id" toon:"account_id"` // Creation timestamp (Unix seconds). CreateAt int64 `json:"create_at" toon:"create_at"` // Creator person ID. CreateBy int64 `json:"create_by" toon:"create_by"` - // Day-of-week mask. + // Weekdays on which the rotation layer is on call. DayMask ScheduleDayMask `json:"day_mask" toon:"day_mask"` - // When the layer becomes effective (Unix seconds). + // When the layer takes effect (Unix seconds). For rotations its time of day is also the daily handoff time. `layer_start` overrides it when sent. EnableTime int64 `json:"enable_time" toon:"enable_time"` - // When the layer expires (Unix seconds, 0 means never). + // Request only. Layer end as a wall-clock date and time in the schedule's time zone; overrides `layer_end`/`expire_time`. Send `{"date": ""}` to make the layer never end. + EndsAt ScheduleLayerEndsAt `json:"ends_at,omitzero" toon:"ends_at,omitempty"` + // When the layer stops (Unix seconds); `0` = never. Must not be earlier than `enable_time`. `layer_end` overrides it when sent. ExpireTime int64 `json:"expire_time" toon:"expire_time"` - // Whether fair rotation is enabled. + // When `true`, the group that starts each full round shifts by one, so that no group is always first. `false` (default) always restarts from the first group. FairRotation bool `json:"fair_rotation" toon:"fair_rotation"` - // Oncall groups participating in the rotation. Null when not set. + // On-call groups of the layer, in rotation order. Each group needs `group_name` (or `name`) and members with at least one person. `start`/`end` are ignored on input. Groups []ScheduleGroup `json:"groups" toon:"groups"` - // Rotation handoff time as a weekly offset in seconds (weekday x 86400 + seconds since midnight), not an absolute Unix timestamp. + // Request only. Handoff weekday and time in the schedule's time zone; sets `handoff_time` and the time of day of `enable_time`. + Handoff ScheduleLayerHandoff `json:"handoff,omitzero" toon:"handoff,omitempty"` + // Weekly handoff point for weekly rotations, as seconds from Monday 00:00 in the schedule's time zone (`weekday × 86400 + seconds of day`, Monday = 0 … Sunday = 6). Not a Unix timestamp. Easier to set with `handoff`. HandoffTime int64 `json:"handoff_time" toon:"handoff_time"` - // Whether the layer is hidden in the UI (0 = no, 1 = yes). + // `1` leaves the layer out of `schedule_layers`; its shifts still feed `final_schedule`. `0` (default) shows it. Hidden int64 `json:"hidden" toon:"hidden"` - // Layer end timestamp (Unix seconds). null means open-ended. + // Same as `expire_time`; takes precedence over it in requests. `null` means the layer never ends. LayerEnd *int64 `json:"layer_end,omitempty" toon:"layer_end,omitempty"` - // User-facing layer name. Null when not set. + // Layer name shown in the console; same value as `name` in responses. LayerName *string `json:"layer_name,omitempty" toon:"layer_name,omitempty"` - // Layer effective start (Unix seconds). Null when not set. + // Same as `enable_time`; takes precedence over it in requests. `null` when `enable_time` is 0. LayerStart *int64 `json:"layer_start,omitempty" toon:"layer_start,omitempty"` - // Whether continuous masking is enabled. + // Only applies when `day_mask` selects 1–6 weekdays. When `true`, each on-call day runs from the layer's start time of day to the same time the next day instead of midnight to midnight. MaskContinuousEnabled bool `json:"mask_continuous_enabled" toon:"mask_continuous_enabled"` - // Layer mode: 0 = common rotation, 1 = override. + // Layer type: + // - `0`: rotation layer — groups take turns according to `rotation_unit`/`rotation_value`. + // - `1`: override layer — the first group in `groups` is on call for the whole `layer_start`–`layer_end` period and takes precedence over rotation layers. Mode int64 `json:"mode" toon:"mode"` - // Layer internal name. + // Layer name. Either `name` or `layer_name` is required; `layer_name` wins when both are set. Name string `json:"name" toon:"name"` - // Legacy end offset inside the restriction window (seconds). + // Legacy single-window end offset in seconds; prefer `restrict_periods`. RestrictEnd int64 `json:"restrict_end" toon:"restrict_end"` - // Restriction mode: 0 = none, 1 = day, 2 = week. + // Restricts the layer to time windows given in `restrict_periods`: + // - `0`: no restriction. + // - `1`: daily windows; offsets are seconds from 00:00 (0–86400). + // - `2`: weekly windows; offsets are seconds from Monday 00:00 (0–604800). Cannot be combined with `day_mask`. + // Windows use the schedule's time zone. RestrictMode int64 `json:"restrict_mode" toon:"restrict_mode"` - // Restriction windows inside each rotation cycle. Null when not set. + // Time windows in which the layer is on call, interpreted by `restrict_mode`. Outside them the layer has nobody on call. `null` when not set. RestrictPeriods []ScheduleRestrictPeriod `json:"restrict_periods" toon:"restrict_periods"` - // Legacy start offset inside the restriction window (seconds). + // Legacy single-window start offset in seconds; prefer `restrict_periods`. RestrictStart int64 `json:"restrict_start" toon:"restrict_start"` - // Rotation duration in seconds. + // Request only. Restriction windows as wall-clock times in the schedule's time zone; replaces `restrict_periods`. With `restrict_mode` 1 use `from`/`to` (`to` = `00:00` means end of day); with `restrict_mode` 2 also set `from_day`/`to_day`. Rejected when `restrict_mode` is 0. + RestrictsWall []ScheduleLayerRestrictsWallItem `json:"restricts_wall,omitempty" toon:"restricts_wall,omitempty"` + // Rotation length in seconds. Legacy alternative to `rotation_unit` + `rotation_value`: when only this is set, the server derives them (whole weeks, days or hours), and when only those are set, it fills this in (a month counts as 30 days). RotationDuration int64 `json:"rotation_duration" toon:"rotation_duration"` // Rotation unit. On-call assignees rotate in turn by this unit. // | Value | Meaning | @@ -10075,38 +10515,40 @@ type ScheduleLayer struct { // | `week` | Rotates weekly. | // | `month` | Rotates monthly. | RotationUnit string `json:"rotation_unit" toon:"rotation_unit"` - // Rotation quantity (number of rotation_unit per cycle). + // Number of `rotation_unit`s each group stays on call before handing off. A rotation layer needs either this (with `rotation_unit`) or `rotation_duration`. RotationValue int64 `json:"rotation_value" toon:"rotation_value"` - // Parent schedule ID. + // ID of the schedule the layer belongs to. Set by the server. ScheduleID int64 `json:"schedule_id" toon:"schedule_id"` + // Request only. Layer start as a wall-clock date and time in the schedule's time zone; overrides `layer_start`/`enable_time`. + StartsAt ScheduleLayerStartsAt `json:"starts_at,omitzero" toon:"starts_at,omitempty"` // Last update timestamp (Unix seconds). UpdateAt int64 `json:"update_at" toon:"update_at"` // Last updater person ID. UpdateBy int64 `json:"update_by" toon:"update_by"` - // Layer weight for ordering. + // Stored as sent; not used when computing shifts. Weight int64 `json:"weight" toon:"weight"` } // ScheduleListRequest is generated from the Flashduty OpenAPI schema. type ScheduleListRequest struct { ListOptions - // Window end timestamp (Unix seconds). + // Window end, 10-digit Unix seconds, after `start` and at most 45 days later. Sending `end` without `start` is rejected. End int64 `json:"end,omitempty" toon:"end,omitempty"` - // Only return schedules created by the current user within their teams. + // Only schedules owned by the caller's teams or created by the caller. `team_ids` narrows the team part; team IDs outside the caller's teams are ignored. IsMyManage bool `json:"is_my_manage,omitempty" toon:"is_my_manage,omitempty"` - // Only return schedules whose owning team the current user belongs to. + // Only schedules owned by the caller's teams. When `team_ids` shares no team with the caller, or the caller belongs to no team, the list is empty. IsMyTeam bool `json:"is_my_team,omitempty" toon:"is_my_team,omitempty"` - // Search keyword matched against schedule name or description. + // Substring matched against the schedule name or description. Query string `json:"query,omitempty" toon:"query,omitempty"` - // When set together with end, computed layer schedules are returned. Span must be less than 45 days. + // Window start, 10-digit Unix seconds. Send together with `end` to compute layers and shifts. Start int64 `json:"start,omitempty" toon:"start,omitempty"` - // Filter by team IDs. + // Only schedules owned by these teams. With `is_my_team` or `is_my_manage`, only the teams the caller belongs to are kept. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` } // ScheduleListResponse is generated from the Flashduty OpenAPI schema. type ScheduleListResponse struct { - // Schedules on this page; null when no schedule matches. + // Schedules on this page; an empty array when none match. Items []ScheduleItem `json:"items" toon:"items"` // Total number of schedules matching the filters. Total int64 `json:"total" toon:"total"` @@ -10114,31 +10556,31 @@ type ScheduleListResponse struct { // ScheduleMember is generated from the Flashduty OpenAPI schema. type ScheduleMember struct { - // Person IDs in this slot. + // Member IDs in this slot; at least one. PersonIDs []int64 `json:"person_ids" toon:"person_ids"` - // Oncall role ID. + // On-call role assigned to the people in this slot; `0` = no role. RoleID int64 `json:"role_id" toon:"role_id"` } // ScheduleNotify is generated from the Flashduty OpenAPI schema. type ScheduleNotify struct { - // Advance notification lead time in seconds. `0` notifies exactly at shift start; omitting disables advance notification. + // Lead time in seconds for the shift-change notification: `0` notifies at the start of the shift, `300` five minutes before. Omitted or `null` disables shift-change notifications. AdvanceInTime *int64 `json:"advance_in_time,omitempty" toon:"advance_in_time,omitempty"` - // Recipient notification preference; null when not configured. - By ScheduleNotifyBy `json:"by" toon:"by"` - // Fixed-time notification config; null when not configured. - FixedTime ScheduleFixedTimeNotifyInfo `json:"fixed_time" toon:"fixed_time"` - // Legacy IM-type to token map. + // Personal notifications sent to the people on call; `null` when not configured. + By any `json:"by" toon:"by"` + // Send a shift summary at a fixed time; `null` when not configured. + FixedTime any `json:"fixed_time" toon:"fixed_time"` + // Legacy map of robot type to webhook token. Entries not already in `webhooks` are added to `webhooks` when read; use `webhooks` instead. Im map[string]string `json:"im,omitempty" toon:"im,omitempty"` - // IM webhook notification channels; null when not configured. + // Group chats or robots that receive shift-change notifications; `null` when not configured. Webhooks []ScheduleImNotify `json:"webhooks" toon:"webhooks"` } // ScheduleNotifyBy is generated from the Flashduty OpenAPI schema. type ScheduleNotifyBy struct { - // Whether to follow each responder's personal notification preference. + // `true`: notify each person through the channels in their own shift-notification preference, ignoring `personal_channels`. `false`: use `personal_channels`. FollowPreference bool `json:"follow_preference" toon:"follow_preference"` - // Personal notification channel keys. + // Channels used when `follow_preference` is `false`: `email`, `sms`, `push` (mobile app), and the IM apps `feishu_app`, `dingtalk_app`, `wecom_app`, `teams_app`, `slack_app`. An IM app value may carry the integration ID as `:` (for example `feishu_app:5427276014131`). Unknown values are stored but never used. `null` when not set. PersonalChannels []string `json:"personal_channels" toon:"personal_channels"` } @@ -10148,21 +10590,21 @@ type ScheduleOncallGroup struct { End Timestamp `json:"end" toon:"end"` // Oncall group on duty for the shift. Group ScheduleGroup `json:"group" toon:"group"` - // Index inside the rotation. + // Always `0` in these responses. Index int64 `json:"index" toon:"index"` // Shift start timestamp (Unix seconds). Start Timestamp `json:"start" toon:"start"` - // Update timestamp (Unix seconds). + // Update time as a Unix timestamp in seconds; always `0` in these responses. UpdateAt Timestamp `json:"update_at" toon:"update_at"` - // Layer weight the shift comes from. + // Always `0` in these responses. Weight int64 `json:"weight" toon:"weight"` } // ScheduleRestrictPeriod is generated from the Flashduty OpenAPI schema. type ScheduleRestrictPeriod struct { - // End offset inside the rotation cycle. + // Window end in seconds, same reference point as `restrict_start`. RestrictEnd int64 `json:"restrict_end" toon:"restrict_end"` - // Start offset inside the rotation cycle. + // Window start in seconds: from 00:00 when `restrict_mode` is 1, from Monday 00:00 when it is 2. RestrictStart int64 `json:"restrict_start" toon:"restrict_start"` } @@ -10176,32 +10618,36 @@ type ScheduleSelfRequest struct { // ScheduleSelfResponse is generated from the Flashduty OpenAPI schema. type ScheduleSelfResponse struct { - // Schedules assigned to the current user (or matching the requested IDs); null when none. + // Matching schedules; an empty array when none match. Items []ScheduleItem `json:"items" toon:"items"` } // ScheduleUpsertRequest is generated from the Flashduty OpenAPI schema. type ScheduleUpsertRequest struct { - // Schedule description. Max 500 characters. + // Schedule description, at most 500 characters. On update, omitting it keeps the current text and an empty string clears it. Description *string `json:"description,omitempty" toon:"description,omitempty"` - // 0 = enabled, 1 = disabled. Defaults to enabled when omitted. + // Create only: `0` = enabled (default), `1` = disabled. Ignored on update — use `status` instead. Disabled *int64 `json:"disabled,omitempty" toon:"disabled,omitempty"` - // Preview window end (Unix seconds, 10 digits). Required for /schedule/preview. Max 45 days after start. + // Preview window end, 10-digit Unix seconds, after `start` and at most 45 days later. Required for `/schedule/preview`; ignored by create and update. End int64 `json:"end,omitempty" toon:"end,omitempty"` - // Rotation layers. + // Rotation layers. Required in practice: on update the list replaces all existing layers, so omitting it deletes every layer. Layers []ScheduleLayer `json:"layers,omitempty" toon:"layers,omitempty"` - // Legacy schedule name field. Used when schedule_name is empty. + // Legacy name field, used on create only when `schedule_name` is empty. Ignored on update. Name *string `json:"name,omitempty" toon:"name,omitempty"` - // Rotation notification configuration. - Notify ScheduleNotify `json:"notify,omitzero" toon:"notify,omitempty"` + // Shift notification configuration. On update, omitting it keeps the current configuration; a sent object replaces it entirely. + Notify any `json:"notify,omitempty" toon:"notify,omitempty"` // Schedule ID, required on update; obtain it from `POST /schedule/list`. ScheduleID *int64 `json:"schedule_id,omitempty" toon:"schedule_id,omitempty"` - // Schedule display name. Max 40 characters. + // Schedule name, at most 40 characters, unique within the account. On update, omitting it keeps the current name. ScheduleName *string `json:"schedule_name,omitempty" toon:"schedule_name,omitempty"` - // Preview window start (Unix seconds, 10 digits). Required for /schedule/preview. + // Preview window start, 10-digit Unix seconds. Required for `/schedule/preview`; ignored by create and update. Start int64 `json:"start,omitempty" toon:"start,omitempty"` - // Owning team ID; obtain it from `POST /team/list`. + // `0` = enabled, `1` = disabled. On update, omitting it keeps the current state. On create it takes precedence over `disabled`. + Status *int64 `json:"status,omitempty" toon:"status,omitempty"` + // ID of the owning team; obtain it from `POST /team/list`. On create, omitting it leaves the schedule without a team (`0`); on update, omitting it keeps the current team. TeamID *int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` + // IANA time zone in which the schedule's wall-clock rules are evaluated, for example `Asia/Shanghai` or `UTC`; abbreviations such as `EST` and `Etc/GMT±N` are rejected. Set on create (default: evaluated in `Asia/Shanghai`); immutable afterwards — on update send nothing or the current value. On preview it sets the evaluation time zone. + TimeZone string `json:"time_zone,omitempty" toon:"time_zone,omitempty"` } // ServiceDeskPlusRequestListRequest is generated from the Flashduty OpenAPI schema. @@ -10291,7 +10737,7 @@ type SessionGetRequest struct { // SessionGetResponse is generated from the Flashduty OpenAPI schema. type SessionGetResponse struct { - // Recent events, ascending by (created_at, event_id). + // The newest page of events (older pages via `search_after_ctx`), ascending by (`created_at`, `event_id`). Internal control events are excluded. Always an array. Events []EventItem `json:"events" toon:"events"` // True when older events remain beyond this page. HasMoreOlder bool `json:"has_more_older" toon:"has_more_older"` @@ -10300,40 +10746,40 @@ type SessionGetResponse struct { // Opaque keyset cursor; pass back as search_after_ctx to fetch the next older page. Omitted when has_more_older is false. SearchAfterCtx string `json:"search_after_ctx" toon:"search_after_ctx"` Session SessionItem `json:"session" toon:"session"` - // Account-wide onboarding flag: true when the account has no knowledge in any scope; not specific to this session. - SuggestInit bool `json:"suggest_init" toon:"suggest_init"` } // SessionItem is generated from the Flashduty OpenAPI schema. type SessionItem struct { - // How the caller received access to this session. Omitted when no access source is resolved. One of: + // How the caller obtained access. Omitted when the caller has no access. One of: // | Value | Meaning | // | --- | --- | - // | `owner` | Caller is the session creator (full access) | - // | `team_member` | Caller belongs to the session's bound team (full access) | - // | `manager` | Manager grant (reserved; never produced by the current version) | - // | `share_link` | Granted via a valid share link (view/fork only; cannot continue or manage) | - // | `participant` | Same-account non-member granted via a participable team session (view/continue/fork only) | + // | `owner` | Caller created the session (full access) | + // | `team_member` | Caller belongs to the session's team (full access) | + // | `manager` | Reserved; not produced by the current version | + // | `share_link` | Granted by a valid share link (view and fork only; view only for subagent child sessions) | + // | `participant` | Another member of the same account on a team session (view, continue, fork; no manage) | AccessSource string `json:"access_source" toon:"access_source"` // Agent app that owns the session. AppName string `json:"app_name" toon:"app_name"` // Unix timestamp in milliseconds when archived; 0 means not archived. - ArchivedAt TimestampMilli `json:"archived_at" toon:"archived_at"` - BoundEnvironment EnvironmentBinding `json:"bound_environment" toon:"bound_environment"` + ArchivedAt TimestampMilli `json:"archived_at" toon:"archived_at"` + // Automation rule that produced this session. Returned by `POST /safari/session/get` only, for sessions started by an automation rule. + Automation SessionItemAutomation `json:"automation" toon:"automation"` + BoundEnvironment EnvironmentBinding `json:"bound_environment" toon:"bound_environment"` // True when the caller can add a new turn to this session. CanContinue bool `json:"can_continue" toon:"can_continue"` // True when the caller can fork this session. CanFork bool `json:"can_fork" toon:"can_fork"` - // True when the caller may rename/archive/delete the session; personal sessions are creator-only, team sessions allow the creator, account admin, or team member. + // True when the caller may rename, archive, or delete the session: the creator of a personal session, or the creator or a member of the owning team for a team session. Account owners and admins get no exemption. CanManage bool `json:"can_manage" toon:"can_manage"` - // True when the caller can view this session. + // True when the caller can read this session: always true for the creator, team members, and other members of the same account on a team session; true through a valid share link otherwise. CanView bool `json:"can_view" toon:"can_view"` ContextResolved ContextResolvedItem `json:"context_resolved" toon:"context_resolved"` - // The bound model's max context size in tokens. 0 means unknown. + // Maximum context size of the session's model, in tokens. Computed by `POST /safari/session/get` only; always 0 in list responses and when the lookup fails. ContextWindow int64 `json:"context_window" toon:"context_window"` // Unix timestamp in milliseconds when the session was created. CreatedAt TimestampMilli `json:"created_at" toon:"created_at"` - // Display name of the session creator, resolved when the response is rendered. Omitted when the member lookup fails. + // Display name of the session creator. Returned by `POST /safari/session/list` only; omitted when the name lookup fails. CreatorName string `json:"creator_name" toon:"creator_name"` // Size in tokens of the LLM context window as of the most recent turn. 0 means no turn has completed. CurrentContextTokens int64 `json:"current_context_tokens" toon:"current_context_tokens"` @@ -10345,18 +10791,15 @@ type SessionItem struct { CurrentTurnTokens int64 `json:"current_turn_tokens" toon:"current_turn_tokens"` // Accumulated ask_user human-wait duration in milliseconds for the current round; resets to 0 at the start of each new round. CurrentTurnWaitMs int64 `json:"current_turn_wait_ms" toon:"current_turn_wait_ms"` - // Surface that created the session. One of: - // | Value | Meaning | - // | --- | --- | - // | `web` | Created from the web console | - // | `im` | Created from an IM client (IM bot / IM H5) | - // | `api` | Created via the public API | - // | `automation` | Created by an automation rule (unattended run) | - // | `subagent` | Child session spawned by a parent's agent_dispatch (audit label; at runtime it executes on the web tool surface) | + // Surface that created the session: + // - `web`: web console (also returned for subagent child sessions and for sessions that predate this field) + // - `im`: IM bot or IM H5 client + // - `api`: public API + // - `automation`: automation rule (unattended run) EntryKind string `json:"entry_kind" toon:"entry_kind"` - // Whether the session still has open tasks, used to tell a handed-off turn from a settled session. Best-effort: when the read fails the field is absent (`omitempty`), which callers must treat as "unknown", never as proof the session is idle. + // True when the session still has open tasks (for example running subagents or background processes), which tells a handed-off turn apart from a settled session. Returned by `POST /safari/session/get` only; omitted when false or when the lookup fails, so treat absence as unknown rather than idle. HasOpenTasks bool `json:"has_open_tasks" toon:"has_open_tasks"` - // True when there is assistant output the caller has not yet viewed. + // True when assistant output exists that the caller has not viewed yet; always false while `is_running` is true. Computed by `POST /safari/session/list` only; always false in `POST /safari/session/get`. HasUnread bool `json:"has_unread" toon:"has_unread"` // True for incognito (non-persisted-memory) sessions. Incognito bool `json:"incognito" toon:"incognito"` @@ -10364,14 +10807,16 @@ type SessionItem struct { IsMine bool `json:"is_mine" toon:"is_mine"` // True when an agent turn is currently in flight for this session. IsRunning bool `json:"is_running" toon:"is_running"` - // Unix timestamp in milliseconds of the most recent assistant-side event. + // Unix timestamp in milliseconds of the latest assistant-side event; user messages alone do not advance it. Omitted when 0. LastEventAt TimestampMilli `json:"last_event_at" toon:"last_event_at"` // Parent session id for subagent (child) sessions; empty otherwise. ParentSessionID string `json:"parent_session_id" toon:"parent_session_id"` // Creator person id. PersonID string `json:"person_id" toon:"person_id"` - // Caller's per-user pin time as a Unix timestamp in milliseconds; 0 means not pinned. + // When the caller pinned this session, as a Unix timestamp in milliseconds; 0 when not pinned. Pins are per user. Filled by `POST /safari/session/list` only; always 0 in `POST /safari/session/get`. PinnedAt TimestampMilli `json:"pinned_at" toon:"pinned_at"` + // Business object the session is about, as a prefixed reference (for example an incident reference). Omitted when the session is not bound to one. + Ref string `json:"ref" toon:"ref"` // Session identifier. SessionID string `json:"session_id" toon:"session_id"` // Session title; may be empty for untitled sessions. @@ -10384,11 +10829,11 @@ type SessionItem struct { SharedAt TimestampMilli `json:"shared_at" toon:"shared_at"` // Person ID that most recently enabled sharing; 0 if never shared. SharedBy int64 `json:"shared_by" toon:"shared_by"` - // Number of process-type tasks (background shell or monitor) still alive when the response was rendered. + // Number of the session's process-type tasks (background shell commands or monitors) still alive when the response was built; 0 when none or when the count cannot be read. StandingTasks int64 `json:"standing_tasks" toon:"standing_tasks"` - // Raw session-state bag (session-scoped keys). Omitted when empty. + // Raw session-state key/value map. Returned by `POST /safari/session/get` only; omitted when empty. State map[string]any `json:"state" toon:"state"` - // Lifecycle status. One of: `enabled` (active), `deleted` (soft-deleted, no longer accessible). + // Lifecycle status. Always `enabled` in responses: deleted sessions are never returned. Status string `json:"status" toon:"status"` // Owning team id; 0 means no team is bound. Immutable after create. TeamID int64 `json:"team_id" toon:"team_id"` @@ -10413,23 +10858,30 @@ type SessionListRequest struct { // | `support-flashcat` | Flashcat-site support agent (exposed over A2A) | // | `ai-sre` | The AI SRE main app | // | `template-assistant` | Notification-template assistant (template editing/validation) | - // | `swe` | Internal benchmarking app (not customer-facing) | + // | `query-assistant` | Monitors query-writing assistant | + // | `swe` | Software-engineering agent app (not offered in the console) | AppName string `json:"app_name" toon:"app_name"` // Ascending order when true, descending when false. Only honored together with `orderby`; when `orderby` is omitted the sort is always `updated_at` descending. Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` - // Restrict to sessions produced by these surfaces; empty returns every kind. + // Restrict to sessions created from these surfaces: `web` (console), `im` (IM bot or IM H5), `api` (public API), `automation` (automation rule). Empty returns every kind. EntryKinds []string `json:"entry_kinds,omitempty" toon:"entry_kinds,omitempty"` - // Include subagent-dispatched sessions in the list. + // When true, also list child sessions spawned by subagent dispatch. Defaults to false (top-level sessions only). IncludeSubagentSessions bool `json:"include_subagent_sessions,omitempty" toon:"include_subagent_sessions,omitempty"` - // Filter by session-name keyword. + // Return only sessions whose `session_name` contains this text; leading and trailing spaces are ignored. Keyword string `json:"keyword,omitempty" toon:"keyword,omitempty"` // Sort field: `created_at` by creation time, `updated_at` by last update; defaults to `updated_at` when omitted. Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` // Filter by who started the session: returns only sessions started by these members (a session is kept when `person_id` matches any of them). Intersects with `scope` and `team_ids`, so it never widens what the caller is allowed to see. PersonIDs []int64 `json:"person_ids,omitempty" toon:"person_ids,omitempty"` - // Visibility scope: `all` (own personal + accessible team sessions), `personal`, or `team`; default `all`. + // Visibility scope: + // - `all` (default): sessions the caller created plus sessions bound to teams the caller belongs to + // - `personal`: the caller's own sessions with no team (`team_id` = 0) + // - `team`: sessions bound to teams the caller belongs to; empty when the caller is in no team Scope string `json:"scope,omitempty" toon:"scope,omitempty"` - // Archive bucket: active (default) returns un-archived, archived returns archived, all returns both. + // Archive filter: + // - `active` (default): sessions that are not archived + // - `archived`: archived sessions only + // - `all`: both Status string `json:"status,omitempty" toon:"status,omitempty"` // Optional explicit team filter; intersects with `scope` and never expands access. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` @@ -10437,11 +10889,9 @@ type SessionListRequest struct { // SessionListResponse is generated from the Flashduty OpenAPI schema. type SessionListResponse struct { - // The page of sessions. + // The page of sessions: on page 1, the caller's matching pinned sessions (newest pin first) followed by up to `limit` other sessions in the requested order. Sessions []SessionItem `json:"sessions" toon:"sessions"` - // Account-wide onboarding flag: true when the account has no knowledge in any scope; not dependent on this call's filters. - SuggestInit bool `json:"suggest_init" toon:"suggest_init"` - // Total number of sessions matching the filter (ignoring pagination). + // Number of matching sessions, ignoring pagination. Pinned sessions prepended on page 1 are not counted. Total int64 `json:"total" toon:"total"` } @@ -10459,11 +10909,11 @@ type SessionTokenUsage struct { // SignedUrLs is generated from the Flashduty OpenAPI schema. type SignedUrLs struct { - // MIME type of the file. + // MIME type, derived from the file-name extension when the file was produced: `text/html` (.html/.htm), `text/markdown` (.md), `text/plain` (.txt/.log), `text/csv`, `text/yaml` (.yaml/.yml), `text/x-python`, `text/x-go`, `text/x-sh`, `application/json`, `application/xml`, `application/pdf`, `image/png`, `image/jpeg`, `image/gif`, `image/svg+xml`, `image/webp`, `application/zip`, `application/gzip` (.tar/.gz/.tgz); any other extension is `application/octet-stream`. ContentType string `json:"content_type" toon:"content_type"` // Relative URL (`/safari/artifact/stream?...`) that serves the file as an attachment. Prepend the API base `https://api.flashcat.cloud` before use; expires with `expires_in`. DownloadURL string `json:"download_url" toon:"download_url"` - // Validity of both URLs in seconds (300). + // Validity of both URLs in seconds. Always `300`. ExpiresIn int64 `json:"expires_in" toon:"expires_in"` // File name including extension. Name string `json:"name" toon:"name"` @@ -10485,19 +10935,19 @@ type SilenceRuleItem struct { DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` // Rule description. Description string `json:"description" toon:"description"` - // Alert event match conditions; matching events are silenced within the time window. + // Alert event conditions (OR of AND groups); matching events are silenced while the time window is active. Filters FilterGroup `json:"filters" toon:"filters"` // Incident the rule is attached to. Always present; the zero ObjectID `000000000000000000000000` means the rule was not created from an incident. FromIncidentID string `json:"from_incident_id" toon:"from_incident_id"` - // When true, the silence rule is automatically deleted after its time window expires. Defaults to false. + // When true, the rule is permanently removed about 24 hours after its one-off window ends; rules with recurring windows are never removed. Returned only when `true`. IsAutoDelete bool `json:"is_auto_delete" toon:"is_auto_delete"` - // When true, silenced alerts are dropped instead of suppressed into incidents. + // When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as silenced by this rule. IsDirectlyDiscard bool `json:"is_directly_discard" toon:"is_directly_discard"` // Whether the rule's time window covers the current moment, evaluated at response time. IsEffective bool `json:"is_effective" toon:"is_effective"` // Rule ID (MongoDB ObjectID). RuleID string `json:"rule_id" toon:"rule_id"` - // Rule name. + // Silence rule name, 1–39 characters. RuleName string `json:"rule_name" toon:"rule_name"` // Rule status: `enabled` or `disabled`; deleted rules never appear in the list. Status string `json:"status" toon:"status"` @@ -10529,13 +10979,13 @@ type SkillItem struct { AccountID int64 `json:"account_id" toon:"account_id"` // Skill author. Author string `json:"author" toon:"author"` - // Whether the caller may edit this skill. + // True when the caller may change this skill: account owners and admins for account-scope skills, team members for team skills. CanEdit bool `json:"can_edit" toon:"can_edit"` // SHA-256 checksum of the skill zip. Checksum string `json:"checksum" toon:"checksum"` // Full SKILL.md content. Omitted in list responses. Content string `json:"content" toon:"content"` - // Set only on install-from-session responses: true = fresh install, false = in-place update. + // Not returned by these endpoints; it is set only by the install-from-session flow. Created bool `json:"created" toon:"created"` // Creation time. Unix timestamp in milliseconds. CreatedAt TimestampMilli `json:"created_at" toon:"created_at"` @@ -10545,7 +10995,9 @@ type SkillItem struct { Description string `json:"description" toon:"description"` // Optional English description. English-locale UI responses prefer this over `description`; the skill catalog also uses it as a stable selection signal when `description` is localized for display. DescriptionEn string `json:"description_en" toon:"description_en"` - // True when a marketplace-sourced skill was edited locally (auto-update skips it). + // Example prompts declared in the SKILL.md frontmatter (up to 10), shown as suggested questions. Omitted when none. + Examples []SkillItemExamplesItem `json:"examples" toon:"examples"` + // True when a marketplace-installed skill was changed locally (for example by uploading a new archive); automatic marketplace updates skip it. IsModified bool `json:"is_modified" toon:"is_modified"` // Skill license. License string `json:"license" toon:"license"` @@ -10559,7 +11011,7 @@ type SkillItem struct { SourceTemplateName string `json:"source_template_name" toon:"source_template_name"` // Template version at install time. SourceTemplateVersion string `json:"source_template_version" toon:"source_template_version"` - // Skill status. Deleted skills are excluded from every API response, so only these two values are ever returned. + // Skill status: `enabled` (agents load it) or `disabled` (kept but not loaded). Deleted skills never appear in responses. Status string `json:"status" toon:"status"` // Tags parsed from the frontmatter. Tags []string `json:"tags" toon:"tags"` @@ -10567,11 +11019,11 @@ type SkillItem struct { TeamID int64 `json:"team_id" toon:"team_id"` // Required tools (builtin or `mcp:server/tool`). Tools []string `json:"tools" toon:"tools"` - // True when the marketplace has a newer template version. + // True when the marketplace template this skill was installed from has a newer version. Computed by `POST /safari/skill/list` only; always false in other responses. UpdateAvailable bool `json:"update_available" toon:"update_available"` // Last update time. Unix timestamp in milliseconds. UpdatedAt TimestampMilli `json:"updated_at" toon:"updated_at"` - // Execution-environment kinds (EnvironmentKind strings, e.g. `byoc`) the skill is restricted to. Omitted when empty, which means the skill is available in all venues. + // Execution environments the skill is restricted to: `cloud` (managed sandbox) and/or `byoc` (self-hosted runner). Omitted when empty, which means every environment. Venues []string `json:"venues" toon:"venues"` // Skill version from the frontmatter. Version string `json:"version" toon:"version"` @@ -10584,9 +11036,12 @@ type SkillListRequest struct { IncludeAccount *bool `json:"include_account,omitempty" toon:"include_account,omitempty"` // Free-text search across skill name, description, English description, skill ID, marketplace source template name, and author. Query string `json:"query,omitempty" toon:"query,omitempty"` - // Restrict results to `all` (default), `account`-only (team_id=0), or `team`-only (excludes account-scoped rows). Overrides `include_account` when set. + // Which skills to return; overrides `include_account` when set: + // - `all` (default): account-scope skills (unless `include_account` is false) plus the caller's team skills + // - `account`: account-scope skills only (`team_id` = 0) + // - `team`: the caller's team skills only Scope string `json:"scope,omitempty" toon:"scope,omitempty"` - // Filter to these team IDs; empty = the caller's visible set. + // Limit team-scope results to these team IDs; IDs of teams the caller does not belong to are dropped. Empty = all of the caller's teams. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` } @@ -10629,15 +11084,15 @@ type SourcemapBinaryImage struct { // CPU architecture for this binary image. Arch string `json:"arch,omitempty" toon:"arch,omitempty"` // Whether this binary belongs to the operating system. - IsSystem bool `json:"is_system" toon:"is_system"` + IsSystem bool `json:"is_system,omitempty" toon:"is_system,omitempty"` // Runtime address. Accepts a hex string such as `0x100000000` or a decimal integer. LoadAddress any `json:"load_address,omitempty" toon:"load_address,omitempty"` // Runtime address. Accepts a hex string such as `0x100000000` or a decimal integer. MaxAddress any `json:"max_address,omitempty" toon:"max_address,omitempty"` // Binary image name. - Name string `json:"name" toon:"name"` + Name string `json:"name,omitempty" toon:"name,omitempty"` // Build UUID identifying the binary or dSYM. - Uuid string `json:"uuid" toon:"uuid"` + Uuid string `json:"uuid,omitempty" toon:"uuid,omitempty"` } // SourcemapCodeSnippet is generated from the Flashduty OpenAPI schema. @@ -10688,7 +11143,7 @@ type SourcemapItem struct { GitCommitSHA string `json:"git_commit_sha" toon:"git_commit_sha"` // Git repository URL associated with this build. GitRepositoryURL string `json:"git_repository_url" toon:"git_repository_url"` - // Storage key uniquely identifying this sourcemap file. + // Record identifier: a 32-character MD5 hex digest derived from the uploaded file's identity (storage path, or service/version/build identifiers for native symbols). Key string `json:"key" toon:"key"` // Platform-specific metadata: `minified_url` (browser/react-native/harmony/miniprogram); `build_id`, `variant`, `version_code` (android mappings), plus `arch`, `lib_name`, `code_id` (android/harmony/electron native symbols); `uuid` (ios); `build_id`, `platform`, `arch`, `flavor`, `code_id`, `debug_id` (flutter); `subpackage`, `minified_url` (miniprogram). Omitted when empty. Metadata map[string]any `json:"metadata" toon:"metadata"` @@ -10723,7 +11178,7 @@ type SourcemapListRequest struct { ListOptions // Sort ascending. Default false (descending). Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` - // Android only. Filter by Gradle plugin build identifier. Max 200 characters. + // Substring filter on the build ID (Android Gradle plugin build identifier, or the build ID of native symbols). Max 200 characters. BuildID string `json:"build_id,omitempty" toon:"build_id,omitempty"` // End of upload time range, Unix epoch milliseconds. Maximum window: 365 days. EndTime int64 `json:"end_time" toon:"end_time"` @@ -10750,7 +11205,7 @@ type SourcemapListRequest struct { // | `flutter` | Flutter Dart AOT symbols | // | `electron` | Electron Breakpad symbols | Type string `json:"type,omitempty" toon:"type,omitempty"` - // iOS only. Filter by dSYM bundle UUID. Max 200 characters. + // iOS only. Substring filter on the dSYM UUID; upper-cased and stripped of hyphens before matching. Max 200 characters. Uuid string `json:"uuid,omitempty" toon:"uuid,omitempty"` // Filter by version strings. Up to 100 values. Versions []string `json:"versions,omitempty" toon:"versions,omitempty"` @@ -10766,7 +11221,7 @@ type SourcemapListResponse struct { // SourcemapStackEnrichRequest is generated from the Flashduty OpenAPI schema. type SourcemapStackEnrichRequest struct { - // Android NDK architecture such as `arm`, `arm64`, `x86`, or `x64`. + // Native CPU architecture, such as `arm`, `arm64`, `x86` or `x64`. With `type: android` and an empty `source_type`, sending `arch` selects NDK native symbolication. Arch string `json:"arch,omitempty" toon:"arch,omitempty"` // Loaded binary images from an iOS crash report. BinaryImages []SourcemapBinaryImage `json:"binary_images,omitempty" toon:"binary_images,omitempty"` @@ -10780,7 +11235,7 @@ type SourcemapStackEnrichRequest struct { Platform string `json:"platform,omitempty" toon:"platform,omitempty"` // Application or service name used when the sourcemap was uploaded. Service string `json:"service" toon:"service"` - // Android error source type. Use `ndk` with `arch` for native symbolication. + // The error's `error.source_type` as reported by the SDK. It reroutes symbolication: for `android`, a value containing `ndk` selects NDK native symbols; for `flutter` and `react-native`, `ios` selects dSYM and `android`/`ndk` selects Android symbols; for `electron`, `macos`, `windows` or `linux` selects Breakpad symbols. Ignored for other types. SourceType string `json:"source_type,omitempty" toon:"source_type,omitempty"` // Raw stack trace to parse and enrich. Stack string `json:"stack,omitempty" toon:"stack,omitempty"` @@ -10847,7 +11302,7 @@ type StatusPageChangeItem struct { AffectedComponents []AffectedStatusPageComponentItem `json:"affected_components" toon:"affected_components"` // Maintenance only: whether the status advances automatically based on the scheduled window. Omitted when false. AutoUpdateBySchedule bool `json:"auto_update_by_schedule" toon:"auto_update_by_schedule"` - // Event ID. + // Event ID, returned by `POST /status-page/change/create`; pass it as `change_id` to the other event endpoints. ChangeID int64 `json:"change_id" toon:"change_id"` // Event close time in Unix seconds. For maintenances this is the scheduled end time; for closed events, the time the event reached its terminal status (`resolved`/`completed`). Omitted when not set. CloseAtSeconds Timestamp `json:"close_at_seconds" toon:"close_at_seconds"` @@ -10863,7 +11318,7 @@ type StatusPageChangeItem struct { PageID int64 `json:"page_id" toon:"page_id"` // Member IDs responsible for this event. Omitted when no responders are assigned. ResponderIDs []int64 `json:"responder_ids" toon:"responder_ids"` - // Event start time in Unix seconds, derived from the first timeline update. Omitted when 0. + // Event start time in Unix seconds. For incidents it is the time of the first timeline entry; for maintenances it is the scheduled start given at creation, or the first entry's time when none was given. Omitted when 0. StartAtSeconds Timestamp `json:"start_at_seconds" toon:"start_at_seconds"` // Current event status. Incident statuses: `investigating`/`identified`/`monitoring`/`resolved`. Maintenance statuses: `scheduled`/`ongoing`/`completed`. Omitted when empty (never for stored events). Status string `json:"status" toon:"status"` @@ -10906,13 +11361,13 @@ type StatusPageChangeUpdateItem struct { // | `ongoing` | In progress (maintenance). | // | `completed` | Completed (maintenance). | Status string `json:"status" toon:"status"` - // Update ID. + // Timeline entry ID (a ULID string), assigned by the server; pass it as `update_id` to edit or delete the entry. UpdateID string `json:"update_id" toon:"update_id"` } // StatusPageComponentChangeItem is generated from the Flashduty OpenAPI schema. type StatusPageComponentChangeItem struct { - // Component ID. + // ID of the component whose status changes; matches `component_id` in `GET /status-page/info`. ComponentID string `json:"component_id" toon:"component_id"` // Component display name. Populated by the backend on read; ignored on write. Omitted when empty. ComponentName string `json:"component_name" toon:"component_name"` @@ -10944,7 +11399,7 @@ type StatusPageComponentItem struct { type StatusPageDraftCreateResponse struct { // Creation time in Unix epoch seconds. CreatedAt Timestamp `json:"created_at" toon:"created_at"` - // Draft ID matching `draft_[A-Za-z0-9]{22}`; the console review link carries it. + // Draft ID matching `draft_[A-Za-z0-9]{22}`; pass it as `draft_id` to `POST /status-page/change/create` or `POST /status-page/change/timeline/create` to publish. DraftID string `json:"draft_id" toon:"draft_id"` } @@ -10984,11 +11439,11 @@ type StatusPageInfoResponse struct { Sections []StatusPageSectionItem `json:"sections" toon:"sections"` // Subscription channel toggles. Subscription StatusPageSubscriptionItem `json:"subscription" toon:"subscription"` - // Preferred event template type: `pre_defined` or `message`. Omitted when never set. + // Event template mode used when publishing events in the console: `message` (status descriptions: per-status texts) or `pre_defined` (full status updates: complete examples with title, status, and description). Omitted when never set; the console then uses `message`. TemplatePreference string `json:"template_preference" toon:"template_preference"` // Page visibility type. `public` pages are accessible to anyone and use email subscriptions; `internal` pages are restricted to account members and use IM subscriptions. Type string `json:"type" toon:"type"` - // URL-safe slug, unique per account. + // URL-safe slug of the page, unique among the account's pages of the same type. URLName string `json:"url_name" toon:"url_name"` } @@ -11026,11 +11481,11 @@ type StatusPageItem struct { Sections []StatusPageSectionItem `json:"sections" toon:"sections"` // Subscription channel toggles. Subscription StatusPageSubscriptionItem `json:"subscription" toon:"subscription"` - // Preferred event template type: `pre_defined` or `message`. Omitted when never set. + // Event template mode used when publishing events in the console: `message` (status descriptions: per-status texts) or `pre_defined` (full status updates: complete examples with title, status, and description). Omitted when never set; the console then uses `message`. TemplatePreference string `json:"template_preference" toon:"template_preference"` // Page visibility type. `public` pages are accessible to anyone and use email subscriptions; `internal` pages are restricted to account members and use IM subscriptions. Type string `json:"type" toon:"type"` - // URL-safe slug, unique per account. + // URL-safe slug of the page, unique among the account's pages of the same type. URLName string `json:"url_name" toon:"url_name"` } @@ -11070,7 +11525,7 @@ type StatusPageMigrationJob struct { // | `failed` | Failed; the `error` field holds the reason. | // | `cancelled` | Canceled by request. | Status string `json:"status" toon:"status"` - // Flashduty target status page ID. Set once the job produces one, or supplied up front for subscriber migration. + // Flashduty target status page ID. For a structure migration it is 0 until the page is created or reused; for a subscriber migration it is the `target_page_id` from the request. TargetPageID int64 `json:"target_page_id" toon:"target_page_id"` // Last status update time as a Unix timestamp in seconds. UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` @@ -11090,11 +11545,11 @@ type StatusPageMigrationProgress struct { SectionsImported int64 `json:"sections_imported" toon:"sections_imported"` // Number of email subscribers successfully imported. SubscribersImported int64 `json:"subscribers_imported" toon:"subscribers_imported"` - // Number of subscribers skipped (e.g. because they would create duplicates). + // Number of source subscribers skipped because they are not email subscribers, have no email address, or are quarantined. Recipients already subscribed on the target page are not counted here. SubscribersSkipped int64 `json:"subscribers_skipped" toon:"subscribers_skipped"` // Number of incident templates successfully imported; templates that fail are skipped and recorded in `warnings`. TemplatesImported int64 `json:"templates_imported" toon:"templates_imported"` - // Total steps this job will perform. + // Total steps of the job: 5 for a structure migration (page, sections, components, incidents and maintenances, templates) and 1 for a subscriber migration. TotalSteps int64 `json:"total_steps" toon:"total_steps"` // Non-fatal warnings recorded during the job. Omitted when empty. Warnings []string `json:"warnings" toon:"warnings"` @@ -11116,7 +11571,7 @@ type StatusPagePreDefinedTemplate struct { TemplateID string `json:"template_id,omitempty" toon:"template_id,omitempty"` // Template title. Title string `json:"title,omitempty" toon:"title,omitempty"` - // Change type the template applies to: `incident` unplanned incident, `maintenance` planned maintenance. + // Change type the template applies to: `incident` unplanned incident, `maintenance` planned maintenance. Set on create; ignored on update. Type string `json:"type,omitempty" toon:"type,omitempty"` } @@ -11166,9 +11621,9 @@ type StringMapPatch struct { type TeamBriefItem struct { // Array of person IDs belonging to the team; empty array (never null) when the team has no members. PersonIDs []uint64 `json:"person_ids" toon:"person_ids"` - // Team ID. + // Team ID, one of the requested `team_ids`. TeamID uint64 `json:"team_id" toon:"team_id"` - // Team name. + // Team name. Deleted teams are included, so this can be the name of a team that no longer appears in `POST /team/list`. TeamName string `json:"team_name" toon:"team_name"` } @@ -11200,7 +11655,7 @@ type TeamInfosRequest struct { // TeamInfosResponse is generated from the Flashduty OpenAPI schema. type TeamInfosResponse struct { - // Array of brief team info for the matched `team_ids`; may be null when no ID matches. + // Brief info for the matched teams, including deleted ones; `null` when no ID matches. Items []TeamBriefItem `json:"items" toon:"items"` } @@ -11216,7 +11671,7 @@ type TeamItem struct { CreatorName string `json:"creator_name" toon:"creator_name"` // Free-form description. Description string `json:"description" toon:"description"` - // Member IDs of team members. + // Person IDs of the team's members (member IDs; the account owner's ID when the owner is in the team). Empty array when the team has no members. PersonIDs []uint64 `json:"person_ids" toon:"person_ids"` // External reference ID for third-party HR system integration. RefID string `json:"ref_id" toon:"ref_id"` @@ -11230,7 +11685,7 @@ type TeamItem struct { UpdatedAt Timestamp `json:"updated_at" toon:"updated_at"` // Member ID of the last editor. UpdatedBy uint64 `json:"updated_by" toon:"updated_by"` - // Display name of the last editor. + // Name of the last editor: the member's name, or the account name when the account owner made the change; empty string when unknown. UpdatedByName string `json:"updated_by_name" toon:"updated_by_name"` } @@ -11252,27 +11707,27 @@ type TeamListResponse struct { ListOptions // Array of teams for the current page, used with `p`, `limit` and `total` for pagination; empty array on an empty page. Items []TeamItem `json:"items" toon:"items"` - // Total number of teams matching the filter. + // Number of non-deleted teams matching the filters, across all pages. Total int64 `json:"total" toon:"total"` } // TeamUpsertRequest is generated from the Flashduty OpenAPI schema. type TeamUpsertRequest struct { - // Default country code applied to any `phones` entries that are not in E.164 format. + // Region hint for `phones` entries without a `+` prefix: an ISO 3166-1 alpha-2 code such as `CN` (the default when omitted) or a digit calling code such as `86`. CountryCode string `json:"countryCode,omitempty" toon:"countryCode,omitempty"` - // Free-form description. + // Free-form description, up to 500 characters. On update, omitting it clears the stored description. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Add existing members to the team by email. Addresses that don't match an existing member are silently ignored — no invitation is sent. + // Emails of existing members to place in the team; merged with `person_ids` and `phones`. Addresses that match no member are ignored and no invitation is sent. Emails []string `json:"emails,omitempty" toon:"emails,omitempty"` - // Member IDs to set as team members. Replaces the existing member list. + // Person IDs to place in the team (member IDs, or the account ID for the account owner). Together with `emails` and `phones` they replace the entire member list; IDs that are not members of the account are ignored. PersonIDs []uint64 `json:"person_ids,omitempty" toon:"person_ids,omitempty"` - // Add existing members to the team by phone number. Numbers not in E.164 format are parsed with `countryCode`; an unparseable number fails the whole request with a 400. Numbers that parse but match no existing member are silently ignored. + // Phone numbers of existing members to place in the team; merged with `person_ids` and `emails`. Numbers without a `+` prefix are parsed with `countryCode`; an unparseable number fails the whole request with `400`, and numbers that match no member are ignored. Phones []string `json:"phones,omitempty" toon:"phones,omitempty"` - // External reference ID for HR system integration. + // External reference ID (for example a department ID in an HR system), usable as a lookup key in `POST /team/info` and `POST /team/delete`. On update, omitting it clears the stored value. RefID string `json:"ref_id,omitempty" toon:"ref_id,omitempty"` // When true and `team_id` is 0, an existing team with the same `team_name` is updated in place instead of returning a name-conflict error. ResetIfNameExist bool `json:"reset_if_name_exist,omitempty" toon:"reset_if_name_exist,omitempty"` - // Team ID. Omit or set to 0 to create a new team. + // ID of the team to update. Omit or set to 0 to create a new team; a non-zero ID must belong to an existing team of the account. TeamID uint64 `json:"team_id,omitempty" toon:"team_id,omitempty"` // Team display name. 1–39 characters. TeamName string `json:"team_name" toon:"team_name"` @@ -11304,13 +11759,13 @@ type TemplateCreateRequest struct { FeishuApp string `json:"feishu_app,omitempty" toon:"feishu_app,omitempty"` // Keep blank lines in the body of Feishu app card v2 messages. FeishuAppCardV2PreserveBlankLines bool `json:"feishu_app_card_v2_preserve_blank_lines,omitempty" toon:"feishu_app_card_v2_preserve_blank_lines,omitempty"` - // Render alert labels as a table in Feishu app cards. + // Render Markdown tables in the `feishu_app` content as native Feishu card tables. FeishuAppCardV2TableEnabled bool `json:"feishu_app_card_v2_table_enabled,omitempty" toon:"feishu_app_card_v2_table_enabled,omitempty"` // Show the Create War Room button on Feishu app cards. FeishuAppWarRoomEnabled bool `json:"feishu_app_war_room_enabled,omitempty" toon:"feishu_app_war_room_enabled,omitempty"` // IM apps whose closed-incident cards keep the custom action buttons. Supported values: `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, `teams_app`. An empty list hides the buttons on every app. IncidentCardClosedActionApps []string `json:"incident_card_closed_action_apps,omitempty" toon:"incident_card_closed_action_apps,omitempty"` - // Incident card fields hidden per IM app type. + // Incident card fields to hide per IM app type. IncidentCardHiddenFields IncidentCardHiddenFields `json:"incident_card_hidden_fields,omitempty" toon:"incident_card_hidden_fields,omitempty"` // Slack robot message template source. Slack string `json:"slack,omitempty" toon:"slack,omitempty"` @@ -11320,13 +11775,13 @@ type TemplateCreateRequest struct { SlackAppWarRoomEnabled bool `json:"slack_app_war_room_enabled,omitempty" toon:"slack_app_war_room_enabled,omitempty"` // SMS template source (Go `text/template` syntax). SMS string `json:"sms,omitempty" toon:"sms,omitempty"` - // Team scope. 0 for account-wide. + // Owning team ID from `POST /team/list`; `0` (default) means account-wide. A non-zero ID must be an existing team. TeamID int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` // Microsoft Teams app message template source. TeamsApp string `json:"teams_app,omitempty" toon:"teams_app,omitempty"` // Telegram bot message template source. Telegram string `json:"telegram,omitempty" toon:"telegram,omitempty"` - // Template name, unique per account. 1–39 characters. + // Template name, 1–39 characters, unique among the account's non-deleted templates and different from the built-in preset template's name in every supported language. TemplateName string `json:"template_name" toon:"template_name"` // Voice call script template source. Voice string `json:"voice,omitempty" toon:"voice,omitempty"` @@ -11334,7 +11789,7 @@ type TemplateCreateRequest struct { Wecom string `json:"wecom,omitempty" toon:"wecom,omitempty"` // WeCom app message template source. WecomApp string `json:"wecom_app,omitempty" toon:"wecom_app,omitempty"` - // Send WeCom robot notifications as `markdown_v2` messages instead of plain markdown. + // Send WeCom robot notifications as `markdown_v2` messages instead of plain markdown. While enabled, the rendered `wecom` content must be at most 4,096 bytes. WecomMarkdownV2Enabled bool `json:"wecom_markdown_v2_enabled,omitempty" toon:"wecom_markdown_v2_enabled,omitempty"` // Zoom bot message template source. Zoom string `json:"zoom,omitempty" toon:"zoom,omitempty"` @@ -11364,7 +11819,7 @@ type TemplateItem struct { CreatorID int64 `json:"creator_id" toon:"creator_id"` // Unix epoch seconds the template was soft-deleted. Absent (omitempty) when the template is live. DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` - // Free-form description. + // Free-form description (up to 500 characters); empty string when none was given. Description string `json:"description" toon:"description"` // DingTalk robot message template source. Dingtalk string `json:"dingtalk" toon:"dingtalk"` @@ -11380,11 +11835,11 @@ type TemplateItem struct { FeishuApp string `json:"feishu_app" toon:"feishu_app"` // Whether Feishu app card v2 messages keep blank lines in the body. FeishuAppCardV2PreserveBlankLines bool `json:"feishu_app_card_v2_preserve_blank_lines" toon:"feishu_app_card_v2_preserve_blank_lines"` - // Whether alert labels use table rendering in Feishu app cards. + // Whether Markdown tables in the `feishu_app` content are rendered as native Feishu card tables. FeishuAppCardV2TableEnabled bool `json:"feishu_app_card_v2_table_enabled" toon:"feishu_app_card_v2_table_enabled"` // Whether Feishu app cards show the Create War Room button. Hidden when the incident has no responders. FeishuAppWarRoomEnabled bool `json:"feishu_app_war_room_enabled" toon:"feishu_app_war_room_enabled"` - // IM apps whose closed-incident cards keep the custom action buttons. Supported values: `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, `teams_app`. An empty list hides the buttons on every app. + // IM apps whose cards for closed incidents keep the custom action buttons (open incidents always show them). Values: `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, `teams_app`. Empty or `null` hides the buttons on closed-incident cards in every app. IncidentCardClosedActionApps []string `json:"incident_card_closed_action_apps" toon:"incident_card_closed_action_apps"` // Incident card fields hidden per IM app type; an empty object when none are configured. IncidentCardHiddenFields IncidentCardHiddenFields `json:"incident_card_hidden_fields" toon:"incident_card_hidden_fields"` @@ -11396,7 +11851,10 @@ type TemplateItem struct { SlackAppWarRoomEnabled bool `json:"slack_app_war_room_enabled" toon:"slack_app_war_room_enabled"` // SMS template source (Go `text/template` syntax). SMS string `json:"sms" toon:"sms"` - // Template lifecycle status. `enabled` templates can be referenced by escalation policies for notifications; `disabled` templates are no longer used for new notifications; `deleted` templates are never returned by list endpoints. + // Template status. + // - `enabled`: usable by escalation rules. + // - `disabled`: not used for new notifications; cannot be set through this API. + // - `deleted`: soft-deleted by `/template/delete`; excluded from `/template/list` but still returned by `/template/info`. Status string `json:"status" toon:"status"` // ID of the team this template is scoped to, or 0 for account-wide. TeamID int64 `json:"team_id" toon:"team_id"` @@ -11404,7 +11862,7 @@ type TemplateItem struct { TeamsApp string `json:"teams_app" toon:"teams_app"` // Telegram bot message template source. Telegram string `json:"telegram" toon:"telegram"` - // Template ID. + // Template ID (24-character hex). The built-in preset template always has the ID `6321aad26c12104586a88916`. TemplateID string `json:"template_id" toon:"template_id"` // Unique template name within the account. TemplateName string `json:"template_name" toon:"template_name"` @@ -11427,17 +11885,17 @@ type TemplateItem struct { // TemplateListRequest is generated from the Flashduty OpenAPI schema. type TemplateListRequest struct { ListOptions - // Ascending sort order. + // Sort ascending when `true`; defaults to newest first. Asc bool `json:"asc,omitempty" toon:"asc,omitempty"` // Filter by creator member ID; obtain member IDs from `POST /member/list`. CreatorID *int64 `json:"creator_id,omitempty" toon:"creator_id,omitempty"` - // When true, only return templates scoped to teams the caller belongs to. + // When `true`, only templates of teams the caller belongs to are returned. If `team_ids` is also sent, only teams in both lists are kept. When they share no team, or the caller belongs to no team, the result is empty. IsMyTeam bool `json:"is_my_team,omitempty" toon:"is_my_team,omitempty"` - // Sort field. + // Sort field: `created_at` (default, creation time) or `updated_at` (last update time). Orderby string `json:"orderby,omitempty" toon:"orderby,omitempty"` - // Regex or substring match on template_name. + // Case-insensitive regular expression matched against `template_name`; an invalid expression is matched as literal text. Query string `json:"query,omitempty" toon:"query,omitempty"` - // Filter by specific team IDs. + // Return only templates of these team IDs (from `POST /team/list`); `0` selects account-wide templates. Empty or omitted applies no team filter. See `is_my_team` for how the two combine. TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` } @@ -11469,13 +11927,13 @@ type TemplateUpdateRequest struct { FeishuApp *string `json:"feishu_app,omitempty" toon:"feishu_app,omitempty"` // When set, keep or drop blank lines in the body of Feishu app card v2 messages. Omit to keep the existing setting. FeishuAppCardV2PreserveBlankLines *bool `json:"feishu_app_card_v2_preserve_blank_lines,omitempty" toon:"feishu_app_card_v2_preserve_blank_lines,omitempty"` - // When set, enable or disable table rendering for alert labels in Feishu app cards. Omit to keep the existing setting. + // Render Markdown tables in the `feishu_app` content as native Feishu card tables. Omit to keep the current setting. FeishuAppCardV2TableEnabled *bool `json:"feishu_app_card_v2_table_enabled,omitempty" toon:"feishu_app_card_v2_table_enabled,omitempty"` // When set, show or hide the Create War Room button on Feishu app cards. Omit to keep the existing setting. FeishuAppWarRoomEnabled *bool `json:"feishu_app_war_room_enabled,omitempty" toon:"feishu_app_war_room_enabled,omitempty"` // Replaces the retained-app list when sent. Supported values: `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, `teams_app`. Omit the field to leave it unchanged. IncidentCardClosedActionApps []string `json:"incident_card_closed_action_apps,omitempty" toon:"incident_card_closed_action_apps,omitempty"` - // Incident card fields hidden per IM app type. + // Incident card fields to hide per IM app type. When sent, replaces the stored value as a whole; omit to keep. IncidentCardHiddenFields IncidentCardHiddenFields `json:"incident_card_hidden_fields,omitempty" toon:"incident_card_hidden_fields,omitempty"` // Slack robot message template source. Omit to keep the current content; send an empty string to clear it. Slack *string `json:"slack,omitempty" toon:"slack,omitempty"` @@ -11493,7 +11951,7 @@ type TemplateUpdateRequest struct { Telegram *string `json:"telegram,omitempty" toon:"telegram,omitempty"` // Target template ID; obtain it from `POST /template/list`. TemplateID string `json:"template_id" toon:"template_id"` - // Template name. 1–39 characters. + // Template name, 1–39 characters. Required and written on every call; must not be used by another template. TemplateName string `json:"template_name" toon:"template_name"` // Voice call script template source. Omit to keep the current content; send an empty string to clear it. Voice *string `json:"voice,omitempty" toon:"voice,omitempty"` @@ -11501,7 +11959,7 @@ type TemplateUpdateRequest struct { Wecom *string `json:"wecom,omitempty" toon:"wecom,omitempty"` // WeCom app message template source. Omit to keep the current content; send an empty string to clear it. WecomApp *string `json:"wecom_app,omitempty" toon:"wecom_app,omitempty"` - // When set, switch WeCom robot notifications between `markdown_v2` and plain markdown. Omit to keep the existing setting. + // Send WeCom robot notifications as `markdown_v2` messages instead of plain markdown. While enabled, the rendered `wecom` content must be at most 4,096 bytes. Omit to keep the current setting. WecomMarkdownV2Enabled *bool `json:"wecom_markdown_v2_enabled,omitempty" toon:"wecom_markdown_v2_enabled,omitempty"` // Zoom bot message template source. Omit to keep the current content; send an empty string to clear it. Zoom *string `json:"zoom,omitempty" toon:"zoom,omitempty"` @@ -11509,15 +11967,15 @@ type TemplateUpdateRequest struct { // TimeFilter is generated from the Flashduty OpenAPI schema. type TimeFilter struct { - // Optional calendar ID; restricts the window to days matching the calendar. + // Service calendar ID from `POST /calendar/list` (for example `cal.xxxx`). When set, the window applies only on the calendar's workdays or days off, as chosen by `is_off`. CalID string `json:"cal_id,omitempty" toon:"cal_id,omitempty"` - // End of the window in `HH:MM`. + // Window end, `HH:MM`, inclusive (`23:59` lasts to midnight). End string `json:"end,omitempty" toon:"end,omitempty"` - // When true, match days marked as days-off in the calendar. + // Used with `cal_id`: `true` applies the window only on the calendar's days off, `false` only on its workdays. IsOff bool `json:"is_off,omitempty" toon:"is_off,omitempty"` - // Days of the week this window repeats on. Empty means every day. + // Days of the week the window applies on: `0` = Sunday … `6` = Saturday. Empty means every day. Repeat []int64 `json:"repeat,omitempty" toon:"repeat,omitempty"` - // Start of the window in `HH:MM`. + // Window start, `HH:MM`, inclusive. Start string `json:"start,omitempty" toon:"start,omitempty"` } @@ -11529,8 +11987,12 @@ type TryLinkPersonRequest struct { // TryLinkPersonResponse is generated from the Flashduty OpenAPI schema. type TryLinkPersonResponse struct { - // Person IDs newly linked during this call. + // Person IDs linked to the IM app during this call. Empty when nobody was newly linked. NewLinkedPersonIDs []int64 `json:"new_linked_person_ids" toon:"new_linked_person_ids"` + // Unlinked members skipped because they have neither an email nor a phone number. + NoContactCount int64 `json:"no_contact_count" toon:"no_contact_count"` + // Members with an email or phone that were looked up but not newly linked: not found on the IM platform, the IM account is already linked to another member, or the lookup failed for them. + UnmatchedCount int64 `json:"unmatched_count" toon:"unmatched_count"` } // UnackIncidentRequest is generated from the Flashduty OpenAPI schema. @@ -11551,11 +12013,11 @@ type UnsubscribeRuleItem struct { DeletedAt Timestamp `json:"deleted_at" toon:"deleted_at"` // Rule description. Description string `json:"description" toon:"description"` - // Alert event match conditions (OR-of-AND); matching events are discarded entirely. Empty means the rule matches nothing. + // Alert event conditions (OR of AND groups); matching events are discarded entirely. Empty means the rule matches nothing; `null` when the last update omitted `filters`. Filters FilterGroup `json:"filters" toon:"filters"` // Rule ID (MongoDB ObjectID). RuleID string `json:"rule_id" toon:"rule_id"` - // Rule name. + // Drop rule name, 1–39 characters. RuleName string `json:"rule_name" toon:"rule_name"` // Rule status: `enabled` or `disabled`; deleted rules never appear in the list. Status string `json:"status" toon:"status"` @@ -11567,13 +12029,13 @@ type UnsubscribeRuleItem struct { // UpdateChannelRequest is generated from the Flashduty OpenAPI schema. type UpdateChannelRequest struct { - // Auto-resolve timing mode: `trigger` starts the timer when the incident triggers, `update` restarts it on every alert update. Applied only when `auto_resolve_timeout` is also present in the request. + // How the auto-resolve timer runs: `trigger` starts it once when the incident is triggered, `update` restarts it whenever a new alert merges in. Applied only together with `auto_resolve_timeout`; if `auto_resolve_timeout` is sent without it, the mode resets to `trigger`. AutoResolveMode string `json:"auto_resolve_mode,omitempty" toon:"auto_resolve_mode,omitempty"` // Auto-resolve timeout in seconds. 0 disables auto-resolve. Max 30 days. AutoResolveTimeout *int64 `json:"auto_resolve_timeout,omitempty" toon:"auto_resolve_timeout,omitempty"` // ID of the channel to update; obtain it from `POST /channel/list`. ChannelID int64 `json:"channel_id" toon:"channel_id"` - // New channel name. 1 to 59 characters. + // New channel name, 1–59 characters, unique within the account. Omit or pass `null` to keep the current name. ChannelName *string `json:"channel_name,omitempty" toon:"channel_name,omitempty"` // New description. Up to 500 characters. Description *string `json:"description,omitempty" toon:"description,omitempty"` @@ -11581,25 +12043,25 @@ type UpdateChannelRequest struct { DisableAutoClose *bool `json:"disable_auto_close,omitempty" toon:"disable_auto_close,omitempty"` // Disable outlier incident detection. DisableOutlierDetection *bool `json:"disable_outlier_detection,omitempty" toon:"disable_outlier_detection,omitempty"` - // Alert event merge configuration. Updated only when present. + // Alert event merge configuration; replaces the stored configuration as a whole when present. EventGroup EventGroup `json:"event_group,omitzero" toon:"event_group,omitempty"` - // Flapping detection configuration. + // Flapping detection configuration; replaces the stored configuration as a whole when present. Flapping Flapping `json:"flapping,omitzero" toon:"flapping,omitempty"` - // Alert grouping configuration. + // Alert grouping configuration; replaces the stored configuration as a whole when present. Group Group `json:"group,omitzero" toon:"group,omitempty"` - // Allow external reporters to file incidents into this channel. + // `true` enables external reporting and generates a new token, returned in the response (any previous token stops working); `false` disables it and clears the token. IsExternalReportEnabled *bool `json:"is_external_report_enabled,omitempty" toon:"is_external_report_enabled,omitempty"` // When true, the channel is visible only to its managing teams. IsPrivate *bool `json:"is_private,omitempty" toon:"is_private,omitempty"` - // Additional teams that can manage the channel. Up to 3 entries. + // Replaces the additional managing teams, up to 3; every ID must exist. Pass `[]` to remove them all; omit to keep the current list. ManagingTeamIDs []int64 `json:"managing_team_ids,omitempty" toon:"managing_team_ids,omitempty"` - // New owning team ID; obtain it from `POST /team/list`. + // New owning team ID; obtain it from `POST /team/list`. Must exist. Omit or pass `null` to keep the current team. TeamID *int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` } // UpdateChannelResponse is generated from the Flashduty OpenAPI schema. type UpdateChannelResponse struct { - // Newly generated token for external reporters. Only returned when `is_external_report_enabled` is set to `true` in the request. Callers should store this value; it cannot be retrieved afterwards. + // Newly generated token for external reporters; the previous token stops working. It can be read again later from `external_report_token` in `POST /channel/info`. ExternalReportToken string `json:"external_report_token" toon:"external_report_token"` } @@ -11607,9 +12069,9 @@ type UpdateChannelResponse struct { type UpdateDropRuleRequest struct { // Owning channel ID; obtain it from `POST /channel/list`. ChannelID int64 `json:"channel_id" toon:"channel_id"` - // Rule description, up to 500 characters. + // Rule description, up to 500 characters. Omitting it clears the stored description. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Alert event match conditions (OR-of-AND); matching events are discarded entirely. When empty, the rule matches nothing. + // Alert event conditions (OR of AND groups); matching events are discarded entirely. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`. The stored conditions are replaced; omitting this field clears them and the rule then matches nothing. Filters FilterGroup `json:"filters,omitempty" toon:"filters,omitempty"` // Drop rule ID (MongoDB ObjectID). RuleID string `json:"rule_id" toon:"rule_id"` @@ -11619,35 +12081,35 @@ type UpdateDropRuleRequest struct { // UpdateEscalationRuleRequest is generated from the Flashduty OpenAPI schema. type UpdateEscalationRuleRequest struct { - // Delay window in seconds. 0 disables delay. + // Delay in seconds before the first notification for a newly assigned incident; `0` notifies immediately. Omitting it resets the value to `0`. AggrWindow int64 `json:"aggr_window,omitempty" toon:"aggr_window,omitempty"` // Owning channel ID; obtain it from `POST /channel/list`. ChannelID int64 `json:"channel_id" toon:"channel_id"` - // Rule description, up to 500 characters. + // Rule description, up to 500 characters. Omitting it clears the stored description. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Incident-level match conditions (OR-of-AND tree): the rule is matched against the incident the alert was grouped into, not against the alert itself. Omit or leave empty to apply the rule to all incidents in the channel. + // Incident conditions (OR of AND groups), matched against the incident the alert was grouped into, not against the alert. Keys: `title`, `description`, `severity` (alias `incident_severity`, `alert_severity`), `status` (alias `incident_status`, `alert_status`), `dedup_key`, `integration_id` (alias `data_source_id`), or any `labels.`. Replaces the stored conditions; omit or leave empty to match every incident in the channel. Filters FilterGroup `json:"filters,omitempty" toon:"filters,omitempty"` // Escalation levels in order. At least one level is required. Layers []EscalateLayer `json:"layers" toon:"layers"` - // Evaluation priority. Lower runs first. + // Evaluation order; lower values are evaluated first. Omit or pass `null` to keep the current value. Priority *int64 `json:"priority,omitempty" toon:"priority,omitempty"` // Escalation rule ID (MongoDB ObjectID). RuleID string `json:"rule_id" toon:"rule_id"` // Rule name, 1 to 39 characters. RuleName string `json:"rule_name" toon:"rule_name"` - // Notification template ID (MongoDB ObjectID). + // Notification template ID (24-character hex); obtain it from `POST /template/list`. Must exist. TemplateID string `json:"template_id" toon:"template_id"` - // Optional recurring time windows during which the rule applies. + // Recurring time windows during which the rule can match. Replaces the stored windows; omit or leave empty to match at any time. TimeFilters []TimeFilter `json:"time_filters,omitempty" toon:"time_filters,omitempty"` } // UpdateFieldRequest is generated from the Flashduty OpenAPI schema. type UpdateFieldRequest struct { - // Replacement default value. Type must match the field's existing `field_type`. + // New default value; its type must match the field's `field_type`. Always written: omitting it clears the default. DefaultValue any `json:"default_value,omitempty" toon:"default_value,omitempty"` - // New description. + // New description. Always written: omitting it clears the description. Description string `json:"description,omitempty" toon:"description,omitempty"` - // New display name. Must remain unique within the account. + // New display name (max 39 characters); must stay unique among non-deleted fields. Always written. DisplayName string `json:"display_name,omitempty" toon:"display_name,omitempty"` // Field ID — 24-character hex ObjectID. FieldID string `json:"field_id" toon:"field_id"` @@ -11661,7 +12123,7 @@ type UpdateIncidentCommentTypeRequest struct { Color string `json:"color,omitempty" toon:"color,omitempty"` // ID of the comment type to update (24-character hex ObjectID). CommentTypeID string `json:"comment_type_id" toon:"comment_type_id"` - // New display name. Trimmed before storing; must be unique within the account (case-insensitive). At most 40 characters. + // New display name. Trimmed before storing; must be unique within the account (case-insensitive). At most 40 characters. Must not contain control or text-direction characters. Name string `json:"name,omitempty" toon:"name,omitempty"` } @@ -11687,19 +12149,19 @@ type UpdateIncidentFieldsRequest struct { type UpdateInhibitRuleRequest struct { // Owning channel ID; obtain it from `POST /channel/list`. ChannelID int64 `json:"channel_id" toon:"channel_id"` - // Rule description, up to 500 characters. + // Rule description, up to 500 characters. Omitting it clears the stored description. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Field keys whose values must be equal between the source (inhibiting) alert and the target (suppressed) alert, e.g. `data_source_id` or `labels.cluster`. + // Keys whose values must be equal on the source alert and the incoming event. Only `title`, `severity` and `labels.` take effect; any other key (for example `data_source_id`) is accepted but makes the rule never fire. Must be present; an empty array also makes the rule inert. Equals []string `json:"equals" toon:"equals"` - // When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule. + // When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule. Omitting it sets it to `false`. IsDirectlyDiscard bool `json:"is_directly_discard,omitempty" toon:"is_directly_discard,omitempty"` // Inhibit rule ID (MongoDB ObjectID). RuleID string `json:"rule_id" toon:"rule_id"` // Rule name, 1 to 39 characters. RuleName string `json:"rule_name" toon:"rule_name"` - // Conditions the source alert must match, evaluated against stored active alerts. Supported keys: `status`, `incident_status`, `alert_status`, `severity`, `incident_severity`, `alert_severity`, `title`, `description`, or any `labels.`. Empty makes the rule inert. + // Conditions the source (inhibiting) alert must match, evaluated against active alerts already stored in the channel. Keys: `title`, `description`, `severity` (alias `incident_severity`, `alert_severity`), `status` (alias `incident_status`, `alert_status`), or any `labels.`. Empty makes the rule inert. Omitting it clears the stored conditions. SourceFilters FilterGroup `json:"source_filters,omitempty" toon:"source_filters,omitempty"` - // Conditions the incoming target alert event must match to be suppressed; empty means every event is a target. + // Conditions the incoming target alert event must match to be inhibited; empty means every incoming event is a target. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`. Omitting it clears the stored conditions. TargetFilters FilterGroup `json:"target_filters,omitempty" toon:"target_filters,omitempty"` } @@ -11707,7 +12169,7 @@ type UpdateInhibitRuleRequest struct { type UpdateIntegrationRequest struct { // New description, at most 499 characters. Description *string `json:"description,omitempty" toon:"description,omitempty"` - // Integration ID. + // ID of a public integration, returned by `POST /integration/list`. An unknown ID or a channel-owned integration returns `ResourceNotFound`. IntegrationID int64 `json:"integration_id" toon:"integration_id"` // Run the plugin test when submitting `settings`; no test is performed for a metadata-only update. IsTest bool `json:"is_test,omitempty" toon:"is_test,omitempty"` @@ -11721,16 +12183,17 @@ type UpdateIntegrationRequest struct { // UpdateRemoteConfigRequest is generated from the Flashduty OpenAPI schema. type UpdateRemoteConfigRequest struct { - // RUM application ID. - ApplicationID string `json:"application_id" toon:"application_id"` - Config RemoteConfig `json:"config" toon:"config"` - // Operator's note on why this version was published. Stored verbatim. + // RUM application ID. Get application IDs via `POST /rum/application/list`. + ApplicationID string `json:"application_id" toon:"application_id"` + // The complete configuration to publish. + Config RemoteConfig `json:"config" toon:"config"` + // Optional free-text note (not an enum) on why this version was published, at most 255 characters; stored verbatim and returned as `reason` by `POST /rum/application/remote-config/history/list`. Reason string `json:"reason,omitempty" toon:"reason,omitempty"` } // UpdateRemoteConfigResponse is generated from the Flashduty OpenAPI schema. type UpdateRemoteConfigResponse struct { - // New published version number. + // Version number allocated to the published configuration (previous highest version + 1). Version int64 `json:"version" toon:"version"` } @@ -11738,13 +12201,13 @@ type UpdateRemoteConfigResponse struct { type UpdateSilenceRuleRequest struct { // Owning channel ID; obtain it from `POST /channel/list`. ChannelID int64 `json:"channel_id" toon:"channel_id"` - // Rule description, up to 500 characters. + // Rule description, up to 500 characters. Omitting it clears the stored description. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Match conditions for the alerts to silence; required and must not be empty. + // Alert event conditions (OR of AND groups); matching events are silenced while the time window is active. Required, with at least one condition. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`. Filters FilterGroup `json:"filters,omitempty" toon:"filters,omitempty"` - // When true, the silence rule is automatically deleted after its time window expires. Defaults to false. + // When true, a rule with a one-off `time_filter` is permanently removed about 24 hours after `end_time` (or after its last update, whichever is later). Rules created with `from_incident_id` are cleaned up the same way. Rules with recurring `time_filters` are never removed automatically. Omitting it sets it to `false`. IsAutoDelete bool `json:"is_auto_delete,omitempty" toon:"is_auto_delete,omitempty"` - // When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule. + // When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as silenced by this rule. Omitting it sets it to `false`. IsDirectlyDiscard bool `json:"is_directly_discard,omitempty" toon:"is_directly_discard,omitempty"` // Silence rule ID (MongoDB ObjectID). RuleID string `json:"rule_id" toon:"rule_id"` @@ -11760,11 +12223,11 @@ type UpdateSilenceRuleRequest struct { type UpdateStatusPageChangeRequest struct { // Target change ID; obtain it from `GET /status-page/change/list`. ChangeID int64 `json:"change_id" toon:"change_id"` - // Linked event IDs. Pass the full replacement list. + // Linked event IDs, replacing the current list. An omitted or empty array keeps the current list. LinkedChanges []string `json:"linked_changes,omitempty" toon:"linked_changes,omitempty"` // Status page ID; obtain it from `GET /status-page/list`. PageID int64 `json:"page_id" toon:"page_id"` - // Member IDs responsible for this event. Pass the full replacement list. + // Member IDs responsible for this event, replacing the current list. An omitted or empty array keeps the current list. Responders []int64 `json:"responders,omitempty" toon:"responders,omitempty"` // New event title, up to 255 characters. Omit to keep the existing value. Title *string `json:"title,omitempty" toon:"title,omitempty"` @@ -11772,11 +12235,11 @@ type UpdateStatusPageChangeRequest struct { // UpdateStatusPageChangeTimelineRequest is generated from the Flashduty OpenAPI schema. type UpdateStatusPageChangeTimelineRequest struct { - // New update timestamp in Unix seconds. + // New update time in Unix seconds; must not be earlier than the previous entry or later than the next one. Omit or pass 0 to keep the current time. AtSeconds int64 `json:"at_seconds,omitempty" toon:"at_seconds,omitempty"` // Owning change ID; obtain it from `GET /status-page/change/list`. ChangeID int64 `json:"change_id" toon:"change_id"` - // New update description (Markdown). + // New update description (Markdown). Omit or pass an empty string to keep the current text; editing the latest entry also updates the event description. Description string `json:"description,omitempty" toon:"description,omitempty"` // Status page ID; obtain it from `GET /status-page/list`. PageID int64 `json:"page_id" toon:"page_id"` @@ -11788,15 +12251,15 @@ type UpdateStatusPageChangeTimelineRequest struct { type UpdateStatusPageRequest struct { // Get-in-touch contact, such as a mailto or website URL. Omit or pass null to keep the existing value. ContactInfo *string `json:"contact_info,omitempty" toon:"contact_info,omitempty"` - // Custom domain for a public status page. Omit or pass null to keep the existing value. + // Custom domain for a public status page; must not be used by another status page. Rejected for internal pages. Omit or pass null to keep the existing value; an empty string removes the domain. CustomDomain *string `json:"custom_domain,omitempty" toon:"custom_domain,omitempty"` // Custom navigation links shown on the status page. Omit or pass an empty array to keep the current links. CustomLinks []map[string]string `json:"custom_links,omitempty" toon:"custom_links,omitempty"` // Dark-mode logo image of the status page. Omit or pass null to keep the existing value. DarkLogo *string `json:"dark_logo,omitempty" toon:"dark_logo,omitempty"` - // How change dates are displayed. Leave empty to keep the current value. `calendar` uses a calendar view; `list` uses a list view. + // How event dates are displayed: `calendar` uses a calendar view, `list` uses a list view. Omit or pass null to keep the current value; an empty string clears the setting. DateView *string `json:"date_view,omitempty" toon:"date_view,omitempty"` - // How uptime is displayed. Leave empty to keep the current value. `chart_and_percentage` shows both chart and percentage; `chart` shows only the chart; `none` hides uptime. + // How uptime is displayed: `chart_and_percentage` shows the chart and the percentage, `chart` shows only the chart, `none` hides uptime. Omit or pass null to keep the current value; an empty string clears the setting. DisplayUptimeMode *string `json:"display_uptime_mode,omitempty" toon:"display_uptime_mode,omitempty"` // Favicon of the status page. Omit or pass null to keep the existing value. Favicon *string `json:"favicon,omitempty" toon:"favicon,omitempty"` @@ -11812,27 +12275,31 @@ type UpdateStatusPageRequest struct { PageHeader *string `json:"page_header,omitempty" toon:"page_header,omitempty"` // Status page ID; obtain it from `GET /status-page/list`. PageID int64 `json:"page_id" toon:"page_id"` - // Browser title shown for the status page. Omit or pass null to keep the existing value. + // Accepted for compatibility but not stored; it has no effect. PageTitle *string `json:"page_title,omitempty" toon:"page_title,omitempty"` - // Subscription channel toggles. Omit or pass null to keep the existing value. + // Subscription channel toggles. A public page can enable only `email` and an internal page only `im`. Omit or pass null to keep the existing value. Subscription StatusPageSubscriptionItem `json:"subscription,omitzero" toon:"subscription,omitempty"` - // Preferred event template type: `pre_defined` or `message`. Omit or pass null to keep the existing value. + // Event template mode used when publishing events in the console: `message` (status descriptions: per-status texts) or `pre_defined` (full status updates: complete examples with title, status, and description). Omit or pass null to keep the current value; the value is not validated. TemplatePreference *string `json:"template_preference,omitempty" toon:"template_preference,omitempty"` - // URL-safe slug, unique per account and page type. Omit or pass null to keep the existing value. + // URL-safe slug; normalized to lowercase with non-alphanumeric characters replaced by hyphens, and must be unique among the account's pages of the same type. Omit or pass null to keep the existing value. URLName *string `json:"url_name,omitempty" toon:"url_name,omitempty"` } // UpdateWorkItemRequest is generated from the Flashduty OpenAPI schema. type UpdateWorkItemRequest struct { - // New description (max 65,535 characters). + // New description, at most 65,535 characters; `""` clears it. `null` or omitted keeps the current value. Description *string `json:"description,omitempty" toon:"description,omitempty"` - // New client-defined priority (max 64 characters). + // New free-form priority, at most 64 characters; `""` clears it. `null` or omitted keeps the current value. Priority *string `json:"priority,omitempty" toon:"priority,omitempty"` - // New status. One of `open`, `in_progress`, `done`, `cancelled`. + // New status. `null` or omitted keeps the current status. + // - `open`: not started. + // - `in_progress`: being worked on. + // - `done`: finished. + // - `cancelled`: no longer needed. Status *string `json:"status,omitempty" toon:"status,omitempty"` - // New title (max 512 characters). + // New title, at most 512 characters; trimmed and must not be blank. `null` or omitted keeps the current title. Title *string `json:"title,omitempty" toon:"title,omitempty"` - // Current item version for optimistic locking. Must match the stored version. + // The item's current `version` (≥ 1) for optimistic locking. Version int64 `json:"version" toon:"version"` // Work item ID (opaque string, max 128 characters). WorkItemID string `json:"work_item_id" toon:"work_item_id"` @@ -11840,17 +12307,17 @@ type UpdateWorkItemRequest struct { // UpsertPostMortemTemplateRequest is generated from the Flashduty OpenAPI schema. type UpsertPostMortemTemplateRequest struct { - // BlockNote JSON template content. + // Template body as BlockNote editor JSON (an array of blocks), serialized as a string. New reports created from this template start from this body. Content string `json:"content" toon:"content"` - // Markdown version of the template content. + // Markdown version of the body, used as the outline when AI generates a report. Empty when omitted. ContentMarkdown string `json:"content_markdown,omitempty" toon:"content_markdown,omitempty"` - // Template description. + // Template description; empty when omitted. Description string `json:"description,omitempty" toon:"description,omitempty"` - // Template name. + // Template name shown in the console. Name string `json:"name" toon:"name"` - // Managing team ID. Required when creating a custom template. + // Managing team ID. Required when creating; the team must exist. On update, a different team ID moves the template; omit it or send 0 to keep the current team. TeamID int64 `json:"team_id,omitempty" toon:"team_id,omitempty"` - // Template ID. Omit to create a new template; provide it to update an existing template. + // ID of the custom template to replace. Omit it to create a new template (the server generates the ID). TemplateID string `json:"template_id,omitempty" toon:"template_id,omitempty"` } @@ -11858,13 +12325,13 @@ type UpsertPostMortemTemplateRequest struct { type UpsertRouteRequest struct { // Ordered list of case branches. Cases are evaluated top to bottom. Cases []RouteCase `json:"cases,omitempty" toon:"cases,omitempty"` - // Fallback branch used when no case matches. + // Fallback branch used when no case yields a channel. Omitting it removes any existing default branch. Default RouteDefault `json:"default,omitzero" toon:"default,omitempty"` - // Integration the rule belongs to. + // Shared integration ID; obtain it from `POST /integration/list`. Channel-exclusive integrations are rejected with `InvalidParameter`. IntegrationID int64 `json:"integration_id" toon:"integration_id"` // Optional sections that group consecutive cases for display. Sections []RouteSection `json:"sections,omitempty" toon:"sections,omitempty"` - // Reserved for optimistic concurrency control; currently ignored — the server increments `version` automatically on every upsert. + // Ignored. The server increments `version` on every upsert and does not compare it with this value. Version int64 `json:"version,omitempty" toon:"version,omitempty"` } @@ -11932,7 +12399,7 @@ type WarRoom struct { type WarRoomDataSourceItem struct { // Account this integration belongs to. AccountID int64 `json:"account_id" toon:"account_id"` - // Plugin category; `im` for the IM integrations returned here. + // Plugin category. Always `im`, because this endpoint returns only IM integrations. Category string `json:"category" toon:"category"` // Unix timestamp in seconds when the integration was created. CreatedAt Timestamp `json:"created_at" toon:"created_at"` @@ -11942,9 +12409,9 @@ type WarRoomDataSourceItem struct { DataSourceID int64 `json:"data_source_id" toon:"data_source_id"` // Integration description. Description string `json:"description" toon:"description"` - // Legacy exclusive-integration linkage; deprecated. + // Deprecated; always `0` in this response. ExclusiveDataSourceID int64 `json:"exclusive_data_source_id" toon:"exclusive_data_source_id"` - // Integration ID, alias of data_source_id. + // Integration ID; same value as `data_source_id`. IntegrationID int64 `json:"integration_id" toon:"integration_id"` // Push key used by alert sources to send to this integration. IntegrationKey string `json:"integration_key" toon:"integration_key"` @@ -11956,13 +12423,13 @@ type WarRoomDataSourceItem struct { NoEditable bool `json:"no_editable" toon:"no_editable"` // Plugin ID backing this integration. PluginID int64 `json:"plugin_id" toon:"plugin_id"` - // Plugin type identifier of the IM integration, for example `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, or `teams_app`. + // IM integration type: `feishu_app` Feishu (Lark), `dingtalk_app` DingTalk, `wecom_app` WeCom, `slack_app` Slack, `teams_app` Microsoft Teams. PluginType string `json:"plugin_type" toon:"plugin_type"` // Localized display name of the integration plugin type. PluginTypeName string `json:"plugin_type_name" toon:"plugin_type_name"` // External reference ID of the integration. RefID string `json:"ref_id" toon:"ref_id"` - // Plugin-specific configuration of the integration. + // Plugin-specific configuration of the integration; includes `war_room_enabled: true`. Secret values are masked as `******`. Settings map[string]any `json:"settings" toon:"settings"` // Integration status: `enabled` or `disabled`. Deleted integrations are never returned. Status string `json:"status" toon:"status"` @@ -11976,13 +12443,13 @@ type WarRoomDataSourceItem struct { // WarRoomItem is generated from the Flashduty OpenAPI schema. type WarRoomItem struct { - // Account ID. + // ID of the account that owns this record; the same for every record returned to one `app_key`. AccountID int64 `json:"account_id" toon:"account_id"` // Chat/group ID on the IM side. ChatID string `json:"chat_id" toon:"chat_id"` // Display name of the group chat on the IM side. ChatName string `json:"chat_name" toon:"chat_name"` - // Creation timestamp (seconds). + // Unix timestamp (seconds) when the war room was created. CreatedAt Timestamp `json:"created_at" toon:"created_at"` // Member ID that created the war room. CreatedBy int64 `json:"created_by" toon:"created_by"` @@ -11992,9 +12459,9 @@ type WarRoomItem struct { IntegrationID int64 `json:"integration_id" toon:"integration_id"` // True when the IM integration behind this war room is disabled or no longer exists. IntegrationUnavailable bool `json:"integration_unavailable" toon:"integration_unavailable"` - // IM plugin type (e.g. `feishu`, `dingtalk`, `wecom`, `slack`). + // Plugin type of the IM integration: `feishu_app` (Feishu), `dingtalk_app` (DingTalk), `wecom_app` (WeCom), or `slack_app` (Slack). Empty string when the integration no longer exists. PluginType string `json:"plugin_type" toon:"plugin_type"` - // War room record status: `enabled` active, `deleted` disbanded. + // Record status. Always `enabled` in this list, because deleted war rooms are not returned. Status string `json:"status" toon:"status"` } @@ -12002,63 +12469,68 @@ type WarRoomItem struct { type WarRoomPersonItem struct { // Account this person belongs to. AccountID int64 `json:"account_id" toon:"account_id"` - // Role the person holds in the related context. + // Identity type of the person. + // - `account`: the account owner. + // - `member`: a regular member of the account. As string `json:"as" toon:"as"` // URL of the person's avatar image. Avatar string `json:"avatar" toon:"avatar"` - // Email address of the person. + // Email address; omitted when the member has not verified it. Email string `json:"email" toon:"email"` - // Preferred language locale of the person. + // Preferred language, e.g. `zh-CN` or `en-US`. Locale string `json:"locale" toon:"locale"` - // Person ID. + // Person ID: a member ID, or the account ID when the person is the account owner (`as` = `account`). PersonID int64 `json:"person_id" toon:"person_id"` // Display name of the person. PersonName string `json:"person_name" toon:"person_name"` - // Phone number of the person. + // Phone number; omitted when the member has not verified it. Phone string `json:"phone" toon:"phone"` - // Current status of the person. + // Membership status. + // - `enabled`: active. + // - `pending`: invited but has not joined yet. + // - `deleted`: removed from the account. Status string `json:"status" toon:"status"` - // Time zone of the person. + // IANA time zone name, e.g. `Asia/Shanghai`. TimeZone string `json:"time_zone" toon:"time_zone"` } // WebhookHistoryDetail is generated from the Flashduty OpenAPI schema. type WebhookHistoryDetail struct { - // Attempt sequence number. + // Number of HTTP tries made for this delivery; retries happen only on connection errors. Attempt int64 `json:"attempt" toon:"attempt"` // Channel ID when applicable. ChannelID int64 `json:"channel_id" toon:"channel_id"` // Name of the associated channel, resolved at query time. ChannelName string `json:"channel_name" toon:"channel_name"` - // Total elapsed time of the attempt in milliseconds. + // Total time of the delivery including retries, in milliseconds. Duration int64 `json:"duration" toon:"duration"` // Destination URL. Endpoint string `json:"endpoint" toon:"endpoint"` - // Error message when delivery failed. + // Error text when the delivery failed (connection error or unexpected status code), truncated. Omitted on success. ErrorMessage string `json:"error_message" toon:"error_message"` - // Event ID. + // ID of this delivery record: the delivery date (`YYYYMMDD`) followed by a random suffix. Pass it to `POST /webhook/history/detail`. EventID string `json:"event_id" toon:"event_id"` // Event time formatted as `YYYY-MM-DD HH:MM:SS.ffffff`. EventTime string `json:"event_time" toon:"event_time"` // Event type code. `i_*` values are incident events (for example `i_new` = incident created); `a_*` values are alert events (for example `a_new` = alert triggered). EventType string `json:"event_type" toon:"event_type"` - // Integration ID. + // ID of the webhook integration that sent the request. IntegrationID int64 `json:"integration_id" toon:"integration_id"` // Source object ID. RefID string `json:"ref_id" toon:"ref_id"` // Title of the source incident or alert, resolved at query time. RefTitle string `json:"ref_title" toon:"ref_title"` - // Outbound request body payload. + // JSON payload sent to the endpoint, truncated to the stored size limit. RequestBody string `json:"request_body" toon:"request_body"` // Serialized outbound request headers. RequestHeaders string `json:"request_headers" toon:"request_headers"` - // Response body. + // Body returned by the endpoint, truncated to the stored size limit. Omitted when empty or when no response was received. ResponseBody string `json:"response_body" toon:"response_body"` // Serialized response headers. ResponseHeaders string `json:"response_headers" toon:"response_headers"` - // Delivery outcome. + // Delivery outcome: `success` when the endpoint answered HTTP 200; `failed` on a connection error or any other status code. Status string `json:"status" toon:"status"` - // HTTP status code. + // HTTP status code returned by the endpoint; `0` when no response was received. StatusCode int64 `json:"status_code" toon:"status_code"` // Source object kind: `incident` or `alert`. WebhookType string `json:"webhook_type" toon:"webhook_type"` @@ -12066,37 +12538,37 @@ type WebhookHistoryDetail struct { // WebhookHistoryItem is generated from the Flashduty OpenAPI schema. type WebhookHistoryItem struct { - // Attempt sequence number. + // Number of HTTP tries made for this delivery; retries happen only on connection errors. Attempt int64 `json:"attempt" toon:"attempt"` // Channel ID associated with the event, when applicable. ChannelID int64 `json:"channel_id" toon:"channel_id"` - // Total elapsed time of the attempt in milliseconds. + // Total time of the delivery including retries, in milliseconds. Duration int64 `json:"duration" toon:"duration"` // Destination URL. Endpoint string `json:"endpoint" toon:"endpoint"` - // Error message when delivery failed. + // Error text when the delivery failed (connection error or unexpected status code), truncated. Omitted on success. ErrorMessage string `json:"error_message" toon:"error_message"` - // Unique event identifier for the delivery attempt. + // ID of this delivery record: the delivery date (`YYYYMMDD`) followed by a random suffix. Pass it to `POST /webhook/history/detail`. EventID string `json:"event_id" toon:"event_id"` // Event time formatted as `YYYY-MM-DD HH:MM:SS.ffffff`. EventTime string `json:"event_time" toon:"event_time"` // Event type code. `i_*` values are incident events (for example `i_new` = incident created); `a_*` values are alert events (for example `a_new` = alert triggered). EventType string `json:"event_type" toon:"event_type"` - // Integration ID that triggered the webhook. + // ID of the webhook integration that sent the request. IntegrationID int64 `json:"integration_id" toon:"integration_id"` // Source object ID (incident ID or alert ID). RefID string `json:"ref_id" toon:"ref_id"` - // Outbound request body payload. + // JSON payload sent to the endpoint, truncated to the stored size limit. RequestBody string `json:"request_body" toon:"request_body"` // Serialized outbound request headers. RequestHeaders string `json:"request_headers" toon:"request_headers"` - // Response body returned by the destination. + // Body returned by the endpoint, truncated to the stored size limit. Omitted when empty or when no response was received. ResponseBody string `json:"response_body" toon:"response_body"` // Serialized response headers from the destination. ResponseHeaders string `json:"response_headers" toon:"response_headers"` - // Delivery outcome. + // Delivery outcome: `success` when the endpoint answered HTTP 200; `failed` on a connection error or any other status code. Status string `json:"status" toon:"status"` - // HTTP status code returned by the destination. + // HTTP status code returned by the endpoint; `0` when no response was received. StatusCode int64 `json:"status_code" toon:"status_code"` // Source object kind: `incident` or `alert`. WebhookType string `json:"webhook_type" toon:"webhook_type"` @@ -12112,7 +12584,7 @@ type WorkItemAssignee struct { // WorkItemCreateResult is generated from the Flashduty OpenAPI schema. type WorkItemCreateResult struct { - // Assignee member IDs that were newly added (and notified). + // Member IDs of the person assignees added by this call (and notified); AI SRE is not included. Omitted when none. AddedAssigneeIDs []int64 `json:"added_assignee_ids" toon:"added_assignee_ids"` // True when the call replayed an earlier request with the same idempotency key and no new item was created. IdempotentReplay bool `json:"idempotent_replay" toon:"idempotent_replay"` @@ -12141,17 +12613,19 @@ type WorkItemItem struct { Description string `json:"description" toon:"description"` // Incident ID (MongoDB ObjectID) the item is anchored to. IncidentID string `json:"incident_id" toon:"incident_id"` - // `action` for an item anchored to an active incident; `follow_up` for a post-mortem follow-up. + // Work item type. + // - `action`: a to-do on an incident that is not closed yet. + // - `follow_up`: a post-mortem follow-up, created on a closed incident or converted from an action. ItemType string `json:"item_type" toon:"item_type"` // Original identifier of the legacy follow-up this item was migrated from. Present only when `source_kind` is `legacy_follow_up`. LegacySourceID string `json:"legacy_source_id" toon:"legacy_source_id"` - // Post-mortem ID (32-character hex string). Present on follow-up items once bound to a post-mortem. + // Post-mortem ID (32-character hex string). Present only on follow-ups bound to a report; omitted otherwise. PostMortemID string `json:"post_mortem_id" toon:"post_mortem_id"` - // Optional client-defined priority (max 64 characters). + // Free-form priority, at most 64 characters; omitted when empty. The console uses `high`, `medium` and `low`, but any string set through the API is returned as-is. Priority string `json:"priority" toon:"priority"` // `native` for items created through this API; `legacy_follow_up` for items migrated from legacy post-mortem follow-ups. SourceKind string `json:"source_kind" toon:"source_kind"` - // Client-defined status (max 64 characters). There is no fixed state machine. + // Item status: `open` (not started), `in_progress` (being worked on), `done` (finished) or `cancelled` (no longer needed). `done` and `cancelled` count as finished. Older items may still hold other free text, which counts as unfinished. Status string `json:"status" toon:"status"` // Item title (max 512 characters). Title string `json:"title" toon:"title"` @@ -12179,12 +12653,12 @@ type WorkItemListResult struct { // WorkItemMutationResult is generated from the Flashduty OpenAPI schema. type WorkItemMutationResult struct { - // Assignee member IDs that were newly added (and notified). + // Member IDs of the person assignees added by this call (and notified); AI SRE is not included. Omitted when none. AddedAssigneeIDs []int64 `json:"added_assignee_ids" toon:"added_assignee_ids"` // True when the call replayed an earlier request with the same idempotency key. IdempotentReplay bool `json:"idempotent_replay" toon:"idempotent_replay"` Item WorkItemItem `json:"item" toon:"item"` - // Assignee member IDs that were removed (never notified). + // Member IDs of the person assignees removed by this call (never notified). Omitted when none. RemovedAssigneeIDs []int64 `json:"removed_assignee_ids" toon:"removed_assignee_ids"` } @@ -12192,19 +12666,19 @@ type WorkItemMutationResult struct { type AccountInfoRestrictions struct { // Whether subdomains of the allowed email domains are also accepted. AllowSubdomain bool `json:"allow_subdomain" toon:"allow_subdomain"` - // Allowed login email domains. + // Email domains allowed for new members; invitations to other domains are rejected. `null` or empty when unrestricted. EmailDomains []string `json:"email_domains" toon:"email_domains"` - // Allowed source IP/CIDR whitelist. + // Source IP addresses or CIDR ranges allowed to call the console and API for this account; `null` or empty when unrestricted. Ips []string `json:"ips" toon:"ips"` } // AddIncidentResponderRequestNotify is generated from the Flashduty OpenAPI schema. type AddIncidentResponderRequestNotify struct { - // When false, use `personal_channels`; when true or omitted, use each responder's personal preference. + // `true`: notify each person through their personal notification preference. `false`: use `personal_channels`, which must then be non-empty. When omitted, `personal_channels` must be set. FollowPreference *bool `json:"follow_preference,omitempty" toon:"follow_preference,omitempty"` - // Channels to use (e.g. `voice`, `sms`, `email`). + // Channels used when `follow_preference` is `false`: `sms`, `voice`, `email`, `push` (mobile app push), or an IM app channel written as `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:`, or `teams_app:`. Ignored when `follow_preference` is `true`. PersonalChannels []string `json:"personal_channels,omitempty" toon:"personal_channels,omitempty"` - // Notification template ID (MongoDB ObjectID). + // Notification template ID, as returned by the notification template endpoints. Must exist in the account; otherwise the call fails with `InvalidParameter`. TemplateID string `json:"template_id,omitempty" toon:"template_id,omitempty"` } @@ -12244,19 +12718,19 @@ type AlertRuleConfigsV2RelateQueriesItem struct { // AlertRuleV2EnabledTimesItem is generated from the Flashduty OpenAPI schema. type AlertRuleV2EnabledTimesItem struct { - // Days of week (0=Sunday). + // Days of week the window applies to, `0` = Sunday through `6` = Saturday; non-empty, no duplicates. Days []int64 `json:"days,omitempty" toon:"days,omitempty"` - // End time, e.g. `18:00`. + // End time in 24-hour `HH:MM` format, e.g. `18:00`. Etime string `json:"etime,omitempty" toon:"etime,omitempty"` - // Start time, e.g. `09:00`. + // Start time in 24-hour `HH:MM` format, e.g. `09:00`. Stime string `json:"stime,omitempty" toon:"stime,omitempty"` } // AssignedToNotify is generated from the Flashduty OpenAPI schema. type AssignedToNotify struct { - // When false, use `personal_channels`; when true or omitted, use each responder's personal preference. + // `true`: notify each person through their personal notification preference. `false`: use `personal_channels`, which must then be non-empty. When omitted, `personal_channels` must be set. FollowPreference *bool `json:"follow_preference,omitempty" toon:"follow_preference,omitempty"` - // Channels to use (e.g. `voice`, `sms`, `email`). + // Channels used when `follow_preference` is `false`: `sms`, `voice`, `email`, `push` (mobile app push), or an IM app channel written as `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:`, or `teams_app:`. Ignored when `follow_preference` is `true`. PersonalChannels []string `json:"personal_channels,omitempty" toon:"personal_channels,omitempty"` // Notification template ID (MongoDB ObjectID). TemplateID string `json:"template_id,omitempty" toon:"template_id,omitempty"` @@ -12270,98 +12744,42 @@ type AuditLogParamsItem struct { Value string `json:"Value" toon:"Value"` } -// CreateChannelRequestEscalateRule is generated from the Flashduty OpenAPI schema. -type CreateChannelRequestEscalateRule struct { - // Delay window in seconds. 0 disables delay. - AggrWindow int64 `json:"aggr_window,omitempty" toon:"aggr_window,omitempty"` - // Notification target. At least one of `person_ids`, `team_ids`, `schedule_to_role_ids`, or `emails` must be set, together with either `by` or `webhooks`. - Target CreateChannelRequestEscalateRuleTarget `json:"target" toon:"target"` - // Notification template ID (MongoDB ObjectID). - TemplateID string `json:"template_id" toon:"template_id"` -} - -// CreateChannelRequestFlapping is generated from the Flashduty OpenAPI schema. -type CreateChannelRequestFlapping struct { - // Observation window in minutes. - InMins int64 `json:"in_mins,omitempty" toon:"in_mins,omitempty"` - // Disable flapping detection. - IsDisabled bool `json:"is_disabled,omitempty" toon:"is_disabled,omitempty"` - // Max state changes allowed within `in_mins`. - MaxChanges int64 `json:"max_changes,omitempty" toon:"max_changes,omitempty"` - // Mute duration in minutes after flapping is detected. - MuteMins int64 `json:"mute_mins,omitempty" toon:"mute_mins,omitempty"` -} - -// CreateChannelRequestGroup is generated from the Flashduty OpenAPI schema. -type CreateChannelRequestGroup struct { - // When true, all listed keys must be present for grouping. - AllEqualsRequired bool `json:"all_equals_required,omitempty" toon:"all_equals_required,omitempty"` - // Per-filter grouping overrides. - Cases []CreateChannelRequestGroupCasesItem `json:"cases,omitempty" toon:"cases,omitempty"` - // Groups of label keys whose equality defines a bucket. - Equals [][]string `json:"equals,omitempty" toon:"equals,omitempty"` - // Label keys used for intelligent grouping embeddings. - IKeys []string `json:"i_keys,omitempty" toon:"i_keys,omitempty"` - // Intelligent grouping similarity threshold. - IScoreThreshold float64 `json:"i_score_threshold,omitempty" toon:"i_score_threshold,omitempty"` - // Grouping method: `i` intelligent, `p` pattern, `n` none. - Method string `json:"method" toon:"method"` - // Alert storm threshold. - StormThreshold int64 `json:"storm_threshold,omitempty" toon:"storm_threshold,omitempty"` - // Multi-level storm thresholds. - StormThresholds []int64 `json:"storm_thresholds,omitempty" toon:"storm_thresholds,omitempty"` - // Grouping time window in minutes. Default max is 1440 minutes (24 h); extended accounts may allow up to 43200 minutes (30 days). - TimeWindow int64 `json:"time_window,omitempty" toon:"time_window,omitempty"` - // Window type, default `tumbling`. `tumbling` is a fixed window counted from incident creation — once it expires, new alerts open a new incident; `sliding` is a sliding window counted from the incident's most recent alert, extended each time a new alert merges in. - WindowType string `json:"window_type,omitempty" toon:"window_type,omitempty"` -} - -// CreateDropRuleRequestFiltersItemItem is generated from the Flashduty OpenAPI schema. -type CreateDropRuleRequestFiltersItemItem struct { - // Field key (e.g. `alert_severity`, `labels.service`). - Key string `json:"key" toon:"key"` - // Filter operator. - Oper string `json:"oper" toon:"oper"` - // Values to match. - Vals []string `json:"vals" toon:"vals"` -} - -// CreateEscalationRuleRequestFiltersItemItem is generated from the Flashduty OpenAPI schema. -type CreateEscalationRuleRequestFiltersItemItem struct { - // Field key (e.g. `alert_severity`, `labels.service`). - Key string `json:"key" toon:"key"` - // Filter operator. - Oper string `json:"oper" toon:"oper"` - // Values to match. - Vals []string `json:"vals" toon:"vals"` +// AutomationRuleItemExecutionLocation is generated from the Flashduty OpenAPI schema. +type AutomationRuleItemExecutionLocation struct { + // Name of the bound chat. Present only when `place=im` and the name is known. + ChatName string `json:"chat_name" toon:"chat_name"` + // Conversation type of the bound chat: `direct` (one-to-one chat with the bot), `group_chat` (a group chat), `group_thread` (a thread in a group chat), `war_room_chat` (an incident war room). Present only when `place=im`. + ConversationMode string `json:"conversation_mode" toon:"conversation_mode"` + // Human-readable destination label: `Web console` for web console rules, otherwise the chat name or platform and conversation type. + Description string `json:"description" toon:"description"` + // Same as the rule's `execution_place`: `web_console` runs in a web console session, `im` runs in the bound IM chat. + Place string `json:"place" toon:"place"` + // IM platform of the bound chat: `feishu` (Feishu/Lark), `dingtalk` (DingTalk), `wecom` (WeCom), `slack` (Slack), `teams` (Microsoft Teams). Present only when `place=im`. + Platform string `json:"platform" toon:"platform"` + // `person`: runs as the owner; `team`: runs under the team in `team_id`. + RunScope string `json:"run_scope" toon:"run_scope"` + // Team the runs belong to; `0` for a personal rule. + TeamID int64 `json:"team_id" toon:"team_id"` } -// CreateEscalationRuleRequestLayersItem is generated from the Flashduty OpenAPI schema. -type CreateEscalationRuleRequestLayersItem struct { - // Wait before moving to the next level, in minutes. - EscalateWindow int64 `json:"escalate_window,omitempty" toon:"escalate_window,omitempty"` - // When true, always escalate regardless of acknowledgement. - ForceEscalate bool `json:"force_escalate,omitempty" toon:"force_escalate,omitempty"` - // Max repeat notifications within the level. - MaxTimes int64 `json:"max_times,omitempty" toon:"max_times,omitempty"` - // Repeat interval in minutes. - NotifyStep float64 `json:"notify_step,omitempty" toon:"notify_step,omitempty"` - // Notification target. At least one of `person_ids`, `team_ids`, `schedule_to_role_ids`, or `emails` must be set, together with either `by` or `webhooks`. - Target CreateEscalationRuleRequestLayersItemTarget `json:"target" toon:"target"` +// AutomationRuleItemLastRun is generated from the Flashduty OpenAPI schema. +type AutomationRuleItemLastRun struct { + // Run ID, as in List Automation runs. + RunID string `json:"run_id" toon:"run_id"` + // Start time, Unix milliseconds. + StartedAt TimestampMilli `json:"started_at" toon:"started_at"` + // Run status, same meanings as `status` in List Automation runs: `queued`, `running`, `retrying` (in progress); `succeeded`, `partial`, `failed`, `skipped` (did not execute or merged into another run), `abandoned` (never completed), `blocked` (ended waiting on a connector authorization). + Status string `json:"status" toon:"status"` } -// CreateEscalationRuleRequestTimeFiltersItem is generated from the Flashduty OpenAPI schema. -type CreateEscalationRuleRequestTimeFiltersItem struct { - // Optional calendar ID; restricts the window to days matching the calendar. - CalID string `json:"cal_id,omitempty" toon:"cal_id,omitempty"` - // End of the window in `HH:MM`. - End string `json:"end,omitempty" toon:"end,omitempty"` - // When true, match days marked as days-off in the calendar. - IsOff bool `json:"is_off,omitempty" toon:"is_off,omitempty"` - // Days of the week this window repeats on. Empty means every day. - Repeat []int64 `json:"repeat,omitempty" toon:"repeat,omitempty"` - // Start of the window in `HH:MM`. - Start string `json:"start,omitempty" toon:"start,omitempty"` +// CreateChannelRequestEscalateRule is generated from the Flashduty OpenAPI schema. +type CreateChannelRequestEscalateRule struct { + // Delay in seconds, 0–3600, before the first notification for a newly assigned incident; `0` notifies immediately. + AggrWindow int64 `json:"aggr_window,omitempty" toon:"aggr_window,omitempty"` + // Who to notify and through which channels. + Target EscalateTarget `json:"target" toon:"target"` + // Notification template ID (24-character hex); obtain it from `POST /template/list`. Must exist. + TemplateID string `json:"template_id" toon:"template_id"` } // CreateIncidentRequestAssignedTo is generated from the Flashduty OpenAPI schema. @@ -12370,42 +12788,20 @@ type CreateIncidentRequestAssignedTo struct { Emails []string `json:"emails,omitempty" toon:"emails,omitempty"` // Escalation rule ID (MongoDB ObjectID); assigns the people at the rule's `layer_idx` layer. EscalateRuleID string `json:"escalate_rule_id,omitempty" toon:"escalate_rule_id,omitempty"` - // Zero-based starting layer index of the escalation rule (default 0, the first layer); an out-of-range value returns an error. Only takes effect with `escalate_rule_id`. + // Zero-based escalation-rule layer to assign (default 0, the first layer). Used only with `escalate_rule_id`; an out-of-range value leaves the incident without responders instead of failing the request. LayerIdx int64 `json:"layer_idx,omitempty" toon:"layer_idx,omitempty"` // Override the notification channels used for this assignment. Notify CreateIncidentRequestAssignedToNotify `json:"notify,omitzero" toon:"notify,omitempty"` // Member IDs to assign directly (1–100). Can be combined with `escalate_rule_id`. PersonIDs []int64 `json:"person_ids,omitempty" toon:"person_ids,omitempty"` - // Assignment type, derived server-side — callers do not set it: `assign` for manual creation, `reassign` for re-assignment, `escalate` for escalation-driven assignment. - // | Value | Meaning | - // |---|---| - // | `assign` | Initial assignment when the incident is created manually. | - // | `reassign` | Re-assignment of an existing incident. | - // | `escalate` | Assignment triggered by escalation policy advancement. | - // | `reopen` | Assignment restarted from the first layer after the incident is reopened. | + // Assignment type. Normally omitted: the server then sets `assign`, because a manual create is always a first assignment. A value you send is stored as-is. + // - `assign`: first assignment of the incident. + // - `reassign`: assignment replacing an earlier one. + // - `escalate`: assignment triggered by escalation to the next layer. + // - `reopen`: assignment restarted from the first layer after the incident is reopened. Type string `json:"type,omitempty" toon:"type,omitempty"` } -// CreateInhibitRuleRequestSourceFiltersItemItem is generated from the Flashduty OpenAPI schema. -type CreateInhibitRuleRequestSourceFiltersItemItem struct { - // Field key (e.g. `alert_severity`, `labels.service`). - Key string `json:"key" toon:"key"` - // Filter operator. - Oper string `json:"oper" toon:"oper"` - // Values to match. - Vals []string `json:"vals" toon:"vals"` -} - -// CreateInhibitRuleRequestTargetFiltersItemItem is generated from the Flashduty OpenAPI schema. -type CreateInhibitRuleRequestTargetFiltersItemItem struct { - // Field key (e.g. `alert_severity`, `labels.service`). - Key string `json:"key" toon:"key"` - // Filter operator. - Oper string `json:"oper" toon:"oper"` - // Values to match. - Vals []string `json:"vals" toon:"vals"` -} - // CreateIntegrationResponseTest is generated from the Flashduty OpenAPI schema. type CreateIntegrationResponseTest struct { // Test failure message; empty on success. @@ -12414,38 +12810,6 @@ type CreateIntegrationResponseTest struct { Success bool `json:"success" toon:"success"` } -// CreateSilenceRuleRequestFiltersItemItem is generated from the Flashduty OpenAPI schema. -type CreateSilenceRuleRequestFiltersItemItem struct { - // Field key (e.g. `alert_severity`, `labels.service`). - Key string `json:"key" toon:"key"` - // Filter operator. - Oper string `json:"oper" toon:"oper"` - // Values to match. - Vals []string `json:"vals" toon:"vals"` -} - -// CreateSilenceRuleRequestTimeFilter is generated from the Flashduty OpenAPI schema. -type CreateSilenceRuleRequestTimeFilter struct { - // Window end, Unix timestamp in seconds. Must be greater than 0. - EndTime int64 `json:"end_time" toon:"end_time"` - // Window start, Unix timestamp in seconds. Must be greater than 0 and less than `end_time`. - StartTime int64 `json:"start_time" toon:"start_time"` -} - -// CreateSilenceRuleRequestTimeFiltersItem is generated from the Flashduty OpenAPI schema. -type CreateSilenceRuleRequestTimeFiltersItem struct { - // Optional calendar ID; restricts the window to days matching the calendar. - CalID string `json:"cal_id,omitempty" toon:"cal_id,omitempty"` - // End of the window in `HH:MM`. - End string `json:"end,omitempty" toon:"end,omitempty"` - // When true, match days marked as days-off in the calendar. - IsOff bool `json:"is_off,omitempty" toon:"is_off,omitempty"` - // Days of the week this window repeats on. Empty means every day. - Repeat []int64 `json:"repeat,omitempty" toon:"repeat,omitempty"` - // Start of the window in `HH:MM`. - Start string `json:"start,omitempty" toon:"start,omitempty"` -} - // CreateStatusPageChangeRequestUpdatesItem is generated from the Flashduty OpenAPI schema. type CreateStatusPageChangeRequestUpdatesItem struct { // Update timestamp in Unix seconds. When omitted or 0 on the first update, defaults to the current time. @@ -12477,31 +12841,59 @@ type CreateStatusPageChangeTimelineRequestComponentChangesItem struct { Status string `json:"status" toon:"status"` } +// CreateStatusPageDraftRequestDraft is generated from the Flashduty OpenAPI schema. +type CreateStatusPageDraftRequestDraft struct { + // Components the draft affects. + AffectedComponents []CreateStatusPageDraftRequestDraftAffectedComponentsItem `json:"affected_components,omitempty" toon:"affected_components,omitempty"` + // Event to append an update to; it must be an event of the same `type` on `page_id`. Omit or pass 0 to draft a new event. + ChangeID int64 `json:"change_id,omitempty" toon:"change_id,omitempty"` + // Scheduled end in Unix seconds, for a new maintenance; must be greater than `start_time` when both are set. + EndTime int64 `json:"end_time,omitempty" toon:"end_time,omitempty"` + // Event or update description (Markdown). Must not be empty. + Message string `json:"message" toon:"message"` + // Event title, 1 to 255 characters. + Name string `json:"name" toon:"name"` + // Target status page ID; must belong to the caller's account. + PageID int64 `json:"page_id" toon:"page_id"` + // Page name for display in the console; not validated. + PageName string `json:"page_name,omitempty" toon:"page_name,omitempty"` + // Scheduled start in Unix seconds, for a new maintenance. + StartTime int64 `json:"start_time,omitempty" toon:"start_time,omitempty"` + // Proposed event status; when set, it must be valid for `type` (`investigating`/`identified`/`monitoring`/`resolved` for incidents, `scheduled`/`ongoing`/`completed` for maintenances). + Status string `json:"status,omitempty" toon:"status,omitempty"` + // Event type the draft creates or updates: `incident` unplanned incident, `maintenance` planned maintenance. + Type string `json:"type" toon:"type"` + // Payload format version chosen by the producer; stored, not interpreted. + V int64 `json:"v,omitempty" toon:"v,omitempty"` +} + // EscalateTargetBy is generated from the Flashduty OpenAPI schema. type EscalateTargetBy struct { - // Notify channels used for Critical severity. Personal channels: `sms`, `voice`, `email`, `push`; IM group-chat channels: `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:`, `teams_app:`. + // Channels used when the incident severity is `Critical`: `sms`, `voice`, `email`, `push`, or a direct message through an IM app integration written as `:`, where `` is `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app` or `teams_app` and `` is the ID of that IM integration. Other values return `InvalidParameter`. Critical []string `json:"critical,omitempty" toon:"critical,omitempty"` - // When true, use each responder's personal preference instead of the lists below. + // When true, each person is notified through the channels in their own notification preferences for the incident's severity, and `critical`, `warning` and `info` are ignored. FollowPreference bool `json:"follow_preference,omitempty" toon:"follow_preference,omitempty"` - // Notify channels used for Info severity. Values as for `critical`. + // Channels used when the incident severity is `Info`; same values as `critical`. Info []string `json:"info,omitempty" toon:"info,omitempty"` - // Notify channels used for Warning severity. Values as for `critical`. + // Channels used when the incident severity is `Warning`; same values as `critical`. Warning []string `json:"warning,omitempty" toon:"warning,omitempty"` } // EscalateTargetWebhooksItem is generated from the Flashduty OpenAPI schema. type EscalateTargetWebhooksItem struct { - // Type-specific settings (chat IDs, URLs, etc.). + // Type-specific settings, such as the robot's webhook token or the app's chat IDs; `feishu_app` and `dingtalk_app` require it. To see the exact shape for a type, configure one in the console and read it back with `POST /channel/escalate/rule/info`. Settings map[string]any `json:"settings" toon:"settings"` - // Webhook type, one of `feishu`, `feishu_app`, `dingtalk`, `dingtalk_app`, `wecom`, `slack`, `slack_app`, `teams_app`, `telegram`, `zoom`. + // Delivery type: + // - `feishu`, `dingtalk`, `wecom`, `slack`, `telegram`, `zoom`: a group robot (incoming webhook) of that IM. + // - `feishu_app`, `dingtalk_app`, `slack_app`, `teams_app`: group chats reached through the corresponding IM app integration. Type string `json:"type" toon:"type"` } // FeedDetailIncidentAssignNotify is generated from the Flashduty OpenAPI schema. type FeedDetailIncidentAssignNotify struct { - // When false, use `personal_channels`; when true or omitted, use each responder's personal preference. + // `true`: notify each person through their personal notification preference. `false`: use `personal_channels`, which must then be non-empty. When omitted, `personal_channels` must be set. FollowPreference bool `json:"follow_preference" toon:"follow_preference"` - // Channels to use (e.g. `voice`, `sms`, `email`). + // Channels used when `follow_preference` is `false`: `sms`, `voice`, `email`, `push` (mobile app push), or an IM app channel written as `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:`, or `teams_app:`. Ignored when `follow_preference` is `true`. PersonalChannels []string `json:"personal_channels" toon:"personal_channels"` // Notification template ID (MongoDB ObjectID). TemplateID string `json:"template_id" toon:"template_id"` @@ -12571,13 +12963,13 @@ type IntegrationDetailTest struct { // PostMortemItemBasics is generated from the Flashduty OpenAPI schema. type PostMortemItemBasics struct { - // Earliest start time among linked incidents (seconds). - IncidentsEarliestStartSeconds int64 `json:"incidents_earliest_start_seconds" toon:"incidents_earliest_start_seconds"` - // Highest severity among linked incidents. + // Earliest start time among linked incidents (Unix seconds). + IncidentsEarliestStartSeconds Timestamp `json:"incidents_earliest_start_seconds" toon:"incidents_earliest_start_seconds"` + // Highest severity among linked incidents: `Critical`, `Warning`, or `Info`; `Ok` only when it was set manually. IncidentsHighestSeverity string `json:"incidents_highest_severity" toon:"incidents_highest_severity"` - // Latest close time among linked incidents (seconds). - IncidentsLatestCloseSeconds int64 `json:"incidents_latest_close_seconds" toon:"incidents_latest_close_seconds"` - // Cumulative duration in seconds. + // Latest close time among linked incidents (Unix seconds); an incident not yet closed contributes its `end_time`. + IncidentsLatestCloseSeconds Timestamp `json:"incidents_latest_close_seconds" toon:"incidents_latest_close_seconds"` + // Seconds from the earliest start to the latest close among linked incidents (not the sum of each incident's duration). IncidentsTotalDurationSeconds int64 `json:"incidents_total_duration_seconds" toon:"incidents_total_duration_seconds"` // Responders involved in the incident(s). Responders []Responder `json:"responders" toon:"responders"` @@ -12589,6 +12981,41 @@ type PostMortemItemContent struct { Content string `json:"content" toon:"content"` } +// PreviewTemplateResponseBlocksItem is generated from the Flashduty OpenAPI schema. +type PreviewTemplateResponseBlocksItem struct { + // Column headers of a `table` block. + Columns []string `json:"columns" toon:"columns"` + // Text of a `markdown` block. + Content string `json:"content" toon:"content"` + // `true` when a `table` block is shown as a native card table; omitted otherwise. + Native bool `json:"native" toon:"native"` + // Rows shown per page in a native table; omitted when not set. + PageSize int64 `json:"page_size" toon:"page_size"` + // Cell values of a `table` block, one array per row. + Rows [][]string `json:"rows" toon:"rows"` + // Block kind: `markdown` (text in `content`) or `table` (a table in `columns`/`rows`). + Type string `json:"type" toon:"type"` +} + +// PreviewTemplateResponseCard is generated from the Flashduty OpenAPI schema. +type PreviewTemplateResponseCard struct { + // Card elements in display order. + Elements []PreviewTemplateResponseCardElementsItem `json:"elements" toon:"elements"` + // Email subject or card title. + Title string `json:"title" toon:"title"` +} + +// PreviewTemplateResponseNoticesItem is generated from the Flashduty OpenAPI schema. +type PreviewTemplateResponseNoticesItem struct { + // Warning kind. + // - `table_not_rendered`: the channel cannot show Markdown tables; they are sent as text. + // - `native_table_fallback`: a table cannot be a native card table and is sent as Markdown; `reason` says why (`too_many_tables`, `too_many_columns`, `too_many_rows`, `cell_too_long`, `unsupported_cell`, `card_too_large`). + // - `content_too_large`: the content exceeds `size_limit_bytes`; `reason` is `truncated` (cut to fit), `compact_fallback` (sent in a compact form) or `rejected` (the channel will refuse it). + Code string `json:"code" toon:"code"` + // Detail for `code`, as listed there; omitted for `table_not_rendered`. + Reason string `json:"reason" toon:"reason"` +} + // RuleConfigsCheckAnydata is generated from the Flashduty OpenAPI schema. type RuleConfigsCheckAnydata struct { // Number of consecutive evaluations that must satisfy the condition before alerting; minimum 1. @@ -12673,7 +13100,7 @@ type RuleConfigsRelateQueriesItem struct { type RUMIssueItemError struct { // Normalized error message, truncated to at most 512 characters. Message string `json:"message" toon:"message"` - // Error type, from the error event's `error_type` field as reported by the SDK. + // Error type reported by the SDK in the error event's `error_type` field — free-form, not a fixed set. Browser errors carry the JavaScript exception name, e.g. `Error`, `TypeError`, `ReferenceError`. Type string `json:"type" toon:"type"` } @@ -12707,7 +13134,7 @@ type RUMIssueItemRegression struct { type RUMIssueItemSuspectedCause struct { // Person ID of the user who manually set the cause; 0 when `source` is `auto`. PersonID int64 `json:"person_id" toon:"person_id"` - // Explanation for the cause determination, generated only by AI analysis; empty string when AI is disabled or analysis has not run. + // Free-text explanation of the cause, written only by AI analysis; empty string when AI analysis is disabled, has not run yet, or the cause was set by a user. Reason string `json:"reason" toon:"reason"` // Origin of the cause: `auto` for system-determined, `user` for manually set. Source string `json:"source" toon:"source"` @@ -12724,9 +13151,71 @@ type RUMIssueItemSuspectedCause struct { Value string `json:"value" toon:"value"` } +// ScheduleLayerEndsAt is generated from the Flashduty OpenAPI schema. +type ScheduleLayerEndsAt struct { + // Calendar date, `YYYY-MM-DD`. + Date string `json:"date,omitempty" toon:"date,omitempty"` + // Time of day, `HH:MM` (24-hour); defaults to `00:00`. + Time string `json:"time,omitempty" toon:"time,omitempty"` +} + +// ScheduleLayerHandoff is generated from the Flashduty OpenAPI schema. +type ScheduleLayerHandoff struct { + // Time of day, `HH:MM` (24-hour). + Time string `json:"time" toon:"time"` + // ISO weekday: `1` = Monday … `7` = Sunday. + Weekday int64 `json:"weekday" toon:"weekday"` +} + +// ScheduleLayerRestrictsWallItem is generated from the Flashduty OpenAPI schema. +type ScheduleLayerRestrictsWallItem struct { + // Window start, `HH:MM`. + From string `json:"from,omitempty" toon:"from,omitempty"` + // ISO weekday the window starts on (`restrict_mode` 2 only): `1` = Monday … `7` = Sunday. + FromDay int64 `json:"from_day,omitempty" toon:"from_day,omitempty"` + // Window end, `HH:MM`. + To string `json:"to,omitempty" toon:"to,omitempty"` + // ISO weekday the window ends on (`restrict_mode` 2 only). + ToDay int64 `json:"to_day,omitempty" toon:"to_day,omitempty"` +} + +// ScheduleLayerStartsAt is generated from the Flashduty OpenAPI schema. +type ScheduleLayerStartsAt struct { + // Calendar date, `YYYY-MM-DD`. + Date string `json:"date" toon:"date"` + // Time of day, `HH:MM` (24-hour); defaults to `00:00`. + Time string `json:"time,omitempty" toon:"time,omitempty"` +} + +// SessionItemAutomation is generated from the Flashduty OpenAPI schema. +type SessionItemAutomation struct { + // True when the caller may open and manage the rule; false when the rule has been deleted. + CanEdit bool `json:"can_edit" toon:"can_edit"` + // ID of the automation rule. + RuleID string `json:"rule_id" toon:"rule_id"` + // Rule name; empty when the rule has since been deleted. + RuleName string `json:"rule_name" toon:"rule_name"` + // How this run was triggered: + // - `schedule`: the rule's schedule fired + // - `manual`: run on demand (console or `POST /safari/automation/rule/run`) + // - `http_post`: the rule's HTTP trigger URL was called + // - `oncall_incident`: an On-call incident event matched the rule + // - `war_room_created`: a war room was created + // - `""`: the run record no longer exists + TriggerKind string `json:"trigger_kind" toon:"trigger_kind"` +} + +// SkillItemExamplesItem is generated from the Flashduty OpenAPI schema. +type SkillItemExamplesItem struct { + // English prompt text. + En string `json:"en" toon:"en"` + // Chinese prompt text. + Zh string `json:"zh" toon:"zh"` +} + // UpsertStatusPageComponentRequestComponentsItem is generated from the Flashduty OpenAPI schema. type UpsertStatusPageComponentRequestComponentsItem struct { - // Time the component became (or becomes) available, in Unix seconds. On create, defaults to the current time; on update, replaces the stored value. + // Time the component became available, in Unix seconds, used as the start of its uptime history. Applies only on create, defaulting to the current time; ignored on update. AvailableSinceSeconds int64 `json:"available_since_seconds,omitempty" toon:"available_since_seconds,omitempty"` // Component ID. Omit to create a new component; supply to update an existing one. ComponentID string `json:"component_id,omitempty" toon:"component_id,omitempty"` @@ -12736,11 +13225,11 @@ type UpsertStatusPageComponentRequestComponentsItem struct { HideAll bool `json:"hide_all,omitempty" toon:"hide_all,omitempty"` // When true, uptime data is hidden from summary responses. HideUptime bool `json:"hide_uptime,omitempty" toon:"hide_uptime,omitempty"` - // Component display name. + // Component display name; must be unique within the page. Name string `json:"name" toon:"name"` - // Display order within its section. + // Display order within its section; on update an omitted value resets to 0. OrderID int64 `json:"order_id,omitempty" toon:"order_id,omitempty"` - // Parent section ID. Omit to place the component at the top level. + // Parent section ID; must be an existing section of the page. Omit to place the component at the top level (on update too). SectionID string `json:"section_id,omitempty" toon:"section_id,omitempty"` } @@ -12752,59 +13241,19 @@ type UpsertStatusPageSectionRequestSectionsItem struct { HideAll bool `json:"hide_all,omitempty" toon:"hide_all,omitempty"` // When true, uptime data for all components in this section is hidden. HideUptime bool `json:"hide_uptime,omitempty" toon:"hide_uptime,omitempty"` - // Section display name. + // Section display name; must be unique within the page. Name string `json:"name" toon:"name"` - // Display order. + // Display order of the section; on update an omitted value resets to 0. OrderID int64 `json:"order_id,omitempty" toon:"order_id,omitempty"` // Section ID. Omit to create a new section; supply to update an existing one. SectionID string `json:"section_id,omitempty" toon:"section_id,omitempty"` } -// CreateChannelRequestEscalateRuleTarget is generated from the Flashduty OpenAPI schema. -type CreateChannelRequestEscalateRuleTarget struct { - // Per-severity personal notification channels. Required unless `webhooks` is provided. - By CreateChannelRequestEscalateRuleTargetBy `json:"by,omitzero" toon:"by,omitempty"` - // Email addresses to notify (push-only scenarios). - Emails []string `json:"emails,omitempty" toon:"emails,omitempty"` - // Member IDs to notify directly; obtain member IDs from `POST /member/list`. - PersonIDs []int64 `json:"person_ids,omitempty" toon:"person_ids,omitempty"` - // Map of schedule ID to the role IDs on that schedule to notify. - ScheduleToRoleIDs map[string][]int64 `json:"schedule_to_role_ids,omitempty" toon:"schedule_to_role_ids,omitempty"` - // Team IDs to notify; obtain team IDs from `POST /team/list`. - TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` - // Group chat / webhook targets. Required unless `by` is provided. - Webhooks []CreateChannelRequestEscalateRuleTargetWebhooksItem `json:"webhooks,omitempty" toon:"webhooks,omitempty"` -} - -// CreateChannelRequestGroupCasesItem is generated from the Flashduty OpenAPI schema. -type CreateChannelRequestGroupCasesItem struct { - // Grouping keys for matching alerts. Supported values: `title`, `description`, `severity`, or any `labels.`. - Equals []string `json:"equals" toon:"equals"` - // AND-ed match conditions evaluated against stored alert fields. - If []FilterCondition `json:"if" toon:"if"` -} - -// CreateEscalationRuleRequestLayersItemTarget is generated from the Flashduty OpenAPI schema. -type CreateEscalationRuleRequestLayersItemTarget struct { - // Per-severity personal notification channels. Required unless `webhooks` is provided. - By CreateEscalationRuleRequestLayersItemTargetBy `json:"by,omitzero" toon:"by,omitempty"` - // Email addresses to notify (push-only scenarios). - Emails []string `json:"emails,omitempty" toon:"emails,omitempty"` - // Member IDs to notify directly; obtain member IDs from `POST /member/list`. - PersonIDs []int64 `json:"person_ids,omitempty" toon:"person_ids,omitempty"` - // Map of schedule ID to the role IDs on that schedule to notify. - ScheduleToRoleIDs map[string][]int64 `json:"schedule_to_role_ids,omitempty" toon:"schedule_to_role_ids,omitempty"` - // Team IDs to notify; obtain team IDs from `POST /team/list`. - TeamIDs []int64 `json:"team_ids,omitempty" toon:"team_ids,omitempty"` - // Group chat / webhook targets. Required unless `by` is provided. - Webhooks []CreateEscalationRuleRequestLayersItemTargetWebhooksItem `json:"webhooks,omitempty" toon:"webhooks,omitempty"` -} - // CreateIncidentRequestAssignedToNotify is generated from the Flashduty OpenAPI schema. type CreateIncidentRequestAssignedToNotify struct { // When false, use `personal_channels`; when true or omitted, use each responder's personal preference. FollowPreference *bool `json:"follow_preference,omitempty" toon:"follow_preference,omitempty"` - // Channels to use (e.g. `voice`, `sms`, `email`). + // Channels to use when `follow_preference` is false: `sms`, `voice`, `email`, `push`, or an IM app channel prefixed `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:` or `teams_app:`. PersonalChannels []string `json:"personal_channels,omitempty" toon:"personal_channels,omitempty"` // Notification template ID (MongoDB ObjectID). TemplateID string `json:"template_id,omitempty" toon:"template_id,omitempty"` @@ -12818,6 +13267,30 @@ type CreateStatusPageChangeRequestUpdatesItemComponentChangesItem struct { Status string `json:"status" toon:"status"` } +// CreateStatusPageDraftRequestDraftAffectedComponentsItem is generated from the Flashduty OpenAPI schema. +type CreateStatusPageDraftRequestDraftAffectedComponentsItem struct { + // Component ID; must exist on the page. + ComponentID string `json:"component_id" toon:"component_id"` + // Component name for display; not validated. + Name string `json:"name,omitempty" toon:"name,omitempty"` + // Proposed component status; when set, it must be valid for `type` (`operational`/`degraded`/`partial_outage`/`full_outage` for incidents, `operational`/`under_maintenance` for maintenances). + Status string `json:"status,omitempty" toon:"status,omitempty"` +} + +// PreviewTemplateResponseCardElementsItem is generated from the Flashduty OpenAPI schema. +type PreviewTemplateResponseCardElementsItem struct { + // Buttons of an `actions` element; omitted for other kinds. + Actions []PreviewTemplateResponseCardElementsItemActionsItem `json:"actions" toon:"actions"` + // Markdown text of a `markdown` element; omitted for other kinds. + Content string `json:"content" toon:"content"` + // Element kind. + // - `template`: where the rendered template (`content`) appears. + // - `markdown`: fixed text in the channel's Markdown, in `content`. + // - `divider`: a horizontal rule. + // - `actions`: a row of buttons, in `actions`. + Type string `json:"type" toon:"type"` +} + // RuleConfigsCheckAnydataRecovery is generated from the Flashduty OpenAPI schema. type RuleConfigsCheckAnydataRecovery struct { // Datasource-specific options for the recovery query, same convention as `queries[].args`; required for Elasticsearch datasources when `mode` is `ql`. @@ -12840,44 +13313,12 @@ type RuleConfigsCheckThresholdRecovery struct { ValueFields []string `json:"value_fields" toon:"value_fields"` } -// CreateChannelRequestEscalateRuleTargetBy is generated from the Flashduty OpenAPI schema. -type CreateChannelRequestEscalateRuleTargetBy struct { - // Notify channels used for Critical severity. Personal channels: `sms`, `voice`, `email`, `push`; IM group-chat channels: `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:`, `teams_app:`. - Critical []string `json:"critical,omitempty" toon:"critical,omitempty"` - // When true, use each responder's personal preference instead of the lists below. - FollowPreference bool `json:"follow_preference,omitempty" toon:"follow_preference,omitempty"` - // Notify channels used for Info severity. Values as for `critical`. - Info []string `json:"info,omitempty" toon:"info,omitempty"` - // Notify channels used for Warning severity. Values as for `critical`. - Warning []string `json:"warning,omitempty" toon:"warning,omitempty"` -} - -// CreateChannelRequestEscalateRuleTargetWebhooksItem is generated from the Flashduty OpenAPI schema. -type CreateChannelRequestEscalateRuleTargetWebhooksItem struct { - // Type-specific settings (chat IDs, URLs, etc.). - Settings map[string]any `json:"settings" toon:"settings"` - // Webhook type, one of `feishu`, `feishu_app`, `dingtalk`, `dingtalk_app`, `wecom`, `slack`, `slack_app`, `teams_app`, `telegram`, `zoom`. - Type string `json:"type" toon:"type"` -} - -// CreateEscalationRuleRequestLayersItemTargetBy is generated from the Flashduty OpenAPI schema. -type CreateEscalationRuleRequestLayersItemTargetBy struct { - // Notify channels used for Critical severity. Personal channels: `sms`, `voice`, `email`, `push`; IM group-chat channels: `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:`, `teams_app:`. - Critical []string `json:"critical,omitempty" toon:"critical,omitempty"` - // When true, use each responder's personal preference instead of the lists below. - FollowPreference bool `json:"follow_preference,omitempty" toon:"follow_preference,omitempty"` - // Notify channels used for Info severity. Values as for `critical`. - Info []string `json:"info,omitempty" toon:"info,omitempty"` - // Notify channels used for Warning severity. Values as for `critical`. - Warning []string `json:"warning,omitempty" toon:"warning,omitempty"` -} - -// CreateEscalationRuleRequestLayersItemTargetWebhooksItem is generated from the Flashduty OpenAPI schema. -type CreateEscalationRuleRequestLayersItemTargetWebhooksItem struct { - // Type-specific settings (chat IDs, URLs, etc.). - Settings map[string]any `json:"settings" toon:"settings"` - // Webhook type, one of `feishu`, `feishu_app`, `dingtalk`, `dingtalk_app`, `wecom`, `slack`, `slack_app`, `teams_app`, `telegram`, `zoom`. - Type string `json:"type" toon:"type"` +// PreviewTemplateResponseCardElementsItemActionsItem is generated from the Flashduty OpenAPI schema. +type PreviewTemplateResponseCardElementsItemActionsItem struct { + // Button style: `primary` (highlighted), `danger` (destructive), `select` (a drop-down menu). Omitted for a plain button. + Style string `json:"style" toon:"style"` + // Button label. + Text string `json:"text" toon:"text"` } // ArtifactsReadStreamRequest holds the query parameters for Download or preview a file. @@ -12890,13 +13331,13 @@ type ArtifactsReadStreamRequest struct { // IncidentsPostMortemInfoRequest holds the query parameters for Get post-mortem. type IncidentsPostMortemInfoRequest struct { - // Post-mortem ID. Deterministic hash derived from account ID and the set of linked incident IDs. + // Post-mortem ID: a 32-character hex string derived from the account ID and the linked incident IDs. PostMortemID string `url:"post_mortem_id"` } // IncidentsPostmortemReadTemplateInfoRequest holds the query parameters for Get post-mortem template detail. type IncidentsPostmortemReadTemplateInfoRequest struct { - // Template ID. + // Template ID: a built-in ID such as `post_mortem_default_tmpl_en-us`, or a custom template ID from `POST /incident/post-mortem/template/list`. TemplateID string `url:"template_id"` } diff --git a/notification_templates.go b/notification_templates.go index a66c58b..b1382af 100644 --- a/notification_templates.go +++ b/notification_templates.go @@ -37,7 +37,7 @@ func (s *NotificationTemplatesService) ReadList(ctx context.Context, req *Templa // Preview template. // -// Render a notification template against incident data or mock data and return the output. +// Render a template source against an incident or mock data and return what the channel would send. // // API: POST /template/preview (template-read-preview). func (s *NotificationTemplatesService) ReadPreview(ctx context.Context, req *PreviewTemplateRequest) (*PreviewTemplateResponse, *Response, error) { @@ -51,7 +51,7 @@ func (s *NotificationTemplatesService) ReadPreview(ctx context.Context, req *Pre // Create a template. // -// Create a new notification template. +// Create a notification template with per-channel message sources. // // API: POST /template/create (template-write-create). func (s *NotificationTemplatesService) WriteCreate(ctx context.Context, req *TemplateCreateRequest) (*TemplateCreateResponse, *Response, error) { @@ -65,7 +65,7 @@ func (s *NotificationTemplatesService) WriteCreate(ctx context.Context, req *Tem // Delete a template. // -// Soft-delete a template by ID. +// Soft-delete a notification template by ID. // // API: POST /template/delete (template-write-delete). func (s *NotificationTemplatesService) WriteDelete(ctx context.Context, req *TemplateIDRequest) (*Response, error) { @@ -74,7 +74,7 @@ func (s *NotificationTemplatesService) WriteDelete(ctx context.Context, req *Tem // Update a template. // -// Update an existing template. Only the fields present in the request are written: a channel you omit keeps its current content, and an explicit empty string clears it. +// Update a notification template; only the fields present in the request are written. // // API: POST /template/update (template-write-update). func (s *NotificationTemplatesService) WriteUpdate(ctx context.Context, req *TemplateUpdateRequest) (*Response, error) { diff --git a/openapi/openapi.en.json b/openapi/openapi.en.json index 52fb1bc..6d90bfc 100644 --- a/openapi/openapi.en.json +++ b/openapi/openapi.en.json @@ -23,25 +23,25 @@ "description": "Invalid request — usually a missing or malformed parameter." }, "Forbidden": { + "description": "The app_key is valid, but its permission scope or the creator's role does not allow this operation or object.", "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + }, "examples": { "noEditPermission": { "value": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "error": { "code": "AccessDenied", "message": "Access Denied." - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + } } } - }, - "schema": { - "$ref": "#/components/schemas/ErrorResponse" } } - }, - "description": "The app_key is valid but lacks permission for this operation." + } }, "NotFound": { "content": { @@ -107,25 +107,34 @@ "description": "The service is temporarily unavailable. Include the request_id when reporting." }, "TooManyRequests": { + "description": "Rate limit hit (per-account limit or the operation's platform-wide limit). Wait for the number of seconds in `Flashcat-Request-Rate-Limit-Delay`, then retry.", "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + }, "examples": { "rateLimited": { "value": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "error": { "code": "RequestTooFrequently", "message": "Request too frequently." - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + } } } - }, - "schema": { - "$ref": "#/components/schemas/ErrorResponse" } } }, - "description": "Rate limit hit. Either the global API limit, a per-account limit, or a per-integration limit." + "headers": { + "Flashcat-Request-Rate-Limit-Delay": { + "description": "Seconds until the current rate-limit window resets. Absent when the request was rejected by the gateway's global protection limit.", + "schema": { + "type": "integer", + "minimum": 0 + } + } + } }, "Unauthorized": { "content": { @@ -151,81 +160,87 @@ }, "schemas": { "A2AAgentCreateRequest": { + "type": "object", "description": "Registration parameters for a new A2A agent.", "properties": { "agent_name": { - "description": "Agent display name.", - "maxLength": 128, - "type": "string" - }, - "allow_insecure_oauth_http": { - "description": "Allow non-loopback HTTP OAuth discovery/metadata endpoints for this agent instead of requiring HTTPS. Defaults to false.", - "type": "boolean" - }, - "allow_insecure_tls_skip_verify": { - "description": "Skip TLS certificate verification when connecting to this agent's endpoint (self-signed/private certs). Defaults to false.", - "type": "boolean" + "type": "string", + "description": "Agent display name, used to address the agent in sessions. Must not contain `@`, must not be `general` or `explore`, and must be unique within its scope (account-wide or one team).", + "maxLength": 128 }, - "auth_config": { - "additionalProperties": { - "type": "string" - }, - "description": "Authentication config key-values, e.g. the API key or bearer token. Values under credential-looking keys (name containing KEY, SECRET, TOKEN, PASSWORD, etc.) are masked back in responses.", - "type": "object" + "instructions": { + "type": "string", + "description": "Natural-language instructions for the remote agent: a Markdown document with optional `summary` frontmatter and a non-empty body, at most 50 KiB (51200 bytes). Required — a deprecated `description` field is still accepted for legacy clients and, if both are sent, must exactly match `instructions`.", + "maxLength": 51200 }, - "auth_mode": { - "description": "Authentication mode: `shared` (default) shares one credential across all users; `per_user_secret` requires `secret_schema.header_name`; `per_user_oauth` runs per-user OAuth.", - "type": "string" + "card_url": { + "type": "string", + "description": "URL of the remote agent card. Must be an absolute `http` or `https` URL with a non-empty host; a URL with no path is resolved to `/.well-known/agent-card.json`. If an execution environment is online, the card is fetched and must declare an A2A 1.x `JSONRPC` or `HTTP+JSON` interface." }, "auth_type": { - "description": "Authentication type for reaching the remote agent: `none` (default when omitted), `api_key`, or `bearer`.", + "type": "string", + "description": "Authentication used to reach the remote agent with a shared credential:\n- `none`: no credential header.\n- `api_key`: sends `auth_config.api_key` in the header named by `auth_config.header`.\n- `bearer`: sends `Authorization: Bearer `.\n\nWhen omitted the value is stored as an empty string, which behaves like `none`.", "enum": [ "none", "api_key", "bearer" - ], - "type": "string" + ] }, - "card_url": { - "description": "URL of the remote agent card. Must be an absolute `http` or `https` URL with a non-empty host; reachability is enforced by the execution environment, not at creation time.", - "type": "string" + "auth_config": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Shared credential key-values: `header` and `api_key` for `auth_type=api_key`, `token` for `auth_type=bearer`. Values of `api_key`, `token`, and `client_secret` are encrypted at rest and masked in responses." + }, + "streaming": { + "type": "boolean", + "description": "Whether the remote agent supports streaming." + }, + "team_id": { + "type": "integer", + "description": "Team scope: 0 = account-wide; >0 = team. Creating at account scope requires the owner/admin role; creating into a team requires actual membership in that team.", + "format": "int64" }, "environments": { - "description": "Execution environments this agent is callable from: `cloud` and/or BYOC runner environment IDs. Omitted or empty means all environments.", + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "instructions": { - "description": "Natural-language instructions for the remote agent: a Markdown document with optional `summary` frontmatter and a non-empty body, at most 50 KiB (51200 bytes). Required — a deprecated `description` field is still accepted for legacy clients and, if both are sent, must exactly match `instructions`.", - "maxLength": 51200, - "type": "string" + "description": "Execution environments this agent is callable from: `cloud` and/or BYOC runner environment IDs. Omitted or empty means all environments." }, - "oauth_metadata": { - "description": "JSON-encoded OAuth metadata; populated by the OAuth discovery flow for `per_user_oauth` mode.", - "type": "string" + "auth_mode": { + "type": "string", + "description": "Who supplies the credential:\n- `shared` (default; an empty value behaves the same): one credential stored on the agent (`auth_type` + `auth_config`) is used for every caller.\n- `per_user_secret`: each user stores their own secret, sent in the header named by `secret_schema.header_name`.\n- `per_user_oauth`: each user completes their own OAuth authorization; discovery and client registration run on first use.\n\n`per_user_secret` requires `secret_schema` with a non-empty `header_name`; any other value returns `InvalidParameter`.", + "enum": [ + "shared", + "per_user_secret", + "per_user_oauth" + ], + "default": "shared" }, "secret_schema": { - "description": "JSON-encoded secret schema, e.g. `{\"header_name\":\"X-Api-Key\"}`; required when `auth_mode=per_user_secret`.", - "type": "string" + "type": "string", + "description": "JSON-encoded secret schema, e.g. `{\"header_name\":\"X-Api-Key\"}`; required when `auth_mode=per_user_secret`." }, - "streaming": { - "description": "Whether the remote agent supports streaming.", - "type": "boolean" + "oauth_metadata": { + "type": "string", + "description": "JSON-encoded OAuth metadata; populated by the OAuth discovery flow for `per_user_oauth` mode." }, - "team_id": { - "description": "Team scope: 0 = account-wide; >0 = team. Creating at account scope requires the owner/admin role; creating into a team requires actual membership in that team.", - "format": "int64", - "type": "integer" + "allow_insecure_oauth_http": { + "type": "boolean", + "description": "Allow non-loopback HTTP OAuth discovery/metadata endpoints for this agent instead of requiring HTTPS. Defaults to false." + }, + "allow_insecure_tls_skip_verify": { + "type": "boolean", + "description": "Skip TLS certificate verification when connecting to this agent's endpoint (self-signed/private certs). Defaults to false." } }, "required": [ "agent_name", "instructions", "card_url" - ], - "type": "object" + ] }, "A2AAgentCreateResponse": { "description": "Result of registering an A2A agent.", @@ -254,133 +269,134 @@ "type": "object" }, "A2AAgentItem": { + "type": "object", "description": "A registered A2A (agent-to-agent) remote agent.", "properties": { + "agent_id": { + "type": "string", + "description": "Unique A2A agent ID (prefix `a2a_`)." + }, "account_id": { + "type": "integer", "description": "Owning account ID.", - "format": "int64", - "type": "integer" + "format": "int64" }, - "agent_card_name": { - "description": "Agent name resolved from the remote card. Omitted until the card has been fetched.", - "type": "string" + "team_id": { + "type": "integer", + "description": "Team scope: 0 = account-wide; >0 = the owning team.", + "format": "int64" }, - "agent_card_skills": { - "description": "Skills advertised by the remote card. Omitted until the card has been fetched.", + "can_edit": { + "type": "boolean", + "description": "Whether the caller may update, enable, disable, or delete this agent: `true` for an account-scoped agent only for the account owner or an admin, for a team agent only for members of that team." + }, + "environments": { + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "agent_id": { - "description": "Unique A2A agent ID (prefix `a2a_`).", - "type": "string" + "description": "Execution environments this agent is callable from (`cloud` and/or BYOC runner environment IDs). Always present; `[]` means all environments (also the value on legacy rows created before this field)." }, "agent_name": { - "description": "Agent display name.", - "type": "string" - }, - "allow_insecure_oauth_http": { - "description": "Allow non-loopback HTTP OAuth discovery/metadata endpoints for this agent instead of requiring HTTPS.", - "type": "boolean" - }, - "allow_insecure_tls_skip_verify": { - "description": "Skip TLS certificate verification when connecting to this agent's endpoint.", - "type": "boolean" + "type": "string", + "description": "Agent display name." }, - "auth_config": { - "additionalProperties": { - "type": "string" - }, - "description": "Authentication config key-values. Values under credential-looking keys (name containing KEY, SECRET, TOKEN, PASSWORD, etc.) are masked. Omitted when empty.", - "type": "object" + "instructions": { + "type": "string", + "description": "Natural-language instructions for the remote agent (formerly named `description`).", + "maxLength": 51200 }, - "auth_mode": { - "description": "Authentication mode. One of: `shared` (a single static credential saved on the resource and shared by all callers in the account; the default — an empty value behaves the same), `per_user_secret` (each user stores their own secret per `secret_schema`, injected per user at runtime), `per_user_oauth` (each user completes their own OAuth grant; discovery and registration run lazily on first use).", - "enum": [ - "shared", - "per_user_secret", - "per_user_oauth" - ], - "type": "string" + "card_url": { + "type": "string", + "description": "URL of the remote agent card." }, "auth_type": { - "description": "Authentication type for reaching the remote agent: `none`, `api_key`, or `bearer`. Rows created before validation was tightened may return an empty string, equivalent to `none`.", + "type": "string", + "description": "Authentication used to reach the remote agent with a shared credential:\n- `none`: no credential header.\n- `api_key`: sends `auth_config.api_key` in the header named by `auth_config.header`.\n- `bearer`: sends `Authorization: Bearer `.\n\nAn empty string means `auth_type` was omitted at creation and behaves like `none`.", "enum": [ "", "none", "api_key", "bearer" - ], - "type": "string" - }, - "can_edit": { - "description": "Whether the caller may edit this agent.", - "type": "boolean" + ] }, - "card_resolve_timeout": { - "description": "Card-resolution timeout in seconds. Always 0 today — the API does not yet expose a way to set it.", - "type": "integer" + "auth_config": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Shared credential key-values (`header`, `api_key`, `token`, …). Values of `api_key`, `token`, `client_secret`, and any other value stored encrypted are masked: longer than 8 characters shows the first and last 4 characters around `****`, otherwise `****`. Omitted when empty." }, - "card_url": { - "description": "URL of the remote agent card.", - "type": "string" + "streaming": { + "type": "boolean", + "description": "Whether the remote agent supports streaming responses." }, - "created_at": { - "description": "Creation time. Unix timestamp in milliseconds.", - "format": "int64", - "type": "integer" + "status": { + "type": "string", + "description": "Whether the agent is offered to AI SRE sessions:\n- `enabled`: available for dispatch (the state after create).\n- `disabled`: kept but not offered; re-enable with `POST /safari/a2a-agent/enable`.", + "enum": [ + "enabled", + "disabled" + ] }, - "created_by": { - "description": "Member ID that created the agent.", - "format": "int64", - "type": "integer" + "agent_card_name": { + "type": "string", + "description": "Agent name read from the remote card on older records. The server no longer fills this in, so it is omitted for new agents." }, - "environments": { - "description": "Execution environments this agent is callable from (`cloud` and/or BYOC runner environment IDs). Always present; `[]` means all environments (also the value on legacy rows created before this field).", + "agent_card_skills": { + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Skill names read from the remote card on older records. The server no longer fills this in, so it is omitted for new agents." }, - "instructions": { - "description": "Natural-language instructions for the remote agent (formerly named `description`).", - "maxLength": 51200, - "type": "string" + "card_resolve_timeout": { + "type": "integer", + "description": "Card-resolution timeout in seconds. Always 0 today — the API does not yet expose a way to set it." }, - "oauth_metadata": { - "description": "JSON-encoded OAuth metadata (per_user_oauth mode).", - "type": "string" + "task_timeout": { + "type": "integer", + "description": "Single-task execution timeout in seconds. Always 0 today — the API does not yet expose a way to set it." + }, + "auth_mode": { + "type": "string", + "description": "Who supplies the credential; omitted when empty, which behaves like `shared`:\n- `shared`: one credential stored on the agent (`auth_type` + `auth_config`) is used for every caller.\n- `per_user_secret`: each user stores their own secret, sent in the header named by `secret_schema.header_name`.\n- `per_user_oauth`: each user completes their own OAuth authorization; discovery and client registration run on first use.", + "enum": [ + "shared", + "per_user_secret", + "per_user_oauth" + ] }, "secret_schema": { - "description": "JSON-encoded secret schema (per_user_secret mode).", - "type": "string" + "type": "string", + "description": "JSON-encoded secret schema (per_user_secret mode)." }, - "status": { - "description": "Agent status.", - "enum": [ - "enabled", - "disabled" - ], - "type": "string" + "oauth_metadata": { + "type": "string", + "description": "JSON-encoded OAuth metadata (per_user_oauth mode)." }, - "streaming": { - "description": "Whether the remote agent supports streaming responses.", - "type": "boolean" + "allow_insecure_oauth_http": { + "type": "boolean", + "description": "Allow non-loopback HTTP OAuth discovery/metadata endpoints for this agent instead of requiring HTTPS." }, - "task_timeout": { - "description": "Single-task execution timeout in seconds. Always 0 today — the API does not yet expose a way to set it.", - "type": "integer" + "allow_insecure_tls_skip_verify": { + "type": "boolean", + "description": "Skip TLS certificate verification when connecting to this agent's endpoint." }, - "team_id": { - "description": "Team scope: 0 = account-wide; >0 = the owning team.", + "created_by": { + "type": "integer", + "description": "Member ID that created the agent.", + "format": "int64" + }, + "created_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Creation time. Unix timestamp in milliseconds." }, "updated_at": { - "description": "Last update time. Unix timestamp in milliseconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update time. Unix timestamp in milliseconds." } }, "required": [ @@ -400,54 +416,53 @@ "created_at", "updated_at", "environments" - ], - "type": "object" + ] }, "A2AAgentListRequest": { + "type": "object", "description": "Pagination, scope, and search filter for listing A2A agents.", "properties": { - "include_account": { - "description": "Include account-scoped (team_id=0) rows. Defaults to true.", - "type": [ - "boolean", - "null" - ] - }, - "limit": { - "default": 20, - "description": "Page size.", - "type": "integer" - }, "offset": { - "default": 0, + "type": "integer", "description": "Pagination offset — number of rows to skip, starting from 0.", - "type": "integer" + "default": 0 }, - "query": { - "description": "Case-insensitive substring search across agent name, instructions, card URL, agent ID, and the resolved card name.", - "maxLength": 128, - "type": "string" + "limit": { + "type": "integer", + "description": "Page size; 0 or less falls back to 20. No upper bound is enforced.", + "default": 20 }, "scope": { - "default": "all", - "description": "Visibility scope: `all` (account-scope plus the caller's visible teams), `account` (account-scope only), or `team` (team-scoped rows across the caller's visible teams).", + "type": "string", "enum": [ "all", "account", "team" ], - "type": "string" + "default": "all", + "description": "Visibility scope: `all` (account-scope plus the caller's visible teams), `account` (account-scope only), or `team` (team-scoped rows across the caller's visible teams)." + }, + "query": { + "type": "string", + "description": "Case-insensitive substring search across agent name, instructions, card URL, agent ID, and the resolved card name.", + "maxLength": 128 }, "team_ids": { - "description": "Filter to these team IDs; empty = the caller's visible set.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Restrict to these team IDs. IDs of teams the caller does not belong to are ignored; empty means all of the caller's teams." + }, + "include_account": { + "type": [ + "boolean", + "null" + ], + "description": "Include account-scoped (`team_id=0`) rows. Defaults to `true`; ignored when `scope` is `account` (always included) or `team` (never included)." } - }, - "type": "object" + } }, "A2AAgentListResponse": { "description": "Paginated A2A agent list.", @@ -472,202 +487,217 @@ "type": "object" }, "A2AAgentUpdateRequest": { + "type": "object", "description": "Partial update of an A2A agent. A null/omitted field is left unchanged.", "properties": { "agent_id": { - "description": "Target agent ID, from the list returned by `POST /safari/a2a-agent/list`.", - "type": "string" + "type": "string", + "description": "Target agent ID, from the list returned by `POST /safari/a2a-agent/list`." }, "agent_name": { - "description": "New display name. Omit to leave unchanged.", - "maxLength": 128, "type": [ "string", "null" - ] + ], + "description": "New display name; omit to leave unchanged. Same rules as create: no `@`, not `general` / `explore`, unique within the scope.", + "maxLength": 128 }, - "allow_insecure_oauth_http": { - "description": "Toggle non-loopback HTTP OAuth discovery for this agent. Omit to leave unchanged.", + "instructions": { "type": [ - "boolean", + "string", "null" - ] + ], + "description": "New instructions document (same contract as create: optional `summary` frontmatter, non-empty body, at most 50 KiB). Omit to leave unchanged. A deprecated `description` field is also accepted; if both are sent they must match.", + "maxLength": 51200 }, - "allow_insecure_tls_skip_verify": { - "description": "Toggle TLS certificate verification skipping for this agent. Omit to leave unchanged.", + "card_url": { "type": [ - "boolean", + "string", "null" - ] - }, - "auth_config": { - "additionalProperties": { - "type": "string" - }, - "description": "Replace the whole auth config; omit to leave unchanged. Keys missing from the map are dropped. For a sensitive key, sending back the masked value keeps the stored secret, while sending an empty string clears it.", - "type": "object" + ], + "description": "New card URL; omit to leave unchanged. Validated and compatibility-checked the same way as on create; a real change also clears `oauth_metadata` unless a new one is sent." }, - "auth_mode": { - "description": "New auth mode: shared, per_user_secret, or per_user_oauth. Changing it always rewrites secret_schema together with it.", + "auth_type": { "type": [ "string", "null" - ] - }, - "auth_type": { - "description": "New auth type: `none`, `api_key`, or `bearer`. Omit to leave unchanged.", + ], + "description": "New auth type; omit to leave unchanged.\n- `none`: no credential header.\n- `api_key`: sends `auth_config.api_key` in the header named by `auth_config.header`.\n- `bearer`: sends `Authorization: Bearer `.", "enum": [ "none", "api_key", "bearer" - ], + ] + }, + "auth_config": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Replace the whole auth config; omit to leave unchanged. Keys missing from the map are dropped. For a sensitive key, sending back the masked value keeps the stored secret, while sending an empty string clears it." + }, + "streaming": { "type": [ - "string", + "boolean", "null" - ] + ], + "description": "Toggle streaming support. Omit to leave unchanged." }, - "card_url": { - "description": "New card URL. Omit to leave unchanged.", + "team_id": { "type": [ - "string", + "integer", "null" - ] + ], + "description": "Reassign team scope; omit to leave unchanged. Moving to a team requires membership in it; moving to account scope (`0`) requires the account owner or an admin. If the team changes without `environments` in the same request, the current runner entries must stay selectable by the caller or the update is rejected.", + "format": "int64" }, "environments": { - "description": "Execution environments this agent is callable from: `cloud` and/or BYOC runner environment IDs. Omit (null) to leave unchanged; send a list to set it — an empty list clears the restriction back to all environments.", - "items": { - "type": "string" - }, "type": [ "array", "null" - ] + ], + "items": { + "type": "string" + }, + "description": "Execution environments this agent is callable from: `cloud` and/or BYOC runner environment IDs. Omit (null) to leave unchanged; send a list to set it — an empty list clears the restriction back to all environments." }, - "instructions": { - "description": "New instructions document (same contract as create: optional `summary` frontmatter, non-empty body, at most 50 KiB). Omit to leave unchanged. A deprecated `description` field is also accepted; if both are sent they must match.", - "maxLength": 51200, + "auth_mode": { "type": [ "string", "null" + ], + "description": "New auth mode; omit to leave unchanged. Values (who supplies the credential):\n- `shared` (default; an empty value behaves the same): one credential stored on the agent (`auth_type` + `auth_config`) is used for every caller.\n- `per_user_secret`: each user stores their own secret, sent in the header named by `secret_schema.header_name`.\n- `per_user_oauth`: each user completes their own OAuth authorization; discovery and client registration run on first use.\n\nWhen sent, `secret_schema` is overwritten with the value in the same request.", + "enum": [ + "shared", + "per_user_secret", + "per_user_oauth" ] }, - "oauth_metadata": { - "description": "New JSON OAuth metadata. If omitted while auth_mode changes, it is cleared to empty.", + "secret_schema": { "type": [ "string", "null" - ] + ], + "description": "New JSON secret schema, e.g. `{\"header_name\":\"X-Api-Key\"}`. Applied only together with `auth_mode`; sent alone it is ignored." }, - "secret_schema": { - "description": "New JSON secret schema.", + "oauth_metadata": { "type": [ "string", "null" - ] + ], + "description": "New JSON OAuth metadata. A non-empty value is stored as sent. When omitted or empty, the stored value is kept unless `auth_mode` or `card_url` changes, in which case it is cleared." }, - "streaming": { - "description": "Toggle streaming support. Omit to leave unchanged.", + "allow_insecure_oauth_http": { "type": [ "boolean", "null" - ] + ], + "description": "Toggle non-loopback HTTP OAuth discovery for this agent. Omit to leave unchanged." }, - "team_id": { - "description": "Reassign team scope. Omit to leave unchanged. Reassigning requires rights on the destination team; if the team changes without also sending a new environment binding, the existing runner binding must remain selectable by the caller or the update is rejected.", - "format": "int64", + "allow_insecure_tls_skip_verify": { "type": [ - "integer", + "boolean", "null" - ] + ], + "description": "Toggle TLS certificate verification skipping for this agent. Omit to leave unchanged." } }, "required": [ "agent_id" - ], - "type": "object" + ] }, "AccountInfo": { + "type": "object", "properties": { "account_id": { + "type": "integer", "description": "Account identifier.", - "format": "uint64", - "type": "integer" + "format": "uint64" }, "account_name": { - "description": "Account name.", - "type": "string" - }, - "avatar": { - "description": "Account avatar URL.", - "type": "string" - }, - "country_code": { - "description": "ISO 3166-1 alpha-2 region code of the contact phone (e.g. \"CN\", \"US\", \"HK\").", - "type": "string" - }, - "created_at": { - "description": "Account creation time, Unix timestamp in seconds.", - "format": "int64", - "type": "integer" + "type": "string", + "description": "Account (organization) name shown in the console." }, "domain": { - "description": "Primary account domain (login subdomain).", - "type": "string" - }, - "email": { - "description": "Account contact email.", - "type": "string" + "type": "string", + "description": "Primary account domain (login subdomain)." }, "extra_domains": { - "description": "Additional account domains.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Additional account domains." }, - "locale": { - "description": "Account language preference (e.g. zh-CN, en-US).", - "type": "string" + "phone": { + "type": "string", + "description": "Account contact phone, masked for privacy." }, - "mp_account_id": { - "description": "Account identifier on the marketplace platform. Omitted together with `mp_plat`.", - "type": "string" + "country_code": { + "type": "string", + "description": "ISO 3166-1 alpha-2 region code of the contact phone (e.g. \"CN\", \"US\", \"HK\")." }, - "mp_plat": { - "description": "Cloud marketplace platform the account was provisioned from. Omitted when the account did not come from a marketplace.", - "type": "string" + "email": { + "type": "string", + "description": "Account contact email." }, - "phone": { - "description": "Account contact phone, masked for privacy.", - "type": "string" + "avatar": { + "type": "string", + "description": "Account avatar URL." + }, + "locale": { + "type": "string", + "description": "Account language preference (`zh-CN` or `en-US`); empty string when not set." + }, + "time_zone": { + "type": "string", + "description": "Account default time zone (IANA name, e.g. `Asia/Shanghai`); members without their own setting follow it. Empty string when not set." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Account creation time, Unix timestamp in seconds." }, "restrictions": { + "type": "object", "description": "Account access restrictions. Omitted when none are configured.", "properties": { - "allow_subdomain": { - "description": "Whether subdomains of the allowed email domains are also accepted.", - "type": "boolean" - }, - "email_domains": { - "description": "Allowed login email domains.", + "ips": { + "type": [ + "array", + "null" + ], "items": { "type": "string" }, - "type": "array" + "description": "Source IP addresses or CIDR ranges allowed to call the console and API for this account; `null` or empty when unrestricted." }, - "ips": { - "description": "Allowed source IP/CIDR whitelist.", + "email_domains": { + "type": [ + "array", + "null" + ], "items": { "type": "string" }, - "type": "array" + "description": "Email domains allowed for new members; invitations to other domains are rejected. `null` or empty when unrestricted." + }, + "allow_subdomain": { + "type": "boolean", + "description": "Whether subdomains of the allowed email domains are also accepted." } - }, - "type": "object" + } }, - "time_zone": { - "description": "Account default timezone (IANA name, e.g. Asia/Shanghai).", - "type": "string" + "mp_plat": { + "type": "string", + "description": "Cloud marketplace the account was provisioned from: `aws` — AWS Marketplace. Omitted when the account did not come from a marketplace.", + "enum": [ + "aws" + ] + }, + "mp_account_id": { + "type": "string", + "description": "Account identifier on the marketplace platform. Omitted together with `mp_plat`." } }, "required": [ @@ -682,8 +712,7 @@ "locale", "time_zone", "created_at" - ], - "type": "object" + ] }, "AckIncidentRequest": { "description": "Parameters for acknowledging one or more incidents.", @@ -720,79 +749,80 @@ "type": "object" }, "AddIncidentResponderRequest": { + "type": "object", "description": "Parameters for adding responders to an existing incident.", + "required": [ + "incident_id", + "person_ids" + ], "properties": { "incident_id": { - "description": "Incident ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Incident ID (MongoDB ObjectID)." + }, + "person_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Member IDs to add as responders. IDs that are already responders, or that do not exist in the account, are skipped." }, "notify": { - "description": "Optional notification override. Defaults to following each person's personal preference.", + "type": "object", + "description": "Notification settings for the newly added responders. Defaults to `{\"follow_preference\": true}`.", "properties": { "follow_preference": { - "description": "When false, use `personal_channels`; when true or omitted, use each responder's personal preference.", "type": [ "boolean", "null" - ] + ], + "description": "`true`: notify each person through their personal notification preference. `false`: use `personal_channels`, which must then be non-empty. When omitted, `personal_channels` must be set." }, "personal_channels": { - "description": "Channels to use (e.g. `voice`, `sms`, `email`).", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Channels used when `follow_preference` is `false`: `sms`, `voice`, `email`, `push` (mobile app push), or an IM app channel written as `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:`, or `teams_app:`. Ignored when `follow_preference` is `true`." }, "template_id": { - "description": "Notification template ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Notification template ID, as returned by the notification template endpoints. Must exist in the account; otherwise the call fails with `InvalidParameter`." } - }, - "type": "object" - }, - "person_ids": { - "description": "Member IDs to add as responders.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + } } - }, - "required": [ - "incident_id", - "person_ids" - ], - "type": "object" + } }, "AddWarRoomMemberRequest": { + "type": "object", "properties": { - "chat_id": { - "description": "Chat ID of the war room within the IM platform.", - "type": "string" - }, "integration_id": { + "type": "integer", "description": "ID of the IM integration hosting the war room; obtain it from `POST /datasource/im/war-room-enabled/list`.", - "format": "int64", - "type": "integer" + "format": "int64" + }, + "chat_id": { + "type": "string", + "description": "Chat ID of the war-room group on the IM platform, as returned for the war room by `POST /incident/war-room/list`." }, "member_ids": { - "description": "Person IDs to add to the war room.", + "type": "array", + "minItems": 1, "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Person IDs (member IDs, or the account ID for the owner) to add. Must not be empty." } }, "required": [ "integration_id", "chat_id", "member_ids" - ], - "type": "object" + ] }, "AffectedStatusPageComponentItem": { "description": "A status page component currently affected by an event, embedding component metadata plus its resulting status.", @@ -850,90 +880,90 @@ "type": "object" }, "AlertEventGlobalListRequest": { + "type": "object", "description": "Filter and pagination criteria for the global raw event list. Time range is required.", + "required": [ + "start_time", + "end_time" + ], "properties": { - "asc": { - "description": "Sort ascending when `true`.", - "type": "boolean" - }, - "channel_ids": { - "description": "Filter by channel IDs. At most 100 entries.", - "items": { - "format": "int64", - "type": "integer" - }, - "maxItems": 100, - "type": "array" + "start_time": { + "type": "integer", + "format": "int64", + "description": "Start of the search window, Unix epoch seconds. Must be greater than 0.", + "exclusiveMinimum": 0 }, "end_time": { - "description": "End of the search window, Unix epoch seconds. Must be greater than `start_time`; the span must not exceed 31 days.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "integration_ids": { - "description": "Filter by integration IDs.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "description": "End of the search window, Unix epoch seconds. Must be greater than `start_time`; the span must not exceed 31 days." }, - "integration_types": { - "description": "Filter by integration types (plugin keys).", - "items": { - "type": "string" - }, - "type": "array" - }, - "limit": { - "description": "Page size, max 100, default 20.", - "format": "int64", - "maximum": 100, - "minimum": 0, + "p": { "type": [ "integer", "null" - ] - }, - "orderby": { - "description": "Sort field; only `event_time` is supported.", - "enum": [ - "event_time" ], - "type": "string" - }, - "p": { - "description": "Page number, starting at 1. Used when `search_after_ctx` is not provided.", "format": "int64", - "minimum": 0, + "description": "Page number, starting at 1. Used when `search_after_ctx` is not provided.", + "minimum": 0 + }, + "limit": { "type": [ "integer", "null" - ] + ], + "format": "int64", + "description": "Page size, max 100, default 20.", + "minimum": 0, + "maximum": 100 }, "search_after_ctx": { - "description": "Pagination cursor: leave empty for the first page, then pass the `search_after_ctx` returned by the previous response.", "type": [ "string", "null" - ] + ], + "description": "Pagination cursor: leave empty for the first page, then pass the `search_after_ctx` returned by the previous response." + }, + "integration_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Filter by integration IDs." + }, + "integration_types": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter by integration types (plugin keys)." + }, + "channel_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Filter by channel IDs. At most 100 entries. Channels the caller cannot access are dropped; if none remain, the result is empty.", + "maxItems": 100 }, "severities": { - "description": "Comma-separated severity filter, e.g. `Critical,Warning`. Accepted values: `Critical`, `Warning`, `Info`, `Ok`.", - "type": "string" + "type": "string", + "description": "Comma-separated filter on `event_severity`, e.g. `Critical,Warning`. Meaningful values: `Critical`, `Warning`, `Info`. Values are not validated; an unknown value (or `Ok`) matches nothing." }, - "start_time": { - "description": "Start of the search window, Unix epoch seconds. Must be greater than 0.", - "exclusiveMinimum": 0, - "format": "int64", - "type": "integer" + "orderby": { + "type": "string", + "description": "Sort field; only `event_time` is supported.", + "enum": [ + "event_time" + ] + }, + "asc": { + "type": "boolean", + "description": "Sort ascending when `true`." } - }, - "required": [ - "start_time", - "end_time" - ], - "type": "object" + } }, "AlertEventGlobalListResponse": { "properties": { @@ -961,113 +991,113 @@ "type": "object" }, "AlertEventItem": { + "type": "object", "description": "A raw alert event.", "properties": { - "account_id": { - "description": "Account ID.", - "format": "int64", - "type": "integer" + "event_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Event ID (MongoDB ObjectID)." }, "alert_id": { - "description": "Parent alert ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Parent alert ID (MongoDB ObjectID)." }, - "alert_key": { - "description": "Deduplication key used to merge events into an alert.", - "type": "string" + "account_id": { + "type": "integer", + "format": "int64", + "description": "ID of the account that owns this record; the same for every record returned to one `app_key`." }, "channel_id": { - "description": "Channel ID the event is routed to.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Channel ID the event is routed to." }, - "created_at": { - "description": "Record creation time, Unix epoch seconds.", + "integration_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Integration that produced this event." + }, + "integration_type": { + "type": "string", + "description": "Plugin type of the integration, such as `prometheus.alert`, `grafana.alert`, `zabbix.alert`, `monit.alert`, or `email.alert`. The set is open and grows with new integrations; `POST /integration/type/list` returns the full list." }, "data_source_id": { - "description": "Deprecated. Use `integration_id` instead.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Deprecated. Use `integration_id` instead." }, - "deleted_at": { - "description": "Soft-delete time, Unix epoch seconds. Omitted when the event is not deleted.", - "format": "int64", - "type": "integer" + "title": { + "type": "string", + "description": "Event title." + }, + "title_rule": { + "type": "string", + "description": "Title template used to derive `title` from labels." }, "description": { - "description": "Event description.", - "type": "string" + "type": "string", + "description": "Event description." }, - "event_id": { - "description": "Event ID (MongoDB ObjectID).", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "alert_key": { + "type": "string", + "description": "Deduplication key used to merge events into an alert." }, "event_severity": { - "description": "Severity of this event: `Critical`, `Warning`, or `Info`. An event never carries `Ok` as severity — `Ok` appears only as `event_status`.", + "type": "string", "enum": [ "Critical", "Warning", "Info" ], - "type": "string" + "description": "Severity of this event: `Critical`, `Warning`, or `Info`. An event never carries `Ok` as severity — `Ok` appears only as `event_status`." }, "event_status": { - "description": "Status carried by this event: `Critical`/`Warning`/`Info` for a firing event, `Ok` for a recovery event.", + "type": "string", "enum": [ "Critical", "Warning", "Info", "Ok" ], - "type": "string" + "description": "Status carried by this event: `Critical`/`Warning`/`Info` for a firing event, `Ok` for a recovery event." }, "event_time": { - "description": "Event timestamp, Unix epoch seconds.", - "format": "int64", - "type": "integer" - }, - "images": { - "description": "Images attached to the event.", - "items": { - "$ref": "#/components/schemas/AlertImage" - }, - "type": "array" - }, - "integration_id": { - "description": "Integration that produced this event.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "integration_type": { - "description": "Type/plugin key of the integration that produced this event.", - "type": "string" + "description": "Event timestamp, Unix epoch seconds." }, "labels": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "Label key-value pairs.", - "type": "object" + "description": "Label key-value pairs." }, - "title": { - "description": "Event title.", - "type": "string" + "images": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AlertImage" + }, + "description": "Images attached to the event." }, - "title_rule": { - "description": "Title template used to derive `title` from labels.", - "type": "string" + "created_at": { + "type": "integer", + "format": "int64", + "description": "Record creation time, Unix epoch seconds." }, "updated_at": { - "description": "Record update time, Unix epoch seconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Record update time, Unix epoch seconds." + }, + "deleted_at": { + "type": "integer", + "format": "int64", + "description": "Soft-delete time, Unix epoch seconds. Omitted when the event is not deleted." } - }, - "type": "object" + } }, "AlertEventListRequest": { "properties": { @@ -1217,231 +1247,243 @@ "type": "string" }, "AlertImage": { + "type": "object", "description": "An image attachment on an alert or event.", + "required": [ + "src" + ], "properties": { - "alt": { - "description": "Alt text.", - "type": "string" - }, "href": { - "description": "Optional link URL when the image is clicked.", - "type": "string" + "type": "string", + "description": "Optional link URL when the image is clicked." }, "src": { - "description": "Image source URL or internal image reference (starts with `img_` or `http`).", - "type": "string" + "type": "string", + "description": "Image source URL or internal image reference (starts with `img_` or `http`)." + }, + "alt": { + "type": "string", + "description": "Alternative text shown when the image cannot be displayed; empty when not set." } - }, - "required": [ - "src" - ], - "type": "object" + } }, "AlertInfo": { + "type": "object", "description": "Detailed alert item.", + "required": [ + "alert_id", + "integration_id", + "data_source_id", + "channel_id", + "account_id", + "description", + "title", + "title_rule", + "alert_key", + "alert_severity", + "alert_status", + "start_time", + "last_time", + "end_time", + "labels", + "ever_muted", + "created_at", + "updated_at", + "integration_name", + "integration_type", + "integration_ref_id", + "channel_name", + "channel_status", + "responder_name", + "responder_email", + "event_cnt", + "images", + "data_source_name", + "data_source_ref_id" + ], "properties": { + "alert_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Alert ID (MongoDB ObjectID)." + }, + "integration_id": { + "type": "integer", + "format": "int64", + "description": "Integration ID that produced the alert." + }, + "data_source_id": { + "type": "integer", + "format": "int64", + "description": "Deprecated. Use `integration_id` instead." + }, + "channel_id": { + "type": "integer", + "format": "int64", + "description": "ID of the channel the alert was routed to; its name is in `channel_name`." + }, "account_id": { - "description": "Account ID.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the account that owns this record; the same for every record returned to one `app_key`." }, - "alert_id": { - "description": "Alert ID (MongoDB ObjectID).", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": { + "type": "string", + "description": "Alert description." + }, + "title": { + "type": "string", + "description": "Alert title." + }, + "title_rule": { + "type": "string", + "description": "Title rendering rule." }, "alert_key": { - "description": "Deduplication key used to merge events into the alert.", - "type": "string" + "type": "string", + "description": "Deduplication key used to merge events into the alert." }, "alert_severity": { - "description": "Current severity.", + "type": "string", "enum": [ "Critical", "Warning", "Info", "Ok" ], - "type": "string" + "description": "Current severity." }, "alert_status": { - "description": "Current status.", + "type": "string", "enum": [ "Critical", "Warning", "Info", "Ok" ], - "type": "string" + "description": "Current status." }, - "channel_id": { - "description": "Channel ID.", + "start_time": { + "type": "integer", "format": "int64", - "type": "integer" - }, - "channel_name": { - "description": "Channel display name.", - "type": "string" + "description": "Unix timestamp (seconds) when the alert first fired." }, - "channel_status": { - "description": "Channel status.", - "type": "string" - }, - "created_at": { - "description": "Creation timestamp (seconds).", + "last_time": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp (seconds) of the most recent event." }, - "data_source_id": { - "description": "Deprecated. Use `integration_id` instead.", + "end_time": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp (seconds) when the alert recovered. 0 if still active." }, - "data_source_name": { - "description": "Deprecated. Use `integration_name`.", - "type": "string" - }, - "data_source_ref_id": { - "description": "Deprecated. Use `integration_ref_id`.", - "type": "string" + "labels": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "Alert labels." }, - "data_source_type": { - "description": "Deprecated. Use `integration_type`.", - "type": "string" + "ever_muted": { + "type": "boolean", + "description": "Whether this alert has ever been silenced." }, "deleted_at": { - "description": "Soft-delete timestamp (seconds). Zero if not deleted.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "description": { - "description": "Alert description.", - "type": "string" - }, - "detail_url": { - "description": "Console URL of this alert (`{console}/alert/detail/{alert_id}`). Empty when the deployment has no console base configured.", - "type": "string" + "description": "Soft-delete timestamp (seconds). Zero if not deleted." }, - "end_time": { - "description": "Unix timestamp (seconds) when the alert recovered. 0 if still active.", + "created_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Creation timestamp (seconds)." }, - "event_cnt": { - "description": "Total number of raw events merged into this alert.", + "updated_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update timestamp (seconds)." }, - "events": { - "description": "Raw alert event preview, populated only when requested. Capped at the 20 newest events per alert.", - "items": { - "$ref": "#/components/schemas/AlertEventItem" - }, - "type": "array" + "integration_name": { + "type": "string", + "description": "Integration display name." }, - "ever_muted": { - "description": "Whether this alert has ever been silenced.", - "type": "boolean" + "integration_type": { + "type": "string", + "description": "Plugin type of the integration, such as `prometheus.alert`, `grafana.alert`, `zabbix.alert`, `monit.alert`, or `email.alert`. The set is open and grows with new integrations; `POST /integration/type/list` returns the full list." }, - "images": { - "description": "Attached images.", - "items": { - "$ref": "#/components/schemas/Image" - }, - "type": "array" + "integration_ref_id": { + "type": "string", + "description": "Integration reference ID." }, - "incident": { - "$ref": "#/components/schemas/IncidentShort", - "description": "Parent incident reference, if the alert has been merged into one." + "channel_name": { + "type": "string", + "description": "Channel display name." }, - "integration_id": { - "description": "Integration ID that produced the alert.", - "format": "int64", - "type": "integer" + "channel_status": { + "type": "string", + "description": "Status of the channel: `enabled`, `disabled`, or `deleted`. Empty string when the record has no channel or the channel no longer exists.", + "enum": [ + "enabled", + "disabled", + "deleted", + "" + ] }, - "integration_name": { - "description": "Integration display name.", - "type": "string" + "responder_name": { + "type": "string", + "description": "Always an empty string in API responses; filled only when the alert is rendered for notifications." }, - "integration_ref_id": { - "description": "Integration reference ID.", - "type": "string" + "responder_email": { + "type": "string", + "description": "Always an empty string in API responses; filled only when the alert is rendered for notifications." }, - "integration_type": { - "description": "Integration type string.", - "type": "string" + "incident": { + "$ref": "#/components/schemas/IncidentShort", + "description": "Parent incident reference, if the alert has been merged into one." }, - "labels": { - "additionalProperties": { - "type": "string" + "events": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AlertEventItem" }, - "description": "Alert labels.", - "type": "object" + "description": "Raw alert event preview, populated only when requested. Capped at the 20 newest events per alert." }, - "last_time": { - "description": "Unix timestamp (seconds) of the most recent event.", + "event_cnt": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Total number of raw events merged into this alert." }, - "responder_email": { - "description": "Primary responder email, if any.", - "type": "string" + "images": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/Image" + }, + "description": "Images attached to the alert; `null` when there are none." }, - "responder_name": { - "description": "Primary responder name, if any.", + "detail_url": { + "description": "Console URL of this alert (`{console}/alert/detail/{alert_id}`). Empty when the deployment has no console base configured.", "type": "string" }, - "start_time": { - "description": "Unix timestamp (seconds) when the alert first fired.", - "format": "int64", - "type": "integer" - }, - "title": { - "description": "Alert title.", - "type": "string" + "data_source_name": { + "type": "string", + "description": "Deprecated. Use `integration_name`." }, - "title_rule": { - "description": "Title rendering rule.", - "type": "string" + "data_source_type": { + "type": "string", + "description": "Deprecated; same value as `integration_type`." }, - "updated_at": { - "description": "Last update timestamp (seconds).", - "format": "int64", - "type": "integer" + "data_source_ref_id": { + "type": "string", + "description": "Deprecated. Use `integration_ref_id`." } - }, - "required": [ - "alert_id", - "integration_id", - "data_source_id", - "channel_id", - "account_id", - "description", - "title", - "title_rule", - "alert_key", - "alert_severity", - "alert_status", - "start_time", - "last_time", - "end_time", - "labels", - "ever_muted", - "created_at", - "updated_at", - "integration_name", - "integration_type", - "integration_ref_id", - "channel_name", - "channel_status", - "responder_name", - "responder_email", - "event_cnt", - "images", - "data_source_name", - "data_source_ref_id" - ], - "type": "object" + } }, "AlertInfoRequest": { "properties": { @@ -1457,382 +1499,377 @@ "type": "object" }, "AlertItem": { + "type": "object", "description": "A single alert with full detail.", "properties": { + "alert_id": { + "type": "string", + "description": "Unique alert ID (ObjectID hex string)." + }, + "integration_id": { + "type": "integer", + "format": "int64", + "description": "ID of the integration that produced this alert." + }, + "data_source_id": { + "type": "integer", + "format": "int64", + "description": "Deprecated: use `integration_id` instead.", + "deprecated": true + }, + "channel_id": { + "type": "integer", + "format": "int64", + "description": "ID of the channel the alert belongs to." + }, "account_id": { - "description": "Account ID.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the account that owns the alert." }, - "alert_id": { - "description": "Unique alert ID (ObjectID hex string).", - "type": "string" + "title": { + "type": "string", + "description": "Alert title." }, - "alert_key": { - "description": "Deduplication key.", - "type": "string" + "title_rule": { + "type": "string", + "description": "Title template used to derive `title` from the event labels (e.g. `$service::$cluster`)." + }, + "description": { + "type": "string", + "description": "Alert description." }, "alert_severity": { - "description": "Current severity — the highest severity ever seen on this alert: `Critical`, `Warning`, or `Info`.", + "type": "string", "enum": [ "Critical", "Warning", "Info" ], - "type": "string" + "description": "Current severity — the highest severity ever seen on this alert: `Critical`, `Warning`, or `Info`." }, "alert_status": { - "description": "Current status: `Critical`/`Warning`/`Info` while firing, `Ok` once recovered.", + "type": "string", "enum": [ "Critical", "Warning", "Info", "Ok" ], - "type": "string" - }, - "channel_id": { - "description": "ID of the channel the alert belongs to.", - "format": "int64", - "type": "integer" + "description": "Current status: `Critical`/`Warning`/`Info` while firing, `Ok` once recovered." }, - "channel_name": { - "description": "Display name of the channel.", - "type": "string" + "alert_key": { + "type": "string", + "description": "Deduplication key." }, - "channel_status": { - "description": "Status of the channel: `enabled` or `disabled`.", - "enum": [ - "enabled", - "disabled" - ], - "type": "string" + "start_time": { + "type": "integer", + "format": "int64", + "description": "First-seen time, Unix epoch seconds." }, - "created_at": { - "description": "Creation timestamp, Unix epoch seconds.", + "last_time": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last-event time, Unix epoch seconds." }, - "data_source_id": { - "deprecated": true, - "description": "Deprecated: use `integration_id` instead.", + "end_time": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Resolution time, Unix epoch seconds. 0 if still active." }, - "data_source_name": { - "deprecated": true, - "description": "Deprecated: use `integration_name` instead.", - "type": "string" + "labels": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "Label key-value pairs; `null` when the alert has no labels." }, - "data_source_ref_id": { - "deprecated": true, - "description": "Deprecated: use `integration_ref_id` instead.", - "type": "string" + "ever_muted": { + "type": "boolean", + "description": "True if this alert has ever been silenced." }, - "data_source_type": { - "deprecated": true, - "description": "Deprecated: use `integration_type` instead. Omitted when empty.", - "type": "string" + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation timestamp, Unix epoch seconds." }, - "deleted_at": { - "description": "Soft-delete time, Unix epoch seconds. Omitted when the alert is not deleted.", + "updated_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update timestamp, Unix epoch seconds." }, - "description": { - "description": "Alert description.", - "type": "string" + "integration_name": { + "type": "string", + "description": "Display name of the integration." }, - "detail_url": { - "description": "Console URL of this alert (`{console}/alert/detail/{alert_id}`). Empty when the deployment has no console base configured.", - "type": "string" + "integration_type": { + "type": "string", + "description": "Type key of the integration that produced the alert, e.g. `prometheus.alert` or `zabbix.alert`; same values as `plugin_type` from `POST /integration/type/list`." }, - "end_time": { - "description": "Resolution time, Unix epoch seconds. 0 if still active.", - "format": "int64", - "type": "integer" + "integration_ref_id": { + "type": "string", + "description": "Owner reference of the integration: `a_` for an account-level integration, `c_` for a channel-owned one." + }, + "channel_name": { + "type": "string", + "description": "Display name of the channel." + }, + "channel_status": { + "type": "string", + "description": "Status of the channel: `enabled` or `disabled`.", + "enum": [ + "enabled", + "disabled" + ] + }, + "responder_name": { + "type": "string", + "description": "Responder display name. Always empty in this response — responder tracking lives on the associated incident." + }, + "responder_email": { + "type": "string", + "description": "Responder email. Always empty in this response — responder tracking lives on the associated incident." }, "event_cnt": { - "description": "Total number of raw events received by this alert.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Total number of raw events received by this alert." + }, + "incident": { + "$ref": "#/components/schemas/IncidentShort", + "description": "Associated incident, if any." }, "events": { - "description": "Raw events of this alert. Omitted here; populated only by `POST /incident/alert/list`.", + "type": "array", "items": { "$ref": "#/components/schemas/AlertEventItem" }, - "type": "array" - }, - "ever_muted": { - "description": "True if this alert has ever been silenced.", - "type": "boolean" + "description": "Raw events of this alert. Omitted here; populated only by `POST /incident/alert/list`." }, "images": { - "description": "Images attached to the alert.", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/components/schemas/AlertImage" }, - "type": "array" - }, - "incident": { - "$ref": "#/components/schemas/IncidentShort", - "description": "Associated incident, if any." - }, - "integration_id": { - "description": "ID of the integration that produced this alert.", - "format": "int64", - "type": "integer" - }, - "integration_name": { - "description": "Display name of the integration.", - "type": "string" - }, - "integration_ref_id": { - "description": "External reference ID of the integration.", - "type": "string" - }, - "integration_type": { - "description": "Type/plugin key of the integration.", - "type": "string" - }, - "labels": { - "additionalProperties": { - "type": "string" - }, - "description": "Label key-value pairs.", - "type": "object" - }, - "last_time": { - "description": "Last-event time, Unix epoch seconds.", - "format": "int64", - "type": "integer" - }, - "responder_email": { - "description": "Responder email. Always empty in this response — responder tracking lives on the associated incident.", - "type": "string" + "description": "Images attached to the alert; `null` when there are none." }, - "responder_name": { - "description": "Responder display name. Always empty in this response — responder tracking lives on the associated incident.", + "detail_url": { + "description": "Console URL of this alert (`{console}/alert/detail/{alert_id}`). Empty when the deployment has no console base configured.", "type": "string" }, - "start_time": { - "description": "First-seen time, Unix epoch seconds.", - "format": "int64", - "type": "integer" + "data_source_name": { + "type": "string", + "description": "Deprecated: use `integration_name` instead.", + "deprecated": true }, - "title": { - "description": "Alert title.", - "type": "string" + "data_source_type": { + "type": "string", + "description": "Deprecated: use `integration_type` instead (same value, e.g. `prometheus.alert`). Omitted when empty.", + "deprecated": true }, - "title_rule": { - "description": "Title template used to derive `title` from the event labels (e.g. `$service::$cluster`).", - "type": "string" + "data_source_ref_id": { + "type": "string", + "description": "Deprecated: use `integration_ref_id` instead.", + "deprecated": true }, - "updated_at": { - "description": "Last update timestamp, Unix epoch seconds.", + "deleted_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Soft-delete time, Unix epoch seconds. Omitted when the alert is not deleted." } - }, - "type": "object" + } }, "AlertListByIDsRequest": { + "type": "object", + "required": [ + "alert_ids" + ], "properties": { "alert_ids": { - "description": "Alert IDs (ObjectID hex strings) to fetch.", + "type": "array", "items": { "type": "string" }, - "minItems": 1, - "type": "array" + "description": "Alert IDs (ObjectID hex strings) to fetch. A malformed ID fails the request; IDs not found in the account are left out of the result." } - }, - "required": [ - "alert_ids" - ], - "type": "object" + } }, "AlertListRequest": { + "type": "object", "description": "Filter and pagination criteria for alert list queries. Time range is required.", + "required": [ + "start_time", + "end_time" + ], "properties": { - "alert_ids": { - "description": "Filter to specific alert IDs (ObjectID hex strings). Invalid IDs are ignored; if none are valid, the result is empty.", - "items": { - "type": "string" - }, - "type": "array" - }, - "alert_keys": { - "description": "Filter by alert deduplication keys.", - "items": { - "type": "string" - }, - "type": "array" - }, - "alert_severity": { - "description": "Comma-separated severity filter, e.g. `Critical,Warning`. Allowed values: `Critical`, `Warning`, `Info`, `Ok`.", - "type": "string" - }, - "asc": { - "description": "Sort ascending by `start_time` when `true`; default is descending.", - "type": "boolean" - }, - "by_updated_at": { - "description": "When `true`, the time range filter is applied on `updated_at` rather than `start_time`.", - "type": "boolean" - }, - "channel_ids": { - "description": "Filter by channel IDs.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "start_time": { + "type": "integer", + "format": "int64", + "description": "Start of the search window, Unix epoch seconds, applied to the alert's `start_time`. A value earlier than the account's data retention period is moved up to the retention start." }, "end_time": { - "description": "End of the search window, Unix epoch seconds. Must be greater than `start_time`; the span must not exceed 31 days and must lie within the account's data retention period.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "End of the search window, Unix epoch seconds. Must be greater than `start_time`; the span must not exceed 31 days (7 days with `by_updated_at`). A value before the start of the data retention period returns `InvalidParameter`." }, - "ever_muted": { - "description": "Filter by whether the alert has ever been silenced.", + "p": { "type": [ - "boolean", + "integer", "null" - ] - }, - "integration_ids": { - "description": "Filter by integration IDs.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + ], + "format": "int64", + "description": "Page number, starting at 1. Used when `search_after_ctx` is not provided; `p * limit` must stay within 10,000 records.", + "minimum": 0 }, - "is_active": { - "description": "Filter by lifecycle: `true` returns only firing alerts (status `Critical`/`Warning`/`Info`), `false` returns only recovered alerts (status `Ok`). Omit or pass `null` to return both.", + "limit": { "type": [ - "boolean", + "integer", "null" - ] - }, - "limit": { - "description": "Page size. Max 100, default 20.", + ], "format": "int64", - "maximum": 100, + "description": "Page size. Max 100, default 20.", "minimum": 0, + "maximum": 100 + }, + "search_after_ctx": { "type": [ - "integer", + "string", "null" - ] + ], + "description": "Opaque cursor from the previous response for the next page." }, - "p": { - "description": "Page number, starting at 1. Used when `search_after_ctx` is not provided; `p * limit` must stay within 10,000 records.", - "format": "int64", - "minimum": 0, + "is_active": { "type": [ - "integer", + "boolean", "null" - ] + ], + "description": "Filter by lifecycle: `true` returns only firing alerts (status `Critical`/`Warning`/`Info`), `false` returns only recovered alerts (status `Ok`). Omit or pass `null` to return both." }, - "search_after_ctx": { - "description": "Opaque cursor from the previous response for the next page.", + "ever_muted": { "type": [ - "string", + "boolean", "null" - ] + ], + "description": "Filter by whether the alert has ever been silenced." }, - "start_time": { - "description": "Start of the search window, Unix epoch seconds.", - "format": "int64", - "type": "integer" + "alert_severity": { + "type": "string", + "description": "Comma-separated filter on `alert_severity`, e.g. `Critical,Warning`. Allowed values: `Critical`, `Warning`, `Info`, `Ok`; other values return `InvalidParameter`. `Ok` matches nothing because `alert_severity` is never `Ok`." + }, + "channel_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Filter by channel IDs." + }, + "integration_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Filter by integration IDs." + }, + "alert_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter to specific alert IDs (ObjectID hex strings). Invalid IDs are ignored; if none are valid, the result is empty." + }, + "alert_keys": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter by alert deduplication keys." + }, + "asc": { + "type": "boolean", + "description": "Sort ascending by `start_time` when `true`; default is descending." + }, + "by_updated_at": { + "type": "boolean", + "description": "When `true`, also require the alert's `updated_at` to fall within [`start_time`, `end_time`], in addition to the `start_time` filter; the span must then not exceed 7 days." } - }, - "required": [ - "start_time", - "end_time" - ], - "type": "object" + } }, "AlertListResponse": { + "type": "object", "description": "Paginated list of alerts.", "properties": { + "total": { + "type": "integer", + "format": "int64", + "description": "Number of matching alerts, capped at 1,000." + }, "has_next_page": { - "description": "True if more pages are available.", - "type": "boolean" + "type": "boolean", + "description": "`true` when another page exists. Exact in both cursor mode (`search_after_ctx` sent) and page-number mode, including past the 1,000 cap of `total`." + }, + "search_after_ctx": { + "type": "string", + "description": "Cursor for the next page — the ObjectID hex of the last alert on this page; pass it back as `search_after_ctx`. Omitted when the page is empty; in cursor mode also omitted when there is no next page." }, "items": { - "description": "Alerts on the current page.", + "type": "array", "items": { "$ref": "#/components/schemas/AlertItem" }, - "type": "array" - }, - "search_after_ctx": { - "description": "Cursor for the next page — the ObjectID hex of the last alert on this page; pass it back as `search_after_ctx`. Present only when `has_next_page` is true.", - "type": "string" - }, - "total": { - "description": "Total matching alerts, capped at 1000.", - "format": "int64", - "type": "integer" + "description": "Alerts on the current page." } - }, - "type": "object" + } }, "AlertMergeRequest": { + "type": "object", + "required": [ + "alert_ids", + "incident_id" + ], "properties": { "alert_ids": { - "description": "Alert IDs to merge (ObjectID hex strings); obtain them from `POST /alert/list`. Every ID must belong to the caller's account.", + "type": "array", "items": { "type": "string" }, - "minItems": 1, - "type": "array" - }, - "comment": { - "description": "Optional comment recorded on the merge feed entry. At most 1024 characters.", - "maxLength": 1024, - "type": "string" + "description": "Alert IDs to merge (ObjectID hex strings); obtain them from `POST /alert/list`. Every ID must belong to the caller's account." }, "incident_id": { + "type": "string", "description": "Target incident ID (ObjectID hex string); obtain it from `POST /incident/list`.", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "pattern": "^[0-9a-fA-F]{24}$" }, - "owner_id": { - "description": "Member ID of the new owner for the target incident; obtain it from `POST /member/list`.", - "format": "int64", - "type": "integer" + "comment": { + "type": "string", + "description": "Optional comment recorded on the merge feed entry. At most 1024 characters.", + "maxLength": 1024 }, "title": { + "type": "string", "description": "Optional new title for the target incident. At most 512 characters.", - "maxLength": 512, - "type": "string" + "maxLength": 512 + }, + "owner_id": { + "type": "integer", + "format": "int64", + "description": "Member ID of the new owner for the target incident; obtain it from `POST /member/list`." } - }, - "required": [ - "alert_ids", - "incident_id" - ], - "type": "object" + } }, "AlertPipeline": { + "type": "object", "description": "A single alert processing rule.", "properties": { - "if": { - "description": "AND-filter list — the rule applies only when every condition matches. `null` or omitted means the rule applies to all events.", - "items": { - "$ref": "#/components/schemas/FilterCondition" - }, - "type": [ - "array", - "null" - ] - }, "kind": { - "description": "Rule type. Rules run in array order; when the `if` condition matches, the event is processed according to `kind`.\n| Value | Meaning |\n|---|---|\n| `title_reset` | Rewrites the event title from the `settings.title` template. |\n| `description_reset` | Rewrites the event description from the `settings.description` template. |\n| `severity_reset` | Resets the event severity and status to `settings.severity` (`Critical`/`Warning`/`Info`). |\n| `alert_drop` | Discards the matching event outright; no alert is created. |\n| `alert_inhibit` | Discards the event (inhibition) when an active source alert matching `settings.source_filters` and correlated via `settings.equals` exists. |", + "type": "string", "enum": [ "title_reset", "description_reset", @@ -1840,9 +1877,20 @@ "alert_drop", "alert_inhibit" ], - "type": "string" + "description": "Rule type. Rules run in array order; when the `if` condition matches, the event is processed according to `kind`.\n| Value | Meaning |\n|---|---|\n| `title_reset` | Rewrites the event title from the `settings.title` template. |\n| `description_reset` | Rewrites the event description from the `settings.description` template. |\n| `severity_reset` | Resets the event severity and status to `settings.severity` (`Critical`/`Warning`/`Info`). |\n| `alert_drop` | Discards the matching event outright; no alert is created. |\n| `alert_inhibit` | Discards the event (inhibition) when an active source alert matching `settings.source_filters` and correlated via `settings.equals` exists. |" + }, + "if": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/FilterCondition" + }, + "description": "AND-filter list — the rule applies only when every condition matches the incoming event. Keys: `severity` (aliases `alert_severity`, `event_severity`), `status`, `title`, `title_rule`, `description`, `alert_key`, `integration_id` (alias `data_source_id`), and `labels.`; other keys return `InvalidParameter`. `null` or omitted means the rule applies to all events." }, "settings": { + "type": "object", "description": "Kind-specific settings. Shape depends on `kind`:\n- `title_reset`: `{ \"title\": \"\" }`\n- `description_reset`: `{ \"description\": \"\" }`\n- `severity_reset`: `{ \"severity\": \"Critical\"|\"Warning\"|\"Info\" }`\n- `alert_drop`: `{}` (empty object)\n- `alert_inhibit`: `{ \"equals\": [\"\", ...], \"source_filters\": }`", "oneOf": [ { @@ -1860,14 +1908,12 @@ { "$ref": "#/components/schemas/ApAlertInhibit" } - ], - "type": "object" + ] } }, "required": [ "kind" - ], - "type": "object" + ] }, "AlertPipelineInfoRequest": { "properties": { @@ -1963,27 +2009,26 @@ "type": "object" }, "AlertPipelineUpsertRequest": { + "type": "object", + "required": [ + "integration_id", + "rules" + ], "properties": { "integration_id": { - "description": "Integration ID to configure.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the integration to configure; account-level and channel-owned integrations are both accepted." }, "rules": { - "description": "Rules to apply, evaluated in array order. Between 1 and 50 entries.", + "type": "array", "items": { "$ref": "#/components/schemas/AlertPipeline" }, - "maxItems": 50, - "minItems": 1, - "type": "array" + "description": "Rules to apply, evaluated in array order. At most 50 entries; an empty array removes all rules.", + "maxItems": 50 } - }, - "required": [ - "integration_id", - "rules" - ], - "type": "object" + } }, "AlertRule": { "description": "Full alert rule configuration.", @@ -2174,131 +2219,179 @@ "type": "object" }, "AlertRuleAudit": { + "type": "object", "description": "An audit record capturing a rule snapshot at a point in time.", + "required": [ + "id", + "account_id", + "alert_rule_id", + "action", + "creator_id", + "creator_name", + "created_at" + ], "properties": { + "id": { + "type": "integer", + "format": "uint64", + "description": "Audit record ID." + }, "account_id": { - "description": "ID of the account that owns the rule.", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the account that owns the rule." + }, + "alert_rule_id": { + "type": "integer", + "format": "uint64", + "description": "ID of the alert rule this record belongs to." }, "action": { + "type": "string", "description": "Action performed: `create` = rule created; `update` = rule updated (covers full updates, field-batch updates, imports and moves).", "enum": [ "create", "update" - ], - "type": "string" - }, - "alert_rule_id": { - "description": "ID of the alert rule this record belongs to.", - "format": "uint64", - "type": "integer" + ] }, "content": { - "description": "JSON string of the full rule snapshot at audit time. Populated on `/monit/rule/audit/detail`, omitted on list responses.", - "type": "string" - }, - "created_at": { - "description": "When this audit record was produced, as a Unix timestamp in seconds; equals the rule's `updated_at` at change time.", - "format": "int64", - "type": "integer" + "type": "string", + "description": "JSON string of the full rule right after the change. Populated on `/monit/rule/audit/detail`, omitted on list responses. Records written by `/monit/rule/v2/create` and `/monit/rule/v2/update` use the `AlertRuleV2` shape; records written by `/monit/rule/update/fields` and `/monit/rule/move` use the stored rule shape, whose checker configs carry legacy recovery settings instead of `recovery_mode` / `end_mode`." }, "creator_id": { - "description": "ID of the user who made this change (taken from the rule's `updater_id` at change time).", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the user who made this change (taken from the rule's `updater_id` at change time)." }, "creator_name": { - "description": "Name of the user who made this change (taken from the rule's `updater_name` at change time).", - "type": "string" + "type": "string", + "description": "Name of the user who made this change (taken from the rule's `updater_name` at change time)." }, - "id": { - "description": "Audit record ID.", - "format": "uint64", - "type": "integer" + "created_at": { + "type": "integer", + "format": "int64", + "description": "When this audit record was produced, as a Unix timestamp in seconds; equals the rule's `updated_at` at change time." } - }, + } + }, + "AlertRuleBasic": { + "type": "object", + "description": "Basic alert rule information for list views. In `include_descendants: true` listings only `id`, `folder_id` and `name` are filled; the other fields carry zero values.", "required": [ "id", "account_id", - "alert_rule_id", - "action", + "folder_id", + "name", + "ds_type", + "enabled", + "debug_log_enabled", + "cron_pattern", + "delay_seconds", "creator_id", "creator_name", - "created_at" + "updater_id", + "updater_name", + "created_at", + "updated_at", + "triggered", + "labels", + "timezone", + "active_alert_count" ], - "type": "object" - }, - "AlertRuleBasic": { - "description": "Basic alert rule information for list views.", "properties": { + "id": { + "type": "integer", + "format": "uint64", + "description": "Unique rule ID." + }, "account_id": { - "description": "Account ID.", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the account that owns the rule; `0` in `include_descendants: true` listings." }, - "active_alert_count": { - "description": "Number of currently active (unrecovered) alerts fired by this rule. `triggered` equals `active_alert_count > 0`.", - "format": "int64", - "type": "integer" + "folder_id": { + "type": "integer", + "format": "uint64", + "description": "ID of the folder that directly contains the rule; in `include_descendants: true` listings it can be a descendant of the requested folder." }, - "created_at": { - "description": "Creation time, as a Unix timestamp in seconds.", - "format": "int64", - "type": "integer" + "name": { + "type": "string", + "description": "Rule name, unique within its folder (at most 128 characters)." }, - "creator_id": { - "description": "ID of the user who created the rule.", - "format": "uint64", - "type": "integer" + "labels": { + "type": [ + "object", + "null" + ], + "additionalProperties": { + "type": "string" + }, + "description": "Custom labels the rule adds to its alert events; `null` in `include_descendants: true` listings." }, - "creator_name": { - "description": "Name of the user who created the rule.", - "type": "string" + "ds_type": { + "type": "string", + "description": "Datasource type the rule queries. Types that support alerting: `prometheus`, `elasticsearch`, `loki`, `clickhouse`, `mysql`, `oracle`, `postgres`, `sls`, `tencent_cls`, `victorialogs`. Only enabled rules are checked against this list, so a disabled rule may carry another value; empty in `include_descendants: true` listings." }, - "cron_pattern": { - "description": "Schedule expression: a 6-field cron with seconds, e.g. `0 * * * * *`, or an `@every 30s` interval descriptor. Must not start with `CRON_TZ=` or `TZ=`; use the `timezone` field instead.", - "type": "string" + "enabled": { + "type": "boolean", + "description": "Whether the rule is enabled." }, "debug_log_enabled": { - "description": "Whether debug logging is enabled.", - "type": "boolean" + "type": "boolean", + "description": "Whether debug logging is on; when `true` the edge writes detailed evaluation logs for this rule." }, - "delay_seconds": { - "description": "Evaluation delay in seconds.", - "type": "integer" + "cron_pattern": { + "type": "string", + "description": "Schedule expression: a 6-field cron with seconds, e.g. `0 * * * * *`, or an `@every 30s` interval descriptor. Must not start with `CRON_TZ=` or `TZ=`; use the `timezone` field instead." }, - "ds_type": { - "description": "Data source type, e.g. `prometheus`.", - "type": "string" + "timezone": { + "type": "string", + "description": "Timezone in which the rule executes. Determines how the cron schedule and effective time windows are interpreted. Only IANA timezone names are accepted (e.g. `Asia/Shanghai`, `UTC`, `Europe/London`); shortcuts and offsets such as `Local`, `UTC+8`, or `CST` are rejected. Treated as `Asia/Shanghai` if empty.", + "default": "Asia/Shanghai" }, - "enabled": { - "description": "Whether the rule is enabled.", - "type": "boolean" + "delay_seconds": { + "type": "integer", + "description": "Seconds the evaluation query window is shifted back to allow for data ingestion latency." }, - "folder_id": { - "description": "Folder ID.", + "creator_id": { + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the user who created the rule." }, - "id": { - "description": "Unique rule ID.", + "creator_name": { + "type": "string", + "description": "Name of the user who created the rule." + }, + "updater_id": { + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the user who last modified the rule." }, - "labels": { - "additionalProperties": { - "type": "string" - }, - "description": "Custom labels.", - "type": "object" + "updater_name": { + "type": "string", + "description": "Name of the user who last modified the rule." }, - "name": { - "description": "Rule name.", - "type": "string" + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation time, as a Unix timestamp in seconds." + }, + "updated_at": { + "type": "integer", + "format": "int64", + "description": "Last modification time, as a Unix timestamp in seconds." + }, + "triggered": { + "type": "boolean", + "description": "True if the rule currently has active alerts." + }, + "active_alert_count": { + "type": "integer", + "format": "int64", + "description": "Number of currently active (unrecovered) alerts fired by this rule. `triggered` equals `active_alert_count > 0`." }, "runtime_state": { - "description": "Runtime evaluation state, derived from edge heartbeats and the edge-reported rule status. Omitted when the state is unavailable.\n\n| Value | Meaning |\n|---|---|\n| `disabled` | The rule is disabled. |\n| `offline` | The edge instance or cluster owning this rule is offline. |\n| `abnormal` | The edge reports evaluation errors. |\n| `stale` | The edge's runtime status report is outdated. |\n| `no_datasource` | No datasource currently matches the rule's `ds_list` / `ds_ids`. |\n| `config_pending` | The latest rule config has not been delivered to the edge yet. |\n| `waiting` | Enabled, but the edge has not reported runtime status yet. |\n| `normal` | Evaluating normally. |", + "type": "string", "enum": [ "disabled", "offline", @@ -2309,54 +2402,9 @@ "waiting", "normal" ], - "type": "string" - }, - "timezone": { - "default": "Asia/Shanghai", - "description": "Timezone in which the rule executes. Determines how the cron schedule and effective time windows are interpreted. Only IANA timezone names are accepted (e.g. `Asia/Shanghai`, `UTC`, `Europe/London`); shortcuts and offsets such as `Local`, `UTC+8`, or `CST` are rejected. Treated as `Asia/Shanghai` if empty.", - "type": "string" - }, - "triggered": { - "description": "True if the rule currently has active alerts.", - "type": "boolean" - }, - "updated_at": { - "description": "Last modification time, as a Unix timestamp in seconds.", - "format": "int64", - "type": "integer" - }, - "updater_id": { - "description": "ID of the user who last modified the rule.", - "format": "uint64", - "type": "integer" - }, - "updater_name": { - "description": "Name of the user who last modified the rule.", - "type": "string" + "description": "Runtime evaluation state, derived from edge heartbeats and the edge-reported rule status. Omitted when the state is unavailable.\n\n| Value | Meaning |\n|---|---|\n| `disabled` | The rule is disabled. |\n| `offline` | The edge instance or cluster owning this rule is offline. |\n| `abnormal` | The edge reports evaluation errors. |\n| `stale` | The edge's runtime status report is outdated. |\n| `no_datasource` | No datasource currently matches the rule's `ds_list` / `ds_ids`. |\n| `config_pending` | The latest rule config has not been delivered to the edge yet. |\n| `waiting` | Enabled, but the edge has not reported runtime status yet. |\n| `normal` | Evaluating normally. |" } - }, - "required": [ - "id", - "account_id", - "folder_id", - "name", - "ds_type", - "enabled", - "debug_log_enabled", - "cron_pattern", - "delay_seconds", - "creator_id", - "creator_name", - "updater_id", - "updater_name", - "created_at", - "updated_at", - "triggered", - "labels", - "timezone", - "active_alert_count" - ], - "type": "object" + } }, "AlertRuleCounter": { "description": "One historical snapshot of the account's alert rule total.", @@ -2516,96 +2564,97 @@ "type": "object" }, "ApAlertDrop": { - "description": "Settings for `alert_drop` rule: no additional settings required. Matched alerts are silently discarded.", - "properties": {}, - "type": "object" + "type": "object", + "description": "Settings for `alert_drop`: no fields; send `{}`. A matching event is discarded and no alert is created or updated.", + "properties": {} }, "ApAlertInhibit": { - "description": "Settings for `alert_inhibit` rule: suppresses source alerts that match the filter when they share the same label values as the current alert.", + "type": "object", + "description": "Settings for `alert_inhibit`: the current event is discarded when an active alert of the same integration, with a different `alert_key` and started within the 10 minutes before the event, matches `source_filters` and has the same value as the event for every `equals` key.", + "required": [ + "equals", + "source_filters" + ], "properties": { "equals": { - "description": "Label keys whose values must be equal between the source and current alert for inhibition to apply.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Keys whose values must be equal on the source alert and the current event: `title`, `severity`, or `labels.`. An empty list, any other key, or a label missing on the event means the rule never inhibits." }, "source_filters": { - "description": "AND-filter list identifying the source alerts to inhibit — every condition must match.", + "type": "array", "items": { "$ref": "#/components/schemas/FilterCondition" }, - "type": "array" + "description": "AND-conditions a source alert must meet. Allowed keys: `severity`, `title`, and `labels.`; other keys return `InvalidParameter`." } - }, - "required": [ - "equals", - "source_filters" - ], - "type": "object" + } }, "ApDescriptionReset": { - "description": "Settings for `description_reset` rule: overrides the alert description.", - "properties": { - "description": { - "description": "New description template.", - "type": "string" - } - }, + "type": "object", + "description": "Settings for `description_reset`: replaces the event description with a rendered template.", "required": [ "description" ], - "type": "object" + "properties": { + "description": { + "type": "string", + "description": "Description template. Only a value starting with `[TPL]` takes effect: the rest is rendered as a Go template against the event and replaces the description. A value without the prefix leaves the description unchanged." + } + } }, "ApSeverityReset": { - "description": "Settings for `severity_reset` rule: forces the alert severity to a fixed value.", + "type": "object", + "description": "Settings for `severity_reset`: sets the event severity, and its status, to a fixed value.", + "required": [ + "severity" + ], "properties": { "severity": { - "description": "Target severity level.", + "type": "string", "enum": [ "Critical", "Warning", "Info" ], - "type": "string" + "description": "Severity to set: `Critical`, `Warning` or `Info`. The event status is set to the same value." } - }, - "required": [ - "severity" - ], - "type": "object" + } }, "ApTitleReset": { - "description": "Settings for `title_reset` rule: overrides the alert title with a template string.", - "properties": { - "title": { - "description": "New title template. Supports Golang template syntax referencing alert fields.", - "type": "string" - } - }, + "type": "object", + "description": "Settings for `title_reset`: replaces the event title using a title rule.", "required": [ "title" ], - "type": "object" + "properties": { + "title": { + "type": "string", + "description": "Title rule. A value starting with `[TPL]` is a Go template rendered against the event, e.g. `[TPL]{{.Labels.service}}`. Otherwise it is a `::`-separated list in which each `$name` part is replaced by the value of label `name` and other parts are kept as written." + } + } }, "ArtifactFileStateItem": { - "description": "Live publish state of one presented file. Returned only for files that have a live published artifact.", + "type": "object", + "description": "Live gallery state of one presented file. Matched by the file's source session and workspace path, so an older version of a republished file also reports the current artifact.", "properties": { - "artifact_id": { - "description": "Artifact ID (`art_` prefix). Also the key of the public-share link.", - "type": "string" - }, "file_id": { - "description": "Echoes the requested presented-file ID.", - "type": "string" + "type": "string", + "description": "The requested presented-file ID this entry answers for." }, - "gallery_path": { - "description": "Console-relative path of the artifact page: `/ai-sre/artifacts/`.", - "type": "string" + "artifact_id": { + "type": "string", + "description": "Artifact ID (`art_` prefix). Also the key of the public-share link." }, "title": { - "description": "Gallery display title of the published artifact.", - "type": "string" + "type": "string", + "description": "Gallery display title of the published artifact." + }, + "gallery_path": { + "type": "string", + "description": "Console-relative path of the artifact page: `/ai-sre/artifacts/`." } }, "required": [ @@ -2613,42 +2662,41 @@ "artifact_id", "title", "gallery_path" - ], - "type": "object" + ] }, "ArtifactFileStateRequest": { + "type": "object", "description": "Probe publish state for a batch of presented files.", "properties": { "file_ids": { - "description": "Presented-file IDs (`pf_` prefix) to probe. At most 50 per call; duplicates and empty strings are ignored.", + "type": "array", "items": { "type": "string" }, "maxItems": 50, "minItems": 1, - "type": "array" + "description": "Presented-file IDs (`pf_` prefix) to check. At most 50 entries per call, counted before duplicates and empty strings are removed; more fails with `InvalidParameter`." } }, "required": [ "file_ids" - ], - "type": "object" + ] }, "ArtifactFileStateResponse": { + "type": "object", "description": "Publish states keyed by file.", "properties": { "items": { - "description": "One entry per requested file that has a live published artifact; files without one are omitted.", + "type": "array", "items": { "$ref": "#/components/schemas/ArtifactFileStateItem" }, - "type": "array" + "description": "One entry per requested file whose session file path currently has a live gallery artifact; files without one, and unknown IDs, are omitted. An empty array when none match." } }, "required": [ "items" - ], - "type": "object" + ] }, "ArtifactIdRequest": { "description": "Identify one gallery artifact.", @@ -2664,74 +2712,76 @@ "type": "object" }, "ArtifactListRequest": { + "type": "object", "description": "Filter and paginate the artifact gallery.", "properties": { - "asc": { - "description": "Sort ascending when true, descending when false. Applies only when `orderby` is set.", - "type": "boolean" - }, - "limit": { - "default": 20, - "description": "Page size. Defaults to 20; capped at 100.", - "maximum": 100, - "type": "integer" - }, - "orderby": { - "description": "Sort field: `created_at` or `updated_at`. Empty means `updated_at` descending.", - "enum": [ - "created_at", - "updated_at" - ], - "type": "string" - }, - "page": { - "default": 1, - "description": "Page number, 1-based.", - "minimum": 1, - "type": "integer" - }, - "query": { - "description": "Case-insensitive substring match on the artifact title.", - "type": "string" - }, "scope": { - "default": "all", - "description": "Visibility scope. `all` (default) lists the caller's own personal artifacts plus artifacts of every team the caller belongs to; `personal` lists only the caller's own; `team` lists only team-owned artifacts of the caller's teams.", + "type": "string", "enum": [ "all", "personal", "team" ], - "type": "string" + "default": "all", + "description": "Visibility scope. `all` (default) lists the caller's own personal artifacts plus artifacts of every team the caller belongs to; `personal` lists only the caller's own; `team` lists only team-owned artifacts of the caller's teams." }, "team_ids": { - "description": "Restrict to artifacts owned by these team IDs, intersected with the caller's visibility — teams the caller does not belong to silently return nothing.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Restrict to artifacts owned by these team IDs, intersected with the `scope` filter. Non-positive IDs are ignored; teams the caller does not belong to return nothing, and personal artifacts are excluded whenever this is set." + }, + "query": { + "type": "string", + "description": "Case-insensitive substring match on the artifact title." + }, + "page": { + "type": "integer", + "default": 1, + "description": "Page number, 1-based. Values below 1 are treated as 1." + }, + "limit": { + "type": "integer", + "default": 20, + "description": "Number of artifacts per page. Values below 1 fall back to 20; values above 100 are capped at 100 (not rejected)." + }, + "orderby": { + "type": "string", + "enum": [ + "created_at", + "updated_at" + ], + "description": "Sort field: `created_at` (publish time) or `updated_at` (last change). Empty sorts by `updated_at` descending. In every case the caller's pinned artifacts come first, and `artifact_id` breaks ties." + }, + "asc": { + "type": "boolean", + "description": "Sort ascending when true, descending when false. Applies only when `orderby` is set." } - }, - "type": "object" + } }, "ArtifactListResponse": { + "type": "object", "description": "A page of gallery artifacts.", "properties": { "items": { - "description": "Artifacts on this page.", + "type": "array", "items": { "$ref": "#/components/schemas/PublishedArtifactItem" }, - "type": "array" + "description": "Artifacts on this page; the caller's pinned artifacts come first. An empty array when nothing matches." }, "total": { - "description": "Total number of artifacts matching the filter across all pages.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Total number of artifacts matching the filter across all pages." } }, - "type": "object" + "required": [ + "items", + "total" + ] }, "ArtifactPublishFromFileRequest": { "description": "Publish a session-produced file to the artifact gallery.", @@ -2775,29 +2825,30 @@ "type": "object" }, "ArtifactShareState": { + "type": "object", "description": "Public-share state of an artifact.", "properties": { "artifact_id": { - "description": "Artifact ID (`art_` prefix). Also the key of the public-share link.", - "type": "string" - }, - "public_url": { - "description": "Anonymous public link served entirely from CDN. Anyone with the link can view the content, no login required.", - "type": "string" + "type": "string", + "description": "Artifact ID (`art_` prefix). Also the key of the public-share link." }, "share_enabled": { - "description": "Always `true` in this response.", - "type": "boolean" + "type": "boolean", + "description": "Always `true` in this response." }, - "shared_at": { - "description": "Unix timestamp in milliseconds of the last share enable or snapshot sync.", - "format": "int64", - "type": "integer" + "public_url": { + "type": "string", + "description": "Anonymous public link, `/share/artifact/`. Anyone with the link can view the content without signing in. The link is the same on every enable." }, "shared_by": { - "description": "Person ID of the member who enabled sharing.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Person ID of the member who enabled sharing. A snapshot sync keeps the original value." + }, + "shared_at": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in milliseconds of the last share enable or snapshot sync." } }, "required": [ @@ -2806,8 +2857,7 @@ "public_url", "shared_by", "shared_at" - ], - "type": "object" + ] }, "ArtifactSignRequest": { "description": "Request signed download/preview URLs for a presented file.", @@ -2827,247 +2877,259 @@ "type": "object" }, "ArtifactUpdateRequest": { + "type": "object", "description": "Partial update of a gallery artifact. Only provided fields change.", "properties": { "artifact_id": { - "description": "Artifact ID (`art_` prefix). Also the key of the public-share link.", - "type": "string" + "type": "string", + "description": "Artifact ID (`art_` prefix). Also the key of the public-share link." }, - "team_id": { - "description": "Transfer target scope. `0` moves the artifact to personal scope (only the creator can manage it); a positive value moves it to a team the caller must belong to. Omit to leave unchanged.", - "format": "int64", + "title": { "type": [ - "integer", + "string", "null" - ] + ], + "description": "New title. Leading and trailing spaces are trimmed; a blank value fails with `InvalidParameter`. Omit or send `null` to keep the current title." }, - "title": { - "description": "New title. Trimmed; must be non-empty when provided. Omit to leave unchanged.", + "team_id": { "type": [ - "string", + "integer", "null" - ] + ], + "format": "int64", + "description": "Transfer target. `0` moves the artifact to personal scope and only its creator may do that; a positive value moves it to that team, and the caller must be a member of the team; a negative value fails with `InvalidParameter`. Omit or send `null` to keep the current scope. The creator (`person_id`) never changes." } }, "required": [ "artifact_id" - ], - "type": "object" + ] }, "AssignIncidentRequest": { + "type": "object", "description": "Parameters for dispatching one or more incidents to a target. Provide `incident_id` or `incident_ids` but not both.", + "required": [ + "assigned_to" + ], "properties": { - "assigned_to": { - "$ref": "#/components/schemas/AssignedTo", - "description": "Assign target; at least one of `person_ids` and `escalate_rule_id` must be set." - }, "incident_id": { - "description": "Single incident ID. Ignored when `incident_ids` is also provided.", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Single incident ID. Ignored when `incident_ids` is also provided." }, "incident_ids": { - "description": "Incident IDs to assign in bulk; obtain them from `POST /incident/list`.", + "type": "array", "items": { - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$" }, - "maxItems": 100, "minItems": 1, - "type": "array" + "maxItems": 100, + "description": "Incident IDs to assign in bulk; obtain them from `POST /incident/list`." + }, + "assigned_to": { + "$ref": "#/components/schemas/AssignedTo", + "description": "Assignment target. Set `person_ids`, `escalate_rule_id`, or `emails`; when none is set, the server re-runs the channel's escalation rule matching." } - }, - "required": [ - "assigned_to" - ], - "type": "object" + } }, "AssignedTo": { - "description": "Incident assignment target. Either `person_ids` or `escalate_rule_id` must be provided.", + "type": "object", + "description": "Assignment target. In requests, set `person_ids`, `escalate_rule_id`, or `emails`; when none is set the server re-runs the channel's escalation rule matching. In responses the object is always present; an incident that was never assigned has empty `type`, `id`, and `assigned_at` of `0`.", "properties": { - "assigned_at": { - "description": "Unix timestamp (seconds) when the assignment was made.", - "format": "int64", - "type": "integer" - }, - "emails": { - "description": "Email recipients, used by integrations such as ServiceNow.", + "person_ids": { + "type": "array", "items": { - "format": "email", - "type": "string" + "type": "integer", + "format": "int64" }, - "maxItems": 100, "minItems": 1, - "type": "array" + "maxItems": 100, + "description": "Member IDs to assign directly." }, "escalate_rule_id": { - "description": "Escalation rule ID (MongoDB ObjectID) to drive assignment.", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Escalation rule ID (MongoDB ObjectID) to drive assignment." }, - "escalate_rule_name": { - "description": "Escalation rule display name, filled by the server.", - "type": "string" + "layer_idx": { + "type": "integer", + "description": "Zero-based escalation level within `escalate_rule_id` (`0` = first level). Responders are taken from this level." }, - "id": { - "description": "Opaque assignment ID generated by the server.", - "type": "string" + "type": { + "type": "string", + "description": "How the assignment happened: `assign` first assignment; `reassign` reassignment of an already assigned incident; `escalate` moved by the escalation flow; `reopen` reassignment after the incident was reopened; empty string in responses when the incident was never assigned. Omit it in requests and the server derives it.", + "enum": [ + "assign", + "reassign", + "escalate", + "reopen", + "" + ] }, - "layer_idx": { - "description": "Current level index within the escalation rule.", - "type": "integer" + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "maxItems": 100, + "description": "Member emails; each is resolved to a member ID and merged into `person_ids`. Emails without a matching member are ignored." }, "notify": { + "type": "object", "description": "Override the notification channels used for this assignment.", "properties": { "follow_preference": { - "description": "When false, use `personal_channels`; when true or omitted, use each responder's personal preference.", "type": [ "boolean", "null" - ] + ], + "description": "`true`: notify each person through their personal notification preference. `false`: use `personal_channels`, which must then be non-empty. When omitted, `personal_channels` must be set." }, "personal_channels": { - "description": "Channels to use (e.g. `voice`, `sms`, `email`).", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Channels used when `follow_preference` is `false`: `sms`, `voice`, `email`, `push` (mobile app push), or an IM app channel written as `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:`, or `teams_app:`. Ignored when `follow_preference` is `true`." }, "template_id": { - "description": "Notification template ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Notification template ID (MongoDB ObjectID)." } - }, - "type": "object" + } }, - "person_ids": { - "description": "Member IDs to assign directly.", + "escalate_rule_name": { + "type": "string", + "description": "Escalation rule name, filled by the server in responses; ignored in requests." + }, + "assigned_at": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp (seconds) when the assignment was made; set by the server." + }, + "id": { + "type": "string", + "description": "Assignment ID generated by the server for each assignment; set by the server." + }, + "effective_person_ids": { + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "maxItems": 100, - "minItems": 1, - "type": "array" - }, - "type": { - "description": "Assignment type: `assign` direct assignment, `reassign` reassignment, `escalate` escalation-rule driven, `reopen` automatic reassignment on reopen.", - "enum": [ - "assign", - "reassign", - "escalate", - "reopen" - ], - "type": "string" + "description": "Member IDs that actually received the assignment: `person_ids` plus the members of the selected escalation level, deduplicated and sorted. Set by the server; omitted when empty." } - }, - "type": "object" + } }, "AuditLog": { + "type": "object", "description": "A single audit log entry.", + "required": [ + "created_at", + "account_id", + "member_id", + "member_name", + "request_id", + "ip", + "operation", + "operation_name", + "body", + "params", + "is_dangerous", + "is_write", + "principal_kind", + "credential_type", + "credential_id" + ], "properties": { - "account_id": { - "description": "ID of the account.", - "format": "uint64", - "type": "integer" - }, - "body": { - "description": "JSON-encoded request body. Bodies containing sensitive fields are base64url-encoded instead; bodies over 10 KB are replaced by a truncation placeholder.", - "type": "string" - }, "created_at": { - "description": "Timestamp of the operation in Unix epoch milliseconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Timestamp of the operation in Unix epoch milliseconds." }, - "credential_id": { - "description": "ID of the credential (the app key ID) when `credential_type` is `app_key`; 0 otherwise.", + "account_id": { + "type": "integer", "format": "uint64", - "type": "integer" - }, - "credential_type": { - "description": "Credential type used for the call. `app_key` for a long-lived console app key, `ephemeral_app_key` for a short-lived key issued to AI SRE, and an empty string for member sessions.", - "type": "string" - }, - "ip": { - "description": "Client IP address of the caller.", - "type": "string" - }, - "is_dangerous": { - "description": "True if this is flagged as a high-risk operation.", - "type": "boolean" - }, - "is_write": { - "description": "True for mutating operations; false for read-only ones.", - "type": "boolean" + "description": "ID of the account the entry belongs to." }, "member_id": { - "description": "ID of the member who performed the action. 0 when the action was performed by the account principal itself.", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the member who performed the action. 0 when the action was performed by the account principal itself." }, "member_name": { - "description": "Display name of the member. Empty when `member_id` is 0.", - "type": "string" + "type": "string", + "description": "Display name of the member. Empty when `member_id` is 0." + }, + "request_id": { + "type": "string", + "description": "Unique request ID for correlation." + }, + "ip": { + "type": "string", + "description": "Client IP address of the caller." }, "operation": { - "description": "Stable machine-readable operation name, e.g. `template:write:create`.", - "type": "string" + "type": "string", + "description": "Stable machine-readable operation name, e.g. `template:write:create`." }, "operation_name": { - "description": "Human-readable Chinese label of the operation (e.g. `创建模板`).", - "type": "string" + "type": "string", + "description": "Human-readable Chinese label of the operation (e.g. `创建模板`)." + }, + "body": { + "type": "string", + "description": "JSON-encoded request body. Bodies containing sensitive fields are base64url-encoded instead; bodies over 10 KB are replaced by a truncation placeholder." }, "params": { - "description": "URL path parameters as an array of key-value pairs, or an empty array when none.", + "type": [ + "array", + "string" + ], "items": { + "type": "object", "properties": { "Key": { - "description": "Name of a URL path parameter (the `:xxx` placeholder in the route).", - "type": "string" + "type": "string", + "description": "Name of a URL path parameter (the `:xxx` placeholder in the route)." }, "Value": { - "description": "The actual value of that path parameter in this request.", - "type": "string" + "type": "string", + "description": "The actual value of that path parameter in this request." } - }, - "type": "object" + } }, - "type": "array" + "description": "URL path parameters as an array of `Key`/`Value` pairs (an empty array when none). Some deployments return the same array as a JSON-encoded string." + }, + "is_dangerous": { + "type": "boolean", + "description": "True if this is flagged as a high-risk operation." + }, + "is_write": { + "type": "boolean", + "description": "True for mutating operations; false for read-only ones." }, "principal_kind": { - "description": "Kind of the caller. `member` — an interactive member session; `service` — an app key credential.", + "type": "string", "enum": [ "member", "service" ], - "type": "string" + "description": "Kind of the caller. `member` — a member or account-owner session; `service` — an app key or a short-lived key issued to AI SRE." }, - "request_id": { - "description": "Unique request ID for correlation.", - "type": "string" + "credential_type": { + "type": "string", + "description": "Credential type used for the call. `app_key` for a long-lived console app key, `ephemeral_app_key` for a short-lived key issued to AI SRE, and an empty string for member sessions." + }, + "credential_id": { + "type": "integer", + "format": "uint64", + "description": "ID of the credential (the app key ID) when `credential_type` is `app_key`; 0 otherwise." } - }, - "required": [ - "created_at", - "account_id", - "member_id", - "member_name", - "request_id", - "ip", - "operation", - "operation_name", - "body", - "params", - "is_dangerous", - "is_write", - "principal_kind", - "credential_type", - "credential_id" - ], - "type": "object" + } }, "AuditOperationListRequest": { "additionalProperties": false, @@ -3111,82 +3173,82 @@ "type": "object" }, "AuditRecordIDRequest": { + "type": "object", + "required": [ + "id" + ], "properties": { "id": { - "description": "Audit record ID — the `id` of an audit row returned by `POST /monit/rule/audits`, NOT the rule ID. Passing a rule ID returns HTTP 400.", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "Audit record ID — the `id` of a row returned by `POST /monit/rule/audits`, not the rule ID. A rule ID is looked up as an audit record ID, which usually returns `InvalidParameter` (`alert rule audit not found`) or an unrelated record." } - }, - "required": [ - "id" - ], - "type": "object" + } }, "AuditSearchRequest": { + "type": "object", "description": "Filter criteria for audit log search. Time range is required.", + "required": [ + "start_time", + "end_time" + ], "properties": { + "start_time": { + "type": "integer", + "format": "int64", + "description": "Start of the search window, Unix epoch seconds. Exclusive — entries at exactly this second are not included.", + "example": 1712620800, + "minimum": 1 + }, "end_time": { + "type": "integer", + "format": "int64", "description": "End of the search window, Unix epoch seconds. Inclusive. Must be after `start_time`; maximum span 90 days.", "example": 1712707200, - "format": "int64", - "minimum": 1, - "type": "integer" - }, - "is_dangerous": { - "description": "When true, return only high-risk (dangerous) operations.", - "type": [ - "boolean", - "null" - ] - }, - "is_write": { - "description": "When true, return only write operations; when false, return only read operations.", - "type": [ - "boolean", - "null" - ] + "minimum": 1 }, "limit": { - "description": "Page size, 0–99. Omit or set to 0 for no page-size cap — all matching rows in the window are returned.", - "example": 20, - "maximum": 99, + "type": "integer", + "description": "Page size, 0–99. Omit or set to 0 to let the server choose the page size (it may return every matching entry).", "minimum": 0, - "type": "integer" + "maximum": 99, + "example": 20 + }, + "request_id": { + "type": "string", + "description": "Filter to a single request by its unique request ID." + }, + "search_after_ctx": { + "type": "string", + "description": "Opaque pagination cursor returned by the previous response. Leave empty for the first page." }, "operations": { - "description": "Filter to specific operation names. Use `POST /audit/operation/list` to get the valid set.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Filter to specific operation names. Use `POST /audit/operation/list` to get the valid set." }, "person_id": { - "description": "Filter by the operator's member ID (get IDs from `POST /member/list`). Pass the account ID to match actions performed by the account principal itself.", + "type": "integer", "format": "uint64", - "type": "integer" - }, - "request_id": { - "description": "Filter to a single request by its unique request ID.", - "type": "string" + "description": "Filter by the operator's member ID (get IDs from `POST /member/list`). Pass the account ID to match actions performed by the account principal itself." }, - "search_after_ctx": { - "description": "Opaque pagination cursor returned by the previous response. Leave empty for the first page.", - "type": "string" + "is_dangerous": { + "type": [ + "boolean", + "null" + ], + "description": "When true, return only high-risk (dangerous) operations." }, - "start_time": { - "description": "Start of the search window, Unix epoch seconds. Exclusive — entries at exactly this second are not included.", - "example": 1712620800, - "format": "int64", - "minimum": 1, - "type": "integer" + "is_write": { + "type": [ + "boolean", + "null" + ], + "description": "When true, return only write operations; when false, return only read operations." } - }, - "required": [ - "start_time", - "end_time" - ], - "type": "object" + } }, "AuditSearchResponse": { "description": "Cursor-paginated audit log search result.", @@ -3216,109 +3278,134 @@ "type": "object" }, "AutomationRuleCreateRequest": { + "type": "object", "description": "Create an Automation rule.", "properties": { - "cron_expr": { - "description": "Run cadence. Supports 4 fields (`hour day month weekday`, minute defaults to 0) and 5 fields (`minute hour day month weekday`). The minute must be one fixed integer; 6-field seconds are not supported. A cron that sets both day-of-month and day-of-week is rejected. The create API currently requires this field even for HTTP-POST-only rules; send a valid cron and set `schedule_trigger_enabled=false`.", - "example": "15 9 * * *", - "type": "string" + "name": { + "type": "string", + "minLength": 1, + "maxLength": 255, + "description": "Display name of the rule, 1–255 characters; leading and trailing spaces are trimmed." + }, + "team_id": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "Scope of the rule. `0` or omitted: a personal rule owned by the caller. `>0`: a team rule; the caller must be a member of that team. The scope cannot be changed after creation." + }, + "run_in": { + "type": "string", + "enum": [ + "web", + "current-chat" + ], + "description": "Where the rule's runs execute. `web` (default): in a web console session. `current-chat`: in the IM chat the rule is created from; accepted only from a live IM conversation with the AI SRE agent, so API calls that send it get `400`." }, "enabled": { - "description": "Whether the rule is enabled after creation. Omitted API value is false; Chat/CLI create sends true by default unless the user asks for disabled.", - "type": "boolean" + "type": "boolean", + "description": "Whether the rule's automatic triggers (schedule, HTTP POST, On-call incident, war room) are armed after creation. Defaults to `false`. Manual runs work either way." }, - "environment_id": { - "description": "BYOC Runner ID. Used only when `environment_kind=byoc`.", - "type": "string" + "cron_expr": { + "type": "string", + "description": "Schedule in local time of `timezone`. Accepts 4 fields (`hour day month weekday`, minute defaults to 0) or 5 fields (`minute hour day month weekday`). The minute must be one fixed integer; seconds (6 fields) are not supported; setting both day-of-month and day-of-week is rejected. Required even for rules that use only other triggers: send a valid expression with `schedule_trigger_enabled=false`.", + "example": "15 9 * * *" + }, + "timezone": { + "type": "string", + "description": "IANA time zone name used to evaluate `cron_expr`, e.g. `Asia/Shanghai`. Ambiguous names such as `Local`, `CST`, `UTC+8`, and `GMT+8` are rejected. When omitted: the caller's member time zone, then the account time zone, then `Asia/Shanghai`." + }, + "schedule_trigger_enabled": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the schedule trigger is enabled. Defaults to `true` when omitted; send `false` for rules that should fire only from other triggers." + }, + "prompt": { + "type": "string", + "minLength": 1, + "description": "Task instruction sent to the AI SRE agent on every run. Must not be empty after trimming spaces." }, "environment_kind": { + "type": "string", "description": "Runtime environment kind. Omit or send an empty value for automatic selection. One of: `cloud` (platform-hosted cloud sandbox), `byoc` (a self-hosted BYOC runner in the account, used with `environment_id`); automatic selection prefers an online BYOC runner and falls back to the cloud sandbox.", "enum": [ "", "cloud", "byoc" - ], - "type": "string" + ] + }, + "environment_id": { + "type": "string", + "description": "BYOC runner ID. Required when `environment_kind=byoc` and rejected for other kinds. A personal rule can only use account-scope runners; a team rule can use account-scope runners or runners of its own team." }, "http_post_trigger_enabled": { - "description": "Whether to create and enable an HTTP POST trigger. When enabled, the response includes a one-time token.", - "type": "boolean" + "type": "boolean", + "description": "Whether to create an enabled HTTP POST trigger. When `true`, the response carries `http_post_trigger_url` and the one-time `http_post_token`." }, - "name": { - "description": "Rule name.", - "maxLength": 255, - "minLength": 1, - "type": "string" + "oncall_incident_trigger_enabled": { + "type": "boolean", + "description": "Whether the On-call incident trigger is enabled. When the trigger is created (this is `true`, or channel IDs or severities are sent), both `oncall_incident_channel_ids` and `oncall_incident_severities` must be non-empty." }, "oncall_incident_channel_ids": { - "description": "On-call integration IDs to watch. Creating or enabling this trigger requires at least one valid ID.", + "type": "array", "items": { + "type": "integer", "format": "int64", - "minimum": 1, - "type": "integer" + "minimum": 1 }, - "type": "array" + "description": "Channel IDs to watch; incidents in these channels can start a run. Each ID must be positive." }, "oncall_incident_severities": { - "description": "Incident severities to watch. Supported values are Critical, Warning, and Info; creating or enabling this trigger requires at least one value.", + "type": "array", "items": { + "type": "string", "enum": [ "Critical", "Warning", "Info" - ], - "type": "string" + ] }, - "type": "array" - }, - "oncall_incident_trigger_enabled": { - "description": "Whether the On-call incident trigger is enabled.", - "type": "boolean" - }, - "prompt": { - "description": "Task prompt sent to the AI SRE agent on each run.", - "minLength": 1, - "type": "string" - }, - "run_in": { - "description": "Execution destination. `current-chat` binds the rule to the authenticated live IM conversation; `web` runs in the web console. Omit it so the server selects `current-chat` for an authenticated IM invocation and `web` otherwise. The server rejects `current-chat` outside a live IM conversation.", - "enum": [ - "current-chat", - "web", - null - ], - "type": [ - "string", - "null" - ] + "description": "Incident severities to watch: `Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels." }, - "schedule_trigger_enabled": { - "description": "Whether the schedule trigger is enabled. Defaults to true when omitted; HTTP-POST-only rules should send false.", + "oncall_incident_merge_similar": { "type": [ "boolean", "null" - ] + ], + "description": "Whether to merge similar incidents into one analysis. When `true` (default), an incident that closely resembles one already being analyzed by this rule (a run in progress or finished within the last 10 minutes) joins that run's session instead of starting a new one; its own run is recorded as `skipped` with `joined_session_id` set. When `false`, every matching incident starts its own run." }, - "team_id": { - "description": "Scope team ID. Explicit 0 means personal scope; >0 means a team in the account. Omit it to inherit the authenticated IM conversation scope when one is available, otherwise let the server select the normal default. A current-chat rule must match that conversation's scope.", - "format": "int64", - "minimum": 0, - "type": [ - "integer", - "null" - ] + "war_room_trigger_enabled": { + "type": "boolean", + "description": "Whether the war room trigger is enabled. It fires when a war room (IM group chat) is created for an incident in one of `war_room_channel_ids` with a severity in `war_room_severities`; the agent then runs inside that group chat. When the trigger is created (this is `true`, or `war_room_channel_ids` is sent), both lists must be non-empty." }, - "timezone": { - "description": "IANA timezone `cron_expr` is evaluated in, e.g. `Asia/Shanghai`. Must be a timezone name loadable by the server; an invalid value is rejected. Defaults to the caller's member timezone, then the account timezone, then the server default (Asia/Shanghai) when omitted.", - "type": "string" + "war_room_channel_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64", + "minimum": 1 + }, + "description": "Channel IDs whose war rooms start a run. Each ID must be positive." + }, + "war_room_severities": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info" + ] + }, + "description": "Incident severities that start a run when their war room is created: `Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels." } }, "required": [ "name", "cron_expr", "prompt" - ], - "type": "object" + ] }, "AutomationRuleIDRequest": { "properties": { @@ -3332,200 +3419,279 @@ ], "type": "object" }, - "AutomationExecutionLocation": { - "description": "Read-only Automation execution destination. It never includes a chat, integration, or session identifier.", + "AutomationRuleItem": { + "type": "object", + "description": "Automation rule.", "properties": { - "chat_name": { - "description": "Display name of the bound IM conversation when available.", - "type": "string" + "rule_id": { + "type": "string", + "description": "Rule ID (prefix `arule_`). Pass it as `rule_id` to get, update, delete, run, and list-runs calls." }, - "conversation_mode": { - "description": "Bound IM conversation mode when execution place is `im`.", - "type": "string" + "account_id": { + "type": "integer", + "format": "int64", + "description": "ID of the account that owns the rule." }, - "description": { - "description": "Human-readable destination description.", - "type": "string" + "team_id": { + "type": "integer", + "format": "int64", + "description": "Scope team ID; `0` means a personal rule. Fixed at creation." }, - "place": { - "description": "Execution destination: `im` or `web_console`.", - "enum": [ - "im", - "web_console" - ], - "type": "string" + "owner_id": { + "type": "integer", + "format": "int64", + "description": "Person ID of the member who created the rule. For a personal rule, the only person who can manage it." }, - "platform": { - "description": "IM platform when execution place is `im`.", - "type": "string" + "name": { + "type": "string", + "description": "Display name of the rule." + }, + "enabled": { + "type": "boolean", + "description": "Whether the rule's automatic triggers are armed. A disabled rule can still be run manually. A personal rule is disabled automatically when its owner leaves the account." }, "run_scope": { - "description": "Pinned execution scope: `person` or `team`.", + "type": "string", "enum": [ "person", "team" ], - "type": "string" - }, - "team_id": { - "description": "Pinned scope team ID. 0 means personal scope.", - "format": "int64", - "type": "integer" - } - }, - "required": [ - "place", - "run_scope", - "team_id", - "description" - ], - "type": "object" - }, - "AutomationRuleItem": { - "description": "Automation rule.", - "properties": { - "account_id": { - "description": "Account ID.", - "format": "int64", - "type": "integer" - }, - "can_edit": { - "description": "True when the caller can manage this rule: the personal rule owner; for team rules, an account admin or a member of the rule's team.", - "type": "boolean" - }, - "created_at": { - "description": "Creation time, Unix milliseconds.", - "format": "int64", - "type": "integer" + "description": "Hidden session run scope. One of: `person` (personal rule, team_id=0, runs as the creator; disabled when the creator leaves the account), `team` (team rule, team_id>0, owned by the team and shared with its members; survives the creator leaving). Derived from the rule's team_id." }, "cron_expr": { - "description": "Normalized 5-field cron expression.", - "type": "string" + "type": "string", + "description": "Normalized 5-field cron expression (`minute hour day month weekday`), evaluated in `timezone`." }, - "enabled": { - "description": "Whether the rule is enabled.", - "type": "boolean" + "timezone": { + "type": "string", + "description": "IANA timezone `cron_expr` is evaluated in. Always populated for rules created after this field shipped; empty on legacy rows created before it, which still resolve to UTC when scheduled." }, - "environment_id": { - "description": "BYOC Runner ID.", - "type": "string" + "prompt": { + "type": "string", + "description": "Task instruction sent to the AI SRE agent on every run." }, "environment_kind": { + "type": "string", "description": "Runtime environment kind. Omit or send an empty value for automatic selection. One of: `cloud` (platform-hosted cloud sandbox), `byoc` (self-hosted BYOC runner in the account); an empty value means automatic selection (prefers an online BYOC runner, falls back to the cloud sandbox).", "enum": [ "", "cloud", "byoc" - ], - "type": "string" - }, - "execution_location": { - "$ref": "#/components/schemas/AutomationExecutionLocation" + ] }, - "execution_place": { - "description": "Configured execution destination for ordinary triggers. War-room triggers resolve their event war room at execution time.", - "enum": [ - "im", - "web_console" - ], - "type": "string" + "environment_id": { + "type": "string", + "description": "BYOC runner ID when `environment_kind=byoc`; empty string otherwise." }, - "http_post_token": { - "description": "HTTP POST trigger token. Returned only on create or token rotation; save it immediately.", - "type": "string" + "schedule_trigger_id": { + "type": "string", + "description": "Schedule trigger ID. Omitted if the rule has no schedule trigger." }, - "http_post_trigger_enabled": { - "description": "Whether the HTTP POST trigger is enabled.", - "type": "boolean" + "schedule_trigger_enabled": { + "type": "boolean", + "description": "Whether the schedule trigger is enabled." }, "http_post_trigger_id": { - "description": "HTTP POST trigger ID. Omitted when the rule has no HTTP POST trigger.", - "type": "string" + "type": "string", + "description": "HTTP POST trigger ID. Omitted when the rule has no HTTP POST trigger." }, "http_post_trigger_url": { - "description": "HTTP POST trigger path. Omitted when the rule has no HTTP POST trigger.", - "type": "string" + "type": "string", + "description": "Path to fire the HTTP POST trigger, `/safari/automation/triggers/{trigger_id}/fire`, relative to the API base URL. Send `POST` with `Authorization: Bearer `. Omitted when the rule has no HTTP POST trigger." }, - "name": { - "description": "Rule name.", - "type": "string" + "http_post_trigger_enabled": { + "type": "boolean", + "description": "Whether the HTTP POST trigger is enabled." + }, + "oncall_incident_trigger_id": { + "type": "string", + "description": "On-call incident trigger ID. Omitted when the rule has no On-call incident trigger." + }, + "oncall_incident_trigger_enabled": { + "type": "boolean", + "description": "Whether the On-call incident trigger is enabled." }, "oncall_incident_channel_ids": { - "description": "On-call integration IDs to watch. Creating or enabling this trigger requires at least one valid ID. Omitted when no On-call incident trigger is configured.", + "type": "array", "items": { + "type": "integer", "format": "int64", - "minimum": 1, - "type": "integer" + "minimum": 1 }, - "type": "array" + "description": "Channel IDs the On-call incident trigger watches. Omitted when the rule has no such trigger." }, "oncall_incident_severities": { - "description": "Incident severities to watch. Supported values are Critical, Warning, and Info; creating or enabling this trigger requires at least one value. Omitted when no On-call incident trigger is configured.", + "type": "array", "items": { + "type": "string", "enum": [ "Critical", "Warning", "Info" - ], - "type": "string" + ] }, - "type": "array" + "description": "Incident severities the On-call incident trigger watches: `Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels. Omitted when the rule has no such trigger." }, - "oncall_incident_trigger_enabled": { - "description": "Whether the On-call incident trigger is enabled.", - "type": "boolean" + "oncall_incident_merge_similar": { + "type": "boolean", + "description": "Whether similar incidents are merged into one analysis (see the create request). `true` when the rule has no On-call incident trigger." }, - "oncall_incident_trigger_id": { - "description": "On-call incident trigger ID. Omitted when the rule has no On-call incident trigger.", - "type": "string" + "war_room_trigger_id": { + "type": "string", + "description": "War room trigger ID. Omitted when the rule has no war room trigger." }, - "owner_id": { - "description": "Creator person ID.", - "format": "int64", - "type": "integer" + "war_room_trigger_enabled": { + "type": "boolean", + "description": "Whether the war room trigger is enabled." }, - "prompt": { - "description": "Task prompt.", - "type": "string" + "war_room_channel_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64", + "minimum": 1 + }, + "description": "Channel IDs whose war rooms start a run. Omitted when the rule has no war room trigger." }, - "rule_id": { - "description": "Rule ID.", - "type": "string" + "war_room_severities": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info" + ] + }, + "description": "Incident severities whose war rooms start a run: `Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels. Omitted when the rule has no war room trigger." }, - "run_scope": { - "description": "Hidden session run scope. One of: `person` (personal rule, team_id=0, runs as the creator; disabled when the creator leaves the account), `team` (team rule, team_id>0, owned by the team and shared with its members; survives the creator leaving). Derived from the rule's team_id.", + "execution_place": { + "type": "string", "enum": [ - "person", - "team" + "web_console", + "im" ], - "type": "string" + "description": "Where runs started by the schedule, HTTP POST, On-call incident, and manual triggers execute: `web_console` (a web console session) or `im` (the IM chat the rule was created from). War room runs always execute in the war room's group chat. Fixed at creation." }, - "schedule_next_fire_at_ms": { - "description": "Next scheduled fire time, Unix milliseconds. 0 means no future scheduled fire is available.", - "format": "int64", - "type": "integer" + "execution_location": { + "type": "object", + "description": "Read-only description of where the rule runs.", + "properties": { + "place": { + "type": "string", + "enum": [ + "web_console", + "im" + ], + "description": "Same as the rule's `execution_place`: `web_console` runs in a web console session, `im` runs in the bound IM chat." + }, + "run_scope": { + "type": "string", + "enum": [ + "person", + "team" + ], + "description": "`person`: runs as the owner; `team`: runs under the team in `team_id`." + }, + "team_id": { + "type": "integer", + "format": "int64", + "description": "Team the runs belong to; `0` for a personal rule." + }, + "platform": { + "type": "string", + "enum": [ + "feishu", + "dingtalk", + "wecom", + "slack", + "teams" + ], + "description": "IM platform of the bound chat: `feishu` (Feishu/Lark), `dingtalk` (DingTalk), `wecom` (WeCom), `slack` (Slack), `teams` (Microsoft Teams). Present only when `place=im`." + }, + "conversation_mode": { + "type": "string", + "enum": [ + "direct", + "group_chat", + "group_thread", + "war_room_chat" + ], + "description": "Conversation type of the bound chat: `direct` (one-to-one chat with the bot), `group_chat` (a group chat), `group_thread` (a thread in a group chat), `war_room_chat` (an incident war room). Present only when `place=im`." + }, + "chat_name": { + "type": "string", + "description": "Name of the bound chat. Present only when `place=im` and the name is known." + }, + "description": { + "type": "string", + "description": "Human-readable destination label: `Web console` for web console rules, otherwise the chat name or platform and conversation type." + } + }, + "required": [ + "place", + "run_scope", + "team_id", + "description" + ] }, - "schedule_trigger_enabled": { - "description": "Whether the schedule trigger is enabled.", - "type": "boolean" + "last_run": { + "type": "object", + "description": "The rule's most recent run. Returned only by List Automation rules, and only when the rule has run at least once.", + "properties": { + "run_id": { + "type": "string", + "description": "Run ID, as in List Automation runs." + }, + "status": { + "type": "string", + "enum": [ + "queued", + "running", + "retrying", + "succeeded", + "partial", + "failed", + "skipped", + "abandoned", + "blocked" + ], + "description": "Run status, same meanings as `status` in List Automation runs: `queued`, `running`, `retrying` (in progress); `succeeded`, `partial`, `failed`, `skipped` (did not execute or merged into another run), `abandoned` (never completed), `blocked` (ended waiting on a connector authorization)." + }, + "started_at": { + "type": "integer", + "format": "int64", + "description": "Start time, Unix milliseconds." + } + }, + "required": [ + "run_id", + "status", + "started_at" + ] }, - "schedule_trigger_id": { - "description": "Schedule trigger ID. Omitted if the rule has no schedule trigger.", - "type": "string" + "http_post_token": { + "type": "string", + "description": "HTTP POST trigger token. Returned only in the response that issues it: create with `http_post_trigger_enabled=true`, an update that creates the trigger, or an update with `rotate_http_post_trigger_token=true`. Save it; it cannot be read again." }, - "team_id": { - "description": "Scope team ID; 0 means personal rule.", - "format": "int64", - "type": "integer" + "can_edit": { + "type": "boolean", + "description": "`true` when the caller can manage (get, update, delete, run) this rule: the owner of a personal rule, or a member of a team rule's team. Account owners and admins get no exemption." }, - "timezone": { - "description": "IANA timezone `cron_expr` is evaluated in. Always populated for rules created after this field shipped; empty on legacy rows created before it, which still resolve to UTC when scheduled.", - "type": "string" + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation time, Unix milliseconds." }, "updated_at": { - "description": "Last update time, Unix milliseconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update time, Unix milliseconds." + }, + "schedule_next_fire_at_ms": { + "type": "integer", + "format": "int64", + "description": "Next scheduled fire time, Unix milliseconds. 0 means no future scheduled fire is available." } }, "required": [ @@ -3541,298 +3707,316 @@ "prompt", "environment_kind", "environment_id", - "execution_place", "schedule_trigger_enabled", "http_post_trigger_enabled", "can_edit", "created_at", "updated_at", "schedule_next_fire_at_ms", - "oncall_incident_trigger_enabled" - ], - "type": "object" + "oncall_incident_trigger_enabled", + "oncall_incident_merge_similar", + "war_room_trigger_enabled", + "execution_place" + ] }, "AutomationRuleListRequest": { - "description": "List Automation rules visible to the caller. `all` includes the caller's personal rules plus accessible team rules; account admins do not see other users' personal rules in list results.", + "type": "object", + "description": "List Automation rules visible to the caller: their own personal rules plus rules of teams they belong to. Account owners and admins are bounded the same way.", "properties": { - "enabled": { - "description": "Filter by enabled state: `true` returns only enabled rules, `false` only disabled; omit or pass null for no filter.", - "type": [ - "boolean", - "null" - ] - }, - "include_person": { - "description": "Compatibility field; when scope is empty and this is false, behaves like team scope.", - "type": [ - "boolean", - "null" - ] - }, - "keyword": { - "description": "Filter by name keyword.", - "maxLength": 64, - "type": "string" + "p": { + "type": "integer", + "default": 1, + "description": "Page number, 1-based." }, "limit": { + "type": "integer", "default": 20, "description": "Page size. Values below 1 fall back to 20; values above 200 are capped at 200.", - "maximum": 200, - "type": "integer" - }, - "p": { - "default": 1, - "description": "Page number, 1-based.", - "type": "integer" + "maximum": 200 }, "scope": { - "description": "Scope filter: `all` (own personal + accessible team rules), `personal`, or `team`; default `all`.", + "type": "string", "enum": [ "all", "personal", "team" ], - "type": "string" + "description": "Scope filter: `all` (default) your personal rules plus rules of your teams; `personal` only your personal rules; `team` only rules of your teams." }, "team_ids": { - "description": "Filter to these team IDs; this narrows results and does not expand access.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Filter to these team IDs; this narrows results and does not expand access." + }, + "include_person": { + "type": [ + "boolean", + "null" + ], + "description": "Legacy switch. Only read when `scope` is empty: `false` behaves like `scope=team`; otherwise ignored." + }, + "enabled": { + "type": [ + "boolean", + "null" + ], + "description": "Filter by enabled state: `true` returns only enabled rules, `false` only disabled; omit or pass null for no filter." + }, + "keyword": { + "type": "string", + "maxLength": 64, + "description": "Returns rules whose name contains this text. At most 64 characters." } - }, - "type": "object" + } }, "AutomationRuleListResponse": { + "type": "object", "properties": { + "total": { + "type": "integer", + "format": "int64", + "description": "Number of rules matching the filters across all pages." + }, "rules": { - "description": "Array of automation rules for the current page, used with `total` for pagination.", + "type": "array", "items": { "$ref": "#/components/schemas/AutomationRuleItem" }, - "type": "array" - }, - "total": { - "description": "Total count.", - "format": "int64", - "type": "integer" + "description": "Array of automation rules for the current page, used with `total` for pagination." } }, "required": [ "total", "rules" - ], - "type": "object" + ] }, "AutomationRuleUpdateRequest": { + "type": "object", "description": "Update an Automation rule. Omit or send null on a field to leave it unchanged.", "properties": { - "cron_expr": { - "description": "Run cadence. Supports 4 fields (`hour day month weekday`, minute defaults to 0) and 5 fields (`minute hour day month weekday`). The minute must be one fixed integer; 6-field seconds are not supported.", - "example": "15 9 * * *", + "rule_id": { + "type": "string", + "description": "Target rule ID, from the list returned by `POST /safari/automation/rule/list`." + }, + "name": { "type": [ "string", "null" - ] + ], + "maxLength": 255, + "description": "New display name, at most 255 characters. An empty string after trimming is rejected." + }, + "team_id": { + "type": [ + "integer", + "null" + ], + "format": "int64", + "minimum": 0, + "description": "The rule's scope cannot be changed. Omit this field, or send the current value; any other value returns `400`." }, "enabled": { - "description": "Whether the rule is enabled.", "type": [ "boolean", "null" - ] + ], + "description": "Whether the rule's automatic triggers are armed. Omit to keep the current value." }, - "environment_id": { - "description": "BYOC Runner ID.", + "cron_expr": { "type": [ "string", "null" - ] + ], + "description": "New schedule, same format as on create: 4 fields (`hour day month weekday`) or 5 fields (`minute hour day month weekday`), fixed-integer minute, no seconds, not both day-of-month and day-of-week. Omit to keep the current expression.", + "example": "15 9 * * *" + }, + "timezone": { + "type": [ + "string", + "null" + ], + "description": "New IANA time zone for `cron_expr`. An empty string stores `UTC`. Omit or send `null` to keep the current time zone." + }, + "schedule_trigger_enabled": { + "type": [ + "boolean", + "null" + ], + "description": "Whether the schedule trigger is enabled. Omit to keep the current value." + }, + "prompt": { + "type": [ + "string", + "null" + ], + "description": "New task instruction for the agent. Omit to keep the current one." }, "environment_kind": { - "description": "Runtime environment kind. Omit or send an empty value for automatic selection.", + "type": [ + "string", + "null" + ], + "description": "New runtime environment: `\"\"` automatic selection (prefers an online BYOC runner, falls back to the cloud sandbox), `cloud` platform-hosted cloud sandbox, `byoc` the runner in `environment_id`. Sending this without `environment_id` clears the stored `environment_id`.", "enum": [ "", "cloud", "byoc" - ], + ] + }, + "environment_id": { "type": [ "string", "null" - ] + ], + "description": "BYOC runner ID; required when the resulting `environment_kind` is `byoc`, rejected otherwise." }, "http_post_trigger_enabled": { - "description": "Whether the HTTP POST trigger is enabled. Sending true creates one when missing.", "type": [ "boolean", "null" - ] + ], + "description": "Enable or disable the HTTP POST trigger. `true` on a rule without one creates it and returns its token in this response." }, - "name": { - "description": "New rule name.", - "maxLength": 255, + "oncall_incident_trigger_enabled": { "type": [ - "string", + "boolean", "null" - ] + ], + "description": "Enable or disable the On-call incident trigger. Creating it on a rule that has none also needs `oncall_incident_channel_ids` and `oncall_incident_severities`." }, "oncall_incident_channel_ids": { - "description": "On-call integration IDs to watch. Creating or enabling this trigger requires at least one valid ID.", + "type": "array", "items": { + "type": "integer", "format": "int64", - "minimum": 1, - "type": "integer" + "minimum": 1 }, - "type": "array" + "description": "Replaces the watched channel IDs when non-empty; an empty or omitted list keeps the stored IDs." }, "oncall_incident_severities": { - "description": "Incident severities to watch. Supported values are Critical, Warning, and Info; creating or enabling this trigger requires at least one value.", + "type": "array", "items": { + "type": "string", "enum": [ "Critical", "Warning", "Info" - ], - "type": "string" + ] }, - "type": "array" + "description": "Replaces the watched severities when non-empty (`Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels); an empty or omitted list keeps the stored values." }, - "oncall_incident_trigger_enabled": { - "description": "Whether the On-call incident trigger is enabled.", + "oncall_incident_merge_similar": { "type": [ "boolean", "null" - ] + ], + "description": "Whether to merge similar incidents into one analysis (see the create request). Omit to keep the current value." }, - "prompt": { - "description": "New task prompt.", + "war_room_trigger_enabled": { "type": [ - "string", + "boolean", "null" - ] - }, - "rotate_http_post_trigger_token": { - "description": "Whether to rotate the HTTP POST trigger token. The new token is returned only in this response.", - "type": "boolean" + ], + "description": "Enable or disable the war room trigger. Creating it on a rule that has none also needs `war_room_channel_ids` and `war_room_severities`. Omit to keep the current value." }, - "rule_id": { - "description": "Target rule ID, from the list returned by `POST /safari/automation/rule/list`.", - "type": "string" + "war_room_channel_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64", + "minimum": 1 + }, + "description": "Replaces the channel IDs whose war rooms start a run when non-empty; an empty or omitted list keeps the stored IDs." }, - "schedule_trigger_enabled": { - "description": "Whether the schedule trigger is enabled.", - "type": [ - "boolean", - "null" - ] + "war_room_severities": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info" + ] + }, + "description": "Replaces the war room severities when non-empty (`Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels); an empty or omitted list keeps the stored values." }, - "timezone": { - "description": "New IANA timezone for evaluating `cron_expr`. Omit or send null to leave the current timezone unchanged.", - "type": [ - "string", - "null" - ] + "rotate_http_post_trigger_token": { + "type": "boolean", + "description": "When `true`, issues a new HTTP POST trigger token and invalidates the old one. The trigger must exist and be enabled. The new token is returned only in this response." } }, "required": [ "rule_id" - ], - "type": "object" + ] }, "AutomationRunItem": { + "type": "object", "properties": { - "account_id": { - "description": "Account ID.", - "format": "int64", - "type": "integer" - }, - "attempts": { - "description": "Attempt count.", - "type": "integer" - }, - "completed_at": { - "description": "Completion time, Unix milliseconds. 0 means not completed.", - "format": "int64", - "type": "integer" - }, - "created_at": { - "description": "Creation time, Unix milliseconds.", - "format": "int64", - "type": "integer" + "run_id": { + "type": "string", + "description": "Run ID (prefix `trun_`)." }, - "duration_ms": { - "description": "Duration in milliseconds.", - "format": "int64", - "type": "integer" + "session_id": { + "type": "string", + "description": "AI SRE session the run executed in. Omitted when the run has not started a session, when it joined another run (see `joined_session_id`), or when it executed in an IM chat." }, - "execution_place": { - "description": "Actual execution destination: `im` or `web_console`. IM runs omit session details and deep links.", - "enum": [ - "im", - "web_console" - ], - "type": "string" + "session_name": { + "type": "string", + "description": "Display name of the run's session, stamped via a batch lookup. Omitted when empty or when the lookup fails." }, - "error_code": { - "description": "Error code; empty when the run did not fail.", - "type": "string" + "joined_session_id": { + "type": "string", + "description": "For an On-call incident run merged into a similar incident's analysis (`status=skipped`): the session it joined. Omitted otherwise." }, - "error_message": { - "description": "Error message; empty when the run did not fail.", - "type": "string" + "joined_session_name": { + "type": "string", + "description": "Display name of `joined_session_id`. Omitted when empty or when the name lookup fails." }, "kind": { + "type": "string", "description": "Run kind; runs listed for a rule are always `automation_rule`.", "enum": [ "automation_rule" - ], - "type": "string" - }, - "occurrence_key": { - "description": "Idempotency key for this occurrence.", - "type": "string" - }, - "result_json": { - "additionalProperties": true, - "description": "Raw run result JSON (carries the run's `session_id` once started); null when empty.", - "type": [ - "object", - "null" ] }, - "rule_id": { - "description": "Rule ID.", - "type": "string" - }, - "run_id": { - "description": "Run ID.", - "type": "string" + "account_id": { + "type": "integer", + "format": "int64", + "description": "ID of the account that owns the run." }, - "session_id": { - "description": "Session created for this run, extracted from `result_json`. Omitted when the run has not (yet) started a session.", - "type": "string" + "rule_id": { + "type": "string", + "description": "ID of the rule this run belongs to." }, - "session_name": { - "description": "Display name of the run's session, stamped via a batch lookup. Omitted when empty or when the lookup fails.", - "type": "string" + "trigger_kind": { + "type": "string", + "enum": [ + "schedule", + "debug", + "manual", + "http_post", + "oncall_incident", + "war_room_created" + ], + "description": "Trigger kind. One of:\n| Value | Meaning |\n| --- | --- |\n| `schedule` | Fired by the rule's schedule trigger |\n| `debug` | Debug run (reserved; current rule runs never carry this kind) |\n| `manual` | Started with Run Automation rule |\n| `http_post` | Fired via the rule's HTTP POST trigger |\n| `oncall_incident` | Fired by a matching On-call incident |\n| `war_room_created` | Fired when a war room was created for a matching incident; runs in that group chat |" }, - "started_at": { - "description": "Start time, Unix milliseconds.", - "format": "int64", - "type": "integer" + "execution_place": { + "type": "string", + "enum": [ + "web_console", + "im" + ], + "description": "Where this run executed: `web_console` (a web console session; `session_id` links to it) or `im` (an IM chat; session details are withheld). `war_room_created` runs are always `im`." }, - "stats_json": { - "additionalProperties": true, - "description": "Raw run statistics JSON; null when empty.", - "type": [ - "object", - "null" - ] + "occurrence_key": { + "type": "string", + "description": "Idempotency key of this occurrence: `manual:` for manual runs, `:` for schedule runs, `oncall_incident::` for On-call incident runs." }, "status": { - "description": "Run status. One of (the first three are in-flight, the rest terminal):\n| Value | Meaning |\n| --- | --- |\n| `queued` | Enqueued, waiting for a worker |\n| `running` | Executing |\n| `retrying` | An attempt failed and a retry is scheduled |\n| `succeeded` | Completed successfully |\n| `partial` | Partially succeeded (currently only produced by memory-consolidation runs; rule runs never reach it) |\n| `failed` | Terminal failure, no further retries |\n| `skipped` | Not executed (e.g. grace period expired, trigger or rule invalid); the reason is kept on the run record |\n| `abandoned` | Still in-flight past the stale threshold and swept as never-completed (e.g. worker died) |\n| `blocked` | Terminal: the run produced output but ended with a connector waiting on a human to complete authorization (distinct from `failed`) |", + "type": "string", "enum": [ "queued", "running", @@ -3844,23 +4028,60 @@ "abandoned", "blocked" ], - "type": "string" + "description": "Run status. One of (the first three are in-flight, the rest terminal):\n| Value | Meaning |\n| --- | --- |\n| `queued` | Enqueued, waiting for a worker |\n| `running` | Executing |\n| `retrying` | An attempt failed and a retry is scheduled |\n| `succeeded` | Completed successfully |\n| `partial` | Partially succeeded (currently only produced by memory-consolidation runs; rule runs never reach it) |\n| `failed` | Terminal failure, no further retries |\n| `skipped` | Not executed (e.g. grace period expired, trigger or rule invalid); the reason is kept on the run record. Also used for an On-call incident run merged into a similar incident's analysis (see `joined_session_id`) |\n| `abandoned` | Still in-flight past the stale threshold and swept as never-completed (e.g. worker died) |\n| `blocked` | Terminal: the run produced output but ended with a connector waiting on a human to complete authorization (distinct from `failed`) |" }, - "trigger_kind": { - "description": "Trigger kind. One of:\n| Value | Meaning |\n| --- | --- |\n| `schedule` | Fired by the rule's schedule trigger |\n| `debug` | Debug run (reserved; current rule runs never carry this kind) |\n| `manual` | Triggered manually by a user |\n| `http_post` | Fired via the rule's HTTP POST webhook |\n| `oncall_incident` | Fired by an on-call incident event |", - "enum": [ - "schedule", - "debug", - "manual", - "http_post", - "oncall_incident" + "attempts": { + "type": "integer", + "description": "Number of execution attempts made for this run." + }, + "started_at": { + "type": "integer", + "format": "int64", + "description": "Start time, Unix milliseconds." + }, + "completed_at": { + "type": "integer", + "format": "int64", + "description": "Completion time, Unix milliseconds. 0 means not completed." + }, + "duration_ms": { + "type": "integer", + "format": "int64", + "description": "Duration in milliseconds." + }, + "error_code": { + "type": "string", + "description": "Error code; empty when the run did not fail." + }, + "error_message": { + "type": "string", + "description": "Error message; empty when the run did not fail." + }, + "stats_json": { + "type": [ + "object", + "null" ], - "type": "string" + "additionalProperties": true, + "description": "Raw run statistics JSON; null when empty." + }, + "result_json": { + "type": [ + "object", + "null" + ], + "additionalProperties": true, + "description": "Raw run result JSON (carries `session_id` once a session started). `null` when empty or when the run executed in an IM chat." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation time, Unix milliseconds." }, "updated_at": { - "description": "Last update time, Unix milliseconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update time, Unix milliseconds." } }, "required": [ @@ -3869,52 +4090,40 @@ "account_id", "rule_id", "trigger_kind", + "execution_place", "occurrence_key", "status", "attempts", "started_at", "completed_at", "duration_ms", - "execution_place", "created_at", "updated_at", "error_code", "error_message", "stats_json", "result_json" - ], - "type": "object" + ] }, "AutomationRunListRequest": { + "type": "object", "properties": { - "limit": { - "default": 20, - "description": "Page size.", - "type": "integer" + "rule_id": { + "type": "string", + "description": "Target rule ID, from the list returned by `POST /safari/automation/rule/list`." }, "p": { + "type": "integer", "default": 1, - "description": "Page number, 1-based.", - "type": "integer" - }, - "rule_id": { - "description": "Target rule ID, from the list returned by `POST /safari/automation/rule/list`.", - "type": "string" - }, - "started_after_ms": { - "description": "Start-time lower bound, Unix milliseconds. Values below the 180-day run-history retention floor are clamped to it (that floor is also the default when omitted).", - "format": "int64", - "minimum": 0, - "type": "integer" + "description": "Page number, 1-based." }, - "started_before_ms": { - "description": "Start-time upper bound, Unix milliseconds. Must be greater than or equal to the effective `started_after_ms`; a value below the retention floor yields an empty result.", - "format": "int64", - "minimum": 0, - "type": "integer" + "limit": { + "type": "integer", + "default": 20, + "description": "Page size. Values below 1 fall back to 20." }, "status": { - "description": "Run status filter: `queued`, `running`, `retrying`, `succeeded`, `partial` (partially succeeded), `failed`, `skipped` (e.g. rule or trigger no longer valid), `abandoned` (stale run terminated by the system), `blocked` (terminal; produced output but a connector is waiting on a human authorization); omit for no filter.", + "type": "string", "enum": [ "queued", "running", @@ -3926,145 +4135,214 @@ "abandoned", "blocked" ], - "type": "string" + "description": "Run status filter: `queued`, `running`, `retrying`, `succeeded`, `partial` (partially succeeded), `failed`, `skipped` (e.g. rule or trigger no longer valid), `abandoned` (stale run terminated by the system), `blocked` (terminal; produced output but a connector is waiting on a human authorization); omit for no filter." }, "trigger_kind": { - "description": "Trigger source filter: `schedule` cron trigger, `debug` debug run, `manual` manual run, `http_post` HTTP POST trigger, `oncall_incident` on-call incident trigger; omit for no filter.", + "type": "string", "enum": [ "schedule", "debug", "manual", "http_post", - "oncall_incident" + "oncall_incident", + "war_room_created" ], - "type": "string" + "description": "Trigger filter: `schedule` schedule trigger, `debug` debug run, `manual` manual run, `http_post` HTTP POST trigger, `oncall_incident` On-call incident trigger, `war_room_created` war room trigger; omit for no filter." + }, + "started_after_ms": { + "type": "integer", + "format": "int64", + "description": "Start-time lower bound, Unix milliseconds. Values below the 180-day run-history retention floor are clamped to it (that floor is also the default when omitted).", + "minimum": 0 + }, + "started_before_ms": { + "type": "integer", + "format": "int64", + "description": "Start-time upper bound, Unix milliseconds. Must be greater than or equal to the effective `started_after_ms`; a value below the retention floor yields an empty result.", + "minimum": 0 } }, "required": [ "rule_id" - ], - "type": "object" + ] }, "AutomationRunListResponse": { + "type": "object", "properties": { + "total": { + "type": "integer", + "format": "int64", + "description": "Number of runs matching the filters across all pages." + }, "runs": { - "description": "Array of run records for the given `rule_id`, filtered by the request's status/trigger-kind/time-range and paginated.", + "type": "array", "items": { "$ref": "#/components/schemas/AutomationRunItem" }, - "type": "array" - }, - "total": { - "description": "Total count.", - "format": "int64", - "type": "integer" + "description": "Array of run records for the given `rule_id`, filtered by the request's status/trigger-kind/time-range and paginated." } }, "required": [ "total", "runs" - ], - "type": "object" + ] }, "AutomationRunView": { + "type": "object", "description": "Reference to the run started by a manual trigger.", "properties": { "run_id": { - "description": "Run ID, always populated once a run is created.", - "type": "string" + "type": "string", + "description": "Run ID, always populated once a run is created." }, "session_id": { - "description": "AI SRE session ID for this run. Always populated in a 200 response, since the call only returns after the session has started.", - "type": "string" + "type": "string", + "description": "AI SRE session started for this run. Omitted when the rule executes in an IM chat (`execution_place=im`)." } }, "required": [ "run_id" - ], - "type": "object" + ] }, "AutomationTemplateItem": { + "type": "object", "properties": { - "description": { - "description": "Template description.", - "type": "string" + "name": { + "type": "string", + "description": "Localized template name; use it as the rule `name`." }, - "enabled": { - "description": "Whether a rule created from this template starts out enabled (prefill value).", - "type": "boolean" + "key": { + "type": "string", + "description": "Stable, locale-independent template ID (lowercase letters, digits, underscores). Present only on templates that other console pages link to directly; omitted otherwise." + }, + "description": { + "type": "string", + "description": "Localized explanation of what a rule created from this template does." }, "icon": { - "description": "Icon identifier.", - "type": "string" + "type": "string", + "description": "Icon identifier the console displays for the template, e.g. `siren`." }, - "name": { - "description": "Template name.", - "type": "string" + "category": { + "type": "string", + "description": "Free-text, localized name of the group the template is shown under in the console, e.g. `Incident Response`. Groups appear in the order of their first template." + }, + "enabled": { + "type": "boolean", + "description": "Prefill for the create request's `enabled`." }, "prompt": { - "description": "Template prompt.", - "type": "string" + "type": "string", + "description": "Prefill for the create request's `prompt`." + }, + "schedule_trigger_enabled": { + "type": "boolean", + "description": "Prefill for `schedule_trigger_enabled`; `true` exactly when `cron_expr` is present." + }, + "cron_expr": { + "type": "string", + "description": "Prefill for `cron_expr`. Omitted when the template does not use the schedule trigger; the create request still needs a valid `cron_expr`." + }, + "http_post_trigger_enabled": { + "type": "boolean", + "description": "Prefill for `http_post_trigger_enabled`." + }, + "oncall_incident_trigger_enabled": { + "type": "boolean", + "description": "Prefill for `oncall_incident_trigger_enabled`; when `true`, add `oncall_incident_channel_ids` before creating." + }, + "oncall_incident_severities": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info" + ] + }, + "description": "Prefill for `oncall_incident_severities` (`Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels). Omitted when the template does not use the On-call incident trigger." + }, + "war_room_trigger_enabled": { + "type": "boolean", + "description": "Prefill for `war_room_trigger_enabled`; when `true`, add `war_room_channel_ids` before creating." + }, + "war_room_severities": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info" + ] + }, + "description": "Prefill for `war_room_severities` (`Critical` (most severe), `Warning`, or `Info` (least severe) — the On-call incident severity levels). Omitted when the template does not use the war room trigger." } }, "required": [ "name", "description", "icon", + "category", "enabled", - "prompt" - ], - "type": "object" + "prompt", + "schedule_trigger_enabled", + "http_post_trigger_enabled", + "oncall_incident_trigger_enabled", + "war_room_trigger_enabled" + ] }, "AutomationTemplateListRequest": { + "type": "object", "properties": { "locale": { - "description": "Template locale such as zh-CN or en-US. Omit to detect from the request locale.", + "type": "string", "maxLength": 16, - "type": "string" + "description": "Template language. A value containing `zh` returns Chinese, one containing `en` returns English, any other non-empty value returns Chinese. When omitted, the `locale`/`lang` query parameter or the `Accept-Language` header decides, defaulting to Chinese." } - }, - "type": "object" + } }, "AutomationTemplateListResponse": { + "type": "object", "properties": { "templates": { - "description": "Array of built-in automation templates, with display text localized by the request `locale` (falling back to request headers).", + "type": "array", "items": { "$ref": "#/components/schemas/AutomationTemplateItem" }, - "type": "array" + "description": "Built-in templates in the resolved language, in display order." } }, "required": [ "templates" - ], - "type": "object" + ] }, "BindWorkItemPostMortemRequest": { + "type": "object", "description": "Parameters for bulk-binding an incident's unbound follow-ups to a post-mortem.", + "required": [ + "post_mortem_id", + "incident_id", + "idempotency_key" + ], "properties": { - "idempotency_key": { - "description": "Client-generated idempotency key (max 128 characters; letters, digits, `_`, `-`, `.`, `:` only).", - "maxLength": 128, - "pattern": "^[A-Za-z0-9_\\-.:]+$", - "type": "string" + "post_mortem_id": { + "type": "string", + "description": "Post-mortem ID (32-character hex string) to bind the follow-ups to." }, "incident_id": { - "description": "Incident ID (MongoDB ObjectID) whose converted-but-unbound follow-ups are bound.", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Incident ID (MongoDB ObjectID) whose converted, unbound items are bound. It must be linked to `post_mortem_id`." }, - "post_mortem_id": { - "description": "Post-mortem ID (32-character hex string) to bind the follow-ups to.", - "type": "string" + "idempotency_key": { + "type": "string", + "maxLength": 128, + "pattern": "^[A-Za-z0-9_\\-.:]+$", + "description": "Client-generated idempotency key (max 128 characters; letters, digits, `_`, `-`, `.`, `:` only)." } - }, - "required": [ - "post_mortem_id", - "incident_id", - "idempotency_key" - ], - "type": "object" + } }, "CalEventIDRequest": { "description": "Calendar event delete request. Provide event_id, or both start_at and end_at.", @@ -4092,69 +4370,69 @@ "type": "object" }, "CalEventItem": { + "type": "object", "description": "Calendar event entry.", + "required": [ + "cal_id", + "event_id", + "summary", + "description", + "start_at", + "end_at", + "is_off", + "created_at", + "updated_at" + ], "properties": { "account_id": { - "description": "Account ID. Only present for private events.", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "Account ID. Only present for private events." + }, + "creator_id": { + "type": "integer", + "format": "uint64", + "description": "Creator person ID. Only present for private events." }, "cal_id": { - "description": "Calendar ID. For public events this is a locale key such as zh-cn.china.official.", - "type": "string" + "type": "string", + "description": "Calendar ID. For public events this is a locale key such as zh-cn.china.official." }, - "created_at": { - "description": "Creation timestamp (Unix seconds).", - "format": "int64", - "type": "integer" + "event_id": { + "type": "string", + "description": "Event ID. `cale.` for the calendar's own events, `non_work.YYYYMMDD` for generated non-working weekdays, and `.` for events inherited from a holiday calendar." }, - "creator_id": { - "description": "Creator person ID. Only present for private events.", - "format": "uint64", - "type": "integer" + "summary": { + "type": "string", + "description": "Event summary." }, "description": { - "description": "Event description.", - "type": "string" + "type": "string", + "description": "Event description." }, - "end_at": { - "description": "Event end date (YYYY-MM-DD, exclusive).", - "type": "string" + "start_at": { + "type": "string", + "description": "Event start date (YYYY-MM-DD)." }, - "event_id": { - "description": "Event ID.", - "type": "string" + "end_at": { + "type": "string", + "description": "Event end date (YYYY-MM-DD, exclusive)." }, "is_off": { - "description": "Whether the event marks a non-working day.", - "type": "boolean" - }, - "start_at": { - "description": "Event start date (YYYY-MM-DD).", - "type": "string" + "type": "boolean", + "description": "Whether the event marks a non-working day." }, - "summary": { - "description": "Event summary.", - "type": "string" + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation timestamp (Unix seconds); `0` for generated `non_work.*` entries." }, "updated_at": { - "description": "Last update timestamp (Unix seconds).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update timestamp (Unix seconds); `0` for generated `non_work.*` entries." } - }, - "required": [ - "cal_id", - "event_id", - "summary", - "description", - "start_at", - "end_at", - "is_off", - "created_at", - "updated_at" - ], - "type": "object" + } }, "CalEventListRequest": { "description": "Calendar event list request. When day > 0 month must also be specified. month and day accept 0 to mean \"not filtered\".", @@ -4309,50 +4587,50 @@ "type": "object" }, "CalendarCreateRequest": { + "type": "object", "description": "Create calendar request. cal_name is required.", + "required": [ + "cal_name" + ], "properties": { "cal_name": { - "description": "Calendar display name.", - "maxLength": 39, + "type": "string", + "description": "Calendar display name; must be unique within the account.", "minLength": 1, - "type": "string" + "maxLength": 39 }, "description": { + "type": "string", "description": "Calendar description.", - "maxLength": 499, - "type": "string" + "maxLength": 499 }, - "extra_cal_ids": { - "description": "Additional public-holiday calendar IDs to inherit events from (for example zh-cn.china.official).", - "items": { - "type": "string" - }, - "type": "array" + "timezone": { + "type": "string", + "description": "IANA timezone, e.g. `America/New_York`. Defaults to `Asia/Shanghai` when empty; an invalid name returns `InvalidParameter`.", + "default": "Asia/Shanghai" }, "team_id": { - "description": "Owning team ID. 0 means no team.", + "type": "integer", "format": "uint64", - "type": "integer" - }, - "timezone": { - "default": "Asia/Shanghai", - "description": "IANA timezone. Defaults to Asia/Shanghai when empty.", - "type": "string" + "description": "Owning team ID; `0` or omitted means no team. A nonzero ID must be a team of the account." }, "workdays": { - "description": "Workday numbers (0 = Sunday, 6 = Saturday).", + "type": "array", "items": { - "maximum": 6, + "type": "integer", "minimum": 0, - "type": "integer" + "maximum": 6 }, - "type": "array" + "description": "Weekly working days, `0` = Sunday … `6` = Saturday. Days not listed are non-working days. When empty, no weekday is treated as non-working." + }, + "extra_cal_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Additional public-holiday calendar IDs to inherit events from (for example zh-cn.china.official)." } - }, - "required": [ - "cal_name" - ], - "type": "object" + } }, "CalendarCreateResponse": { "description": "Create calendar response.", @@ -4391,103 +4669,103 @@ "type": "object" }, "CalendarItem": { + "type": "object", "description": "Service calendar detail.", + "required": [ + "account_id", + "team_id", + "cal_id", + "cal_name", + "description", + "timezone", + "kind", + "created_at", + "updated_at", + "creator_id", + "updated_by", + "status" + ], "properties": { "account_id": { - "description": "Account ID.", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the account that owns the calendar." + }, + "team_id": { + "type": "integer", + "format": "uint64", + "description": "Owning team ID (0 when not assigned)." }, "cal_id": { - "description": "Calendar ID.", - "type": "string" + "type": "string", + "description": "Calendar ID." }, "cal_name": { - "description": "Calendar display name.", - "type": "string" - }, - "created_at": { - "description": "Creation timestamp (Unix seconds).", - "format": "int64", - "type": "integer" - }, - "creator_id": { - "description": "Creator person ID.", - "format": "uint64", - "type": "integer" + "type": "string", + "description": "Calendar display name." }, "description": { - "description": "Calendar description.", - "type": "string" + "type": "string", + "description": "Calendar description." }, - "extra_cal_ids": { - "description": "Inherited public-holiday calendar IDs. Omitted when empty.", - "items": { - "type": "string" - }, - "type": "array" + "timezone": { + "type": "string", + "description": "IANA timezone." }, "kind": { + "type": "string", "description": "Calendar kind. `region.official.holiday` is a public regional holiday calendar (served by the central holiday service), `religion.holiday` is a public religious holiday calendar (reserved, currently no data), and `personal` is an account-created personal/team calendar.", "enum": [ "region.official.holiday", "religion.holiday", "personal" - ], - "type": "string" + ] }, - "status": { - "description": "Calendar status. `enabled` means usable; `deleted` means removed and never returned by list endpoints.", - "enum": [ - "enabled", - "deleted" - ], - "type": "string" + "workdays": { + "type": "array", + "items": { + "type": "integer", + "minimum": 0, + "maximum": 6 + }, + "description": "Weekly working days, `0` = Sunday … `6` = Saturday. Days not listed are non-working days. When empty, no weekday is treated as non-working. Omitted when empty." }, - "team_id": { - "description": "Owning team ID (0 when not assigned).", - "format": "uint64", - "type": "integer" + "extra_cal_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Inherited public-holiday calendar IDs. Omitted when empty." }, - "timezone": { - "description": "IANA timezone.", - "type": "string" + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation timestamp (Unix seconds)." }, "updated_at": { - "description": "Last update timestamp (Unix seconds).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update timestamp (Unix seconds)." + }, + "creator_id": { + "type": "integer", + "format": "uint64", + "description": "Creator person ID." }, "updated_by": { - "description": "Last updater person ID.", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "Last updater person ID." }, - "workdays": { - "description": "Workday numbers (0 = Sunday, 6 = Saturday). Omitted when empty.", - "items": { - "maximum": 6, - "minimum": 0, - "type": "integer" - }, - "type": "array" + "status": { + "type": "string", + "description": "Calendar status. `enabled` means usable; `deleted` means removed and never returned by list endpoints.", + "enum": [ + "enabled", + "deleted" + ] } - }, - "required": [ - "account_id", - "team_id", - "cal_id", - "cal_name", - "description", - "timezone", - "kind", - "created_at", - "updated_at", - "creator_id", - "updated_by", - "status" - ], - "type": "object" + } }, "CalendarListRequest": { "description": "Calendar list request. kind filters by calendar kind; no_locale disables locale filtering for public holiday calendars.", @@ -4530,65 +4808,65 @@ "type": "object" }, "CalendarUpdateRequest": { + "type": "object", "description": "Update calendar request. cal_id is required; all other fields are optional and only applied when provided.", + "required": [ + "cal_id" + ], "properties": { "cal_id": { - "description": "Calendar ID; obtain it from `POST /calendar/list`.", - "type": "string" + "type": "string", + "description": "Calendar ID; obtain it from `POST /calendar/list`." }, "cal_name": { - "description": "New calendar name.", - "maxLength": 39, - "minLength": 1, "type": [ "string", "null" - ] + ], + "description": "New calendar name; must be unique within the account.", + "minLength": 1, + "maxLength": 39 }, "description": { - "description": "New description.", - "maxLength": 499, "type": [ "string", "null" - ] - }, - "extra_cal_ids": { - "description": "Additional public-holiday calendar IDs to inherit events from.", - "items": { - "type": "string" - }, - "type": "array" + ], + "description": "New description.", + "maxLength": 499 }, - "team_id": { - "description": "New owning team ID; obtain it from `POST /team/list`.", - "format": "uint64", + "timezone": { "type": [ - "integer", + "string", "null" - ] + ], + "description": "New IANA timezone, e.g. `Asia/Shanghai`; an invalid name returns `InvalidParameter`." }, - "timezone": { - "description": "New IANA timezone.", + "team_id": { "type": [ - "string", + "integer", "null" - ] + ], + "format": "uint64", + "description": "New owning team ID; obtain it from `POST /team/list`. `0` removes the team; a nonzero ID must be a team of the account." }, "workdays": { - "description": "Workday numbers (0 = Sunday, 6 = Saturday).", + "type": "array", "items": { - "maximum": 6, + "type": "integer", "minimum": 0, - "type": "integer" + "maximum": 6 }, - "type": "array" + "description": "Weekly working days, `0` = Sunday … `6` = Saturday. Days not listed are non-working days. When empty, no weekday is treated as non-working. When sent, replaces the stored list; omit to keep it." + }, + "extra_cal_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Public holiday calendar IDs to inherit events from (see `POST /calendar/list` with `kind` = `region.official.holiday`). When sent, replaces the stored list; an empty array removes them all; omit to keep it." } - }, - "required": [ - "cal_id" - ], - "type": "object" + } }, "CancelStatusPageMigrationRequest": { "description": "Parameters for cancelling an in-progress migration job.", @@ -4604,17 +4882,41 @@ "type": "object" }, "ChangeEventItem": { + "type": "object", "properties": { + "event_id": { + "type": "string", + "description": "Change event ID, a MongoDB ObjectID hex string." + }, "account_id": { + "type": "integer", "description": "Account this change event belongs to.", - "format": "int64", - "type": "integer" + "format": "int64" + }, + "channel_id": { + "type": "integer", + "description": "Collaboration channel this change event is routed to.", + "format": "int64" + }, + "integration_id": { + "type": "integer", + "description": "Integration that reported this change event.", + "format": "int64" + }, + "title": { + "type": "string", + "description": "Change event title." + }, + "description": { + "type": "string", + "description": "Change event description." }, "change_key": { - "description": "Stable key that groups events belonging to the same change.", - "type": "string" + "type": "string", + "description": "Stable key that groups events belonging to the same change." }, "change_status": { + "type": "string", "description": "Lifecycle status of the change event, reported by the change source as execution progresses.\n| Value | Meaning |\n|---|---|\n| `Planned` | Planned, not started. |\n| `Ready` | Ready for execution. |\n| `Processing` | Being executed. |\n| `Canceled` | Canceled. |\n| `Done` | Completed. |\n| `Failed` | Failed. |", "enum": [ "Planned", @@ -4623,81 +4925,112 @@ "Canceled", "Done", "Failed" - ], - "type": "string" - }, - "channel_id": { - "description": "Collaboration channel this change event is routed to.", - "format": "int64", - "type": "integer" - }, - "created_at": { - "description": "Unix timestamp in seconds when the change event was created.", - "format": "int64", - "type": "integer" - }, - "deleted_at": { - "description": "Unix timestamp in seconds when the change event was deleted. Omitted when not deleted.", - "format": "int64", - "type": "integer" - }, - "description": { - "description": "Change event description.", - "type": "string" + ] }, - "event_id": { - "description": "Change event ID, a MongoDB ObjectID hex string.", - "type": "string" + "link": { + "type": "string", + "description": "External link to the source change record." }, "event_time": { - "description": "Unix timestamp in seconds when the change event occurred.", - "format": "int64", - "type": "integer" - }, - "integration_id": { - "description": "Integration that reported this change event.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp in seconds when the change event occurred." }, "labels": { + "type": [ + "object", + "null" + ], "additionalProperties": { "type": "string" }, - "description": "Key-value labels attached to the change event.", - "type": "object" - }, - "link": { - "description": "External link to the source change record.", - "type": "string" + "description": "Key-value labels attached to the change event." }, - "title": { - "description": "Change event title.", - "type": "string" + "created_at": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in seconds when the change event was created." }, "updated_at": { - "description": "Unix timestamp in seconds when the change event was last updated.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp in seconds when the change event was last updated." + }, + "deleted_at": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in seconds when the change event was deleted. Omitted when not deleted." } }, - "type": "object" + "required": [ + "event_id", + "account_id", + "channel_id", + "integration_id", + "title", + "description", + "change_key", + "change_status", + "link", + "event_time", + "labels", + "created_at", + "updated_at" + ] }, "ChangeItem": { + "type": "object", "properties": { + "change_id": { + "type": "string", + "description": "Change ID, a MongoDB ObjectID hex string." + }, "account_id": { + "type": "integer", "description": "Account this change belongs to.", - "format": "int64", - "type": "integer" + "format": "int64" }, - "change_id": { - "description": "Change ID, a MongoDB ObjectID hex string.", - "type": "string" + "channel_id": { + "type": "integer", + "description": "Collaboration channel this change is routed to.", + "format": "int64" + }, + "channel_name": { + "type": "string", + "description": "Name of the collaboration channel; an empty string when the change is not routed to an existing channel." + }, + "channel_status": { + "type": "string", + "description": "Status of the collaboration channel: `enabled` or `disabled`; an empty string when the change is not routed to an existing channel.", + "enum": [ + "enabled", + "disabled", + "" + ] + }, + "integration_id": { + "type": "integer", + "description": "Integration that reported this change.", + "format": "int64" + }, + "integration_name": { + "type": "string", + "description": "Name of the reporting integration." + }, + "title": { + "type": "string", + "description": "Change title." + }, + "description": { + "type": "string", + "description": "Change description." }, "change_key": { - "description": "Stable key that groups events belonging to the same change.", - "type": "string" + "type": "string", + "description": "Stable key that groups events belonging to the same change." }, "change_status": { + "type": "string", "description": "Current lifecycle status of the change.\n| Value | Meaning |\n|---|---|\n| `Planned` | Planned, not started. |\n| `Ready` | Ready for execution. |\n| `Processing` | Being executed. |\n| `Canceled` | Canceled. |\n| `Done` | Completed. |\n| `Failed` | Failed. |", "enum": [ "Planned", @@ -4706,100 +5039,85 @@ "Canceled", "Done", "Failed" - ], - "type": "string" + ] }, - "channel_id": { - "description": "Collaboration channel this change is routed to.", + "start_time": { + "type": "integer", "format": "int64", - "type": "integer" - }, - "channel_name": { - "description": "Name of the collaboration channel.", - "type": "string" - }, - "channel_status": { - "description": "Status of the collaboration channel: `enabled` or `disabled`.", - "enum": [ - "enabled", - "disabled" - ], - "type": "string" - }, - "description": { - "description": "Change description.", - "type": "string" + "description": "Unix timestamp in seconds when the change started." }, - "end_time": { - "description": "Unix timestamp in seconds when the change ended.", + "last_time": { + "type": "integer", "format": "int64", - "type": "integer" - }, - "events": { - "description": "Underlying change events, returned only when include_events is true.", - "items": { - "$ref": "#/components/schemas/ChangeEventItem" - }, - "type": "array" + "description": "Unix timestamp in seconds of the most recent change activity." }, - "integration_id": { - "description": "Integration that reported this change.", + "end_time": { + "type": "integer", "format": "int64", - "type": "integer" - }, - "integration_name": { - "description": "Name of the reporting integration.", - "type": "string" + "description": "Unix timestamp in seconds when the change ended." }, "labels": { + "type": [ + "object", + "null" + ], "additionalProperties": { "type": "string" }, - "description": "Key-value labels attached to the change.", - "type": "object" - }, - "last_time": { - "description": "Unix timestamp in seconds of the most recent change activity.", - "format": "int64", - "type": "integer" + "description": "Key-value labels attached to the change; `null` when it has none." }, "link": { - "description": "External link to the source change record.", - "type": "string" - }, - "start_time": { - "description": "Unix timestamp in seconds when the change started.", - "format": "int64", - "type": "integer" + "type": "string", + "description": "External link to the source change record." }, - "title": { - "description": "Change title.", - "type": "string" + "events": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ChangeEventItem" + }, + "description": "Raw change events reported by the integration that make up this change. Present only when `include_events` is `true`." } }, - "type": "object" + "required": [ + "change_id", + "account_id", + "channel_id", + "channel_name", + "channel_status", + "integration_id", + "integration_name", + "title", + "description", + "change_key", + "change_status", + "start_time", + "last_time", + "end_time", + "labels", + "link" + ] }, "ChannelCreateResponse": { + "type": "object", + "required": [ + "channel_id", + "channel_name" + ], "properties": { "channel_id": { - "description": "Newly created channel ID.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Newly created channel ID." }, "channel_name": { - "description": "Channel name echoed back from the request.", - "type": "string" + "type": "string", + "description": "Channel name echoed back from the request." }, "external_report_token": { - "description": "External report token. Emitted only when external reporting is enabled.", - "type": "string" + "type": "string", + "description": "Token for external reporters. Returned only when the request set `is_external_report_enabled` to `true`; it can be read again later from `POST /channel/info`." } - }, - "required": [ - "channel_id", - "channel_name" - ], - "type": "object" + } }, "ChannelIDRequest": { "properties": { @@ -4845,219 +5163,219 @@ "type": "object" }, "ChannelInfosResponse": { + "type": "object", + "required": [ + "items" + ], "properties": { "items": { - "description": "Brief info for the requested `channel_ids` that actually exist; IDs not found are ignored.", + "type": "array", "items": { "$ref": "#/components/schemas/ChannelShort" }, - "type": "array" + "description": "Requested channels that exist, including deleted ones; unknown IDs are skipped. Ordered by channel creation, not by request order." } - }, - "required": [ - "items" - ], - "type": "object" + } }, "ChannelItem": { + "type": "object", "description": "Channel detail record. All fields are optional; they are emitted only when populated.", "properties": { - "account_id": { - "description": "Owning account ID.", - "format": "int64", - "type": "integer" - }, - "active_incident_highest_severity": { - "description": "Highest severity among the channel's active (triggered or processing) incidents: `Critical`, `Warning` or `Info`. Omitted when there are no active incidents.", - "enum": [ - "Critical", - "Warning", - "Info" - ], - "type": "string" - }, - "auto_resolve_mode": { - "description": "How the auto-resolve timer is reset. `trigger` (default) starts the timer once when the incident is triggered — later merged alerts do not affect it; `update` restarts the timer from the latest alert time whenever a new alert merges into the incident.", - "enum": [ - "trigger", - "update" - ], - "type": "string" - }, - "auto_resolve_timeout": { - "description": "Auto-resolve timeout in seconds. 0 disables auto-resolve.", + "channel_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Channel ID; pass it as `channel_id` to the other channel and rule endpoints." }, - "channel_id": { - "description": "Channel ID.", + "team_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Owning team ID." }, - "channel_name": { - "description": "Channel name.", - "type": "string" + "team_name": { + "type": "string", + "description": "Owning team name, resolved from the team directory. Returned only by `POST /channel/list` without `is_brief`; omitted when the lookup fails." }, - "created_at": { - "description": "Creation time, Unix timestamp in seconds.", - "format": "int64", - "type": "integer" + "managing_team_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Additional teams that can manage the channel." }, "creator_id": { - "description": "Member ID who created the channel.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Member ID who created the channel." }, "creator_name": { - "description": "Name of the member who created the channel (resolved from the member directory; empty when unavailable).", - "type": "string" + "type": "string", + "description": "Name of the member who created the channel. Returned only by `POST /channel/list` without `is_brief`; omitted when the lookup fails." }, - "deleted_at": { - "description": "Deletion time, Unix timestamp in seconds. Non-zero only for soft-deleted channels.", + "account_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Owning account ID." }, - "description": { - "description": "Free-form description.", - "type": "string" + "channel_name": { + "type": "string", + "description": "Channel name, unique within the account, 1–59 characters." }, - "disable_auto_close": { - "description": "When true, automatic incident closing is disabled.", - "type": "boolean" + "description": { + "type": "string", + "description": "Free-form description." }, - "disable_outlier_detection": { - "description": "When true, outlier incident detection is disabled.", - "type": "boolean" + "status": { + "type": "string", + "enum": [ + "enabled", + "disabled", + "deleted" + ], + "description": "Channel status:\n- `enabled`: incoming alert events are processed.\n- `disabled`: incoming alert events are discarded.\n- `deleted`: the channel was deleted; returned only by `POST /channel/info` and `POST /channel/infos`, never by `POST /channel/list`." }, - "event_group": { - "$ref": "#/components/schemas/EventGroup", - "description": "Alert event merge configuration." + "deleted_at": { + "type": "integer", + "format": "int64", + "description": "Deletion time, Unix timestamp in seconds. Non-zero only for soft-deleted channels." }, - "external_report_token": { - "description": "Token granted to external reporters. Omitted unless external reporting is enabled on the channel.", - "type": "string" + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation time, Unix timestamp in seconds." }, - "flapping": { - "$ref": "#/components/schemas/Flapping", - "description": "Flapping detection configuration." + "updated_at": { + "type": "integer", + "format": "int64", + "description": "Last update time, Unix timestamp in seconds." }, - "group": { - "$ref": "#/components/schemas/Group", - "description": "Alert grouping configuration." + "auto_resolve_timeout": { + "type": "integer", + "format": "int64", + "description": "Auto-resolve timeout in seconds. 0 disables auto-resolve." }, - "is_external_report_enabled": { - "description": "Whether external reporters can file incidents into this channel.", - "type": "boolean" + "auto_resolve_mode": { + "type": "string", + "enum": [ + "trigger", + "update" + ], + "description": "How the auto-resolve timer is reset. `trigger` (default) starts the timer once when the incident is triggered — later merged alerts do not affect it; `update` restarts the timer from the latest alert time whenever a new alert merges into the incident." }, "is_private": { - "description": "When true, the channel is visible only to its managing teams.", - "type": "boolean" + "type": "boolean", + "description": "When true, the channel is visible only to its managing teams." }, - "is_starred": { - "description": "Whether the current user has starred this channel. Present only in `POST /channel/list` responses.", - "type": "boolean" + "disable_outlier_detection": { + "type": "boolean", + "description": "When true, outlier incident detection is disabled." }, - "last_incident_at": { - "description": "Time of the most recent incident, Unix timestamp in seconds.", - "format": "int64", - "type": "integer" + "disable_auto_close": { + "type": "boolean", + "description": "When true, automatic incident closing is disabled." }, - "managing_team_ids": { - "description": "Additional teams that can manage the channel.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "group": { + "$ref": "#/components/schemas/Group", + "description": "Alert grouping configuration. When never set, `{\"method\": \"n\"}` (no grouping) is returned." + }, + "flapping": { + "$ref": "#/components/schemas/Flapping", + "description": "Flapping detection configuration. When never set, the defaults are returned: enabled, 4 changes within 60 minutes, muted for 120 minutes." }, "progress_to_incident_cnts": { "$ref": "#/components/schemas/IncProgressCnts", - "description": "Incident counts by progress over the last 30 days." + "description": "Counts of incidents started in the last 30 days that are still open, by progress. Not returned with `is_brief`." }, - "status": { - "description": "Channel status. `enabled` receives and processes events normally; `disabled` drops incoming events outright; `deleted` is returned only when fetching a channel by ID — list endpoints never return it.", + "is_starred": { + "type": "boolean", + "description": "Whether the caller has starred this channel. Returned only by `POST /channel/list`." + }, + "active_incident_highest_severity": { + "type": "string", "enum": [ - "enabled", - "disabled", - "deleted" + "Critical", + "Warning", + "Info" ], - "type": "string" + "description": "Highest severity among the channel's active (triggered or processing) incidents: `Critical`, `Warning` or `Info`. Omitted when there are no active incidents." }, - "team_id": { - "description": "Owning team ID.", + "last_incident_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Time of the most recent incident, Unix timestamp in seconds." }, - "team_name": { - "description": "Owning team name (resolved from the team directory; empty when unavailable).", - "type": "string" + "is_external_report_enabled": { + "type": "boolean", + "description": "Whether external reporters can file incidents into this channel." }, - "updated_at": { - "description": "Last update time, Unix timestamp in seconds.", - "format": "int64", - "type": "integer" + "external_report_token": { + "type": "string", + "description": "Token external reporters use to file incidents into this channel. Returned only when external reporting is enabled." + }, + "event_group": { + "$ref": "#/components/schemas/EventGroup", + "description": "Alert event merge configuration. When never set, merging is enabled with a 1,440-minute window." } - }, - "type": "object" + } }, "ChannelRuleIDRequest": { + "type": "object", + "required": [ + "channel_id", + "rule_id" + ], "properties": { "channel_id": { - "description": "Owning channel ID; obtain it from `POST /channel/list`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Owning channel ID; obtain it from `POST /channel/list`." }, "rule_id": { - "description": "Rule ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Rule ID (24-character hex), as returned in `rule_id` by the create or list endpoint of the same rule type." } - }, - "required": [ - "channel_id", - "rule_id" - ], - "type": "object" + } }, "ChannelScopedListRequest": { + "type": "object", + "required": [ + "channel_id" + ], "properties": { "channel_id": { - "description": "Channel to list rules for.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Channel whose rules to list; obtain it from `POST /channel/list`." } - }, - "required": [ - "channel_id" - ], - "type": "object" + } }, "ChannelShort": { + "type": "object", + "required": [ + "channel_id", + "channel_name" + ], "properties": { "channel_id": { - "description": "Channel ID.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Channel ID, one of the requested `channel_ids`." }, "channel_name": { - "description": "Channel name.", - "type": "string" + "type": "string", + "description": "Channel name, unique within the account." }, "status": { - "description": "Channel status: `enabled` processes events normally; `disabled` discards incoming events; `deleted` is soft-deleted.", + "type": "string", "enum": [ "enabled", "disabled", "deleted" ], - "type": "string" + "description": "Channel status:\n- `enabled`: incoming alert events are processed.\n- `disabled`: incoming alert events are discarded.\n- `deleted`: the channel was deleted." } - }, - "required": [ - "channel_id", - "channel_name" - ], - "type": "object" + } }, "CommentIncidentRequest": { "description": "Parameters for adding a comment to one or more incidents.", @@ -5133,786 +5451,359 @@ "type": "object" }, "ContextResolvedItem": { - "description": "Snapshot of the three-tier knowledge resolution for this session.", + "type": "object", + "description": "Knowledge versions the session's context resolved. In `POST /safari/session/get` only `versions` is filled (with `resolved_at_ms` = 0); the object is omitted until the agent has resolved knowledge at least once.", "properties": { "account_pack_id": { - "description": "Resolved account-scope knowledge ID.", - "type": "string" + "type": "string", + "description": "Resolved account-scope knowledge ID." + }, + "team_pack_id": { + "type": "string", + "description": "Resolved team-scope knowledge ID." }, "incident_id": { - "description": "Bound incident id, when war-room originated.", - "type": "string" + "type": "string", + "description": "Bound incident id, when war-room originated." }, "resolved_at_ms": { - "description": "Unix timestamp in milliseconds when the knowledge was resolved.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "team_pack_id": { - "description": "Resolved team-scope knowledge ID.", - "type": "string" + "description": "Unix timestamp in milliseconds when the knowledge was resolved." }, "versions": { + "type": "object", "additionalProperties": { "type": "integer" }, - "description": "Resolved version map, one entry per knowledge.", - "type": "object" + "description": "Map from knowledge ID to the version the agent last loaded." } }, "required": [ "resolved_at_ms" - ], - "type": "object" + ] }, "ConvertWorkItemRequest": { + "type": "object", "description": "Parameters for converting an action item into a post-mortem follow-up in place.", + "required": [ + "work_item_id", + "version", + "idempotency_key" + ], "properties": { - "idempotency_key": { - "description": "Client-generated idempotency key (max 128 characters; letters, digits, `_`, `-`, `.`, `:` only).", + "work_item_id": { + "type": "string", "maxLength": 128, - "pattern": "^[A-Za-z0-9_\\-.:]+$", - "type": "string" + "description": "Work item ID (opaque string, max 128 characters)." + }, + "version": { + "type": "integer", + "format": "int64", + "description": "The item's current `version` (≥ 1) for optimistic locking." }, "target_status": { - "description": "Optional status to set on the converted follow-up. One of `open`, `in_progress`, `done`, `cancelled`.", + "type": [ + "string", + "null" + ], "enum": [ "open", "in_progress", "done", - "cancelled" + "cancelled", + null ], "maxLength": 64, - "type": [ - "string", - "null" - ] - }, - "version": { - "description": "Current item version for optimistic locking. Must match the stored version.", - "format": "int64", - "type": "integer" + "description": "Optional status to set on the converted follow-up; omitted or `null` keeps the current status. Values: `open` (not started), `in_progress` (being worked on), `done` (finished), `cancelled` (no longer needed)." }, - "work_item_id": { - "description": "Work item ID (opaque string, max 128 characters).", + "idempotency_key": { + "type": "string", "maxLength": 128, - "type": "string" + "pattern": "^[A-Za-z0-9_\\-.:]+$", + "description": "Client-generated idempotency key (max 128 characters; letters, digits, `_`, `-`, `.`, `:` only)." } - }, - "required": [ - "work_item_id", - "version", - "idempotency_key" - ], - "type": "object" + } }, "CreateChannelRequest": { + "type": "object", "description": "Parameters for creating a channel.", + "required": [ + "team_id", + "channel_name" + ], "properties": { - "auto_resolve_mode": { - "description": "Auto-resolve timing mode: `trigger` starts the timer when the incident triggers, `update` restarts it on every alert update.", - "enum": [ - "trigger", - "update" - ], - "type": "string" - }, - "auto_resolve_timeout": { - "description": "Auto-resolve timeout in seconds. 0 disables auto-resolve. Max 30 days.", + "team_id": { + "type": "integer", "format": "int64", - "maximum": 2592000, - "minimum": 0, - "type": "integer" + "description": "Owning team ID; obtain it from `POST /team/list`. Required and must exist." + }, + "managing_team_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "maxItems": 3, + "description": "Additional teams that can manage the channel. Up to 3 entries." }, "channel_name": { - "description": "Channel name. 1 to 59 characters.", - "maxLength": 59, + "type": "string", "minLength": 1, - "type": "string" + "maxLength": 59, + "description": "Channel name, 1–59 characters, unique within the account." }, "description": { - "description": "Free-form description. Up to 500 characters.", + "type": "string", "maxLength": 500, - "type": "string" - }, - "disable_auto_close": { - "description": "Disable automatic incident closing.", - "type": "boolean" - }, - "disable_outlier_detection": { - "description": "Disable outlier incident detection.", - "type": "boolean" + "description": "Free-form description. Up to 500 characters." }, "escalate_rule": { - "description": "Default escalation rule applied to the channel. Omit to skip default escalation.", - "properties": { - "aggr_window": { - "description": "Delay window in seconds. 0 disables delay.", - "maximum": 3600, - "minimum": 0, - "type": "integer" - }, - "target": { - "description": "Notification target. At least one of `person_ids`, `team_ids`, `schedule_to_role_ids`, or `emails` must be set, together with either `by` or `webhooks`.", - "properties": { - "by": { - "description": "Per-severity personal notification channels. Required unless `webhooks` is provided.", - "properties": { - "critical": { - "description": "Notify channels used for Critical severity. Personal channels: `sms`, `voice`, `email`, `push`; IM group-chat channels: `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:`, `teams_app:`.", - "items": { - "type": "string" - }, - "type": "array" - }, - "follow_preference": { - "description": "When true, use each responder's personal preference instead of the lists below.", - "type": "boolean" - }, - "info": { - "description": "Notify channels used for Info severity. Values as for `critical`.", - "items": { - "type": "string" - }, - "type": "array" - }, - "warning": { - "description": "Notify channels used for Warning severity. Values as for `critical`.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "type": "object" - }, - "emails": { - "description": "Email addresses to notify (push-only scenarios).", - "items": { - "format": "email", - "type": "string" - }, - "type": "array" - }, - "person_ids": { - "description": "Member IDs to notify directly; obtain member IDs from `POST /member/list`.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "schedule_to_role_ids": { - "additionalProperties": { - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "description": "Map of schedule ID to the role IDs on that schedule to notify.", - "type": "object" - }, - "team_ids": { - "description": "Team IDs to notify; obtain team IDs from `POST /team/list`.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "webhooks": { - "description": "Group chat / webhook targets. Required unless `by` is provided.", - "items": { - "properties": { - "settings": { - "additionalProperties": true, - "description": "Type-specific settings (chat IDs, URLs, etc.).", - "type": "object" - }, - "type": { - "description": "Webhook type, one of `feishu`, `feishu_app`, `dingtalk`, `dingtalk_app`, `wecom`, `slack`, `slack_app`, `teams_app`, `telegram`, `zoom`.", - "type": "string" - } - }, - "required": [ - "type", - "settings" - ], - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - }, - "template_id": { - "description": "Notification template ID (MongoDB ObjectID).", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" - } - }, + "type": "object", + "description": "Creates an enabled escalation rule named `Default` with a single level that notifies `target` once. Omit to create the channel without escalation rules.", "required": [ "template_id", "target" ], - "type": "object" - }, - "event_group": { - "$ref": "#/components/schemas/EventGroup", - "description": "Alert event merge configuration. Omit to use the default (merge enabled, 1440-minute window)." - }, - "flapping": { - "description": "Flapping detection configuration.", "properties": { - "in_mins": { - "description": "Observation window in minutes.", - "maximum": 1440, - "minimum": 1, - "type": "integer" - }, - "is_disabled": { - "description": "Disable flapping detection.", - "type": "boolean" + "aggr_window": { + "type": "integer", + "minimum": 0, + "maximum": 3600, + "description": "Delay in seconds, 0–3600, before the first notification for a newly assigned incident; `0` notifies immediately." }, - "max_changes": { - "description": "Max state changes allowed within `in_mins`.", - "maximum": 100, - "minimum": 2, - "type": "integer" + "template_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Notification template ID (24-character hex); obtain it from `POST /template/list`. Must exist." }, - "mute_mins": { - "description": "Mute duration in minutes after flapping is detected.", - "maximum": 1440, - "minimum": 0, - "type": "integer" + "target": { + "$ref": "#/components/schemas/EscalateTarget", + "description": "Who to notify and through which channels." } - }, - "type": "object" + } }, "group": { - "description": "Alert grouping configuration.", - "properties": { - "all_equals_required": { - "description": "When true, all listed keys must be present for grouping.", - "type": "boolean" - }, - "cases": { - "description": "Per-filter grouping overrides.", - "items": { - "description": "Conditional grouping override: stored alerts matching `if` are grouped by `equals` instead of the top-level grouping keys.", - "properties": { - "equals": { - "description": "Grouping keys for matching alerts. Supported values: `title`, `description`, `severity`, or any `labels.`.", - "items": { - "type": "string" - }, - "maxItems": 5, - "minItems": 1, - "type": "array" - }, - "if": { - "description": "AND-ed match conditions evaluated against stored alert fields.", - "items": { - "$ref": "#/components/schemas/FilterCondition" - }, - "type": "array" - } - }, - "required": [ - "if", - "equals" - ], - "type": "object" - }, - "maxItems": 100, - "type": "array" - }, - "equals": { - "description": "Groups of label keys whose equality defines a bucket.", - "items": { - "items": { - "type": "string" - }, - "type": "array" - }, - "maxItems": 5, - "type": "array" - }, - "i_keys": { - "description": "Label keys used for intelligent grouping embeddings.", - "items": { - "type": "string" - }, - "maxItems": 10, - "type": "array" - }, - "i_score_threshold": { - "description": "Intelligent grouping similarity threshold.", - "format": "float", - "maximum": 1, - "minimum": 0.5, - "type": "number" - }, - "method": { - "description": "Grouping method: `i` intelligent, `p` pattern, `n` none.", - "enum": [ - "i", - "p", - "n" - ], - "type": "string" - }, - "storm_threshold": { - "description": "Alert storm threshold.", - "maximum": 10000, - "minimum": 0, - "type": "integer" - }, - "storm_thresholds": { - "description": "Multi-level storm thresholds.", - "items": { - "type": "integer" - }, - "maxItems": 5, - "type": "array" - }, - "time_window": { - "description": "Grouping time window in minutes. Default max is 1440 minutes (24 h); extended accounts may allow up to 43200 minutes (30 days).", - "minimum": 0, - "type": "integer" - }, - "window_type": { - "description": "Window type, default `tumbling`. `tumbling` is a fixed window counted from incident creation — once it expires, new alerts open a new incident; `sliding` is a sliding window counted from the incident's most recent alert, extended each time a new alert merges in.", - "enum": [ - "tumbling", - "sliding" - ], - "type": "string" - } - }, - "required": [ - "method" - ], - "type": "object" + "$ref": "#/components/schemas/Group", + "description": "Alert grouping configuration. Omit for no grouping (`method` `n`)." }, - "is_external_report_enabled": { - "description": "Allow external reporters to file incidents into this channel.", - "type": "boolean" + "flapping": { + "$ref": "#/components/schemas/Flapping", + "description": "Flapping detection configuration. Omit to use the defaults." }, - "is_private": { - "description": "When true, the channel is visible only to its managing teams.", - "type": "boolean" + "auto_resolve_timeout": { + "type": "integer", + "format": "int64", + "minimum": 0, + "maximum": 2592000, + "description": "Auto-resolve timeout in seconds. 0 disables auto-resolve. Max 30 days." }, - "managing_team_ids": { - "description": "Additional teams that can manage the channel. Up to 3 entries.", - "items": { - "format": "int64", - "type": "integer" - }, - "maxItems": 3, - "type": "array" + "auto_resolve_mode": { + "type": "string", + "enum": [ + "trigger", + "update" + ], + "description": "How the auto-resolve timer runs. `trigger` (default) starts the timer once when the incident is triggered; `update` restarts it whenever a new alert merges into the incident." }, "plugin_ids": { - "description": "IDs of plugins (integrations) subscribed to this channel.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Integration type IDs (the `plugin_id` shown on integrations returned by `POST /integration/list`). For each ID, a channel-exclusive integration of that type is created, named after the type. An unknown ID returns `InvalidParameter`." }, - "team_id": { - "description": "Owning team ID; obtain it from `POST /team/list`.", - "format": "int64", - "type": "integer" + "is_private": { + "type": "boolean", + "description": "When true, the channel is visible only to its managing teams." + }, + "disable_outlier_detection": { + "type": "boolean", + "description": "Disable outlier incident detection." + }, + "disable_auto_close": { + "type": "boolean", + "description": "Disable automatic incident closing." + }, + "is_external_report_enabled": { + "type": "boolean", + "description": "When true, external reporters can file incidents into this channel, and the response carries the generated `external_report_token`." + }, + "event_group": { + "$ref": "#/components/schemas/EventGroup", + "description": "Alert event merge configuration. Omit to use the default (merge enabled, 1440-minute window)." } - }, - "required": [ - "team_id", - "channel_name" - ], - "type": "object" + } }, "CreateDropRuleRequest": { + "type": "object", "description": "Parameters for creating a channel drop rule.", + "required": [ + "channel_id", + "rule_name" + ], "properties": { "channel_id": { - "description": "Owning channel ID; obtain it from `POST /channel/list`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Owning channel ID; obtain it from `POST /channel/list`." + }, + "rule_name": { + "type": "string", + "minLength": 1, + "maxLength": 39, + "description": "Rule name, 1 to 39 characters." }, "description": { - "description": "Rule description, up to 500 characters.", + "type": "string", "maxLength": 500, - "type": "string" + "description": "Rule description, up to 500 characters." }, "filters": { - "description": "Alert event match conditions (OR-of-AND); matching events are discarded entirely — no alert, incident, or notification is produced. When omitted or empty, the rule matches nothing.", - "items": { - "items": { - "properties": { - "key": { - "description": "Field key (e.g. `alert_severity`, `labels.service`).", - "type": "string" - }, - "oper": { - "description": "Filter operator.", - "enum": [ - "IN", - "NOTIN" - ], - "type": "string" - }, - "vals": { - "description": "Values to match.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "key", - "oper", - "vals" - ], - "type": "object" - }, - "type": "array" - }, - "type": "array" - }, - "rule_name": { - "description": "Rule name, 1 to 39 characters.", - "maxLength": 39, - "minLength": 1, - "type": "string" + "$ref": "#/components/schemas/FilterGroup", + "description": "Alert event conditions (OR of AND groups). A matching event is discarded entirely: no alert, incident or notification. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`. When omitted or empty, the rule matches nothing." } - }, - "required": [ - "channel_id", - "rule_name" - ], - "type": "object" + } }, "CreateEscalationRuleRequest": { + "type": "object", "description": "Parameters for creating an escalation rule.", + "required": [ + "channel_id", + "template_id", + "rule_name", + "layers" + ], "properties": { - "aggr_window": { - "description": "Delay window in seconds. 0 disables delay.", - "maximum": 3600, - "minimum": 0, - "type": "integer" - }, "channel_id": { - "description": "Owning channel ID; obtain it from `POST /channel/list`.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "description": { - "description": "Rule description, up to 500 characters.", - "maxLength": 500, - "type": "string" - }, - "filters": { - "description": "Incident-level match conditions (OR-of-AND tree): the rule is matched against the incident the alert was grouped into, not against the alert itself. Omit or leave empty to apply the rule to all incidents in the channel.", - "items": { - "items": { - "properties": { - "key": { - "description": "Field key (e.g. `alert_severity`, `labels.service`).", - "type": "string" - }, - "oper": { - "description": "Filter operator.", - "enum": [ - "IN", - "NOTIN" - ], - "type": "string" - }, - "vals": { - "description": "Values to match.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "key", - "oper", - "vals" - ], - "type": "object" - }, - "type": "array" - }, - "type": "array" - }, - "layers": { - "description": "Escalation levels in order. At least one level is required.", - "items": { - "properties": { - "escalate_window": { - "description": "Wait before moving to the next level, in minutes.", - "maximum": 720, - "minimum": 0, - "type": "integer" - }, - "force_escalate": { - "description": "When true, always escalate regardless of acknowledgement.", - "type": "boolean" - }, - "max_times": { - "description": "Max repeat notifications within the level.", - "maximum": 6, - "minimum": 0, - "type": "integer" - }, - "notify_step": { - "description": "Repeat interval in minutes.", - "format": "float", - "maximum": 120, - "minimum": 0.5, - "type": "number" - }, - "target": { - "description": "Notification target. At least one of `person_ids`, `team_ids`, `schedule_to_role_ids`, or `emails` must be set, together with either `by` or `webhooks`.", - "properties": { - "by": { - "description": "Per-severity personal notification channels. Required unless `webhooks` is provided.", - "properties": { - "critical": { - "description": "Notify channels used for Critical severity. Personal channels: `sms`, `voice`, `email`, `push`; IM group-chat channels: `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:`, `teams_app:`.", - "items": { - "type": "string" - }, - "type": "array" - }, - "follow_preference": { - "description": "When true, use each responder's personal preference instead of the lists below.", - "type": "boolean" - }, - "info": { - "description": "Notify channels used for Info severity. Values as for `critical`.", - "items": { - "type": "string" - }, - "type": "array" - }, - "warning": { - "description": "Notify channels used for Warning severity. Values as for `critical`.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "type": "object" - }, - "emails": { - "description": "Email addresses to notify (push-only scenarios).", - "items": { - "format": "email", - "type": "string" - }, - "type": "array" - }, - "person_ids": { - "description": "Member IDs to notify directly; obtain member IDs from `POST /member/list`.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "schedule_to_role_ids": { - "additionalProperties": { - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "description": "Map of schedule ID to the role IDs on that schedule to notify.", - "type": "object" - }, - "team_ids": { - "description": "Team IDs to notify; obtain team IDs from `POST /team/list`.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "webhooks": { - "description": "Group chat / webhook targets. Required unless `by` is provided.", - "items": { - "properties": { - "settings": { - "additionalProperties": true, - "description": "Type-specific settings (chat IDs, URLs, etc.).", - "type": "object" - }, - "type": { - "description": "Webhook type, one of `feishu`, `feishu_app`, `dingtalk`, `dingtalk_app`, `wecom`, `slack`, `slack_app`, `teams_app`, `telegram`, `zoom`.", - "type": "string" - } - }, - "required": [ - "type", - "settings" - ], - "type": "object" - }, - "type": "array" - } - }, - "type": "object" - } - }, - "required": [ - "target" - ], - "type": "object" - }, - "type": "array" + "description": "Owning channel ID; obtain it from `POST /channel/list`." }, "priority": { - "description": "Evaluation priority. Lower runs first.", - "maximum": 200, - "minimum": 0, "type": [ "integer", "null" - ] + ], + "minimum": 0, + "maximum": 200, + "description": "Evaluation order from `0` to `200`; lower values are evaluated first. Omit to place the rule after all existing rules (current highest priority + 1)." }, - "rule_name": { - "description": "Rule name, 1 to 39 characters.", - "maxLength": 39, - "minLength": 1, - "type": "string" + "aggr_window": { + "type": "integer", + "minimum": 0, + "maximum": 3600, + "description": "Delay in seconds, 0–3600, before the first notification for a newly assigned incident; `0` notifies immediately." }, "template_id": { - "description": "Notification template ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Notification template ID (24-character hex); obtain it from `POST /template/list`. Must exist." + }, + "rule_name": { + "type": "string", + "minLength": 1, + "maxLength": 39, + "description": "Rule name, 1 to 39 characters." + }, + "description": { + "type": "string", + "maxLength": 500, + "description": "Rule description, up to 500 characters." + }, + "layers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EscalateLayer" + }, + "description": "Escalation levels in order; the incident starts at the first level." }, "time_filters": { - "description": "Optional recurring time windows during which the rule applies.", + "type": "array", "items": { - "description": "Recurring time window. `start`/`end` use 24-hour `HH:MM` format; `repeat` uses ISO-style weekday indices (0=Sunday … 6=Saturday).", - "properties": { - "cal_id": { - "description": "Optional calendar ID; restricts the window to days matching the calendar.", - "type": "string" - }, - "end": { - "description": "End of the window in `HH:MM`.", - "type": "string" - }, - "is_off": { - "description": "When true, match days marked as days-off in the calendar.", - "type": "boolean" - }, - "repeat": { - "description": "Days of the week this window repeats on. Empty means every day.", - "items": { - "type": "integer" - }, - "type": "array" - }, - "start": { - "description": "Start of the window in `HH:MM`.", - "type": "string" - } - }, - "type": "object" + "$ref": "#/components/schemas/TimeFilter" }, - "type": "array" + "description": "Recurring time windows during which the rule can match; omit or leave empty to match at any time." + }, + "filters": { + "$ref": "#/components/schemas/FilterGroup", + "description": "Incident conditions (OR of AND groups), matched against the incident the alert was grouped into, not against the alert. Keys: `title`, `description`, `severity` (alias `incident_severity`, `alert_severity`), `status` (alias `incident_status`, `alert_status`), `dedup_key`, `integration_id` (alias `data_source_id`), or any `labels.`. Omit or leave empty to match every incident in the channel." } - }, - "required": [ - "channel_id", - "template_id", - "rule_name", - "layers" - ], - "type": "object" + } }, "CreateFieldRequest": { + "type": "object", + "required": [ + "field_name", + "display_name", + "field_type", + "value_type" + ], "properties": { - "default_value": { - "description": "Optional default value. Type must match `field_type`: `bool` for checkbox; one of `options` for single_select; subset of `options` for multi_select; string ≤3000 chars for text.", - "oneOf": [ - { - "type": "boolean" - }, - { - "type": "string" - }, - { - "items": { - "type": "string" - }, - "type": "array" - }, - { - "type": "null" - } - ] - }, - "description": { - "description": "Optional free-text description.", - "maxLength": 499, - "type": "string" + "field_name": { + "type": "string", + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]{0,39}$", + "maxLength": 39, + "description": "Machine name: 1–39 characters of `[a-zA-Z0-9_]`, starting with a letter or underscore. Immutable after creation." }, "display_name": { - "description": "Human-readable name. Must be unique within the account.", + "type": "string", "maxLength": 39, - "type": "string" + "description": "Human-readable name. Must be unique within the account." }, - "field_name": { - "description": "Machine name. Must start with a letter or underscore; 1–40 chars of `[a-zA-Z0-9_]`. Immutable after creation.", - "maxLength": 39, - "pattern": "^[a-zA-Z_][a-zA-Z0-9_]{0,39}$", - "type": "string" + "description": { + "type": "string", + "maxLength": 499, + "description": "Optional free-text description." }, "field_type": { - "description": "Field type, immutable after creation.\n| Value | Meaning |\n|---|---|\n| `text` | Free text; `value_type` must be `string`, no `options`. |\n| `single_select` | Single choice from `options`; `value_type` must be `string`. |\n| `multi_select` | Multiple choices from `options`; `value_type` must be `string`. |\n| `checkbox` | Boolean checkbox; `value_type` must be `bool`, no `options`. |", + "type": "string", "enum": [ "checkbox", "multi_select", "single_select", "text" ], - "type": "string" - }, - "options": { - "description": "Required and non-empty for `single_select`/`multi_select` (unique strings, each 1–200 chars). Must be omitted or empty for `checkbox`/`text`.", - "items": { - "type": "string" - }, - "type": "array" + "description": "Field type, immutable after creation.\n| Value | Meaning |\n|---|---|\n| `text` | Free text; `value_type` must be `string`, no `options`. |\n| `single_select` | Single choice from `options`; `value_type` must be `string`. |\n| `multi_select` | Multiple choices from `options`; `value_type` must be `string`. |\n| `checkbox` | Boolean checkbox; `value_type` must be `bool`, no `options`. |" }, "value_type": { - "description": "Value type. `checkbox` requires `bool`; all other types require `string`. Immutable after creation. `float` is a reserved value currently rejected for every `field_type`.", + "type": "string", "enum": [ "string", "bool", "float" ], - "type": "string" + "description": "Value type. `checkbox` requires `bool`; all other types require `string`. Immutable after creation. `float` is a reserved value currently rejected for every `field_type`." + }, + "options": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Required and non-empty for `single_select`/`multi_select` (unique strings, each 1–200 chars). Must be omitted or empty for `checkbox`/`text`." + }, + "default_value": { + "description": "Optional default value. Type must match `field_type`: `bool` for checkbox; one of `options` for single_select; subset of `options` for multi_select; string ≤3000 chars for text.", + "oneOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ] } - }, - "required": [ - "field_name", - "display_name", - "field_type", - "value_type" - ], - "type": "object" + } }, "CreateFieldResponse": { "properties": { @@ -5933,24 +5824,24 @@ "type": "object" }, "CreateIncidentCommentTypeRequest": { + "type": "object", "description": "Parameters for creating a comment type. At most 10 comment types per account.", - "properties": { - "color": { - "description": "Label color as a hex value in #RRGGBB format. Normalized to uppercase.", - "pattern": "^#[0-9A-Fa-f]{6}$", - "type": "string" - }, - "name": { - "description": "Display name. Trimmed before storing; must be unique within the account (case-insensitive). At most 40 characters.", - "maxLength": 40, - "type": "string" - } - }, "required": [ "name", "color" ], - "type": "object" + "properties": { + "name": { + "type": "string", + "maxLength": 40, + "description": "Display name. Trimmed before storing; must be unique within the account (case-insensitive). At most 40 characters. Must not contain control or text-direction characters." + }, + "color": { + "type": "string", + "pattern": "^#[0-9A-Fa-f]{6}$", + "description": "Label color as a hex value in #RRGGBB format. Normalized to uppercase." + } + } }, "CreateIncidentCommentTypeResponse": { "description": "Result of creating a comment type.", @@ -5971,493 +5862,323 @@ "type": "object" }, "CreateIncidentRequest": { + "type": "object", "description": "Parameters for manually creating an incident.", + "required": [ + "incident_severity" + ], "properties": { + "incident_severity": { + "type": "string", + "enum": [ + "Info", + "Warning", + "Critical" + ], + "description": "Incident severity: `Info`, `Warning` or `Critical` (most severe)." + }, + "title": { + "type": "string", + "maxLength": 512, + "description": "Incident title, up to 512 characters. Required (non-blank) when the account has a create form." + }, + "description": { + "type": "string", + "maxLength": 1024, + "description": "Incident description, up to 1024 characters." + }, + "channel_id": { + "type": "integer", + "format": "int64", + "description": "Channel to file the incident into; must exist in the account. Optional unless the account has a create form; leave it unset for a standalone incident." + }, "assigned_to": { - "description": "Incident assignment target. May be omitted entirely: when unset or empty, the channel's default assignment applies; required when the account's create form is in effect. `person_ids`, `escalate_rule_id`, and `emails` can be combined — responders are the union.", + "type": "object", + "description": "Who to assign. When omitted or empty, the channel's escalation rules decide (a standalone incident gets no responders); required when the account has a create form. `person_ids`, `escalate_rule_id` and `emails` can be combined — responders are the union. Assignment runs after creation, and its failure does not undo the incident.", "properties": { - "emails": { - "description": "Recipients to assign by email (1–100): resolved to account members and merged into `person_ids`; emails with no matching member are ignored.", + "person_ids": { + "type": "array", "items": { - "format": "email", - "type": "string" + "type": "integer", + "format": "int64" }, - "maxItems": 100, "minItems": 1, - "type": "array" + "maxItems": 100, + "description": "Member IDs to assign directly (1–100). Can be combined with `escalate_rule_id`." }, "escalate_rule_id": { - "description": "Escalation rule ID (MongoDB ObjectID); assigns the people at the rule's `layer_idx` layer.", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Escalation rule ID (MongoDB ObjectID); assigns the people at the rule's `layer_idx` layer." }, "layer_idx": { - "description": "Zero-based starting layer index of the escalation rule (default 0, the first layer); an out-of-range value returns an error. Only takes effect with `escalate_rule_id`.", - "type": "integer" + "type": "integer", + "description": "Zero-based escalation-rule layer to assign (default 0, the first layer). Used only with `escalate_rule_id`; an out-of-range value leaves the incident without responders instead of failing the request." + }, + "type": { + "type": "string", + "enum": [ + "assign", + "reassign", + "escalate", + "reopen" + ], + "description": "Assignment type. Normally omitted: the server then sets `assign`, because a manual create is always a first assignment. A value you send is stored as-is.\n- `assign`: first assignment of the incident.\n- `reassign`: assignment replacing an earlier one.\n- `escalate`: assignment triggered by escalation to the next layer.\n- `reopen`: assignment restarted from the first layer after the incident is reopened." + }, + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "minItems": 1, + "maxItems": 100, + "description": "Recipients to assign by email (1–100): resolved to account members and merged into `person_ids`; emails with no matching member are ignored." }, "notify": { + "type": "object", "description": "Override the notification channels used for this assignment.", "properties": { "follow_preference": { - "description": "When false, use `personal_channels`; when true or omitted, use each responder's personal preference.", "type": [ "boolean", "null" - ] + ], + "description": "When false, use `personal_channels`; when true or omitted, use each responder's personal preference." }, "personal_channels": { - "description": "Channels to use (e.g. `voice`, `sms`, `email`).", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Channels to use when `follow_preference` is false: `sms`, `voice`, `email`, `push`, or an IM app channel prefixed `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:` or `teams_app:`." }, "template_id": { - "description": "Notification template ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Notification template ID (MongoDB ObjectID)." } - }, - "type": "object" - }, - "person_ids": { - "description": "Member IDs to assign directly (1–100). Can be combined with `escalate_rule_id`.", - "items": { - "format": "int64", - "type": "integer" - }, - "maxItems": 100, - "minItems": 1, - "type": "array" - }, - "type": { - "description": "Assignment type, derived server-side — callers do not set it: `assign` for manual creation, `reassign` for re-assignment, `escalate` for escalation-driven assignment.\n| Value | Meaning |\n|---|---|\n| `assign` | Initial assignment when the incident is created manually. |\n| `reassign` | Re-assignment of an existing incident. |\n| `escalate` | Assignment triggered by escalation policy advancement. |\n| `reopen` | Assignment restarted from the first layer after the incident is reopened. |", - "enum": [ - "assign", - "reassign", - "escalate", - "reopen" - ], - "type": "string" + } } - }, - "type": "object" - }, - "channel_id": { - "description": "Channel to file the incident into. Optional; leave unset for a standalone incident.", - "format": "int64", - "type": "integer" - }, - "description": { - "description": "Incident description, up to 1024 characters.", - "maxLength": 1024, - "type": "string" + } }, "fields": { "$ref": "#/components/schemas/CustomFieldValues", "description": "Custom field values keyed by field name. When a create form applies, only its visible fields are accepted." - }, - "incident_severity": { - "description": "Incident severity: `Info`, `Warning` or `Critical` (most severe).", - "enum": [ - "Info", - "Warning", - "Critical" - ], - "type": "string" - }, - "title": { - "description": "Incident title, up to 512 characters.", - "maxLength": 512, - "type": "string" } - }, - "required": [ - "incident_severity" - ], - "type": "object" + } }, "CreateIncidentResponse": { + "type": "object", "description": "Result of manually creating an incident.", + "required": [ + "incident_id", + "title" + ], "properties": { "incident_id": { - "description": "Newly created incident ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Newly created incident ID (MongoDB ObjectID)." }, "title": { - "description": "Echoes the incident title from the request.", - "type": "string" + "type": "string", + "description": "Incident title as sent in the request; empty when the request had no title." } - }, - "required": [ - "incident_id", - "title" - ], - "type": "object" + } }, "CreateInhibitRuleRequest": { + "type": "object", "description": "Parameters for creating an inhibit rule.", + "required": [ + "channel_id", + "rule_name", + "equals" + ], "properties": { "channel_id": { - "description": "Owning channel ID; obtain it from `POST /channel/list`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Owning channel ID; obtain it from `POST /channel/list`." + }, + "rule_name": { + "type": "string", + "minLength": 1, + "maxLength": 39, + "description": "Rule name, 1 to 39 characters." }, "description": { - "description": "Rule description, up to 500 characters.", + "type": "string", "maxLength": 500, - "type": "string" + "description": "Rule description, up to 500 characters." }, "equals": { - "description": "Field keys whose values must be equal between the source (inhibiting) alert and the target (suppressed) alert, e.g. `data_source_id` or `labels.cluster`.", + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "is_directly_discard": { - "description": "When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule.", - "type": "boolean" - }, - "rule_name": { - "description": "Rule name, 1 to 39 characters.", - "maxLength": 39, - "minLength": 1, - "type": "string" + "description": "Keys whose values must be equal on the source alert and the incoming event. Only `title`, `severity` and `labels.` take effect; any other key (for example `data_source_id`) is accepted but makes the rule never fire. Must be present; an empty array also makes the rule inert." }, "source_filters": { - "description": "Conditions the source alert must match, evaluated against stored active alerts. Supported keys: `status`, `incident_status`, `alert_status`, `severity`, `incident_severity`, `alert_severity`, `title`, `description`, or any `labels.`. Empty makes the rule inert.", - "items": { - "items": { - "properties": { - "key": { - "description": "Field key (e.g. `alert_severity`, `labels.service`).", - "type": "string" - }, - "oper": { - "description": "Filter operator.", - "enum": [ - "IN", - "NOTIN" - ], - "type": "string" - }, - "vals": { - "description": "Values to match.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "key", - "oper", - "vals" - ], - "type": "object" - }, - "type": "array" - }, - "type": "array" + "$ref": "#/components/schemas/FilterGroup", + "description": "Conditions the source (inhibiting) alert must match, evaluated against active alerts already stored in the channel. Keys: `title`, `description`, `severity` (alias `incident_severity`, `alert_severity`), `status` (alias `incident_status`, `alert_status`), or any `labels.`. Empty makes the rule inert." }, "target_filters": { - "description": "Conditions the incoming target alert event must match to be suppressed; empty means every event is a target.", - "items": { - "items": { - "properties": { - "key": { - "description": "Field key (e.g. `alert_severity`, `labels.service`).", - "type": "string" - }, - "oper": { - "description": "Filter operator.", - "enum": [ - "IN", - "NOTIN" - ], - "type": "string" - }, - "vals": { - "description": "Values to match.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "key", - "oper", - "vals" - ], - "type": "object" - }, - "type": "array" - }, - "type": "array" + "$ref": "#/components/schemas/FilterGroup", + "description": "Conditions the incoming target alert event must match to be inhibited; empty means every incoming event is a target. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`." + }, + "is_directly_discard": { + "type": "boolean", + "description": "When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule." } - }, - "required": [ - "channel_id", - "rule_name", - "equals" - ], - "type": "object" + } }, "CreateSilenceRuleRequest": { + "type": "object", "description": "Parameters for creating a silence rule. Exactly one of `time_filter` or `time_filters` must be provided, and `filters` must be non-empty.", + "required": [ + "channel_id", + "rule_name" + ], "properties": { "channel_id": { - "description": "Owning channel ID; obtain it from `POST /channel/list`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Owning channel ID; obtain it from `POST /channel/list`." + }, + "rule_name": { + "type": "string", + "minLength": 1, + "maxLength": 39, + "description": "Rule name, 1 to 39 characters." }, "description": { - "description": "Rule description, up to 500 characters.", + "type": "string", "maxLength": 500, - "type": "string" + "description": "Rule description, up to 500 characters." }, - "filters": { - "description": "Alert event match conditions (OR-of-AND). Required and must contain at least one condition.", + "from_incident_id": { + "type": "string", + "description": "ID of the incident this rule is created from (24-character hex). The incident must exist, and only one enabled silence rule may exist per incident.", + "pattern": "^[0-9a-fA-F]{24}$" + }, + "time_filters": { + "type": "array", "items": { - "items": { - "properties": { - "key": { - "description": "Field key (e.g. `alert_severity`, `labels.service`).", - "type": "string" - }, - "oper": { - "description": "Filter operator.", - "enum": [ - "IN", - "NOTIN" - ], - "type": "string" - }, - "vals": { - "description": "Values to match.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "key", - "oper", - "vals" - ], - "type": "object" - }, - "type": "array" + "$ref": "#/components/schemas/TimeFilter" }, - "type": "array" + "description": "Recurring silence windows. Set exactly one of `time_filters` or `time_filter`." }, - "from_incident_id": { - "description": "Incident ID (ObjectID hex) to attach the rule to. Optional; when set, only one enabled silence rule may exist per incident.", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "time_filter": { + "$ref": "#/components/schemas/OnceTimeFilter", + "description": "One-off silence window. Set exactly one of `time_filter` or `time_filters`." }, - "is_auto_delete": { - "description": "When true, the silence rule is automatically deleted after its time window expires. Defaults to false.", - "type": "boolean" + "filters": { + "$ref": "#/components/schemas/FilterGroup", + "description": "Alert event conditions (OR of AND groups); matching events are silenced while the time window is active. Required, with at least one condition. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`." }, "is_directly_discard": { - "description": "When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule.", - "type": "boolean" - }, - "rule_name": { - "description": "Rule name, 1 to 39 characters.", - "maxLength": 39, - "minLength": 1, - "type": "string" - }, - "time_filter": { - "description": "One-off time window defined by unix seconds.", - "properties": { - "end_time": { - "description": "Window end, Unix timestamp in seconds. Must be greater than 0.", - "exclusiveMinimum": 0, - "format": "int64", - "type": "integer" - }, - "start_time": { - "description": "Window start, Unix timestamp in seconds. Must be greater than 0 and less than `end_time`.", - "exclusiveMinimum": 0, - "format": "int64", - "type": "integer" - } - }, - "required": [ - "start_time", - "end_time" - ], - "type": "object" + "type": "boolean", + "description": "When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule." }, - "time_filters": { - "description": "Recurring time windows during which silencing applies. Mutually exclusive with `time_filter`.", - "items": { - "description": "Recurring time window. `start`/`end` use 24-hour `HH:MM` format; `repeat` uses ISO-style weekday indices (0=Sunday … 6=Saturday).", - "properties": { - "cal_id": { - "description": "Optional calendar ID; restricts the window to days matching the calendar.", - "type": "string" - }, - "end": { - "description": "End of the window in `HH:MM`.", - "type": "string" - }, - "is_off": { - "description": "When true, match days marked as days-off in the calendar.", - "type": "boolean" - }, - "repeat": { - "description": "Days of the week this window repeats on. Empty means every day.", - "items": { - "type": "integer" - }, - "type": "array" - }, - "start": { - "description": "Start of the window in `HH:MM`.", - "type": "string" - } - }, - "type": "object" - }, - "type": "array" + "is_auto_delete": { + "type": "boolean", + "description": "When true, a rule with a one-off `time_filter` is permanently removed about 24 hours after `end_time` (or after its last update, whichever is later). Rules created with `from_incident_id` are cleaned up the same way. Rules with recurring `time_filters` are never removed automatically. Defaults to `false`." } - }, - "required": [ - "channel_id", - "rule_name" - ], - "type": "object" + } }, "CreateStatusPageChangeRequest": { + "type": "object", "description": "Parameters for creating a status page incident or maintenance event. The first update must contain `component_changes` to define affected components; retrospective events require at least 2 updates.", + "required": [ + "page_id", + "type", + "title", + "description", + "status", + "updates" + ], "properties": { - "auto_update_by_schedule": { - "description": "Maintenance only: automatically advance the status based on the scheduled window.", - "type": "boolean" - }, - "close_at_seconds": { - "description": "Event close time in Unix seconds. Must be greater than or equal to the first update's `at_seconds`. For retrospective events this is the time the event ended; for maintenances with `auto_update_by_schedule` it schedules the automatic transition to `completed` and must be within 30 days from now.", + "page_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Status page ID; obtain it from `GET /status-page/list`." }, - "description": { - "description": "Event description (Markdown). Must not be empty.", - "type": "string" + "type": { + "type": "string", + "enum": [ + "incident", + "maintenance" + ], + "description": "Change type: `incident` unplanned incident, `maintenance` planned maintenance." }, - "is_retrospective": { - "description": "Mark this event as a retrospective (historical) one.", - "type": "boolean" + "title": { + "type": "string", + "maxLength": 255, + "description": "Event title, up to 255 characters." }, - "linked_changes": { - "description": "Linked change IDs (related incidents, deployments, etc.).", - "items": { - "type": "string" - }, - "type": "array" + "description": { + "type": "string", + "description": "Event description (Markdown). Must not be empty." }, - "notify_subscribers": { - "description": "Notify subscribers about this event and all its updates.", - "type": "boolean" + "status": { + "type": "string", + "enum": [ + "investigating", + "identified", + "monitoring", + "resolved", + "scheduled", + "ongoing", + "completed" + ], + "description": "Initial event status. `investigating`/`identified`/`monitoring`/`resolved` apply to incidents; `scheduled`/`ongoing`/`completed` apply to maintenances." }, - "page_id": { - "description": "Status page ID; obtain it from `GET /status-page/list`.", + "start_at_seconds": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Event start time in Unix seconds. Maintenances store this value as the scheduled start (with `auto_update_by_schedule`, the time the event switches to `ongoing`); when it is omitted or 0, and always for incidents, the start time is the first update's `at_seconds`." }, "responders": { - "description": "Member IDs responsible for the event.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" - }, - "start_at_seconds": { - "description": "Event start time in Unix seconds. The stored start time is always derived from the first update's `at_seconds` (which defaults to the current time when omitted); for maintenances with `auto_update_by_schedule`, this value schedules the automatic transition to `ongoing`.", - "format": "int64", - "type": "integer" - }, - "status": { - "description": "Initial event status. `investigating`/`identified`/`monitoring`/`resolved` apply to incidents; `scheduled`/`ongoing`/`completed` apply to maintenances.", - "enum": [ - "investigating", - "identified", - "monitoring", - "resolved", - "scheduled", - "ongoing", - "completed" - ], - "type": "string" + "description": "Member IDs responsible for the event." }, - "title": { - "description": "Event title, up to 255 characters.", - "maxLength": 255, - "type": "string" + "linked_changes": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Linked change IDs (related incidents, deployments, etc.)." }, - "type": { - "description": "Change type: `incident` unplanned incident, `maintenance` planned maintenance.", - "enum": [ - "incident", - "maintenance" - ], - "type": "string" + "close_at_seconds": { + "type": "integer", + "format": "int64", + "description": "Event close time in Unix seconds; must be greater than or equal to the first update's `at_seconds`. For maintenances this is the scheduled end; with `auto_update_by_schedule` the event switches to `completed` at this time, which must be within 30 days from now. For a retrospective event in a terminal status, omitting it uses the latest update's time." }, "updates": { - "description": "Timeline updates. At least one update is required, and at least one of them must contain `component_changes`. Immediate events normally pass one update; retrospective events must pass all historical updates.", + "type": "array", "items": { + "type": "object", "description": "One timeline update entry.", "properties": { + "update_id": { + "type": "string", + "description": "Update ID. Server-assigned on create; supply when replaying historical updates." + }, "at_seconds": { - "description": "Update timestamp in Unix seconds. When omitted or 0 on the first update, defaults to the current time.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "component_changes": { - "description": "Component status transitions applied by this update.", - "items": { - "properties": { - "component_id": { - "description": "Component ID; obtain it from `GET /status-page/info`.", - "type": "string" - }, - "status": { - "description": "New component status. `operational`/`degraded`/`partial_outage`/`full_outage` apply to incidents; `operational`/`under_maintenance` apply to maintenances.", - "enum": [ - "operational", - "degraded", - "partial_outage", - "full_outage", - "under_maintenance" - ], - "type": "string" - } - }, - "required": [ - "component_id", - "status" - ], - "type": "object" - }, - "type": "array" + "description": "Update timestamp in Unix seconds. When omitted or 0 on the first update, defaults to the current time." }, - "description": { - "description": "Update description (Markdown).", + "status": { "type": [ "string", "null" - ] - }, - "status": { - "description": "Change status after this update. May be omitted (or null) when the overall status does not change. The first four values apply to incident-type changes, the last three to maintenance-type changes.\n| Value | Meaning |\n|---|---|\n| `investigating` | Investigating (incident). |\n| `identified` | Root cause identified (incident). |\n| `monitoring` | Fix deployed, monitoring (incident). |\n| `resolved` | Resolved (incident). |\n| `scheduled` | Scheduled (maintenance). |\n| `ongoing` | In progress (maintenance). |\n| `completed` | Completed (maintenance). |", + ], "enum": [ "investigating", "identified", @@ -6467,55 +6188,123 @@ "ongoing", "completed" ], + "description": "Change status after this update. May be omitted (or null) when the overall status does not change. The first four values apply to incident-type changes, the last three to maintenance-type changes.\n| Value | Meaning |\n|---|---|\n| `investigating` | Investigating (incident). |\n| `identified` | Root cause identified (incident). |\n| `monitoring` | Fix deployed, monitoring (incident). |\n| `resolved` | Resolved (incident). |\n| `scheduled` | Scheduled (maintenance). |\n| `ongoing` | In progress (maintenance). |\n| `completed` | Completed (maintenance). |" + }, + "description": { "type": [ "string", "null" - ] + ], + "description": "Update description (Markdown)." }, - "update_id": { - "description": "Update ID. Server-assigned on create; supply when replaying historical updates.", - "type": "string" + "component_changes": { + "type": "array", + "items": { + "type": "object", + "required": [ + "component_id", + "status" + ], + "properties": { + "component_id": { + "type": "string", + "description": "Component ID; obtain it from `GET /status-page/info`." + }, + "status": { + "type": "string", + "enum": [ + "operational", + "degraded", + "partial_outage", + "full_outage", + "under_maintenance" + ], + "description": "New component status. `operational`/`degraded`/`partial_outage`/`full_outage` apply to incidents; `operational`/`under_maintenance` apply to maintenances." + } + } + }, + "description": "Component status transitions applied by this update." } - }, - "type": "object" + } }, - "minItems": 1, - "type": "array" + "description": "Timeline updates in non-decreasing `at_seconds` order. At least one update is required, and at least one of them must contain `component_changes`. Immediate events normally pass one update; retrospective events must pass at least 2.", + "minItems": 1 + }, + "notify_subscribers": { + "type": "boolean", + "description": "Notify subscribers about this event. On creation one notification is sent for the last update; later timeline entries also notify while this is `true`." + }, + "auto_update_by_schedule": { + "type": "boolean", + "description": "Maintenance only: automatically advance the status based on the scheduled window." + }, + "is_retrospective": { + "type": "boolean", + "description": "Mark the event as retrospective (a past event recorded afterwards). Requires at least 2 entries in `updates`." + }, + "draft_id": { + "type": "string", + "description": "ID of a draft created by `POST /status-page/draft/create` to publish with this event. The draft must be pending, target this `page_id` and `type`, and have no `change_id`; it is marked published once the event is created. Omit when not publishing a draft." } - }, + } + }, + "CreateStatusPageChangeTimelineRequest": { + "type": "object", + "description": "Parameters for appending an update to a status page event timeline.", "required": [ "page_id", - "type", - "title", - "description", + "change_id", "status", - "updates" + "description" ], - "type": "object" - }, - "CreateStatusPageChangeTimelineRequest": { - "description": "Parameters for appending an update to a status page event timeline.", "properties": { - "at_seconds": { - "description": "Update timestamp in Unix seconds. Defaults to the current time when omitted or 0.", + "page_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Status page ID; obtain it from `GET /status-page/list`." }, "change_id": { - "description": "Target change ID; obtain it from `GET /status-page/change/list`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Target change ID; obtain it from `GET /status-page/change/list`." + }, + "at_seconds": { + "type": "integer", + "format": "int64", + "description": "Update time in Unix seconds; must not be earlier than the event's latest timeline entry. Defaults to the current time when omitted or 0." + }, + "status": { + "type": "string", + "enum": [ + "investigating", + "identified", + "monitoring", + "resolved", + "scheduled", + "ongoing", + "completed" + ], + "description": "Event status after this update; must be valid for the event type. Pass the current status to post an update without a status change. When moving to `resolved` or `completed`, all affected components must be back to `operational`.\n| Value | Meaning |\n|---|---|\n| `investigating` | Investigating (incident). |\n| `identified` | Root cause identified (incident). |\n| `monitoring` | Fix deployed, monitoring (incident). |\n| `resolved` | Resolved (incident). |\n| `scheduled` | Scheduled (maintenance). |\n| `ongoing` | In progress (maintenance). |\n| `completed` | Completed (maintenance). |" + }, + "description": { + "type": "string", + "description": "Update description (Markdown). Must not be empty." }, "component_changes": { - "description": "Component status transitions applied by this update. Component IDs must be unique.", + "type": "array", "items": { + "type": "object", + "required": [ + "component_id", + "status" + ], "properties": { "component_id": { - "description": "Component ID; obtain it from `GET /status-page/info`.", - "type": "string" + "type": "string", + "description": "Component ID; obtain it from `GET /status-page/info`." }, "status": { - "description": "New component status. `operational`/`degraded`/`partial_outage`/`full_outage` apply to incidents; `operational`/`under_maintenance` apply to maintenances.", + "type": "string", "enum": [ "operational", "degraded", @@ -6523,137 +6312,216 @@ "full_outage", "under_maintenance" ], - "type": "string" + "description": "New component status. `operational`/`degraded`/`partial_outage`/`full_outage` apply to incidents; `operational`/`under_maintenance` apply to maintenances." } - }, - "required": [ - "component_id", - "status" - ], - "type": "object" + } }, - "type": "array" - }, - "description": { - "description": "Update description (Markdown). Must not be empty.", - "type": "string" + "description": "Component status transitions applied by this update. Component IDs must be unique." }, - "page_id": { - "description": "Status page ID; obtain it from `GET /status-page/list`.", - "format": "int64", - "type": "integer" - }, - "status": { - "description": "Change status after this update; must be valid for the change type. When transitioning to `resolved` or `completed`, all affected components must be back to `operational`.\n| Value | Meaning |\n|---|---|\n| `investigating` | Investigating (incident). |\n| `identified` | Root cause identified (incident). |\n| `monitoring` | Fix deployed, monitoring (incident). |\n| `resolved` | Resolved (incident). |\n| `scheduled` | Scheduled (maintenance). |\n| `ongoing` | In progress (maintenance). |\n| `completed` | Completed (maintenance). |", - "enum": [ - "investigating", - "identified", - "monitoring", - "resolved", - "scheduled", - "ongoing", - "completed" - ], - "type": "string" + "draft_id": { + "type": "string", + "description": "ID of a pending draft created by `POST /status-page/draft/create` whose `change_id` is this event; it is marked published when the update is stored. Omit when not publishing a draft." } - }, - "required": [ - "page_id", - "change_id", - "status", - "description" - ], - "type": "object" + } }, "CreateStatusPageDraftRequest": { + "type": "object", "description": "Parameters for storing a status page draft. The `draft` payload is stored verbatim; only the validated fields listed below are interpreted.", + "required": [ + "draft" + ], "properties": { "draft": { - "description": "Draft payload, stored verbatim, up to 64 KB serialized. Validated fields: `page_id`, `type` (`incident` or `maintenance`), `name`, `message`; optional `change_id` (append an update to an existing event when > 0), `status`, `affected_components`, and `start_time`/`end_time` (Unix epoch seconds, new maintenance only).", - "type": "object" + "type": "object", + "description": "Draft payload, stored verbatim (at most 64 KB serialized). The server validates the fields below and keeps any other fields unchanged for the console.", + "required": [ + "page_id", + "type", + "name", + "message" + ], + "additionalProperties": true, + "properties": { + "v": { + "type": "integer", + "description": "Payload format version chosen by the producer; stored, not interpreted." + }, + "page_id": { + "type": "integer", + "format": "int64", + "description": "Target status page ID; must belong to the caller's account." + }, + "page_name": { + "type": "string", + "description": "Page name for display in the console; not validated." + }, + "type": { + "type": "string", + "enum": [ + "incident", + "maintenance" + ], + "description": "Event type the draft creates or updates: `incident` unplanned incident, `maintenance` planned maintenance." + }, + "name": { + "type": "string", + "maxLength": 255, + "description": "Event title, 1 to 255 characters." + }, + "message": { + "type": "string", + "description": "Event or update description (Markdown). Must not be empty." + }, + "change_id": { + "type": "integer", + "format": "int64", + "description": "Event to append an update to; it must be an event of the same `type` on `page_id`. Omit or pass 0 to draft a new event." + }, + "status": { + "type": "string", + "enum": [ + "investigating", + "identified", + "monitoring", + "resolved", + "scheduled", + "ongoing", + "completed" + ], + "description": "Proposed event status; when set, it must be valid for `type` (`investigating`/`identified`/`monitoring`/`resolved` for incidents, `scheduled`/`ongoing`/`completed` for maintenances)." + }, + "affected_components": { + "type": "array", + "description": "Components the draft affects.", + "items": { + "type": "object", + "required": [ + "component_id" + ], + "properties": { + "component_id": { + "type": "string", + "description": "Component ID; must exist on the page." + }, + "name": { + "type": "string", + "description": "Component name for display; not validated." + }, + "status": { + "type": "string", + "enum": [ + "operational", + "degraded", + "partial_outage", + "full_outage", + "under_maintenance" + ], + "description": "Proposed component status; when set, it must be valid for `type` (`operational`/`degraded`/`partial_outage`/`full_outage` for incidents, `operational`/`under_maintenance` for maintenances)." + } + } + } + }, + "start_time": { + "type": "integer", + "format": "int64", + "description": "Scheduled start in Unix seconds, for a new maintenance." + }, + "end_time": { + "type": "integer", + "format": "int64", + "description": "Scheduled end in Unix seconds, for a new maintenance; must be greater than `start_time` when both are set." + } + } }, "source": { - "description": "Opaque marker of the drafting origin, e.g. `ai_sre:sess_xxx`. Up to 64 characters.", + "type": "string", "maxLength": 64, - "type": "string" + "description": "Free-form text recording where the draft came from, such as an AI session reference; stored and shown with the draft, not interpreted. Up to 64 characters." } - }, - "required": [ - "draft" - ], - "type": "object" + } }, "CreateStatusPageRequest": { + "type": "object", "properties": { - "contact_info": { - "description": "Get-in-touch contact, such as a mailto or website URL.", - "type": "string" + "name": { + "type": "string", + "description": "Display name of the status page.", + "maxLength": 255 + }, + "url_name": { + "type": "string", + "description": "URL-safe slug; normalized to lowercase with non-alphanumeric characters replaced by hyphens, and must be unique among the account's pages of the same type.", + "maxLength": 255 + }, + "type": { + "type": "string", + "description": "Visibility type: `public` accessible to anyone, `internal` restricted to logged-in members of this account.", + "enum": [ + "public", + "internal" + ] }, "custom_domain": { - "description": "Custom domain for a public status page.", - "maxLength": 255, - "type": "string" + "type": "string", + "description": "Custom domain; allowed only for public pages and must not be used by another status page.", + "maxLength": 255 }, - "custom_links": { - "description": "Custom navigation links shown on the status page.", - "items": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - "type": "array" + "page_title": { + "type": "string", + "description": "Accepted for compatibility but not stored; it has no effect." + }, + "page_header": { + "type": "string", + "description": "Header content shown on the status page." + }, + "page_footer": { + "type": "string", + "description": "Footer content shown on the status page." }, "date_view": { + "type": "string", "description": "How change dates are displayed: `calendar` calendar view, `list` list view.", "enum": [ "calendar", "list" - ], - "type": "string" + ] }, "display_uptime_mode": { + "type": "string", "description": "Uptime display mode: `chart_and_percentage` chart plus percentage, `chart` chart only, `none` hidden.", "enum": [ "chart_and_percentage", "chart", "none" - ], - "type": "string" - }, - "name": { - "description": "Display name of the status page.", - "maxLength": 255, - "type": "string" - }, - "page_footer": { - "description": "Footer content shown on the status page.", - "type": "string" + ] }, - "page_header": { - "description": "Header content shown on the status page.", - "type": "string" + "custom_links": { + "type": "array", + "description": "Custom navigation links shown on the status page.", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Link text shown on the page." + }, + "value": { + "type": "string", + "description": "URL the link text points to, such as `https://www.example.com`." + } + }, + "additionalProperties": { + "type": "string" + } + } }, - "page_title": { - "description": "Browser title shown for the status page.", - "type": "string" + "contact_info": { + "type": "string", + "description": "Get-in-touch contact, such as a mailto or website URL." }, "subscription": { "$ref": "#/components/schemas/StatusPageSubscriptionItem", - "description": "Subscription channel toggles." - }, - "type": { - "description": "Visibility type: `public` accessible to anyone, `internal` restricted to logged-in members of this account.", - "enum": [ - "public", - "internal" - ], - "type": "string" - }, - "url_name": { - "description": "URL-safe slug, unique per account and page type.", - "maxLength": 255, - "type": "string" + "description": "Subscription channel toggles; both default to `false`. A public page can enable only `email` and an internal page only `im`." } }, "required": [ @@ -6662,8 +6530,7 @@ "type", "date_view", "display_uptime_mode" - ], - "type": "object" + ] }, "CreateStatusPageResponse": { "properties": { @@ -6689,91 +6556,67 @@ "type": "object" }, "CreateWarRoomRequest": { + "type": "object", "description": "Parameters for opening an incident war room in an IM integration.", + "required": [ + "incident_id", + "integration_id" + ], "properties": { - "add_observers": { - "description": "When true, also add historical responders of the incident as observers.", - "type": "boolean" - }, "incident_id": { - "description": "Incident ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Incident ID (MongoDB ObjectID)." }, "integration_id": { - "description": "IM integration ID. Must have war room enabled; Feishu, DingTalk, WeCom (self-built), Slack and Teams are supported.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "IM integration ID with war room enabled; obtain it from `POST /datasource/im/war-room-enabled/list`. Feishu, DingTalk, WeCom (self-built app only), and Slack are supported." }, "member_ids": { - "description": "Additional member IDs to add to the war room.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Member IDs to invite into the group; every ID must be a valid member of the account." + }, + "add_observers": { + "type": "boolean", + "description": "When true, also invite members who were assigned or added as responders earlier but are no longer current responders." } - }, - "required": [ - "incident_id", - "integration_id" - ], - "type": "object" + } }, "CreateWorkItemRequest": { + "type": "object", "description": "Parameters for creating an incident work item.", + "required": [ + "item_type", + "title", + "incident_id", + "idempotency_key" + ], "properties": { - "assignee_ids": { - "description": "Legacy alias for the initial assignees. Equivalent to `assignees` with every entry `type` `person`. Mutually exclusive with `assignees`: sending both returns an error. Assignees must be active members who can already read the anchor; assignment never grants access.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "assignees": { - "description": "Initial assignees. Each entry is `{type, id?}`. `type` is `person` or `ai_sre`; an `ai_sre` entry omits `id`. Mutually exclusive with `assignee_ids`: sending both returns an error. `assignee_ids` is the legacy alias and is equivalent to an all-`person` list. At most 20 entries. Person assignees must be active members who can already read the anchor; assignment never grants access.", - "items": { - "$ref": "#/components/schemas/WorkItemAssignee" - }, - "maxItems": 20, - "type": "array" - }, - "description": { - "description": "Optional longer description (max 65,535 characters).", - "maxLength": 65535, - "type": "string" - }, - "idempotency_key": { - "description": "Client-generated idempotency key (max 128 characters; letters, digits, `_`, `-`, `.`, `:` only).", - "maxLength": 128, - "pattern": "^[A-Za-z0-9_\\-.:]+$", - "type": "string" - }, - "incident_id": { - "description": "Incident ID (MongoDB ObjectID) the item is anchored to.", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" - }, "item_type": { - "description": "`action` anchors to an active incident and must not set `post_mortem_id`; `follow_up` requires `post_mortem_id`.", + "type": "string", "enum": [ "action", "follow_up" ], - "type": "string" + "description": "Work item type.\n- `action`: a to-do on an incident that is not closed yet; must not set `post_mortem_id`.\n- `follow_up`: a post-mortem follow-up on a closed incident; `post_mortem_id` is optional." }, - "post_mortem_id": { - "description": "Post-mortem ID (32-character hex string). Required for `follow_up`, forbidden for `action`. The post-mortem must be linked to `incident_id`.", - "type": "string" + "title": { + "type": "string", + "maxLength": 512, + "description": "Item title, at most 512 characters; leading and trailing spaces are trimmed and it must not be blank." }, - "priority": { - "description": "Optional client-defined priority (max 64 characters).", - "maxLength": 64, - "type": "string" + "description": { + "type": "string", + "maxLength": 65535, + "description": "Optional longer description (max 65,535 characters)." }, "status": { - "description": "Initial status. One of `open`, `in_progress`, `done`, `cancelled`; defaults to `open` when omitted or blank.", + "type": "string", "enum": [ "open", "in_progress", @@ -6781,21 +6624,45 @@ "cancelled" ], "maxLength": 64, - "type": "string" + "description": "Initial status. One of `open`, `in_progress`, `done`, `cancelled`; defaults to `open` when omitted or blank." }, - "title": { - "description": "Item title (max 512 characters).", - "maxLength": 512, - "type": "string" + "priority": { + "type": "string", + "maxLength": 64, + "description": "Optional free-form priority, at most 64 characters. The console uses `high`, `medium` and `low`; any other string is stored as-is." + }, + "incident_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Incident ID (MongoDB ObjectID) the item is anchored to." + }, + "post_mortem_id": { + "type": "string", + "description": "Post-mortem ID (32-character hex string). Forbidden for `action`. Optional for `follow_up`: when set, the incident must be linked to that report; when omitted, the incident's post-mortem is used if it exists." + }, + "assignee_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Legacy alias for the initial assignees. Equivalent to `assignees` with every entry `type` `person`. Mutually exclusive with `assignees`: sending both returns an error. Assignees must be active members who can already read the anchor; assignment never grants access." + }, + "assignees": { + "description": "Initial assignees. Each entry is `{type, id?}`. `type` is `person` or `ai_sre`; an `ai_sre` entry omits `id`. Mutually exclusive with `assignee_ids`: sending both returns an error. `assignee_ids` is the legacy alias and is equivalent to an all-`person` list. At most 20 entries. Person assignees must be active members who can already read the anchor; assignment never grants access.", + "items": { + "$ref": "#/components/schemas/WorkItemAssignee" + }, + "maxItems": 20, + "type": "array" + }, + "idempotency_key": { + "type": "string", + "maxLength": 128, + "pattern": "^[A-Za-z0-9_\\-.:]+$", + "description": "Client-generated idempotency key (max 128 characters; letters, digits, `_`, `-`, `.`, `:` only)." } - }, - "required": [ - "item_type", - "title", - "incident_id", - "idempotency_key" - ], - "type": "object" + } }, "CustomFieldValues": { "additionalProperties": true, @@ -6881,64 +6748,64 @@ "type": "object" }, "DSElasticSearchConfig": { + "type": "object", "description": "Elasticsearch datasource configuration.", "properties": { - "api_key": { - "description": "Elastic Cloud API key. Only for `cloud` deployment.", - "type": "string" - }, - "certificate_fingerprint": { - "description": "SHA-256 fingerprint of the Elasticsearch CA certificate, used to verify the server chain (the recommended check for ES 8 default security).", - "type": "string" - }, - "cloud_id": { - "description": "Elastic Cloud deployment ID. Only for `cloud` deployment.", - "type": "string" - }, "deployment": { - "description": "Deployment type. `cloud` uses Elastic Cloud; `self-managed` uses a self-hosted cluster.", + "type": "string", "enum": [ "cloud", "self-managed" ], - "type": "string" + "description": "Deployment type; required. `cloud` uses Elastic Cloud (`address` is not needed); `self-managed` uses a self-hosted cluster (`address` is required)." }, - "headers": { - "description": "Custom HTTP headers added to every request, each entry formatted as `Key: Value`.", - "items": { - "type": "string" - }, - "type": "array" + "timeout_mills": { + "type": "integer", + "format": "int64", + "description": "Per-query timeout in milliseconds; `0` or omitted uses the default of 10000 (10 seconds)." }, - "password": { - "description": "Authentication password for self-managed clusters; ignored when `service_token` is set.", - "type": "string" + "cloud_id": { + "type": "string", + "description": "Elastic Cloud deployment ID. Only for `cloud` deployment." }, - "service_token": { - "description": "Service token; overrides username/password if set.", - "type": "string" + "api_key": { + "type": "string", + "description": "Elastic Cloud API key. Only for `cloud` deployment." }, - "timeout_mills": { - "description": "Per-query timeout in milliseconds; `0` or omitted uses the default of 10000 (10 seconds).", - "format": "int64", - "type": "integer" + "username": { + "type": "string", + "description": "Username for `self-managed` deployment." + }, + "password": { + "type": "string", + "description": "Authentication password for self-managed clusters; ignored when `service_token` is set." + }, + "service_token": { + "type": "string", + "description": "Service token; overrides username/password if set." }, "tls_ca": { - "description": "PEM-encoded CA certificate used to verify the Elasticsearch server certificate.", - "type": "string" + "type": "string", + "description": "PEM-encoded CA certificate used to verify the Elasticsearch server certificate." }, - "username": { - "description": "Username for `self-managed` deployment.", - "type": "string" + "certificate_fingerprint": { + "type": "string", + "description": "SHA-256 fingerprint of the Elasticsearch CA certificate, used to verify the server chain (the recommended check for ES 8 default security)." + }, + "headers": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Custom HTTP headers added to every request, each entry formatted as `Key: Value`." } - }, - "type": "object" + } }, "DSKafkaConfig": { "description": "Diagnostic datasource connection configuration.", "properties": { "password": { - "description": "Authentication password; supports ${env:NAME}. Omit on update to preserve; explicitly send an empty string to clear. Literal passwords are omitted from responses.", + "description": "Authentication password; supports ${env:NAME}. Required with `username` for SASL authentication and must be empty when `sasl_mechanism` is `none`. On update, omit to keep the stored password; explicitly send an empty string to clear. Literal passwords are omitted from responses.", "type": "string", "x-flashduty-preserve-absence": true }, @@ -6970,7 +6837,7 @@ }, "tls_enabled": { "default": false, - "description": "Whether TLS is enabled; defaults to false.", + "description": "Whether TLS is enabled; defaults to false. When false, all `tls_*` fields are cleared on save.", "type": "boolean" }, "tls_key": { @@ -6995,7 +6862,7 @@ "type": "boolean" }, "username": { - "description": "Authentication username; an ${env:NAME} reference is supported.", + "description": "Authentication username; an ${env:NAME} reference is supported. Required when `sasl_mechanism` is `plain`, `scram-sha-256` or `scram-sha-512`; must be empty when it is `none`.", "type": "string" } }, @@ -7087,7 +6954,7 @@ }, "tls_enabled": { "default": false, - "description": "Whether TLS is enabled; defaults to false.", + "description": "Whether TLS is enabled; defaults to false. When false, all `tls_*` fields are cleared on save.", "type": "boolean" }, "tls_max_version": { @@ -7107,7 +6974,7 @@ "type": "boolean" }, "username": { - "description": "Authentication username; an ${env:NAME} reference is supported.", + "description": "Authentication username; an ${env:NAME} reference is supported. Must be configured together with `password`.", "type": "string" } }, @@ -7222,61 +7089,75 @@ "type": "object" }, "DSPayload": { + "type": "object", "description": "Type-specific datasource configuration. Include only the block matching `type_ident`.", "properties": { + "prometheus": { + "$ref": "#/components/schemas/DSPrometheusConfig", + "description": "Settings for `type_ident` `prometheus`." + }, + "loki": { + "$ref": "#/components/schemas/DSLokiConfig", + "description": "Settings for `type_ident` `loki`." + }, + "mysql": { + "$ref": "#/components/schemas/DSMySQLConfig", + "description": "Settings for `type_ident` `mysql`." + }, + "oracle": { + "$ref": "#/components/schemas/DSOracleConfig", + "description": "Settings for `type_ident` `oracle`." + }, + "postgres": { + "$ref": "#/components/schemas/DSPostgresConfig", + "description": "Settings for `type_ident` `postgres`." + }, "clickhouse": { - "$ref": "#/components/schemas/DSClickHouseConfig" + "$ref": "#/components/schemas/DSClickHouseConfig", + "description": "Settings for `type_ident` `clickhouse`." }, "elasticsearch": { - "$ref": "#/components/schemas/DSElasticSearchConfig" + "$ref": "#/components/schemas/DSElasticSearchConfig", + "description": "Settings for `type_ident` `elasticsearch`." + }, + "sls": { + "$ref": "#/components/schemas/DSSLSConfig", + "description": "Settings for `type_ident` `sls`." + }, + "victorialogs": { + "$ref": "#/components/schemas/DSVictoriaLogsConfig", + "description": "Settings for `type_ident` `victorialogs`." + }, + "tencent_cls": { + "$ref": "#/components/schemas/DSTencentCLSConfig", + "description": "Tencent CLS credentials. Required when `type_ident` is `tencent_cls`." }, "kafka": { "$ref": "#/components/schemas/DSKafkaConfig", - "x-flashduty-preserve-absence": true - }, - "loki": { - "$ref": "#/components/schemas/DSLokiConfig" + "x-flashduty-preserve-absence": true, + "description": "Settings for `type_ident` `kafka` (diagnostic-only)." }, "mongodb_mongod": { "$ref": "#/components/schemas/DSMongoDBConfig", - "x-flashduty-preserve-absence": true + "x-flashduty-preserve-absence": true, + "description": "Settings for `type_ident` `mongodb_mongod` (diagnostic-only); same fields as `mongodb_mongos`." }, "mongodb_mongos": { "$ref": "#/components/schemas/DSMongoDBConfig", - "x-flashduty-preserve-absence": true - }, - "mysql": { - "$ref": "#/components/schemas/DSMySQLConfig" - }, - "oracle": { - "$ref": "#/components/schemas/DSOracleConfig" - }, - "postgres": { - "$ref": "#/components/schemas/DSPostgresConfig" - }, - "prometheus": { - "$ref": "#/components/schemas/DSPrometheusConfig" + "x-flashduty-preserve-absence": true, + "description": "Settings for `type_ident` `mongodb_mongos` (diagnostic-only); same fields as `mongodb_mongod`." }, "redis_node": { "$ref": "#/components/schemas/DSRedisNodeConfig", - "x-flashduty-preserve-absence": true + "x-flashduty-preserve-absence": true, + "description": "Settings for `type_ident` `redis_node` (diagnostic-only)." }, "redis_sentinel": { "$ref": "#/components/schemas/DSRedisSentinelConfig", - "x-flashduty-preserve-absence": true - }, - "sls": { - "$ref": "#/components/schemas/DSSLSConfig" - }, - "tencent_cls": { - "$ref": "#/components/schemas/DSTencentCLSConfig", - "description": "Tencent CLS credentials. Required when `type_ident` is `tencent_cls`." - }, - "victorialogs": { - "$ref": "#/components/schemas/DSVictoriaLogsConfig" + "x-flashduty-preserve-absence": true, + "description": "Settings for `type_ident` `redis_sentinel` (diagnostic-only)." } - }, - "type": "object" + } }, "DSPostgresConfig": { "description": "PostgreSQL datasource configuration.", @@ -7333,64 +7214,64 @@ "type": "object" }, "DSPrometheusConfig": { + "type": "object", "description": "Prometheus datasource configuration. TLS fields are inherited from TLSClientConfig.", "properties": { "basic_auth_enabled": { - "description": "Enable HTTP Basic Auth.", - "type": "boolean" - }, - "basic_auth_password": { - "description": "Basic auth password.", - "type": "string" + "type": "boolean", + "description": "Enable HTTP Basic Auth." }, "basic_auth_username": { - "description": "Basic auth username.", - "type": "string" + "type": "string", + "description": "Basic Auth username, effective when `basic_auth_enabled` is `true`." + }, + "basic_auth_password": { + "type": "string", + "description": "Basic Auth password, effective when `basic_auth_enabled` is `true`. Returned as stored in create, update and info responses." }, "headers": { - "description": "Custom HTTP headers in `Key: Value` format.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Custom HTTP headers in `Key: Value` format." }, "params": { - "description": "Custom query parameters in `key=value` format.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Custom query parameters in `key=value` format." }, "tls_ca": { - "description": "PEM-encoded CA certificate used to verify the server certificate.", - "type": "string" + "type": "string", + "description": "PEM-encoded CA certificate used to verify the server certificate." }, "tls_cert": { - "description": "PEM-encoded client certificate for mutual TLS; must be configured together with `tls_key`.", - "type": "string" + "type": "string", + "description": "PEM-encoded client certificate for mutual TLS; must be configured together with `tls_key`." }, "tls_key": { - "description": "PEM-encoded client private key; must be configured together with `tls_cert`.", - "type": "string" - }, - "tls_max_version": { - "description": "Maximum TLS version, one of `1.0`, `1.1`, `1.2`, `1.3`; empty means no constraint.", - "type": "string" + "type": "string", + "description": "PEM-encoded client private key; must be configured together with `tls_cert`." }, - "tls_min_version": { - "description": "Minimum TLS version, one of `1.0`, `1.1`, `1.2`, `1.3`; empty means no constraint and it must not exceed `tls_max_version`.", - "type": "string" + "tls_skip_verify": { + "type": "boolean", + "description": "Whether to skip server certificate verification (insecure, for self-signed setups only)." }, "tls_server_name": { - "description": "Server name used for TLS SNI and certificate verification; defaults to the host from the connection address when empty.", - "type": "string" + "type": "string", + "description": "Server name used for TLS SNI and certificate verification; defaults to the host from the connection address when empty." }, - "tls_skip_verify": { - "description": "Whether to skip server certificate verification (insecure, for self-signed setups only).", - "type": "boolean" + "tls_min_version": { + "type": "string", + "description": "Minimum TLS version, one of `1.0`, `1.1`, `1.2`, `1.3`; empty means no constraint and it must not exceed `tls_max_version`." + }, + "tls_max_version": { + "type": "string", + "description": "Maximum TLS version, one of `1.0`, `1.1`, `1.2`, `1.3`; empty means no constraint." } - }, - "type": "object" + } }, "DSRedisNodeConfig": { "description": "Diagnostic datasource connection configuration.", @@ -7414,7 +7295,7 @@ "type": "integer" }, "username": { - "description": "Authentication username; an ${env:NAME} reference is supported.", + "description": "Authentication username; an ${env:NAME} reference is supported. When set, `password` is required (on update, omit `password` to keep the stored one).", "type": "string" } }, @@ -7436,7 +7317,7 @@ "type": "integer" }, "username": { - "description": "Authentication username; an ${env:NAME} reference is supported.", + "description": "Authentication username; an ${env:NAME} reference is supported. When set, `password` is required (on update, omit `password` to keep the stored one).", "type": "string" } }, @@ -7541,42 +7422,72 @@ "type": "object" }, "DataSourceItem": { + "type": "object", "description": "A monitoring datasource.", + "required": [ + "id", + "account_id", + "type_ident", + "name", + "enabled", + "note", + "address", + "edge_cluster_name", + "updated_at", + "payload", + "alerting_enabled", + "manage_team_id", + "readonly_team_ids", + "creator_id" + ], "properties": { - "account_id": { - "description": "Account ID.", + "id": { + "type": "integer", "format": "uint64", - "type": "integer" + "description": "Unique datasource ID. Pass it as `id` to update, delete and info, and as `datasource_id` to tool invocation." }, - "address": { - "description": "Connection address. For Prometheus/Loki/VictoriaLogs: HTTP URL. For MySQL/Oracle/Postgres/ClickHouse: `host:port`. For SLS: endpoint without http/https prefix. Redis/MongoDB diagnostic types: one host:port, bracket IPv6; no URI, userinfo or query. Kafka: 1–32 unique comma-separated host:port bootstrap addresses; payload has no broker list. At most 4096 characters after normalization.", - "maxLength": 4096, - "type": "string" + "account_id": { + "type": "integer", + "format": "uint64", + "description": "ID of the account that owns the datasource; always the caller's account." }, - "alerting_enabled": { - "description": "Whether alert evaluation is allowed. Alerting also requires enabled=true and an alerting-capable type. Always false for diagnostic-only types; false does not block non-alerting queries or tools.", - "type": "boolean" + "type_ident": { + "type": "string", + "enum": [ + "prometheus", + "loki", + "mysql", + "oracle", + "postgres", + "clickhouse", + "elasticsearch", + "sls", + "tencent_cls", + "victorialogs", + "redis_node", + "redis_sentinel", + "mongodb_mongod", + "mongodb_mongos", + "kafka" + ], + "description": "Datasource type.\n\nAlerting types (can evaluate alert rules):\n- `prometheus`: Prometheus-compatible metrics.\n- `loki`: Grafana Loki logs.\n- `mysql`: MySQL.\n- `oracle`: Oracle Database.\n- `postgres`: PostgreSQL.\n- `clickhouse`: ClickHouse.\n- `elasticsearch`: Elasticsearch.\n- `sls`: Alibaba Cloud Simple Log Service.\n- `tencent_cls`: Tencent Cloud Log Service (CLS).\n- `victorialogs`: VictoriaLogs.\n\nDiagnostic-only types (cannot evaluate alerts, `alerting_enabled` is always `false`):\n- `redis_node`: a single Redis node.\n- `redis_sentinel`: Redis Sentinel.\n- `mongodb_mongod`: a MongoDB mongod instance.\n- `mongodb_mongos`: a MongoDB mongos router.\n- `kafka`: a Kafka cluster.\n\nThe `payload` key that holds the type-specific settings has the same name as the type." }, - "edge_cluster_name": { - "description": "Monitors edge cluster name responsible for evaluating rules using this datasource.", - "type": "string" + "name": { + "type": "string", + "description": "Datasource name, unique within the account across all types." }, "enabled": { - "description": "Whether business execution is enabled. Disabled datasources reject business queries and tools; enabling does not change alerting_enabled.", - "type": "boolean" - }, - "id": { - "description": "Unique datasource ID.", - "format": "uint64", - "type": "integer" - }, - "name": { - "description": "Datasource display name.", - "type": "string" + "type": "boolean", + "description": "Whether business execution is enabled. Disabled datasources reject business queries and tools; enabling does not change alerting_enabled." }, "note": { - "description": "Optional description.", - "type": "string" + "type": "string", + "description": "Free-text note; an empty string when not set." + }, + "address": { + "type": "string", + "description": "Connection address as stored, after normalization. The format depends on `type_ident`; see the `address` field of the create request for each type. At most 4096 characters.", + "maxLength": 4096 }, "payload": { "anyOf": [ @@ -7589,99 +7500,183 @@ ], "description": "Type-specific configuration block; must contain the key matching `type_ident`. Always `null` in `/monit/datasource/list` responses (the list query does not read the payload column); populated in create/update/info responses. For `tencent_cls`, `secret_key` is masked to an empty string unless it is an `${env:...}` reference. For diagnostic types, password and Kafka tls_key are omitted from responses unless they are ${env:...} references. On update, omit those fields to preserve stored secrets; explicitly send an empty string to clear. Other configuration fields retain their existing behavior." }, - "type_ident": { - "description": "Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。", - "type": "string" + "edge_cluster_name": { + "type": "string", + "description": "Monitors edge cluster name responsible for evaluating rules using this datasource." }, "updated_at": { - "description": "Last update timestamp, Unix epoch seconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update timestamp, Unix epoch seconds." + }, + "alerting_enabled": { + "description": "Whether alert evaluation is allowed. Alerting also requires enabled=true and an alerting-capable type. Always false for diagnostic-only types; false does not block non-alerting queries or tools.", + "type": "boolean" + }, + "manage_team_id": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "description": "ID of the managing team. Its members can edit, delete, enable or disable the datasource and view its full configuration. `null` means no managing team: any caller with the Datasources Manage permission can manage it. The creator, the account owner and Admin members can always manage." + }, + "readonly_team_ids": { + "type": [ + "array", + "null" + ], + "items": { + "type": "integer", + "format": "uint64" + }, + "description": "IDs of the teams allowed to query and reference the datasource, in addition to the managing team, the creator, the account owner and Admin members. `null` or an empty array means every member of the account can query it." + }, + "creator_id": { + "type": [ + "integer", + "null" + ], + "format": "uint64", + "description": "ID of the member who created the datasource; `null` when not recorded. The creator can always manage the datasource." + }, + "my_perm": { + "type": "string", + "enum": [ + "manage", + "readonly" + ], + "description": "The caller's access level on this datasource. Only present in list responses.\n- `manage`: can edit, delete, enable or disable the datasource, view its configuration and query it.\n- `readonly`: can query and reference the datasource but not change it or read its configuration." } - }, - "required": [ - "id", - "account_id", - "type_ident", - "name", - "enabled", - "note", - "address", - "edge_cluster_name", - "updated_at", - "payload", - "alerting_enabled" - ], - "type": "object" + } }, "DataSourceListRequest": { + "type": "object", "description": "Filter parameters for listing datasources.", "properties": { "type": { - "description": "Datasource type identifier. Omit to return all types. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。", - "type": "string" + "type": "string", + "description": "Return only datasources of this type; omit or leave empty to return all types. An unrecognized value matches nothing and returns an empty array.\n\nAlerting types (can evaluate alert rules):\n- `prometheus`: Prometheus-compatible metrics.\n- `loki`: Grafana Loki logs.\n- `mysql`: MySQL.\n- `oracle`: Oracle Database.\n- `postgres`: PostgreSQL.\n- `clickhouse`: ClickHouse.\n- `elasticsearch`: Elasticsearch.\n- `sls`: Alibaba Cloud Simple Log Service.\n- `tencent_cls`: Tencent Cloud Log Service (CLS).\n- `victorialogs`: VictoriaLogs.\n\nDiagnostic-only types (cannot evaluate alerts, `alerting_enabled` is always `false`):\n- `redis_node`: a single Redis node.\n- `redis_sentinel`: Redis Sentinel.\n- `mongodb_mongod`: a MongoDB mongod instance.\n- `mongodb_mongos`: a MongoDB mongos router.\n- `kafka`: a Kafka cluster.", + "enum": [ + "prometheus", + "loki", + "mysql", + "oracle", + "postgres", + "clickhouse", + "elasticsearch", + "sls", + "tencent_cls", + "victorialogs", + "redis_node", + "redis_sentinel", + "mongodb_mongod", + "mongodb_mongos", + "kafka" + ] + }, + "name": { + "type": "string", + "description": "Return only the datasource whose name equals this value exactly (names are unique within the account, so at most one item). Omit or leave empty for no name filter." } - }, - "type": "object" + } }, "DataSourceListResponse": { - "description": "List of datasources. The `payload` column is not read by this endpoint, so `payload` is `null` in every item.", + "type": "array", + "description": "Datasources of the account that the caller can query, sorted by name; an empty array when nothing matches. `payload` is `null` in every item because the list does not read it; each item also carries `my_perm`.", "items": { "$ref": "#/components/schemas/DataSourceItem" - }, - "type": "array" + } }, "DataSourceUpsertRequest": { - "description": "Request body for creating or updating a datasource. `id` is required only for update. `address` is required for all types except Elasticsearch with `deployment=cloud`.", + "type": "object", + "description": "Request body for creating or updating a datasource. `id` is required for update and ignored on create. An update replaces `type_ident`, `name`, `note`, `address`, `payload` and `edge_cluster_name` with the values sent, so resend them all; only `enabled`, `alerting_enabled`, `manage_team_id` and `readonly_team_ids` keep their current value when omitted. `address` is required for all types except Elasticsearch with `deployment=cloud`.", + "required": [ + "type_ident", + "name", + "edge_cluster_name", + "payload" + ], "properties": { + "id": { + "type": "integer", + "format": "uint64", + "description": "Datasource ID. Required for update (an unknown ID, or one in another account, fails with `ResourceNotFound`); ignored on create." + }, + "type_ident": { + "type": "string", + "enum": [ + "prometheus", + "loki", + "mysql", + "oracle", + "postgres", + "clickhouse", + "elasticsearch", + "sls", + "tencent_cls", + "victorialogs", + "redis_node", + "redis_sentinel", + "mongodb_mongod", + "mongodb_mongos", + "kafka" + ], + "description": "Datasource type.\n\nAlerting types (can evaluate alert rules):\n- `prometheus`: Prometheus-compatible metrics.\n- `loki`: Grafana Loki logs.\n- `mysql`: MySQL.\n- `oracle`: Oracle Database.\n- `postgres`: PostgreSQL.\n- `clickhouse`: ClickHouse.\n- `elasticsearch`: Elasticsearch.\n- `sls`: Alibaba Cloud Simple Log Service.\n- `tencent_cls`: Tencent Cloud Log Service (CLS).\n- `victorialogs`: VictoriaLogs.\n\nDiagnostic-only types (cannot evaluate alerts, `alerting_enabled` is always `false`):\n- `redis_node`: a single Redis node.\n- `redis_sentinel`: Redis Sentinel.\n- `mongodb_mongod`: a MongoDB mongod instance.\n- `mongodb_mongos`: a MongoDB mongos router.\n- `kafka`: a Kafka cluster.\n\nThe `payload` key that holds the type-specific settings has the same name as the type." + }, + "name": { + "type": "string", + "description": "Datasource name; required and unique within the account across all types. This is the name referenced as `ds_name` in query APIs. Duplicates fail with `InvalidParameter`." + }, + "note": { + "type": "string", + "description": "Free-text note. On update, an omitted or empty value clears the stored note." + }, "address": { - "description": "Connection address. Required for every type except `elasticsearch` with `deployment: cloud`. Prometheus/Loki/VictoriaLogs: HTTP URL; MySQL/Oracle/Postgres/ClickHouse: `host:port`; SLS: endpoint without the `http(s)://` prefix; `tencent_cls`: must be `cls.tencentcloudapi.com` or `cls.internal.tencentcloudapi.com` (requires Monitors edge >= v0.66.0). Redis/MongoDB diagnostic types: one host:port, bracket IPv6; no URI, userinfo or query. Kafka: 1–32 unique comma-separated host:port bootstrap addresses; payload has no broker list. At most 4096 characters after normalization.", - "maxLength": 4096, - "type": "string" + "type": "string", + "description": "Connection address, required for every type except `elasticsearch` with `deployment: cloud`. At most 4096 characters after normalization. Format by type:\n- `prometheus`, `loki`, `victorialogs`: HTTP URL; `http://` is prepended when the value does not start with `http`.\n- `mysql`, `oracle`, `postgres`: `host:port`.\n- `clickhouse`: one or more comma-separated `host:port` endpoints; duplicates are rejected.\n- `elasticsearch` with `self-managed`: one or more comma-separated HTTP(S) URLs (scheme defaults to `http://`) that share identical query parameters; duplicates are rejected. Not needed for `cloud`.\n- `sls`: endpoint without the `http://` or `https://` prefix.\n- `tencent_cls`: exactly `cls.tencentcloudapi.com` or `cls.internal.tencentcloudapi.com` (requires Monitors edge >= v0.66.0).\n- `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`: a single `host:port` (bracket IPv6) with no URI, userinfo or query.\n- `kafka`: 1-32 unique comma-separated `host:port` bootstrap addresses (the payload has no broker list).", + "maxLength": 4096 }, - "alerting_enabled": { - "description": "Whether this datasource may evaluate alerts. Omitted on create: true for alerting types, false for diagnostic-only types; omitted on update: preserve current value. null is invalid. redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka reject true. Disabling is rejected with conflict when enabled rules reference the datasource.", - "type": "boolean", - "x-flashduty-preserve-absence": true + "payload": { + "$ref": "#/components/schemas/DSPayload", + "description": "Type-specific configuration block; must include the key named by `type_ident`. An update replaces the whole payload, so resend every setting you want to keep (including credentials of non-diagnostic types, which the info endpoint returns). Exceptions: for the diagnostic types, omit the password (and the Kafka `tls_key`) to keep the stored value or send an empty string to clear it; for `tencent_cls`, an omitted or empty `secret_key` keeps the stored key. Stored secrets are not carried over when `type_ident` changes." }, "edge_cluster_name": { - "description": "Monitors edge cluster name responsible for evaluating rules using this datasource.", - "type": "string" + "type": "string", + "description": "Name of the Monitors edge cluster that evaluates rules and runs queries for this datasource. It must be an existing edge cluster of the account, otherwise the call fails with `InvalidParameter`. Changing it on update closes open alerts of rules that use this datasource." }, "enabled": { + "type": "boolean", "description": "Whether business execution is enabled. Omitted on create: true; omitted on update: preserve the current value. Explicit false disables execution; null is invalid. Does not change alerting_enabled.", + "x-flashduty-preserve-absence": true + }, + "alerting_enabled": { + "description": "Whether this datasource may evaluate alerts. Omitted on create: true for alerting types, false for diagnostic-only types; omitted on update: preserve current value. null is invalid. redis_node, redis_sentinel, mongodb_mongod, mongodb_mongos and kafka reject true. Disabling is rejected with conflict when enabled rules reference the datasource.", "type": "boolean", "x-flashduty-preserve-absence": true }, - "id": { - "description": "Datasource ID. Required for update; omit for create.", + "manage_team_id": { + "type": [ + "integer", + "null" + ], "format": "uint64", - "type": "integer" - }, - "name": { - "description": "Datasource display name. This is the name referenced as `ds_name` in query APIs.", - "type": "string" - }, - "note": { - "description": "Optional description.", - "type": "string" - }, - "payload": { - "$ref": "#/components/schemas/DSPayload", - "description": "Type-specific configuration block. Must include the key matching `type_ident`. For diagnostic types, password and Kafka tls_key are omitted from responses unless they are ${env:...} references. On update, omit those fields to preserve stored secrets; explicitly send an empty string to clear. Other configuration fields retain their existing behavior." + "description": "ID of the managing team (see the response field of the same name). On create, omitted means no managing team. On update, omitted keeps the current value, while `null` or `0` clears it. Required whenever `readonly_team_ids` is non-empty.", + "x-flashduty-preserve-absence": true }, - "type_ident": { - "description": "Datasource type identifier. Allowed: `prometheus`, `loki`, `mysql`, `oracle`, `postgres`, `clickhouse`, `elasticsearch`, `sls`, `tencent_cls`, `victorialogs`, `redis_node`, `redis_sentinel`, `mongodb_mongod`, `mongodb_mongos`, `kafka`。", - "type": "string" + "readonly_team_ids": { + "type": [ + "array", + "null" + ], + "items": { + "type": "integer", + "format": "uint64" + }, + "description": "IDs of the teams allowed to query and reference the datasource (see the response field of the same name). On create, omitted means unrestricted. On update, omitted keeps the current value, while `null` or an empty array clears it (everyone can query). Duplicates and `0` are dropped. Requires `manage_team_id`: a non-empty list without a managing team fails with `InvalidParameter`.", + "x-flashduty-preserve-absence": true } - }, - "required": [ - "type_ident", - "name", - "edge_cluster_name", - "payload" - ], - "type": "object" + } }, "DatasourceQueryExecution": { "type": "object", @@ -8043,7 +8038,7 @@ "type": "integer" }, "datasource_id": { - "description": "Datasource ID from /monit/datasource/list.", + "description": "ID of the datasource to run the tool against, from `/monit/datasource/list`. The caller needs query access to it. For query tools (`.query`) the ID must not exceed 9007199254740991.", "format": "uint64", "minimum": 1, "type": "integer" @@ -8106,7 +8101,7 @@ "DatasourceToolTruncation": { "properties": { "reason": { - "description": "Why the result was truncated. Presence of this object indicates truncation.", + "description": "Why the result was truncated, as reported by the executing Edge; treat it as an opaque string. The object is present only when the result was truncated.", "type": "string" } }, @@ -8156,17 +8151,17 @@ "type": "object" }, "DeletePostMortemTemplateRequest": { + "type": "object", "description": "Parameters for deleting a post-mortem template.", - "properties": { - "template_id": { - "description": "Template ID; obtain it from `POST /incident/post-mortem/template/list`.", - "type": "string" - } - }, "required": [ "template_id" ], - "type": "object" + "properties": { + "template_id": { + "type": "string", + "description": "ID of the custom template to delete; obtain it from `POST /incident/post-mortem/template/list`." + } + } }, "DeleteStatusPageChangeRequest": { "description": "Parameters for deleting a status page event.", @@ -8302,44 +8297,52 @@ "type": "object" }, "DeleteWarRoomRequest": { + "type": "object", "description": "Parameters for deleting an incident war room.", + "required": [ + "incident_id", + "integration_id" + ], "properties": { "incident_id": { - "description": "Incident ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Incident ID (MongoDB ObjectID)." }, "integration_id": { - "description": "IM integration ID; obtain it from `POST /datasource/im/war-room-enabled/list`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "IM integration ID; obtain it from `POST /datasource/im/war-room-enabled/list`." + }, + "unlink_only": { + "type": "boolean", + "description": "When true, only remove the link between the incident and the war room without dissolving the group. Allowed only for account owners and admins, only when the IM integration is disabled or deleted, and requires `chat_id`." + }, + "chat_id": { + "type": "string", + "description": "Chat ID of the war room to unlink, from `POST /incident/war-room/list`. Required when `unlink_only` is `true` and must match the current war room; ignored otherwise." } - }, - "required": [ - "incident_id", - "integration_id" - ], - "type": "object" + } }, "DeleteWorkItemRequest": { + "type": "object", "description": "Parameters for soft-deleting a work item.", - "properties": { - "version": { - "description": "Current item version for optimistic locking. Must match the stored version.", - "format": "int64", - "type": "integer" - }, - "work_item_id": { - "description": "Work item ID (opaque string, max 128 characters).", - "maxLength": 128, - "type": "string" - } - }, "required": [ "work_item_id", "version" ], - "type": "object" + "properties": { + "work_item_id": { + "type": "string", + "maxLength": 128, + "description": "Work item ID (opaque string, max 128 characters)." + }, + "version": { + "type": "integer", + "format": "int64", + "description": "The item's current `version` (≥ 1) for optimistic locking." + } + } }, "DimensionInsightItem": { "allOf": [ @@ -8460,16 +8463,16 @@ ] }, "DimensionInsightResponse": { + "type": "object", "properties": { "items": { - "description": "Insight metric rows aggregated by the endpoint's dimension (account/team/channel); further split by hour bucket or time bucket when `split_hours` or `aggregate_unit` is enabled.", + "type": "array", "items": { "$ref": "#/components/schemas/DimensionInsightItem" }, - "type": "array" + "description": "Metric rows, newest bucket first. Buckets or dimension values without incidents produce no row; an empty array means no incidents matched." } - }, - "type": "object" + } }, "DisableIncidentMergeRequest": { "description": "Parameters for disabling automatic merging on incidents.", @@ -8510,25 +8513,29 @@ "type": "object" }, "DoIncidentCustomActionResponse": { - "description": "Result of a custom action dispatch.", + "type": [ + "object", + "null" + ], + "description": "`null` when the action's HTTP request succeeded; an object with `message` when it failed.", "properties": { "message": { - "description": "Error message if the action's HTTP call failed; omitted on success.", - "type": "string" + "type": "string", + "description": "Error returned by the HTTP request to the action's URL (for example, a timeout after 2 seconds)." } - }, - "type": "object" + } }, "DutyError": { + "type": "object", "description": "Error payload inside the response envelope. Present only on non-2xx responses.", "properties": { "code": { "$ref": "#/components/schemas/ErrorCode" }, "message": { - "description": "Human-readable error message, localized by the caller's Accept-Language. May contain field names, IDs, or other context from the failing request.", - "example": "The specified parameter template_id is not valid.", - "type": "string" + "type": "string", + "description": "Human-readable error message in the response language (`locale` / `lang` query parameter or `Accept-Language` header). May name the offending field; do not parse it.", + "example": "The specified parameter template_id is not valid." }, "reason": { "description": "Optional machine-readable rejection reason, including datasource tool failures. Inspect alongside HTTP status and code.", @@ -8539,8 +8546,7 @@ "required": [ "code", "message" - ], - "type": "object" + ] }, "EmptyObject": { "additionalProperties": false, @@ -8553,62 +8559,62 @@ "type": "object" }, "EmptyResponse": { - "description": "Empty response body. The server returns `data: null` on success.", - "properties": {}, - "type": "object" + "type": "object", + "description": "No payload. Depending on the operation, `data` is `{}` or omitted from the envelope; rely only on the HTTP 200 status and the absence of `error`.", + "properties": {} }, "EnabledTime": { + "type": "object", "description": "Time window in which the rule is active.", "properties": { "days": { - "description": "Days of week, 0 = Sunday.", + "type": "array", "items": { "type": "integer" }, - "type": "array" - }, - "etime": { - "description": "End time, e.g. `18:00`.", - "type": "string" + "description": "Days of week the window applies to, `0` = Sunday through `6` = Saturday; non-empty, no duplicates." }, "stime": { - "description": "Start time, e.g. `09:00`.", - "type": "string" + "type": "string", + "description": "Start time in 24-hour `HH:MM` format, e.g. `09:00`." + }, + "etime": { + "type": "string", + "description": "End time in 24-hour `HH:MM` format, e.g. `18:00`." } - }, - "type": "object" + } }, "EnrichFilter": { + "type": "object", + "required": [ + "key", + "oper", + "vals" + ], "description": "A single label filter condition.", "properties": { "key": { - "description": "Event key to match on (e.g. `labels.severity`, `title`). Must be non-empty.", - "minLength": 1, - "type": "string" + "type": "string", + "description": "Event key to match on: `title`, `description`, `labels.` or another alert/change event key. A `labels.` key must use a valid label name.", + "minLength": 1 }, "oper": { - "description": "Match operator. `IN` matches when any value matches; `NOTIN` matches when none of the values match.", + "type": "string", "enum": [ "IN", "NOTIN" ], - "type": "string" + "description": "Match operator.\n- `IN`: matches when the key's value matches any of `vals`. A key missing from the event never matches.\n- `NOTIN`: matches when the value matches none of `vals`. A key missing from the event always matches." }, "vals": { - "description": "Values to match against. Must contain at least one value.", + "type": "array", "items": { "type": "string" }, - "minItems": 1, - "type": "array" + "description": "Values to match (at least one). Each value is one of: an exact string; `/regex/` for a regular expression; a wildcard pattern with `*` and `?`; `cidr:` (e.g. `cidr:203.0.113.0/24`) for an IP range; `num:lt:`, `num:le:`, `num:gt:` or `num:ge:` for a numeric comparison.", + "minItems": 1 } - }, - "required": [ - "key", - "oper", - "vals" - ], - "type": "object" + } }, "EnrichRule": { "description": "An enrichment rule with an optional condition and type-specific settings.", @@ -8681,52 +8687,53 @@ "type": "object" }, "EnrichmentItem": { + "type": "object", "description": "Enrichment rule set for an integration.", "properties": { - "created_at": { - "description": "Creation timestamp, Unix seconds.", - "format": "int64", - "type": "integer" - }, - "creator_id": { - "description": "Creator member ID.", - "format": "int64", - "type": "integer" - }, - "deleted_at": { - "description": "Deletion time, Unix seconds. Omitted when the rule set is not deleted; read endpoints never return soft-deleted rule sets, so this is effectively always omitted.", - "format": "int64", - "type": "integer" - }, "integration_id": { - "description": "Integration ID.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the integration this rule set belongs to; one integration has at most one rule set." }, "rules": { - "description": "Ordered enrichment rules.", + "type": "array", "items": { "$ref": "#/components/schemas/EnrichRule" }, - "type": "array" + "description": "Rules in execution order; each rule sees the labels written by the rules before it." }, "status": { - "description": "Rule set status: `enabled` (active) or `deleted` (soft-deleted). Read endpoints exclude soft-deleted rule sets, so responses always carry `enabled`.", + "type": "string", "enum": [ "enabled", "deleted" ], - "type": "string" + "description": "Rule set status: `enabled` (active) or `deleted` (soft-deleted). Read endpoints exclude soft-deleted rule sets, so responses always carry `enabled`." + }, + "updated_by": { + "type": "integer", + "format": "int64", + "description": "Last updater member ID." + }, + "creator_id": { + "type": "integer", + "format": "int64", + "description": "Creator member ID." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation timestamp, Unix seconds." }, "updated_at": { - "description": "Last update timestamp, Unix seconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update timestamp, Unix seconds." }, - "updated_by": { - "description": "Last updater member ID.", + "deleted_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Deletion time, Unix seconds. Omitted when the rule set is not deleted; read endpoints never return soft-deleted rule sets, so this is effectively always omitted." } }, "required": [ @@ -8737,8 +8744,7 @@ "creator_id", "created_at", "updated_at" - ], - "type": "object" + ] }, "EnrichmentListRequest": { "properties": { @@ -8773,67 +8779,74 @@ "type": "object" }, "EnrichmentUpsertRequest": { + "type": "object", + "required": [ + "integration_id", + "rules" + ], "properties": { "integration_id": { - "description": "Integration ID to configure enrichment rules for.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Integration ID to configure enrichment rules for." }, "rules": { - "description": "Ordered list of enrichment rules. Replaces all existing rules.", + "type": "array", "items": { "$ref": "#/components/schemas/EnrichRule" }, - "type": "array" + "description": "Ordered rule list that replaces the integration's whole rule set; send `[]` to remove all rules. Rules run in this order." } - }, - "required": [ - "integration_id", - "rules" - ], - "type": "object" + } }, "EnvironmentBinding": { - "description": "The runner or cloud sandbox the session is bound to. Null until the first message.", + "type": "object", + "description": "The runner or cloud sandbox the session is bound to. Returned by `POST /safari/session/get` only; omitted until the session has been bound (after its first message).", "properties": { - "id": { - "description": "Environment identifier: a cloud sandbox ID for `cloud` bindings, a runner/environment ID for `byoc` bindings.", - "type": "string" - }, "kind": { + "type": "string", "description": "Environment kind bound to the session: `cloud` (managed sandbox) or `byoc` (self-hosted runner).", "enum": [ "cloud", "byoc" - ], - "type": "string" + ] + }, + "id": { + "type": "string", + "description": "Environment identifier: a cloud sandbox ID for `cloud` bindings, a runner/environment ID for `byoc` bindings." }, "name": { - "description": "Human-readable environment name; empty for cloud bindings using the default allowlist.", - "type": "string" + "type": "string", + "description": "Human-readable environment name; empty for cloud bindings using the default allowlist." + }, + "team_id": { + "type": "integer", + "format": "int64", + "description": "Team that owns the bound environment; 0 for account-scope environments." }, "status": { - "description": "Live binding health, namespaced by kind: BYOC uses online/pending/offline/deleted; cloud uses available/rebuilding/expired.", + "type": "string", + "description": "Live health of the binding. Omitted when unknown.\n\nFor `byoc`:\n- `online`: runner connected and ready\n- `degraded`: runner connected but its executor is unhealthy; messages are still accepted\n- `pending`: runner has never connected\n- `offline`: runner heartbeat lost; messages cannot be served\n- `deleted`: the environment no longer exists; choose another\n\nFor `cloud`:\n- `available`: the sandbox can serve the next message (paused or starting sandboxes resume automatically)\n- `rebuilding`: the sandbox is being resumed or recreated\n- `expired`: the sandbox failed permanently and cannot recover by itself\n- `deleted`: the selected cloud environment template was deleted", "enum": [ "online", + "degraded", "pending", "offline", "deleted", "available", "rebuilding", "expired" - ], - "type": "string" + ] } }, "required": [ "kind", "id" - ], - "type": "object" + ] }, "ErrorCode": { - "description": "Flashduty error code enum. Every failed API response sets `error.code` to one of these stable wire strings. HTTP status is informational — the authoritative signal is the enum value.\n\n| Code | HTTP | Meaning |\n|---|---|---|\n| `OK` | 200 | Reserved — not returned on real errors. |\n| `InvalidParameter` | 400 | A required parameter is missing or failed validation. |\n| `BadRequest` | 400 | Generic 400 used when no more specific code fits. |\n| `InvalidContentType` | 400 | The `Content-Type` header is not `application/json`. |\n| `ResourceNotFound` | 400 | The referenced resource does not exist. Note: returned as HTTP 400, not 404 (historical choice). |\n| `NoLicense` | 400 | The feature is license-gated and no active license was found. |\n| `ReferenceExist` | 400 | Deletion blocked — other entities still reference this resource. |\n| `Unauthorized` | 401 | `app_key` is missing, invalid, or expired. |\n| `BalanceNotEnough` | 402 | Billing-gated operation with insufficient account balance. |\n| `AccessDenied` | 403 | Authenticated but lacking the permission required for this operation. |\n| `RouteNotFound` | 404 | The request URL path is not a known route. |\n| `MethodNotAllowed` | 405 | The HTTP method is not allowed on this otherwise-known path. |\n| `UndonedOrderExist` | 409 | An outstanding billing order blocks this new one. Wait and retry. |\n| `RequestLocked` | 423 | Operation temporarily locked due to repeated failures. |\n| `EntityTooLarge` | 413 | Request body exceeds the configured max size. |\n| `RequestTooFrequently` | 429 | Rate limit hit — API-global, per-account, or per-integration. |\n| `RequestVerifyRequired` | 428 | Second-factor verification required but not supplied. |\n| `DangerousOperation` | 428 | High-risk operation requires MFA verification. |\n| `InternalError` | 500 | Unhandled server-side error. Include `request_id` in the bug report. |\n| `ServiceUnavailable` | 503 | A backend dependency is unavailable. Try again later. |", + "type": "string", + "description": "Error code. Every failed response sets `error.code` to one of these stable strings; branch on it rather than on the HTTP status.\n\n| Code | HTTP | Meaning |\n|---|---|---|\n| `OK` | 200 | Reserved; never returned on a failed request. |\n| `InvalidParameter` | 400 | A parameter is missing, has the wrong type, or failed validation; `message` usually names the field. |\n| `BadRequest` | 400 | The request breaks a business rule or conflicts with the current state of an object; `message` says which. |\n| `InvalidContentType` | 400 | The body is not sent as `application/json`. |\n| `ResourceNotFound` | 400 | The referenced object does not exist in this account or was deleted. Returned as HTTP 400, not 404. |\n| `NoLicense` | 400 | The account's plan does not include the feature, a plan quota is used up, the plan has expired, or credits are insufficient. |\n| `ReferenceExist` | 400 | The object is still referenced by other objects, so it cannot be deleted. |\n| `Unauthorized` | 401 | The APP Key is missing, invalid, or deleted. |\n| `BalanceNotEnough` | 402 | Console-only (billing); not returned by Open API operations. |\n| `AccessDenied` | 403 | The APP Key's permission scope or the creator's role does not allow this operation or object. |\n| `RouteNotFound` | 404 | No operation matches the HTTP method and path. |\n| `MethodNotAllowed` | 405 | The path exists but not for this HTTP method. |\n| `UndonedOrderExist` | 409 | Console-only (billing); not returned by Open API operations. |\n| `EntityTooLarge` | 413 | The request body exceeds the size limit. |\n| `RequestLocked` | 423 | Console-only (sign-in protection); not returned by Open API operations. |\n| `RequestVerifyRequired` | 428 | Console-only (verification code); not returned by Open API operations. |\n| `DangerousOperation` | 428 | Console-only (MFA for high-risk actions); not returned by Open API operations. |\n| `RequestTooFrequently` | 429 | A rate limit was hit; wait for the `Flashcat-Request-Rate-Limit-Delay` response header (seconds) before retrying. |\n| `InternalError` | 500 | Unexpected server error; retry with backoff and include `request_id` when reporting. |\n| `ServiceUnavailable` | 503 | A backend dependency is overloaded or unavailable; retry with backoff. |", "enum": [ "OK", "InvalidParameter", @@ -8848,38 +8861,37 @@ "RouteNotFound", "MethodNotAllowed", "UndonedOrderExist", - "RequestLocked", "EntityTooLarge", - "RequestTooFrequently", + "RequestLocked", "RequestVerifyRequired", "DangerousOperation", + "RequestTooFrequently", "InternalError", "ServiceUnavailable" ], - "example": "InvalidParameter", - "type": "string", "x-enumDescriptions": { - "AccessDenied": "Authenticated but lacking the permission required for this operation.", - "BadRequest": "Generic 400 used when no more specific code fits.", - "BalanceNotEnough": "Billing-gated operation with insufficient account balance.", - "DangerousOperation": "High-risk operation requires MFA verification.", - "EntityTooLarge": "Request body exceeds the configured max size.", - "InternalError": "Unhandled server-side error. Include `request_id` in the bug report.", - "InvalidContentType": "The `Content-Type` header is not `application/json`.", - "InvalidParameter": "A required parameter is missing or failed validation.", - "MethodNotAllowed": "The HTTP method is not allowed on this otherwise-known path.", - "NoLicense": "The feature is license-gated and no active license was found.", - "OK": "Reserved — not returned on real errors.", - "ReferenceExist": "Deletion blocked — other entities still reference this resource.", - "RequestLocked": "Operation temporarily locked due to repeated failures.", - "RequestTooFrequently": "Rate limit hit — API-global, per-account, or per-integration.", - "RequestVerifyRequired": "Second-factor verification required but not supplied.", - "ResourceNotFound": "The referenced resource does not exist. Note: returned as HTTP 400, not 404 (historical choice).", - "RouteNotFound": "The request URL path is not a known route.", - "ServiceUnavailable": "A backend dependency is unavailable. Try again later.", - "Unauthorized": "`app_key` is missing, invalid, or expired.", - "UndonedOrderExist": "An outstanding billing order blocks this new one. Wait and retry." - } + "OK": "Reserved; never returned on a failed request.", + "InvalidParameter": "A parameter is missing, has the wrong type, or failed validation; `message` usually names the field.", + "BadRequest": "The request breaks a business rule or conflicts with the current state of an object; `message` says which.", + "InvalidContentType": "The body is not sent as `application/json`.", + "ResourceNotFound": "The referenced object does not exist in this account or was deleted. Returned as HTTP 400, not 404.", + "NoLicense": "The account's plan does not include the feature, a plan quota is used up, the plan has expired, or credits are insufficient.", + "ReferenceExist": "The object is still referenced by other objects, so it cannot be deleted.", + "Unauthorized": "The APP Key is missing, invalid, or deleted.", + "BalanceNotEnough": "Console-only (billing); not returned by Open API operations.", + "AccessDenied": "The APP Key's permission scope or the creator's role does not allow this operation or object.", + "RouteNotFound": "No operation matches the HTTP method and path.", + "MethodNotAllowed": "The path exists but not for this HTTP method.", + "UndonedOrderExist": "Console-only (billing); not returned by Open API operations.", + "EntityTooLarge": "The request body exceeds the size limit.", + "RequestLocked": "Console-only (sign-in protection); not returned by Open API operations.", + "RequestVerifyRequired": "Console-only (verification code); not returned by Open API operations.", + "DangerousOperation": "Console-only (MFA for high-risk actions); not returned by Open API operations.", + "RequestTooFrequently": "A rate limit was hit; wait for the `Flashcat-Request-Rate-Limit-Delay` response header (seconds) before retrying.", + "InternalError": "Unexpected server error; retry with backoff and include `request_id` when reporting.", + "ServiceUnavailable": "A backend dependency is overloaded or unavailable; retry with backoff." + }, + "example": "InvalidParameter" }, "ErrorResponse": { "description": "Response envelope for errors. `error` is required; `data` is absent.", @@ -8900,433 +8912,470 @@ "type": "object" }, "ErsComposition": { + "type": "object", + "title": "composition", + "required": [ + "result_label", + "template" + ], "properties": { - "override": { - "description": "When `true`, overwrite the label if it already exists. Defaults to `false`.", - "type": "boolean" - }, "result_label": { + "type": "string", "description": "Destination label key the composed value is written to. Must match `^[a-zA-Z_][a-zA-Z0-9_]*$`.", - "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", - "type": "string" + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, "template": { - "description": "Go `text/template` string (1–500 characters) rendered against the event struct — e.g. `{{.Title}}`, `{{.Description}}`, `{{.Labels.key}}`. Example: `{{.Labels.region}}-{{.Labels.env}}`.", + "type": "string", "maxLength": 500, - "minLength": 1, - "type": "string" + "description": "Go `text/template` string (1–500 characters) rendered against the event struct — e.g. `{{.Title}}`, `{{.Description}}`, `{{.Labels.key}}`. Example: `{{.Labels.region}}-{{.Labels.env}}`.", + "minLength": 1 + }, + "override": { + "type": "boolean", + "description": "When `false` (default) the rule is skipped if `result_label` already exists on the event; when `true` the existing value is overwritten." } - }, - "required": [ - "result_label", - "template" - ], - "title": "composition", - "type": "object" + } }, "ErsDrop": { + "type": "object", + "title": "drop", + "required": [ + "drop_labels" + ], "properties": { "drop_labels": { - "description": "List of label keys to remove from the alert.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Label names to remove from the event (at least one), given without the `labels.` prefix.", + "minItems": 1 } - }, - "required": [ - "drop_labels" - ], - "title": "drop", - "type": "object" + } }, "ErsExtraction": { + "type": "object", + "title": "extraction", + "required": [ + "source_field", + "result_label" + ], "properties": { - "g_json": { - "description": "GJson path expression used to extract a value from a JSON-encoded field. Mutually exclusive with `pattern`.", - "type": "string" + "source_field": { + "type": "string", + "description": "Source field to extract from. Must be `title`, `description`, or a label key prefixed with `labels.` (e.g. `labels.env`)." }, - "override": { - "description": "When `true`, overwrite the label if it already exists. Defaults to `false`.", - "type": "boolean" + "result_label": { + "type": "string", + "description": "Destination label key the extracted value is written to. Must match `^[a-zA-Z_][a-zA-Z0-9_]*$`.", + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, "pattern": { - "description": "RE2 regular expression applied to the source value. Must contain at least one capture group; the captured groups are joined with a space and written to `result_label`. Mutually exclusive with `g_json`.", - "type": "string" + "type": "string", + "description": "Regular expression (RE2) applied to the source value; may be wrapped in `/.../`. All capture groups are joined with a space and written to `result_label`. Nothing is written when the expression does not match, has no capture group, or the first group is empty. Exactly one of `pattern` and `g_json` must be set." }, - "result_label": { - "description": "Destination label key the extracted value is written to. Must match `^[a-zA-Z_][a-zA-Z0-9_]*$`.", - "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", - "type": "string" + "g_json": { + "type": "string", + "description": "GJSON path (a leading `$.` is ignored) used when the source value is a JSON string, e.g. `host.name`. If the source value is not valid JSON the rule is skipped; if the path does not exist an empty string is written. Exactly one of `pattern` and `g_json` must be set." }, - "source_field": { - "description": "Source field to extract from. Must be `title`, `description`, or a label key prefixed with `labels.` (e.g. `labels.env`).", - "type": "string" + "override": { + "type": "boolean", + "description": "When `false` (default) the rule is skipped if `result_label` already exists on the event; when `true` the existing value is overwritten." } - }, - "required": [ - "source_field", - "result_label" - ], - "title": "extraction", - "type": "object" + } }, "ErsMapping": { + "type": "object", + "title": "mapping", + "required": [ + "result_labels" + ], "properties": { - "api_id": { - "description": "Mapping API ID (MongoDB ObjectID hex). Required when `mapping_type` is `api`.", - "type": "string" + "result_labels": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" + }, + "description": "Label keys to fill from the lookup result (at least one). For `schema` they are normally the schema's `result_labels`; for `api` they are sent to the API as `result_label_keys`.", + "minItems": 1 }, "mapping_type": { - "default": "schema", - "description": "Mapping source type. `schema` uses a mapping schema table; `api` calls an external HTTP API.", + "type": "string", "enum": [ "schema", "api" ], - "type": "string" + "default": "schema", + "description": "Lookup source.\n- `schema` (default): look up a row in the mapping schema `schema_id` using the event's values of the schema's `source_labels`; the rule does nothing if any source label is missing or no row matches.\n- `api`: call the mapping API `api_id` with the event; runs for alert events only." }, - "override": { - "description": "When `true`, overwrite labels that already exist. Defaults to `false`.", - "type": "boolean" + "schema_id": { + "type": "string", + "description": "Mapping schema ID (MongoDB ObjectID hex). Required when `mapping_type` is `schema`." }, - "result_labels": { - "description": "Label keys to populate from the mapping lookup result. Each must match `^[a-zA-Z_][a-zA-Z0-9_]*$`.", - "items": { - "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", - "type": "string" - }, - "type": "array" + "api_id": { + "type": "string", + "description": "Mapping API ID (MongoDB ObjectID hex). Required when `mapping_type` is `api`." }, - "schema_id": { - "description": "Mapping schema ID (MongoDB ObjectID hex). Required when `mapping_type` is `schema`.", - "type": "string" + "override": { + "type": "boolean", + "description": "When `false` (default) the rule is skipped if every label in `result_labels` already exists, and otherwise only the missing labels are filled. When `true` all `result_labels` are overwritten with the lookup result." } - }, - "required": [ - "result_labels" - ], - "title": "mapping", - "type": "object" + } }, "EscalateLayer": { + "type": "object", + "required": [ + "target" + ], "properties": { - "escalate_window": { - "description": "Wait before moving to the next level, in minutes.", - "maximum": 720, - "minimum": 0, - "type": "integer" - }, - "force_escalate": { - "description": "When true, always escalate regardless of acknowledgement.", - "type": "boolean" - }, "max_times": { - "description": "Max repeat notifications within the level.", - "maximum": 6, + "type": "integer", "minimum": 0, - "type": "integer" + "maximum": 6, + "description": "Total notifications sent in this level, including the first, 0–6; `0` and `1` both notify once." }, "notify_step": { - "description": "Repeat interval in minutes.", + "type": "number", "format": "float", - "maximum": 120, "minimum": 0.5, - "type": "number" + "maximum": 120, + "description": "Minutes between repeat notifications in this level, 0.5–120, kept to one decimal place. Used only when `max_times` is greater than 1." }, "target": { "$ref": "#/components/schemas/EscalateTarget" + }, + "escalate_window": { + "type": "integer", + "minimum": 0, + "maximum": 720, + "description": "Minutes to wait after this level's first notification before escalating to the next level, 0–720. Ignored on the last level." + }, + "force_escalate": { + "type": "boolean", + "description": "When true, escalate even after the incident has been acknowledged (`Processing`). When false, escalation stops once the incident is acknowledged. Closed or snoozed incidents never escalate." } - }, - "required": [ - "target" - ], - "type": "object" + } }, "EscalateRuleItem": { + "type": "object", + "required": [ + "account_id", + "channel_id", + "priority", + "aggr_window", + "rule_name", + "description", + "layers", + "time_filters", + "filters", + "status", + "template_id", + "rule_id", + "updated_by", + "created_at", + "updated_at" + ], "properties": { "account_id": { - "description": "Owning account ID.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "aggr_window": { - "description": "Delay window in seconds.", - "type": "integer" + "description": "Owning account ID." }, "channel_id": { - "description": "Channel the rule belongs to.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Channel the rule belongs to." }, - "channel_name": { - "description": "Channel name, populated for cross-channel listing responses.", - "type": "string" + "priority": { + "type": "integer", + "description": "Evaluation order from `0` to `200`: lower values are evaluated first, ties broken by creation time. The first enabled rule whose time windows and filters match a new incident takes it." }, - "created_at": { - "description": "Creation time, Unix timestamp in seconds.", - "format": "int64", - "type": "integer" + "aggr_window": { + "type": "integer", + "description": "Delay in seconds, 0–3600, before the first notification for a newly assigned incident is sent; `0` notifies immediately." }, - "deleted_at": { - "description": "Deletion time, Unix timestamp in seconds. Omitted unless the rule is soft-deleted; deleted rules are excluded from list responses.", - "format": "int64", - "type": "integer" + "rule_name": { + "type": "string", + "description": "Rule name, 1–39 characters." }, "description": { - "description": "Rule description.", - "type": "string" - }, - "filters": { - "$ref": "#/components/schemas/FilterGroup", - "description": "Incident-level match conditions (OR-of-AND tree): the rule is matched against the incident the alert was grouped into, not against the alert itself. Omit or leave empty to apply the rule to all incidents in the channel." + "type": "string", + "description": "Rule description." }, "layers": { - "description": "Escalation levels in order.", + "type": "array", "items": { "$ref": "#/components/schemas/EscalateLayer" }, - "type": "array" - }, - "priority": { - "description": "Evaluation priority. Lower runs first.", - "type": "integer" + "description": "Escalation levels in order." }, - "rule_id": { - "description": "Escalation rule ID (MongoDB ObjectID).", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "time_filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TimeFilter" + }, + "description": "Recurring time windows during which the rule can match; empty means at any time." }, - "rule_name": { - "description": "Rule name.", - "type": "string" + "filters": { + "$ref": "#/components/schemas/FilterGroup", + "description": "Incident conditions (OR of AND groups), matched against the incident the alert was grouped into. Empty means the rule matches every incident in the channel." }, "status": { - "description": "Rule status: `enabled` means active, `disabled` means paused, `deleted` is soft-deleted (possible only from the detail endpoint; lists never return deleted rules).", + "type": "string", "enum": [ "enabled", "disabled", "deleted" ], - "type": "string" + "description": "Rule status: `enabled` means active, `disabled` means paused, `deleted` is soft-deleted (possible only from the detail endpoint; lists never return deleted rules)." }, "template_id": { - "description": "Notification template ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Notification template ID (24-character hex); see `POST /template/list`." }, - "time_filters": { - "description": "Recurring time windows during which the rule applies.", - "items": { - "$ref": "#/components/schemas/TimeFilter" - }, - "type": "array" + "rule_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Escalation rule ID (MongoDB ObjectID)." }, - "updated_at": { - "description": "Last update time, Unix timestamp in seconds.", + "updated_by": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Member ID that last updated the rule." }, - "updated_by": { - "description": "Member ID that last updated the rule.", + "deleted_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Deletion time, Unix timestamp in seconds. Omitted unless the rule is soft-deleted; deleted rules are excluded from list responses." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation time, Unix timestamp in seconds." + }, + "updated_at": { + "type": "integer", + "format": "int64", + "description": "Last update time, Unix timestamp in seconds." } - }, - "required": [ - "account_id", - "channel_id", - "priority", - "aggr_window", - "rule_name", - "description", - "layers", - "time_filters", - "filters", - "status", - "template_id", - "rule_id", - "updated_by", - "created_at", - "updated_at" - ], - "type": "object" + } }, "EscalateTarget": { + "type": "object", "description": "Notification target. At least one of `person_ids`, `team_ids`, `schedule_to_role_ids`, or `emails` must be set, together with either `by` or `webhooks`.", "properties": { + "person_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Member IDs to notify directly; obtain them from `POST /member/list`. Every ID must exist." + }, + "team_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Team IDs whose members are notified; obtain them from `POST /team/list`. Each team must have at least one member." + }, + "schedule_to_role_ids": { + "type": "object", + "additionalProperties": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + } + }, + "description": "Notify whoever is on call: keys are schedule IDs (from `POST /schedule/list`) written as strings, values are the role IDs on that schedule. Each value must be non-empty." + }, + "emails": { + "type": "array", + "items": { + "type": "string", + "format": "email" + }, + "description": "Email addresses of account members; each address is resolved to the member who owns it when the level fires." + }, "by": { - "description": "Per-severity personal notification channels. Required unless `webhooks` is provided.", + "type": [ + "object", + "null" + ], + "description": "Personal notification channels for the people in this target, per incident severity. Required unless `webhooks` is set; returned as `null` when not set.", "properties": { + "follow_preference": { + "type": "boolean", + "description": "When true, each person is notified through the channels in their own notification preferences for the incident's severity, and `critical`, `warning` and `info` are ignored." + }, "critical": { - "description": "Notify channels used for Critical severity. Personal channels: `sms`, `voice`, `email`, `push`; IM group-chat channels: `feishu_app:`, `dingtalk_app:`, `wecom_app:`, `slack_app:`, `teams_app:`.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Channels used when the incident severity is `Critical`: `sms`, `voice`, `email`, `push`, or a direct message through an IM app integration written as `:`, where `` is `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app` or `teams_app` and `` is the ID of that IM integration. Other values return `InvalidParameter`." }, - "follow_preference": { - "description": "When true, use each responder's personal preference instead of the lists below.", - "type": "boolean" + "warning": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Channels used when the incident severity is `Warning`; same values as `critical`." }, "info": { - "description": "Notify channels used for Info severity. Values as for `critical`.", + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "warning": { - "description": "Notify channels used for Warning severity. Values as for `critical`.", - "items": { - "type": "string" - }, - "type": "array" + "description": "Channels used when the incident severity is `Info`; same values as `critical`." } - }, - "type": "object" - }, - "emails": { - "description": "Email addresses to notify (push-only scenarios).", - "items": { - "format": "email", - "type": "string" - }, - "type": "array" - }, - "person_ids": { - "description": "Member IDs to notify directly.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "schedule_to_role_ids": { - "additionalProperties": { - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "description": "Map of schedule ID to the role IDs on that schedule to notify.", - "type": "object" - }, - "team_ids": { - "description": "Team IDs to notify.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + } }, "webhooks": { - "description": "Group chat / webhook targets. Required unless `by` is provided.", + "type": [ + "array", + "null" + ], + "description": "Group chats to notify through robots or IM apps. Required unless `by` is set; returned as `null` when not set.", "items": { - "properties": { - "settings": { - "additionalProperties": true, - "description": "Type-specific settings (chat IDs, URLs, etc.).", - "type": "object" - }, - "type": { - "description": "Webhook type, one of `feishu`, `feishu_app`, `dingtalk`, `dingtalk_app`, `wecom`, `slack`, `slack_app`, `teams_app`, `telegram`, `zoom`.", - "type": "string" - } - }, + "type": "object", "required": [ "type", "settings" ], - "type": "object" - }, - "type": "array" + "properties": { + "type": { + "type": "string", + "description": "Delivery type:\n- `feishu`, `dingtalk`, `wecom`, `slack`, `telegram`, `zoom`: a group robot (incoming webhook) of that IM.\n- `feishu_app`, `dingtalk_app`, `slack_app`, `teams_app`: group chats reached through the corresponding IM app integration.", + "enum": [ + "feishu", + "dingtalk", + "wecom", + "slack", + "telegram", + "zoom", + "feishu_app", + "dingtalk_app", + "slack_app", + "teams_app" + ] + }, + "settings": { + "type": "object", + "additionalProperties": true, + "description": "Type-specific settings, such as the robot's webhook token or the app's chat IDs; `feishu_app` and `dingtalk_app` require it. To see the exact shape for a type, configure one in the console and read it back with `POST /channel/escalate/rule/info`." + } + } + } } - }, - "type": "object" + } }, "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": { - "description": "When true, repeated events merge into the existing alert; when false, every event creates a separate alert. Defaults to true.", - "type": "boolean" + "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": { - "description": "Merge window in minutes, 1-1440 (24 h); accounts with the extended limit may use up to 10080 (7 days). Defaults to 1440.", + "type": "integer", "minimum": 1, - "type": "integer" + "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." } - }, - "type": "object" + } }, "EventItem": { + "type": "object", "description": "One persisted session event. content/actions/usage_metadata carry the raw ADK envelope; treat them as opaque structured payloads.", "properties": { - "actions": { - "additionalProperties": true, - "description": "ADK actions envelope (state deltas, transfers, escalation).", - "type": "object" + "event_id": { + "type": "string", + "description": "Event identifier." + }, + "session_id": { + "type": "string", + "description": "Owning session id." + }, + "invocation_id": { + "type": "string", + "description": "ID of the invocation (one agent turn) that wrote this event. Omitted when empty." + }, + "root_invocation_id": { + "type": "string", + "description": "Invocation ID of the top-level user turn this event belongs to, linking events written by nested subagent invocations back to it. Omitted when empty." + }, + "delivery_mode": { + "type": "string", + "enum": [ + "reply_only" + ], + "description": "Delivery mode negotiated for the IM request that produced this event. `reply_only`: the IM client shows only explicit replies, not the agent's final text. Omitted for normal delivery." + }, + "is_error": { + "type": "boolean", + "description": "True when this is an assistant event recording a runtime failure whose message is safe to show to users. Omitted when false." }, "author": { - "description": "Event author (e.g. user, the agent name).", - "type": "string" + "type": "string", + "description": "Event author (e.g. user, the agent name)." + }, + "person_id": { + "type": "integer", + "format": "int64", + "description": "Member ID of the person who sent this user message. Omitted on assistant and tool events and when no member is recorded (automation runs, some IM turns)." }, "branch": { - "description": "ADK branch path for nested agents.", - "type": "string" + "type": "string", + "description": "ADK branch path for nested agents." }, "content": { + "type": "object", "additionalProperties": true, - "description": "ADK content envelope {role, parts:[...]}.", - "type": "object" + "description": "ADK content envelope {role, parts:[...]}." }, - "created_at": { - "description": "Unix timestamp in milliseconds when the event was written.", - "format": "int64", - "type": "integer" - }, - "error_code": { - "description": "Error code when the event represents a failure.", - "type": "string" + "actions": { + "type": "object", + "additionalProperties": true, + "description": "ADK actions envelope (state deltas, transfers, escalation)." }, - "error_message": { - "description": "Human-readable error message, when present.", - "type": "string" + "usage_metadata": { + "type": "object", + "additionalProperties": true, + "description": "Per-turn token usage metadata." }, - "event_id": { - "description": "Event identifier.", - "type": "string" + "partial": { + "type": "boolean", + "description": "True for a streaming partial chunk." }, - "invocation_id": { - "description": "ADK invocation id grouping a turn.", - "type": "string" + "turn_complete": { + "type": "boolean", + "description": "True on the terminal event of a turn." }, - "partial": { - "description": "True for a streaming partial chunk.", - "type": "boolean" + "error_code": { + "type": "string", + "description": "Error code when the event represents a failure." }, - "session_id": { - "description": "Owning session id.", - "type": "string" + "error_message": { + "type": "string", + "description": "Human-readable error message, when present." }, "status": { + "type": "string", "description": "Event status. One of: `normal` (a live event included in the context fed to the model), `compressed` (folded into a compaction summary boundary event; no longer loaded for the model, kept as history only).", "enum": [ "normal", "compressed" - ], - "type": "string" - }, - "turn_complete": { - "description": "True on the terminal event of a turn.", - "type": "boolean" + ] }, - "usage_metadata": { - "additionalProperties": true, - "description": "Per-turn token usage metadata.", - "type": "object" + "created_at": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in milliseconds when the event was written." } }, "required": [ @@ -9335,8 +9384,7 @@ "partial", "turn_complete", "created_at" - ], - "type": "object" + ] }, "ExploreData": { "description": "Explore query result payload.", @@ -9362,67 +9410,78 @@ "type": "object" }, "ExploreField": { + "type": "object", "description": "One column of a frame. Values are columnar and may contain nulls.", + "required": [ + "name", + "type", + "values" + ], "properties": { - "labels": { - "additionalProperties": { - "type": "string" - }, - "description": "Label set of this column. Only `time_series` value fields may carry labels; a `table` field must not.", - "type": "object" - }, "name": { - "description": "Column name, at most 1 MiB of UTF-8.", - "type": "string" + "type": "string", + "description": "Column name, at most 1 MiB of UTF-8." }, "type": { - "description": "Column type. `string` is rejected inside a `time_series` frame; `float` holds numbers and `time` holds UTC RFC3339Nano strings.", + "type": "string", "enum": [ "string", "float", "time" ], - "type": "string" + "description": "Column type. `string` is rejected inside a `time_series` frame; `float` holds numbers and `time` holds UTC RFC3339Nano strings." + }, + "labels": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Label set of this column. Only `time_series` value fields may carry labels; a `table` field must not." }, "values": { - "description": "Column values in row order.", + "type": "array", "items": { + "oneOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "null" + } + ], "description": "One cell. `time` cells are UTC RFC3339Nano strings; `float` cells may be the strings `NaN`, `+Inf`, and `-Inf`; any cell may be null except a time value inside a `time_series` frame." }, - "type": "array" + "description": "Column values in row order." } - }, - "required": [ - "name", - "type", - "values" - ], - "type": "object" + } }, "ExploreFrame": { + "type": "object", "description": "One columnar frame. Every field in the frame has the same number of values.", + "required": [ + "kind", + "fields" + ], "properties": { - "fields": { - "description": "Columns of the frame.", - "items": { - "$ref": "#/components/schemas/ExploreField" - }, - "type": "array" - }, "kind": { - "description": "Frame shape. `table` is an unlabeled table, while `time_series` carries exactly one time field and one float field.", + "type": "string", "enum": [ "table", "time_series" ], - "type": "string" + "description": "Frame shape. `table` is an unlabeled table. `time_series` carries exactly one time field and one float field; its time values are strictly increasing and never null." + }, + "fields": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ExploreField" + }, + "description": "Columns of the frame." } - }, - "required": [ - "kind", - "fields" - ], - "type": "object" + } }, "ExploreLogEntry": { "description": "One log entry.", @@ -9466,71 +9525,79 @@ "type": "object" }, "ExploreResult": { + "type": "object", "description": "Result body. Exactly one of `frames`, `samples`, or `entries` is present and matches `kind`.", + "required": [ + "kind" + ], "properties": { - "applied_limit": { - "description": "Entry limit applied to a logs result; at most 1000.", - "type": "integer" - }, - "entries": { - "description": "Log entries. Present when `kind` is `logs`; never longer than `applied_limit`.", - "items": { - "$ref": "#/components/schemas/ExploreLogEntry" - }, - "type": "array" - }, - "frames": { - "description": "Columnar frames. Present when `kind` is `frames`; at most 1,000 frames.", - "items": { - "$ref": "#/components/schemas/ExploreFrame" - }, - "type": "array" - }, - "has_more": { - "description": "Whether a logs result was truncated by `applied_limit`.", - "type": "boolean" - }, "kind": { - "description": "Result shape. `frames` returns columnar tables or time series, `samples` returns instant values with labels, and `logs` returns log entries.", + "type": "string", "enum": [ "frames", "samples", "logs" ], - "type": "string" + "description": "Result shape. `frames` returns columnar tables or time series, `samples` returns instant values with labels, and `logs` returns log entries." + }, + "frames": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ExploreFrame" + }, + "description": "Columnar frames. Present when `kind` is `frames`; at most 1,000 frames, 1,000 table rows in total, and 100,000 values in total." }, "samples": { - "description": "Instant samples. Present when `kind` is `samples`; at most 1,000 samples.", + "type": "array", "items": { "$ref": "#/components/schemas/ExploreSample" }, - "type": "array" + "description": "Instant samples. Present when `kind` is `samples`; at most 1,000 samples." + }, + "entries": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ExploreLogEntry" + }, + "description": "Log entries. Present when `kind` is `logs`; never longer than `applied_limit`." + }, + "applied_limit": { + "type": "integer", + "description": "Entry limit applied to a logs result: 1 to 1000 (1 to 100 for `sls` data sources). Present only when `kind` is `logs`." + }, + "has_more": { + "type": "boolean", + "description": "Whether a logs result was truncated by `applied_limit`." } - }, - "required": [ - "kind" - ], - "type": "object" + } }, "ExploreSample": { + "type": "object", "description": "One instant sample.", + "required": [ + "labels", + "value" + ], "properties": { "labels": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "Label set of the sample. May be empty but never null.", - "type": "object" + "description": "Label set of the sample. May be empty but never null." }, "value": { + "oneOf": [ + { + "type": "number" + }, + { + "type": "string" + } + ], "description": "Sample value: a number, or one of the strings `NaN`, `+Inf`, and `-Inf`. Never null." } - }, - "required": [ - "labels", - "value" - ], - "type": "object" + } }, "PrometheusLabelValuesResponse": { "description": "Native Prometheus HTTP API response returned by the queried data source. This endpoint does not wrap the payload in the Flashduty response envelope.", @@ -9566,80 +9633,82 @@ "type": "object" }, "QueryExploreExecution": { - "description": "Time semantics of the query. The accepted companion fields depend on `kind`: `instant` takes only `to_ms` (plus optional `from_ms`), `range` requires `from_ms`, `to_ms`, and `max_data_points`, and `window` takes only `from_ms` and `to_ms`. `step_seconds` is never accepted over HTTP.", + "type": "object", + "description": "Time semantics of the query. The accepted companion fields depend on `kind`: `instant` takes `to_ms` (and optionally `from_ms`), `range` requires `from_ms`, `to_ms`, and `max_data_points`, and `window` takes only `from_ms` and `to_ms`. When both times are present, `from_ms` must be less than `to_ms`. `step_seconds` is never accepted over HTTP.", + "required": [ + "kind" + ], "properties": { - "from_ms": { - "description": "Unix timestamp in milliseconds for the start of the range. Required for `range` and `window`; optional for `instant`.", - "format": "int64", - "type": "integer" - }, "kind": { - "description": "Execution kind. `instant` evaluates at a single point in time, `range` evaluates a series over a range, and `window` returns raw rows inside a time window.", + "type": "string", "enum": [ "instant", "range", "window" ], - "type": "string" + "description": "Execution kind.\n\n- `instant`: evaluate at a single point in time.\n- `range`: evaluate a series over `from_ms` to `to_ms`, with a step derived from `max_data_points` and `min_step_seconds`.\n- `window`: query the interval from `from_ms` to `to_ms` with no step." + }, + "from_ms": { + "type": "integer", + "format": "int64", + "description": "Start of the interval as a Unix timestamp in milliseconds; non-negative and less than `to_ms`. Required for `range` and `window`; optional for `instant`.", + "minimum": 0 + }, + "to_ms": { + "type": "integer", + "format": "int64", + "description": "End of the interval (or the evaluation time for `instant`) as a Unix timestamp in milliseconds; non-negative. Required for every execution kind.", + "minimum": 0 }, "max_data_points": { - "description": "Maximum number of points to return. Required for `range` and rejected for `instant` and `window`.", + "type": "integer", "format": "int64", - "maximum": 5000, "minimum": 2, - "type": "integer" + "maximum": 5000, + "description": "Maximum number of points to return. Required for `range` and rejected for `instant` and `window`." }, "min_step_seconds": { - "description": "Lower bound, in seconds, for the step derived from `max_data_points`. Optional and only accepted for `range`.", + "type": "integer", "format": "int64", "minimum": 1, - "type": "integer" - }, - "to_ms": { - "description": "Unix timestamp in milliseconds for the end of the range. Required for every execution kind.", - "format": "int64", - "type": "integer" + "description": "Lower bound, in seconds, for the step derived from `max_data_points`. Optional and only accepted for `range`." } - }, - "required": [ - "kind" - ], - "type": "object" + } }, "QueryExploreRequest": { + "type": "object", "description": "Explore query request. All four top-level fields are required and unknown fields are rejected.", + "required": [ + "datasource_id", + "expr", + "args", + "execution" + ], "properties": { + "datasource_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "maximum": 9007199254740991, + "description": "Data source ID from `/monit/datasource/list`. Must be a positive JavaScript-safe integer for an enabled data source of the authenticated account that the caller may query." + }, + "expr": { + "type": "string", + "minLength": 1, + "description": "Query expression in the data source's native language (PromQL, LogsQL, SQL, and so on). Non-empty UTF-8 of at most 64 KiB; `mysql` allows at most 16 KiB and `tencent_cls` at most 12 KiB." + }, "args": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "Macro substitutions keyed by variable name, used for Grafana-style variables. Keys are at most 256 bytes, values at most 64 KiB, with a 128 KiB total budget.", "maxProperties": 128, - "type": "object" - }, - "datasource_id": { - "description": "Data source ID from `/monit/datasource/list`. Must be a positive JavaScript-safe integer and belong to the authenticated account.", - "format": "int64", - "maximum": 9007199254740991, - "minimum": 1, - "type": "integer" + "description": "Macro substitutions keyed by variable name, used for Grafana-style variables. Keys are at most 256 bytes, values at most 64 KiB, with a 128 KiB total budget." }, "execution": { "$ref": "#/components/schemas/QueryExploreExecution" - }, - "expr": { - "description": "Query expression in the data source's native language (PromQL, LogsQL, SQL, and so on). Non-empty UTF-8 of at most 64 KiB; some data source types enforce a lower limit.", - "minLength": 1, - "type": "string" } - }, - "required": [ - "datasource_id", - "expr", - "args", - "execution" - ], - "type": "object" + } }, "ExportStatusPageSubscribersRequest": { "description": "Parameters for exporting a status page subscriber list.", @@ -9663,43 +9732,43 @@ "type": "object" }, "ExportedStatusPageSubscriberItem": { + "type": "object", "description": "A status page subscriber, as returned by the subscriber list and export endpoints.", + "required": [ + "recipient", + "method", + "components", + "all" + ], "properties": { - "all": { - "description": "Whether the subscriber is subscribed to all components.", - "type": "boolean" - }, - "components": { - "description": "Components this subscriber has subscribed to.", - "items": { - "$ref": "#/components/schemas/StatusPageComponentItem" - }, - "type": "array" - }, - "locale": { - "description": "Preferred locale for notifications. Omitted when empty.", - "type": "string" + "recipient": { + "type": "string", + "description": "Subscriber recipient: email address for public pages, user ID for internal pages." }, "method": { - "description": "Subscription notification method. `email` is email subscription (public pages); `im` is IM subscription (internal pages). Determined by the page type.", + "type": "string", "enum": [ "email", "im" ], - "type": "string" + "description": "Subscription notification method. `email` is email subscription (public pages); `im` is IM subscription (internal pages). Determined by the page type." }, - "recipient": { - "description": "Subscriber recipient: email address for public pages, user ID for internal pages.", - "type": "string" + "components": { + "type": "array", + "items": { + "$ref": "#/components/schemas/StatusPageComponentItem" + }, + "description": "Components the subscriber follows; each item carries only `component_id` and `name`. Empty when `all` is `true`." + }, + "all": { + "type": "boolean", + "description": "Whether the subscriber is subscribed to all components." + }, + "locale": { + "type": "string", + "description": "Preferred locale for notifications. Omitted when empty." } - }, - "required": [ - "recipient", - "method", - "components", - "all" - ], - "type": "object" + } }, "FacetCountItem": { "description": "A facet value and its occurrence count.", @@ -9868,26 +9937,29 @@ "type": "object" }, "FeedDetailIncidentAck": { + "type": "object", "description": "Detail payload for `i_ack`.", "properties": { + "progress": { + "type": "string", + "description": "`Processing` when this acknowledgement moved the incident from `Triggered` to `Processing`; omitted when the incident was already `Processing`.", + "enum": [ + "Processing" + ] + }, "comment": { - "description": "Form summary recorded as a timeline comment. Omitted when no acknowledgement form summary was submitted.", - "type": "string" + "type": "string", + "description": "Form summary recorded as a timeline comment. Omitted when no acknowledgement form summary was submitted." }, "images": { - "description": "Images from the acknowledgement form, recorded on the timeline entry only. Omitted when none were submitted.", + "type": "array", "items": { "$ref": "#/components/schemas/Image" }, - "type": "array" - }, - "progress": { - "description": "Progress note entered at acknowledgement.", - "type": "string" + "description": "Images from the acknowledgement form, recorded on the timeline entry only. Omitted when none were submitted." } }, - "title": "i_ack", - "type": "object" + "title": "i_ack" }, "FeedDetailIncidentAddRspd": { "description": "Detail payload for `i_a_rspd`.", @@ -9935,27 +10007,28 @@ "type": "object" }, "FeedDetailIncidentComment": { + "type": "object", "description": "Detail payload for `i_comm`.", "properties": { "comment": { - "description": "Comment body.", - "type": "string" + "type": "string", + "description": "Comment body." }, - "comment_type": { - "$ref": "#/components/schemas/IncidentCommentTypeDisplay" + "mute_reply": { + "type": "boolean", + "description": "Whether replies to this comment are muted." }, "comment_type_id": { - "description": "ObjectID of the account-level comment type attached to the comment.", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "ObjectID of the account-level comment type attached to the comment." }, - "mute_reply": { - "description": "Whether replies to this comment are muted.", - "type": "boolean" + "comment_type": { + "$ref": "#/components/schemas/IncidentCommentTypeDisplay", + "description": "Name and color of the attached comment type, resolved at read time; omitted when no comment type is attached or it no longer exists." } }, - "title": "i_comm", - "type": "object" + "title": "i_comm" }, "FeedDetailIncidentCustomAction": { "description": "Detail payload for `i_custom`.", @@ -9974,46 +10047,47 @@ "type": "object" }, "FeedDetailIncidentMerge": { + "type": "object", "description": "Detail payload for `i_merge`.", "properties": { "comment": { - "description": "Merge comment.", - "type": "string" - }, - "owner_id": { - "description": "Member ID that performed the merge.", - "format": "int64", - "type": "integer" - }, - "remove_source_incidents": { - "description": "True if the source incidents were removed after merging.", - "type": "boolean" + "type": "string", + "description": "Merge comment." }, "source_incidents": { - "description": "Source incidents that were merged.", + "type": "array", "items": { "$ref": "#/components/schemas/IncidentShort" }, - "type": "array" - }, - "source_responders": { - "description": "Responder member IDs carried over from the source incidents.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "description": "Incidents merged into the target; present on the target incident's entry." }, "target_incident": { - "$ref": "#/components/schemas/IncidentShort" + "$ref": "#/components/schemas/IncidentShort", + "description": "Incident this incident was merged into; present on each source incident's entry." + }, + "owner_id": { + "type": "integer", + "format": "int64", + "description": "Not set by incident merges, which never change the owner; present only on older entries." }, "title": { - "description": "Resulting incident title.", - "type": "string" + "type": "string", + "description": "New title the merge set on the target incident; present only on the target's entry and only when the title changed." + }, + "remove_source_incidents": { + "type": "boolean", + "description": "`true` when the source incidents were permanently deleted after the merge." + }, + "source_responders": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Member IDs that were responders on the source incidents, for reference; they are not added to the target's responders." } }, - "title": "i_merge", - "type": "object" + "title": "i_merge" }, "FeedDetailIncidentMuteByFlapping": { "description": "Detail payload for `i_m_flapping`.", @@ -10042,22 +10116,23 @@ "type": "object" }, "FeedDetailIncidentNew": { + "type": "object", "description": "Detail payload for `i_new`.", "properties": { - "reporter_email": { - "description": "Email of the reporter when the incident was created externally.", - "type": "string" - }, "severity": { - "$ref": "#/components/schemas/FeedSeverity" + "$ref": "#/components/schemas/FeedSeverity", + "description": "Severity of the incident when it was created." }, "title": { - "description": "Initial incident title.", - "type": "string" + "type": "string", + "description": "Initial incident title." + }, + "reporter_email": { + "type": "string", + "description": "Email of the reporter when the incident was created externally." } }, - "title": "i_new", - "type": "object" + "title": "i_new" }, "FeedDetailIncidentNotify": { "description": "Detail payload for `i_notify`.", @@ -10124,15 +10199,15 @@ "type": "object" }, "FeedDetailIncidentReopen": { + "type": "object", "description": "Detail payload for `i_reopen`.", "properties": { "reason": { - "description": "Reason why the incident was reopened.", - "type": "string" + "type": "string", + "description": "Free-text reason passed as `reason` to `POST /incident/reopen`; omitted when none was given." } }, - "title": "i_reopen", - "type": "object" + "title": "i_reopen" }, "FeedDetailIncidentResetDescription": { "additionalProperties": false, @@ -10180,32 +10255,34 @@ "type": "object" }, "FeedDetailIncidentResetSeverity": { + "type": "object", "description": "Detail payload for `i_r_severity`.", "properties": { "from": { - "$ref": "#/components/schemas/FeedSeverity" + "$ref": "#/components/schemas/FeedSeverity", + "description": "Severity before the change." }, "to": { - "$ref": "#/components/schemas/FeedSeverity" + "$ref": "#/components/schemas/FeedSeverity", + "description": "Severity after the change." } }, - "title": "i_r_severity", - "type": "object" + "title": "i_r_severity" }, "FeedDetailIncidentResetTitle": { + "type": "object", "description": "Detail payload for `i_r_title`.", "properties": { "from": { - "description": "Previous title.", - "type": "string" + "type": "string", + "description": "Title before the change." }, "to": { - "description": "New title.", - "type": "string" + "type": "string", + "description": "Title after the change." } }, - "title": "i_r_title", - "type": "object" + "title": "i_r_title" }, "FeedDetailIncidentResolve": { "description": "Detail payload for `i_rslv`.", @@ -10266,113 +10343,150 @@ "type": "object" }, "FeedDetailIncidentUnack": { + "type": "object", "description": "Detail payload for `i_unack`.", "properties": { "progress": { - "description": "Progress note entered when acknowledgement was removed.", - "type": "string" + "type": "string", + "description": "`Triggered` when removing this acknowledgement returned the incident to `Triggered` (no responder still acknowledged); omitted otherwise.", + "enum": [ + "Triggered" + ] } }, - "title": "i_unack", - "type": "object" + "title": "i_unack" }, "FeedDetailIncidentWake": { + "type": "object", "description": "Detail payload for `i_wake`.", "properties": { "snoozedBefore": { - "description": "Unix timestamp at which the prior snooze was scheduled to end.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp (seconds) at which the cancelled snooze would have ended." } }, - "title": "i_wake", - "type": "object" + "title": "i_wake" }, "FeedDetailIncidentWarRoomCreate": { + "type": "object", "description": "Detail payload for `i_wr_create`.", "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "description": "Integration ID that hosts the war room chat group." + }, "chat_id": { - "description": "Chat group identifier.", - "type": "string" + "type": "string", + "description": "Chat group identifier." }, "chat_name": { - "description": "Chat group display name.", - "type": "string" + "type": "string", + "description": "Chat group display name." }, - "integration_id": { - "description": "Integration ID that hosts the war room chat group.", - "format": "int64", - "type": "integer" + "plugin_type": { + "type": "string", + "description": "Plugin type of the IM integration: `feishu_app` (Feishu), `dingtalk_app` (DingTalk), `wecom_app` (WeCom), or `slack_app` (Slack).", + "enum": [ + "feishu_app", + "dingtalk_app", + "wecom_app", + "slack_app" + ] }, "integration_name": { - "description": "Integration display name.", - "type": "string" - }, - "plugin_type": { - "description": "Chat integration plugin type.", - "type": "string" + "type": "string", + "description": "Integration display name." }, "share_link": { - "description": "Shareable join link for the war room.", - "type": "string" + "type": "string", + "description": "Shareable join link for the war room." } }, - "title": "i_wr_create", - "type": "object" + "title": "i_wr_create" }, "FeedDetailIncidentWarRoomDelete": { + "type": "object", "description": "Detail payload for `i_wr_delete`.", "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "description": "Integration ID that hosted the war room chat group." + }, + "unlink_only": { + "type": "boolean", + "description": "`true` when the war room was only unlinked from the incident (`unlink_only` request) and the group was not dissolved. Omitted otherwise." + }, "chat_id": { - "description": "Chat group identifier.", - "type": "string" + "type": "string", + "description": "Chat group identifier." }, "chat_name": { - "description": "Chat group display name.", - "type": "string" + "type": "string", + "description": "Chat group display name." }, - "integration_id": { - "description": "Integration ID that hosted the war room chat group.", - "format": "int64", - "type": "integer" + "plugin_type": { + "type": "string", + "description": "Plugin type of the IM integration: `feishu_app` (Feishu), `dingtalk_app` (DingTalk), `wecom_app` (WeCom), or `slack_app` (Slack).", + "enum": [ + "feishu_app", + "dingtalk_app", + "wecom_app", + "slack_app" + ] }, "integration_name": { - "description": "Integration display name.", - "type": "string" - }, - "plugin_type": { - "description": "Chat integration plugin type.", - "type": "string" + "type": "string", + "description": "Integration display name." } }, - "title": "i_wr_delete", - "type": "object" + "title": "i_wr_delete" }, "FeedDetailWorkItemAssigneesChanged": { + "type": "object", "description": "Detail payload for `i_wi_assignees`.", "properties": { - "added_assignee_ids": { - "description": "Member IDs added as assignees.", + "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." + }, + "assignee_ids": { + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Assignee member IDs after the change." }, - "added_assignees": { + "added_assignee_ids": { "type": "array", "items": { - "$ref": "#/components/schemas/WorkItemAssignee" + "type": "integer", + "format": "int64" }, - "description": "Assignees added by this change, in submitted order. `added_assignee_ids` is the person-only subset. Omitted when nothing was added." + "description": "Member IDs added as assignees." }, - "assignee_ids": { - "description": "Assignee member IDs after the change.", + "removed_assignee_ids": { + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Member IDs removed from assignees." }, "assignees": { "type": "array", @@ -10381,21 +10495,12 @@ }, "description": "Assignees of the work item. Each entry is `{type, id?}`; an `ai_sre` entry omits `id`. Omitted when there is no assignee." }, - "item_type": { - "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem.", - "enum": [ - "action", - "follow_up" - ], - "type": "string" - }, - "removed_assignee_ids": { - "description": "Member IDs removed from assignees.", + "added_assignees": { + "type": "array", "items": { - "format": "int64", - "type": "integer" + "$ref": "#/components/schemas/WorkItemAssignee" }, - "type": "array" + "description": "Assignees added by this change, in submitted order. `added_assignee_ids` is the person-only subset. Omitted when nothing was added." }, "removed_assignees": { "type": "array", @@ -10403,130 +10508,151 @@ "$ref": "#/components/schemas/WorkItemAssignee" }, "description": "Assignees removed by this change. `removed_assignee_ids` is the person-only subset. Omitted when nothing was removed." - }, - "title": { - "description": "Work item title.", - "type": "string" - }, - "work_item_id": { - "description": "Work item ID.", - "type": "string" } }, - "title": "i_wi_assignees", - "type": "object" + "title": "i_wi_assignees" }, "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": { - "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem.", + "type": "string", "enum": [ "action", "follow_up" ], - "type": "string" - }, - "post_mortem_id": { - "description": "ID of the post-mortem the work item is bound to.", - "type": "string" + "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem." }, "title": { - "description": "Work item title.", - "type": "string" + "type": "string", + "description": "Work item title." }, - "work_item_id": { - "description": "Work item ID.", - "type": "string" + "post_mortem_id": { + "type": "string", + "description": "ID of the post-mortem the work item is bound to." } }, - "title": "i_wi_bound", - "type": "object" + "title": "i_wi_bound" }, "FeedDetailWorkItemCompleted": { + "type": "object", "description": "Detail payload for `i_wi_completed`.", "properties": { - "from_status": { - "description": "Status label before completion.", - "type": "string" + "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": { - "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem.", + "type": "string", "enum": [ "action", "follow_up" ], - "type": "string" - }, - "post_mortem_id": { - "description": "ID of the post-mortem the work item is bound to.", - "type": "string" + "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem." }, "title": { - "description": "Work item title.", - "type": "string" + "type": "string", + "description": "Work item title." + }, + "from_status": { + "type": "string", + "description": "Status before completion, usually `open` or `in_progress`; items created before these statuses existed may carry other text." }, "to_status": { - "description": "Status label after completion.", - "type": "string" + "type": "string", + "description": "Status after completion; always `done`.", + "enum": [ + "done" + ] }, - "work_item_id": { - "description": "Work item ID.", - "type": "string" + "post_mortem_id": { + "type": "string", + "description": "ID of the post-mortem the work item is bound to." } }, - "title": "i_wi_completed", - "type": "object" + "title": "i_wi_completed" }, "FeedDetailWorkItemConverted": { + "type": "object", "description": "Detail payload for `i_wi_converted`.", "properties": { + "work_item_id": { + "type": "string", + "description": "Work item ID (`wi_` followed by a random string); use it with the `/incident/work-item/*` endpoints." + }, + "title": { + "type": "string", + "description": "Work item title." + }, "from_type": { - "description": "Work item type before the conversion. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem. Conversion currently only supports `action` → `follow_up`, so `from_type` is always `action` in this event.", + "type": "string", "enum": [ "action", "follow_up" ], - "type": "string" - }, - "post_mortem_id": { - "description": "ID of the post-mortem the work item is bound to.", - "type": "string" - }, - "status": { - "description": "Work item status label after the conversion.", - "type": "string" - }, - "title": { - "description": "Work item title.", - "type": "string" + "description": "Work item type before the conversion. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem. Conversion currently only supports `action` → `follow_up`, so `from_type` is always `action` in this event." }, "to_type": { - "description": "Work item type after the conversion. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem. Conversion currently only supports `action` → `follow_up`, so `to_type` is always `follow_up` in this event, and a successful conversion immediately tries to bind the incident's post-mortem.", + "type": "string", "enum": [ "action", "follow_up" ], - "type": "string" + "description": "Work item type after the conversion. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem. Conversion currently only supports `action` → `follow_up`, so `to_type` is always `follow_up` in this event, and a successful conversion immediately tries to bind the incident's post-mortem." }, - "work_item_id": { - "description": "Work item ID.", - "type": "string" + "post_mortem_id": { + "type": "string", + "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)." } }, - "title": "i_wi_converted", - "type": "object" + "title": "i_wi_converted" }, "FeedDetailWorkItemCreated": { + "type": "object", "description": "Detail payload for `i_wi_created`.", "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, convertible to `follow_up` later; `follow_up`: an improvement item anchored to a post-mortem, requiring the incident to be linked to that post-mortem at creation." + }, + "title": { + "type": "string", + "description": "Work item title." + }, + "status": { + "type": "string", + "description": "Work item status at creation: `open` not started; `in_progress` being worked on; `done` completed; `cancelled` no longer needed.", + "enum": [ + "open", + "in_progress", + "done", + "cancelled" + ] + }, "assignee_ids": { - "description": "Assignee member IDs.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Assignee member IDs." }, "assignees": { "type": "array", @@ -10535,152 +10661,120 @@ }, "description": "Assignees of the work item. Each entry is `{type, id?}`; an `ai_sre` entry omits `id`. Omitted when there is no assignee." }, - "item_type": { - "description": "Work item type. `action`: an action item anchored to the incident itself, convertible to `follow_up` later; `follow_up`: an improvement item anchored to a post-mortem, requiring the incident to be linked to that post-mortem at creation.", - "enum": [ - "action", - "follow_up" - ], - "type": "string" - }, "post_mortem_id": { - "description": "ID of the post-mortem the work item is bound to.", - "type": "string" - }, - "status": { - "description": "Work item status label (e.g. `open`, `done`).", - "type": "string" - }, - "title": { - "description": "Work item title.", - "type": "string" - }, - "work_item_id": { - "description": "Work item ID.", - "type": "string" + "type": "string", + "description": "ID of the post-mortem the work item is bound to." } }, - "title": "i_wi_created", - "type": "object" + "title": "i_wi_created" }, "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": { - "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem.", + "type": "string", "enum": [ "action", "follow_up" ], - "type": "string" - }, - "post_mortem_id": { - "description": "ID of the post-mortem the work item is bound to.", - "type": "string" + "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem." }, "title": { - "description": "Work item title.", - "type": "string" + "type": "string", + "description": "Work item title." }, - "work_item_id": { - "description": "Work item ID.", - "type": "string" + "post_mortem_id": { + "type": "string", + "description": "ID of the post-mortem the work item is bound to." } }, - "title": "i_wi_deleted", - "type": "object" + "title": "i_wi_deleted" }, "FeedDetailWorkItemUpdated": { + "type": "object", "description": "Detail payload for `i_wi_updated`. Only the fields that changed carry `from_*`/`to_*` values.", "properties": { - "from_description": { - "description": "Description before the update.", - "type": "string" - }, - "from_priority": { - "description": "Priority label before the update.", - "type": "string" - }, - "from_status": { - "description": "Status label before the update.", - "type": "string" - }, - "from_title": { - "description": "Title before the update.", - "type": "string" + "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": { - "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem.", + "type": "string", "enum": [ "action", "follow_up" ], - "type": "string" + "description": "Work item type. `action`: an action item anchored to the incident itself; `follow_up`: an improvement item anchored to a post-mortem." }, "title": { - "description": "Work item title.", - "type": "string" + "type": "string", + "description": "Work item title." }, - "to_description": { - "description": "Description after the update.", - "type": "string" + "from_title": { + "type": "string", + "description": "Title before the update." }, - "to_priority": { - "description": "Priority label after the update.", - "type": "string" + "from_status": { + "type": "string", + "description": "Status before the update; present only when the status changed. Usually one of `open`, `in_progress`, `done`, `cancelled`; items created before these statuses existed may carry other text." }, "to_status": { - "description": "Status label after the update.", - "type": "string" + "type": "string", + "description": "Status after the update; present only when the status changed. `open` not started; `in_progress` being worked on; `done` completed; `cancelled` no longer needed.", + "enum": [ + "open", + "in_progress", + "done", + "cancelled" + ] }, - "work_item_id": { - "description": "Work item ID.", - "type": "string" + "from_priority": { + "type": "string", + "description": "Priority before the update. Free-text priority label defined by the client (up to 64 characters); present only when the priority changed." + }, + "to_priority": { + "type": "string", + "description": "Priority after the update. Free-text priority label defined by the client (up to 64 characters); present only when the priority changed." + }, + "from_description": { + "type": "string", + "description": "Description before the update." + }, + "to_description": { + "type": "string", + "description": "Description after the update." } }, - "title": "i_wi_updated", - "type": "object" + "title": "i_wi_updated" }, "FeedItem": { + "type": "object", "description": "A single alert activity feed entry. The `detail` field is discriminated by `type`; see the per-type `FeedDetailAlert*` schemas.", + "required": [ + "ref_id", + "type", + "detail", + "account_id", + "creator_id", + "created_at", + "updated_at" + ], "properties": { - "account_id": { - "description": "Account ID.", - "format": "int64", - "type": "integer" - }, - "created_at": { - "description": "Creation timestamp in Unix epoch milliseconds.", - "format": "int64", - "type": "integer" - }, - "creator_id": { - "description": "Member ID of the creator. 0 for system-generated entries.", - "format": "int64", - "type": "integer" + "ref_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "ObjectID of the alert this entry references." }, - "deleted_at": { - "description": "Soft-delete time, Unix epoch milliseconds. Omitted when not deleted.", - "format": "int64", - "type": "integer" + "type": { + "$ref": "#/components/schemas/AlertFeedType" }, "detail": { "description": "Type-specific payload; the concrete shape is determined by `type`. May be `null` for entries stored without detail.", - "discriminator": { - "mapping": { - "a_ack": "#/components/schemas/FeedDetailAlertAck", - "a_close": "#/components/schemas/FeedDetailAlertClose", - "a_comm": "#/components/schemas/FeedDetailAlertComment", - "a_m_flapping": "#/components/schemas/FeedDetailAlertMuteByFlapping", - "a_m_inhibit": "#/components/schemas/FeedDetailAlertMuteByInhibit", - "a_m_silence": "#/components/schemas/FeedDetailAlertMuteBySilence", - "a_merge": "#/components/schemas/FeedDetailAlertMerge", - "a_new": "#/components/schemas/FeedDetailAlertTrigger", - "a_unack": "#/components/schemas/FeedDetailAlertUnack", - "a_update": "#/components/schemas/FeedDetailAlertUpdate" - }, - "propertyName": "type" - }, "oneOf": [ { "$ref": "#/components/schemas/FeedDetailAlertTrigger" @@ -10712,20 +10806,47 @@ { "$ref": "#/components/schemas/FeedDetailAlertClose" } - ] + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "a_new": "#/components/schemas/FeedDetailAlertTrigger", + "a_update": "#/components/schemas/FeedDetailAlertUpdate", + "a_comm": "#/components/schemas/FeedDetailAlertComment", + "a_merge": "#/components/schemas/FeedDetailAlertMerge", + "a_m_silence": "#/components/schemas/FeedDetailAlertMuteBySilence", + "a_m_inhibit": "#/components/schemas/FeedDetailAlertMuteByInhibit", + "a_m_flapping": "#/components/schemas/FeedDetailAlertMuteByFlapping", + "a_ack": "#/components/schemas/FeedDetailAlertAck", + "a_unack": "#/components/schemas/FeedDetailAlertUnack", + "a_close": "#/components/schemas/FeedDetailAlertClose" + } + } }, - "ref_id": { - "description": "ObjectID of the alert this entry references.", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "account_id": { + "type": "integer", + "format": "int64", + "description": "ID of the account that owns the alert." }, - "type": { - "$ref": "#/components/schemas/AlertFeedType" + "creator_id": { + "type": "integer", + "format": "int64", + "description": "Member ID of the creator. 0 for system-generated entries." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation timestamp in Unix epoch milliseconds." }, "updated_at": { - "description": "Last update timestamp in Unix epoch milliseconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update timestamp in Unix epoch milliseconds." + }, + "deleted_at": { + "type": "integer", + "format": "int64", + "description": "Soft-delete time, Unix epoch milliseconds. Omitted when not deleted." }, "via": { "type": "string", @@ -10735,17 +10856,7 @@ "type": "string", "description": "AI SRE session that produced the entry. Omitted when no agent wrote it." } - }, - "required": [ - "ref_id", - "type", - "detail", - "account_id", - "creator_id", - "created_at", - "updated_at" - ], - "type": "object" + } }, "FeedSeverity": { "description": "Severity level.", @@ -10758,28 +10869,30 @@ "type": "string" }, "FieldDeleteReference": { + "type": "object", "description": "Custom form that still references the field.", + "required": [ + "kind", + "name", + "href" + ], "properties": { - "href": { - "description": "Console URL for the referencing custom form.", - "type": "string" - }, "kind": { - "const": "custom_form", + "type": "string", "description": "Referenced resource kind. Always `custom_form` for this response.", - "type": "string" + "enum": [ + "custom_form" + ] }, "name": { - "description": "Human label of the referencing custom form's type (a Chinese label, e.g. `解决故障` for the resolve form).", - "type": "string" + "type": "string", + "description": "Human label of the referencing custom form's type (a Chinese label, e.g. `解决故障` for the resolve form)." + }, + "href": { + "type": "string", + "description": "Console URL for the referencing custom form." } - }, - "required": [ - "kind", - "name", - "href" - ], - "type": "object" + } }, "FieldDeleteReferenceError": { "description": "Error response returned when a custom form still references the field.", @@ -11005,70 +11118,70 @@ "type": "object" }, "FilterCondition": { + "type": "object", + "required": [ + "key", + "oper", + "vals" + ], "properties": { "key": { - "description": "Field name to filter on. Use plain names for built-in alert fields (e.g. `alert_severity`, `alert_key`, `check`, `resource`, `service`, `cluster`) or the `labels.` prefix for custom alert labels (e.g. `labels.env`, `labels.region`).", - "type": "string" + "type": "string", + "description": "Field to match. Which built-in keys are allowed depends on the rule type and is listed on the field that holds the conditions; any `labels.` key (for example `labels.env`) is always accepted. An unknown key returns `InvalidParameter`. When the alert or incident has no value for the key, `IN` does not match and `NOTIN` matches." }, "oper": { - "description": "Filter operator. `IN` — value must match one of `vals`; `NOTIN` — value must not match any of `vals`. Supports regex patterns wrapped in `/pattern/`.", + "type": "string", "enum": [ "IN", "NOTIN" ], - "type": "string" + "description": "Match operator, case-sensitive. `IN`: matches when the field value matches any entry in `vals`. `NOTIN`: matches when it matches none of them." }, "vals": { - "description": "List of values to match against. Each entry is a plain string or a `/regex/` pattern.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Values to compare, at least one. Each entry is matched as: an exact string; a wildcard pattern when it contains `*` or `?` (must match the whole value); a regular expression when wrapped in slashes, such as `/^db-/` (may match anywhere in the value); an IP range written `cidr:`, such as `cidr:203.0.113.0/24`; or a numeric comparison `num::` with `lt`, `le`, `gt` or `ge`, such as `num:gt:90`." } - }, - "required": [ - "key", - "oper", - "vals" - ], - "type": "object" + } }, "FilterGroup": { "$ref": "#/components/schemas/OrFilterGroup" }, "Flapping": { + "type": "object", "description": "Flapping detection configuration.", "properties": { - "in_mins": { - "description": "Observation window in minutes.", - "maximum": 1440, - "minimum": 1, - "type": "integer" - }, "is_disabled": { - "description": "Disable flapping detection.", - "type": "boolean" + "type": "boolean", + "description": "When true, flapping detection is turned off." }, "max_changes": { - "description": "Max state changes allowed within `in_mins`.", - "maximum": 100, + "type": "integer", "minimum": 2, - "type": "integer" + "maximum": 100, + "description": "Max state changes allowed within `in_mins`, 2–100. When omitted or `0`, all three values fall back to the defaults: 4 changes, `in_mins` 60, `mute_mins` 120." }, - "mute_mins": { - "description": "Mute duration in minutes after flapping is detected.", + "in_mins": { + "type": "integer", + "minimum": 1, "maximum": 1440, + "description": "Observation window in minutes." + }, + "mute_mins": { + "type": "integer", "minimum": 0, - "type": "integer" + "maximum": 1440, + "description": "Mute duration in minutes after flapping is detected." } - }, - "type": "object" + } }, "GetRemoteConfigRequest": { "description": "Get remote config request", "properties": { "application_id": { - "description": "RUM application ID.", + "description": "RUM application ID. Get application IDs via `POST /rum/application/list`.", "type": "string" } }, @@ -11081,7 +11194,15 @@ "description": "Live remote configuration and its version.", "properties": { "config": { - "$ref": "#/components/schemas/RemoteConfig" + "anyOf": [ + { + "$ref": "#/components/schemas/RemoteConfig" + }, + { + "type": "null" + } + ], + "description": "The live configuration (the newest published version). `null` when the application has never been configured." }, "updated_at": { "description": "Unix timestamp in milliseconds - when the current version was published. 0 when never configured.", @@ -11093,31 +11214,40 @@ "type": "integer" } }, - "type": "object" + "type": "object", + "required": [ + "config", + "version", + "updated_at" + ] }, "GetWarRoomDefaultObserversRequest": { + "type": "object", "properties": { "incident_id": { - "description": "Incident ID, a MongoDB ObjectID hex string.", - "type": "string" + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Incident ID (MongoDB ObjectID)." } }, "required": [ "incident_id" - ], - "type": "object" + ] }, "GetWarRoomDefaultObserversResponse": { + "type": "object", "properties": { "observers": { - "description": "Historical responders suggested as default war-room observers.", + "type": "array", "items": { "$ref": "#/components/schemas/WarRoomPersonItem" }, - "type": "array" + "description": "Suggested observers, in timeline order. Empty array when there are none." } }, - "type": "object" + "required": [ + "observers" + ] }, "GetWarRoomDetailRequest": { "description": "Parameters for retrieving a war room's live detail.", @@ -11139,130 +11269,130 @@ "type": "object" }, "GetWebhookHistoryDetailRequest": { + "type": "object", "description": "Lookup parameters for a single webhook delivery record.", + "required": [ + "event_id", + "integration_id" + ], "properties": { "event_id": { - "description": "Event ID returned by `ListWebhookHistory`.", - "type": "string" + "type": "string", + "description": "`event_id` of a record returned by `POST /webhook/history/list`. It starts with the delivery date (`YYYYMMDD`); an ID without that prefix fails the request." }, "integration_id": { - "description": "Integration ID the event belongs to; available in the items returned by `POST /webhook/history/list`.", + "type": "integer", "format": "int64", "minimum": 1, - "type": "integer" + "description": "Integration ID the event belongs to; available in the items returned by `POST /webhook/history/list`." } - }, - "required": [ - "event_id", - "integration_id" - ], - "type": "object" + } }, "Group": { + "type": "object", "description": "Alert grouping configuration.", + "required": [ + "method" + ], "properties": { - "all_equals_required": { - "description": "When true, all listed keys must be present for grouping.", - "type": "boolean" - }, - "cases": { - "description": "Per-filter grouping overrides.", - "items": { - "description": "Conditional grouping override: stored alerts matching `if` are grouped by `equals` instead of the top-level grouping keys.", - "properties": { - "equals": { - "description": "Grouping keys for matching alerts. Supported values: `title`, `description`, `severity`, or any `labels.`.", - "items": { - "type": "string" - }, - "maxItems": 5, - "minItems": 1, - "type": "array" - }, - "if": { - "description": "AND-ed match conditions evaluated against stored alert fields.", - "items": { - "$ref": "#/components/schemas/FilterCondition" - }, - "type": "array" - } - }, - "required": [ - "if", - "equals" - ], - "type": "object" - }, - "maxItems": 100, - "type": "array" + "method": { + "type": "string", + "enum": [ + "i", + "p", + "n" + ], + "description": "Grouping method:\n- `n`: no grouping; every new alert opens its own incident.\n- `p`: rule-based grouping by the keys in `equals` and `cases`; requires the Standard license or higher.\n- `i`: intelligent grouping by content similarity (see `i_keys`, `i_score_threshold`); requires the Pro license." }, "equals": { - "description": "Groups of label keys whose equality defines a bucket.", + "type": "array", "items": { + "type": "array", "items": { "type": "string" - }, - "type": "array" + } }, "maxItems": 5, - "type": "array" + "description": "Key sets for rule-based (`p`) grouping, up to 5 sets. A new alert joins an active incident when every key of any one set has the same value on both. Keys: `title`, `description`, `severity`, or `labels.`; each set must be non-empty. With `p`, at least one of `equals` or `cases` is required." }, - "i_keys": { - "description": "Label keys used for intelligent grouping embeddings.", + "cases": { + "type": "array", + "maxItems": 100, + "description": "Per-filter grouping overrides.", "items": { - "type": "string" - }, - "maxItems": 10, - "type": "array" + "type": "object", + "description": "Conditional grouping override: stored alerts matching `if` are grouped by `equals` instead of the top-level grouping keys.", + "required": [ + "if", + "equals" + ], + "properties": { + "if": { + "type": "array", + "description": "AND-ed match conditions evaluated against stored alert fields.", + "items": { + "$ref": "#/components/schemas/FilterCondition" + } + }, + "equals": { + "type": "array", + "items": { + "type": "string" + }, + "minItems": 1, + "maxItems": 5, + "description": "Grouping keys for matching alerts. Supported values: `title`, `description`, `severity`, or any `labels.`." + } + } + } }, - "i_score_threshold": { - "description": "Intelligent grouping similarity threshold.", - "format": "float", - "maximum": 1, - "minimum": 0.5, - "type": "number" + "all_equals_required": { + "type": "boolean", + "description": "When true, a key set matches only if every key in it is present on the alert. When false, missing keys compare as empty, but at least one key of the set must be present." }, - "method": { - "description": "Grouping method: `i` intelligent, `p` pattern, `n` none.", + "time_window": { + "type": "integer", + "minimum": 0, + "description": "Grouping time window in minutes. Default max is 1440 minutes (24 h); extended accounts may allow up to 43200 minutes (30 days)." + }, + "window_type": { + "type": "string", "enum": [ - "i", - "p", - "n" + "tumbling", + "sliding" ], - "type": "string" + "description": "Window type, default `tumbling`. `tumbling` is a fixed window counted from incident creation — once it expires, new alerts open a new incident; `sliding` is a sliding window counted from the incident's most recent alert, extended each time a new alert merges in." }, "storm_threshold": { - "description": "Alert storm threshold.", - "maximum": 10000, + "type": "integer", "minimum": 0, - "type": "integer" + "maximum": 10000, + "description": "Legacy single storm threshold; used only when `storm_thresholds` is empty and the value is greater than 1. `0` disables it." }, "storm_thresholds": { - "description": "Multi-level storm thresholds.", + "type": "array", "items": { "type": "integer" }, "maxItems": 5, - "type": "array" + "description": "Alert counts at which an incident storm event fires: when the number of alerts merged into one incident reaches a threshold, a storm notification is sent. Up to 5 values, each at least 2; duplicates are removed and values are sorted." }, - "time_window": { - "description": "Grouping time window in minutes. Default max is 1440 minutes (24 h); extended accounts may allow up to 43200 minutes (30 days).", - "minimum": 0, - "type": "integer" + "i_keys": { + "type": "array", + "items": { + "type": "string" + }, + "maxItems": 10, + "description": "Fields used by intelligent (`i`) grouping, up to 10: `title`, `description`, `severity`, or `labels.`. Empty uses `title`, `description`, `labels.service` and `labels.resource`." }, - "window_type": { - "description": "Window type, default `tumbling`. `tumbling` is a fixed window counted from incident creation — once it expires, new alerts open a new incident; `sliding` is a sliding window counted from the incident's most recent alert, extended each time a new alert merges in.", - "enum": [ - "tumbling", - "sliding" - ], - "type": "string" + "i_score_threshold": { + "type": "number", + "format": "float", + "minimum": 0.5, + "maximum": 1, + "description": "Minimum similarity, 0.5–1, for intelligent grouping to merge an alert into an existing incident. Omitted or `0` uses 0.9." } - }, - "required": [ - "method" - ], - "type": "object" + } }, "IDRequest": { "description": "Request with a single numeric ID.", @@ -11279,111 +11409,111 @@ "type": "object" }, "Image": { + "type": "object", "description": "Image or attachment reference.", + "required": [ + "src" + ], "properties": { - "alt": { - "description": "Alt text.", - "type": "string" + "src": { + "type": "string", + "description": "Image source. Either an `img_` upload token or an `http(s)` URL." }, "href": { - "description": "Optional link the image points to.", - "type": "string" + "type": "string", + "description": "Optional link the image points to." }, - "src": { - "description": "Image source. Either an `img_` upload token or an `http(s)` URL.", - "type": "string" + "alt": { + "type": "string", + "description": "Alternative text shown when the image cannot be displayed; empty when not set." } - }, - "required": [ - "src" - ], - "type": "object" + } }, "ImportStatusPageSubscriberItem": { + "type": "object", "description": "A single subscriber to import.", + "required": [ + "recipient" + ], "properties": { - "all": { - "description": "When true, the subscriber receives notifications for all components. Must be true when `component_ids` and `change_ids` are both empty.", - "type": "boolean" + "recipient": { + "type": "string", + "maxLength": 255, + "description": "Email address (for public pages) or user ID (for internal pages)." }, - "change_ids": { - "description": "Specific event IDs the subscriber should receive notifications for.", + "component_ids": { + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "string" }, - "type": "array" + "description": "Component IDs the subscriber should receive notifications for." }, - "component_ids": { - "description": "Component IDs the subscriber should receive notifications for.", + "change_ids": { + "type": "array", "items": { - "type": "string" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Specific event IDs the subscriber should receive notifications for." }, - "locale": { - "description": "Preferred locale for notifications. Defaults to the request locale when omitted.", - "type": "string" + "all": { + "type": "boolean", + "description": "When `true`, the subscriber receives notifications for all components and events, and `component_ids`/`change_ids` are ignored. Must be `true` when both lists are empty." }, - "recipient": { - "description": "Email address (for public pages) or user ID (for internal pages).", - "maxLength": 255, - "type": "string" + "locale": { + "type": "string", + "description": "Preferred locale for notifications. Defaults to the request locale when omitted." } - }, - "required": [ - "recipient" - ], - "type": "object" + } }, "ImportStatusPageSubscribersRequest": { + "type": "object", "description": "Parameters for bulk-importing subscribers. Each subscriber must have a non-empty `recipient` (≤255 chars) and subscribe to at least one component, change, or set `all: true`.", + "required": [ + "page_id", + "method" + ], "properties": { + "page_id": { + "type": "integer", + "format": "int64", + "description": "Target status page ID; obtain it from `GET /status-page/list`." + }, "method": { - "description": "Subscription method. `email` is only valid for public pages; `im` is only valid for internal pages.", + "type": "string", "enum": [ "email", "im" ], - "type": "string" - }, - "page_id": { - "description": "Target status page ID; obtain it from `GET /status-page/list`.", - "format": "int64", - "type": "integer" + "description": "Subscription method. `email` is only valid for public pages; `im` is only valid for internal pages." }, "subscribers": { - "description": "Subscribers to import.", + "type": "array", "items": { "$ref": "#/components/schemas/ImportStatusPageSubscriberItem" }, - "type": "array" + "description": "Subscribers to import. Each recipient's existing subscriptions on this page are replaced; an empty or omitted list does nothing." } - }, - "required": [ - "page_id", - "method" - ], - "type": "object" + } }, "IncProgressCnts": { + "type": "object", + "required": [ + "Triggered", + "Processing" + ], "properties": { - "Processing": { - "description": "Count of processing incidents in the last 30 days.", + "Triggered": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Incidents started in the last 30 days that are still `Triggered` (not yet acknowledged)." }, - "Triggered": { - "description": "Count of triggered incidents in the last 30 days.", + "Processing": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Incidents started in the last 30 days that are `Processing` (acknowledged, not yet closed)." } - }, - "required": [ - "Triggered", - "Processing" - ], - "type": "object" + } }, "IncidentActionImage": { "description": "Image attached to an acknowledgement or resolution timeline entry.", @@ -11407,9 +11537,23 @@ "type": "object" }, "IncidentCardHiddenFields": { + "type": "object", + "description": "Incident-card fields to hide, keyed by IM app type. Only supported IM app types and field names are accepted.", + "propertyNames": { + "type": "string", + "enum": [ + "feishu_app", + "dingtalk_app", + "slack_app", + "teams_app", + "wecom_app" + ] + }, "additionalProperties": { - "description": "Incident-card field names to hide for this IM app.", + "type": "array", + "description": "Fields to hide on this app's incident cards: `channel` (channel name), `snoozed_before` (snooze end time), `severity`, `responders`, `aggregate_alert_count` (number of merged alerts), `detail` (Detail button), `ai_analysis` (AI Analysis button).", "items": { + "type": "string", "enum": [ "channel", "snoozed_before", @@ -11418,23 +11562,9 @@ "aggregate_alert_count", "detail", "ai_analysis" - ], - "type": "string" - }, - "type": "array" - }, - "description": "Incident-card fields to hide, keyed by IM app type. Only supported IM app types and field names are accepted.", - "propertyNames": { - "enum": [ - "feishu_app", - "dingtalk_app", - "slack_app", - "teams_app", - "wecom_app" - ], - "type": "string" - }, - "type": "object" + ] + } + } }, "IncidentCommentTypeDisplay": { "description": "Resolved display of an account-level comment type, populated at read time from the current type definition.", @@ -11525,69 +11655,28 @@ "type": "object" }, "IncidentFeedItem": { + "type": "object", "description": "Single incident timeline entry. The `detail` field is discriminated by `type`; see the per-type `FeedDetail*` schemas.", + "required": [ + "ref_id", + "type", + "detail", + "account_id", + "creator_id", + "created_at", + "updated_at" + ], "properties": { - "account_id": { - "description": "Account ID.", - "format": "int64", - "type": "integer" - }, - "created_at": { - "description": "Creation timestamp in milliseconds.", - "format": "int64", - "type": "integer" - }, - "creator_id": { - "description": "User ID of the actor. `0` means system-generated.", - "format": "int64", - "type": "integer" + "ref_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "ID of the incident the entry belongs to; equals the requested `incident_id`." }, - "deleted_at": { - "description": "Soft-delete timestamp in milliseconds. Zero if not deleted.", - "format": "int64", - "type": "integer" + "type": { + "$ref": "#/components/schemas/IncidentFeedType" }, "detail": { "description": "Type-specific payload. The concrete shape is determined by `type`; `null` when the entry has no structured detail.", - "discriminator": { - "mapping": { - "a_merge": "#/components/schemas/FeedDetailAlertMerge", - "i_a_rspd": "#/components/schemas/FeedDetailIncidentAddRspd", - "i_ack": "#/components/schemas/FeedDetailIncidentAck", - "i_assign": "#/components/schemas/FeedDetailIncidentAssign", - "i_auto_refresh": "#/components/schemas/FeedDetailIncidentAutoRefreshCard", - "i_comm": "#/components/schemas/FeedDetailIncidentComment", - "i_custom": "#/components/schemas/FeedDetailIncidentCustomAction", - "i_m_flapping": "#/components/schemas/FeedDetailIncidentMuteByFlapping", - "i_m_reply": "#/components/schemas/FeedDetailIncidentMuteReply", - "i_merge": "#/components/schemas/FeedDetailIncidentMerge", - "i_new": "#/components/schemas/FeedDetailIncidentNew", - "i_notify": "#/components/schemas/FeedDetailIncidentNotify", - "i_r_desc": "#/components/schemas/FeedDetailIncidentResetDescription", - "i_r_field": "#/components/schemas/FeedDetailIncidentResetField", - "i_r_impact": "#/components/schemas/FeedDetailIncidentResetImpact", - "i_r_rc": "#/components/schemas/FeedDetailIncidentResetRootCause", - "i_r_rsltn": "#/components/schemas/FeedDetailIncidentResetResolution", - "i_r_severity": "#/components/schemas/FeedDetailIncidentResetSeverity", - "i_r_title": "#/components/schemas/FeedDetailIncidentResetTitle", - "i_reopen": "#/components/schemas/FeedDetailIncidentReopen", - "i_rslv": "#/components/schemas/FeedDetailIncidentResolve", - "i_snooze": "#/components/schemas/FeedDetailIncidentSnooze", - "i_storm": "#/components/schemas/FeedDetailIncidentStorm", - "i_unack": "#/components/schemas/FeedDetailIncidentUnack", - "i_wake": "#/components/schemas/FeedDetailIncidentWake", - "i_wi_assignees": "#/components/schemas/FeedDetailWorkItemAssigneesChanged", - "i_wi_bound": "#/components/schemas/FeedDetailWorkItemBound", - "i_wi_completed": "#/components/schemas/FeedDetailWorkItemCompleted", - "i_wi_converted": "#/components/schemas/FeedDetailWorkItemConverted", - "i_wi_created": "#/components/schemas/FeedDetailWorkItemCreated", - "i_wi_deleted": "#/components/schemas/FeedDetailWorkItemDeleted", - "i_wi_updated": "#/components/schemas/FeedDetailWorkItemUpdated", - "i_wr_create": "#/components/schemas/FeedDetailIncidentWarRoomCreate", - "i_wr_delete": "#/components/schemas/FeedDetailIncidentWarRoomDelete" - }, - "propertyName": "type" - }, "oneOf": [ { "$ref": "#/components/schemas/FeedDetailIncidentNew" @@ -11690,36 +11779,118 @@ }, { "$ref": "#/components/schemas/FeedDetailAlertMerge" + }, + { + "type": "object", + "title": "i_wi_auto_converted", + "description": "Detail payload for `i_wi_auto_converted`.", + "properties": { + "count": { + "type": "integer", + "description": "Number of action items converted to follow-ups." + }, + "work_item_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "IDs of the converted work items." + }, + "titles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Titles of the converted work items, in the same order as `work_item_ids`." + }, + "post_mortem_id": { + "type": "string", + "description": "ID of the post-mortem the follow-ups are bound to; empty when the incident has no post-mortem." + } + } } - ] + ], + "discriminator": { + "propertyName": "type", + "mapping": { + "i_new": "#/components/schemas/FeedDetailIncidentNew", + "i_assign": "#/components/schemas/FeedDetailIncidentAssign", + "i_a_rspd": "#/components/schemas/FeedDetailIncidentAddRspd", + "i_notify": "#/components/schemas/FeedDetailIncidentNotify", + "i_storm": "#/components/schemas/FeedDetailIncidentStorm", + "i_snooze": "#/components/schemas/FeedDetailIncidentSnooze", + "i_wake": "#/components/schemas/FeedDetailIncidentWake", + "i_ack": "#/components/schemas/FeedDetailIncidentAck", + "i_unack": "#/components/schemas/FeedDetailIncidentUnack", + "i_comm": "#/components/schemas/FeedDetailIncidentComment", + "i_rslv": "#/components/schemas/FeedDetailIncidentResolve", + "i_reopen": "#/components/schemas/FeedDetailIncidentReopen", + "i_merge": "#/components/schemas/FeedDetailIncidentMerge", + "i_r_title": "#/components/schemas/FeedDetailIncidentResetTitle", + "i_r_desc": "#/components/schemas/FeedDetailIncidentResetDescription", + "i_r_impact": "#/components/schemas/FeedDetailIncidentResetImpact", + "i_r_rc": "#/components/schemas/FeedDetailIncidentResetRootCause", + "i_r_rsltn": "#/components/schemas/FeedDetailIncidentResetResolution", + "i_r_severity": "#/components/schemas/FeedDetailIncidentResetSeverity", + "i_r_field": "#/components/schemas/FeedDetailIncidentResetField", + "i_m_flapping": "#/components/schemas/FeedDetailIncidentMuteByFlapping", + "i_m_reply": "#/components/schemas/FeedDetailIncidentMuteReply", + "i_custom": "#/components/schemas/FeedDetailIncidentCustomAction", + "i_wr_create": "#/components/schemas/FeedDetailIncidentWarRoomCreate", + "i_wr_delete": "#/components/schemas/FeedDetailIncidentWarRoomDelete", + "i_auto_refresh": "#/components/schemas/FeedDetailIncidentAutoRefreshCard", + "i_wi_created": "#/components/schemas/FeedDetailWorkItemCreated", + "i_wi_updated": "#/components/schemas/FeedDetailWorkItemUpdated", + "i_wi_assignees": "#/components/schemas/FeedDetailWorkItemAssigneesChanged", + "i_wi_completed": "#/components/schemas/FeedDetailWorkItemCompleted", + "i_wi_converted": "#/components/schemas/FeedDetailWorkItemConverted", + "i_wi_bound": "#/components/schemas/FeedDetailWorkItemBound", + "i_wi_deleted": "#/components/schemas/FeedDetailWorkItemDeleted", + "a_merge": "#/components/schemas/FeedDetailAlertMerge" + } + } }, - "ref_id": { - "description": "ObjectID of the source alert or incident this entry references.", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "account_id": { + "type": "integer", + "format": "int64", + "description": "ID of the account that owns this record; the same for every record returned to one `app_key`." }, - "type": { - "$ref": "#/components/schemas/IncidentFeedType" + "creator_id": { + "type": "integer", + "format": "int64", + "description": "User ID of the actor. `0` means system-generated." + }, + "deleted_at": { + "type": "integer", + "format": "int64", + "description": "Soft-delete timestamp in milliseconds. Zero if not deleted." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation timestamp in milliseconds." }, "updated_at": { - "description": "Last update timestamp in milliseconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update timestamp in milliseconds." + }, + "via": { + "type": "string", + "enum": [ + "ai_sre" + ], + "description": "`ai_sre` when AI SRE performed the action on behalf of `creator_id`; omitted for direct actions." + }, + "agent_session_id": { + "type": "string", + "description": "ID of the AI SRE session that performed the action; present only when `via` is `ai_sre` and a session was recorded." } - }, - "required": [ - "ref_id", - "type", - "detail", - "account_id", - "creator_id", - "created_at", - "updated_at" - ], - "type": "object" + } }, "IncidentFeedType": { - "description": "Incident timeline entry type. Each value identifies one lifecycle event; the matching `detail` payload shape is determined by this field. Incident types are prefixed with `i_`.\n\n| Type | Meaning |\n|---|---|\n| `i_new` | Incident Created: A new incident was created automatically or manually. |\n| `i_assign` | Assigned: Incident was assigned to responders. |\n| `i_a_rspd` | Responder Added: Additional responders joined the incident. |\n| `i_notify` | Notification dispatched through a channel at a specific escalation level. |\n| `i_storm` | Alert storm threshold reached on the incident. |\n| `i_snooze` | Notifications snoozed for a given duration. |\n| `i_wake` | Snooze cancelled and notifications resumed. |\n| `i_ack` | Acknowledged: Responder confirmed they are working on the incident. |\n| `i_unack` | Acknowledgement removed. |\n| `i_comm` | Comment: Responder logged progress or key information. |\n| `i_rslv` | Resolved: Incident was marked as resolved. |\n| `i_reopen` | Reopened: Resolved incident was reopened, possibly due to recurrence. |\n| `i_merge` | Merged: Multiple related incidents were merged into one. |\n| `i_r_title` | Title updated. |\n| `i_r_desc` | Description updated. |\n| `i_r_impact` | Impact updated. |\n| `i_r_rc` | Root cause updated. |\n| `i_r_rsltn` | Resolution updated. |\n| `i_r_severity` | Severity Changed: Incident severity level was adjusted. |\n| `i_r_field` | Custom field value updated. |\n| `i_m_flapping` | Incident muted by flapping detection. |\n| `i_m_reply` | Mute reply marker on a comment. |\n| `i_custom` | Action: Automated action or script was triggered. |\n| `i_wr_create` | War Room Created: Chat group was created for collaborative response. |\n| `i_wr_delete` | War room chat group deleted. |\n| `i_auto_refresh` | Card auto-refresh event posted back to the timeline. |\n| `i_wi_created` | Work Item Created: An Action or Follow-up was created. |\n| `i_wi_updated` | Work Item Updated: Title, description, status, or priority was changed. |\n| `i_wi_assignees` | Work Item Assignees Changed: Assignees were updated. |\n| `i_wi_completed` | Work Item Completed: An assignee marked the work item complete. |\n| `i_wi_converted` | Work Item Converted: An Action was converted to a Follow-up. |\n| `i_wi_bound` | Work Item Bound: A converted Follow-up was bound to a post-mortem. |\n| `i_wi_deleted` | Work Item Deleted: An Action or Follow-up was soft-deleted. |\n| `a_merge` | Alert Merged: An alert was merged into an existing incident. |", + "type": "string", + "description": "Incident timeline entry type. Each value identifies one lifecycle event; the matching `detail` payload shape is determined by this field. Incident types are prefixed with `i_`.\n\n| Type | Meaning |\n|---|---|\n| `i_new` | Incident Created: A new incident was created automatically or manually. |\n| `i_assign` | Assigned: Incident was assigned to responders. |\n| `i_a_rspd` | Responder Added: Additional responders joined the incident. |\n| `i_notify` | Notification dispatched through a channel at a specific escalation level. |\n| `i_storm` | Alert storm threshold reached on the incident. |\n| `i_snooze` | Notifications snoozed for a given duration. |\n| `i_wake` | Snooze cancelled and notifications resumed. |\n| `i_ack` | Acknowledged: Responder confirmed they are working on the incident. |\n| `i_unack` | Acknowledgement removed. |\n| `i_comm` | Comment: Responder logged progress or key information. |\n| `i_rslv` | Resolved: Incident was marked as resolved. |\n| `i_reopen` | Reopened: Resolved incident was reopened, possibly due to recurrence. |\n| `i_merge` | Merged: Multiple related incidents were merged into one. |\n| `i_r_title` | Title updated. |\n| `i_r_desc` | Description updated. |\n| `i_r_impact` | Impact updated. |\n| `i_r_rc` | Root cause updated. |\n| `i_r_rsltn` | Resolution updated. |\n| `i_r_severity` | Severity Changed: Incident severity level was adjusted. |\n| `i_r_field` | Custom field value updated. |\n| `i_m_flapping` | Incident muted by flapping detection. |\n| `i_m_reply` | Mute reply marker on a comment. |\n| `i_custom` | Action: Automated action or script was triggered. |\n| `i_wr_create` | War Room Created: Chat group was created for collaborative response. |\n| `i_wr_delete` | War room chat group deleted. |\n| `i_auto_refresh` | Card auto-refresh event posted back to the timeline. |\n| `i_wi_created` | Work Item Created: An Action or Follow-up was created. |\n| `i_wi_updated` | Work Item Updated: Title, description, status, or priority was changed. |\n| `i_wi_assignees` | Work Item Assignees Changed: Assignees were updated. |\n| `i_wi_completed` | Work Item Completed: An assignee marked the work item complete. |\n| `i_wi_converted` | Work Item Converted: An Action was converted to a Follow-up. |\n| `i_wi_bound` | Work Item Bound: A converted Follow-up was bound to a post-mortem. |\n| `i_wi_deleted` | Work Item Deleted: An Action or Follow-up was soft-deleted. |\n| `i_wi_auto_converted` | Work Items Auto-converted: Closing the incident converted its unfinished action items to follow-ups. |\n| `a_merge` | Alert Merged: An alert was merged into an existing incident. |", "enum": [ "i_new", "i_assign", @@ -11754,399 +11925,436 @@ "i_wi_converted", "i_wi_bound", "i_wi_deleted", + "i_wi_auto_converted", "a_merge" - ], - "type": "string" + ] }, "IncidentInfo": { + "type": "object", "description": "Detailed incident record.", + "required": [ + "incident_id", + "account_id", + "channel_id", + "team_id", + "integration_id", + "integration_ids", + "integration_types", + "dedup_key", + "equals_md5", + "start_time", + "end_time", + "last_time", + "ack_time", + "close_time", + "creator_id", + "closer_id", + "owner_id", + "incident_status", + "incident_severity", + "progress", + "title", + "description", + "ai_summary", + "impact", + "root_cause", + "resolution", + "num", + "created_at", + "updated_at", + "snoozed_before", + "group_method", + "ever_muted", + "labels", + "fields", + "assigned_to", + "alert_cnt", + "active_alert_cnt", + "alert_event_cnt", + "responders", + "account_name", + "account_locale", + "account_time_zone", + "channel_name", + "channel_status", + "detail_url", + "silence_url", + "post_mortem_id", + "images", + "manual_overrides", + "has_unfinished_work_item" + ], "properties": { - "account_id": { - "description": "Account ID that owns the incident.", - "format": "int64", - "type": "integer" - }, - "account_locale": { - "description": "Account locale.", - "type": "string" - }, - "account_name": { - "description": "Account name.", - "type": "string" - }, - "account_time_zone": { - "description": "Account time zone.", - "type": "string" + "incident_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Incident ID (MongoDB ObjectID)." }, - "ack_time": { - "description": "Unix timestamp (seconds) when the incident was first acknowledged. 0 if unacknowledged.", + "account_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Account ID that owns the incident." }, - "active_alert_cnt": { - "description": "Count of alerts currently in Critical/Warning/Info state.", + "channel_id": { + "type": "integer", "format": "int64", - "type": "integer" - }, - "ai_summary": { - "description": "AI-generated summary of the incident.", - "type": "string" + "description": "Channel ID. 0 for standalone incidents." }, - "alert_cnt": { - "description": "Total count of alerts merged into this incident.", + "team_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the team that owns the incident's channel. 0 when the channel has no team." }, - "alert_event_cnt": { - "description": "Total raw alert event count across all merged alerts.", + "integration_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "First integration associated with the incident." }, - "alerts": { - "description": "Embedded alerts, only populated for notification templates and custom actions.", + "integration_ids": { + "type": [ + "array", + "null" + ], "items": { - "$ref": "#/components/schemas/AlertInfo" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "IDs of all integrations contributing alerts to this incident; `null` for incidents without integrations, such as manually created ones." }, - "assigned_to": { - "$ref": "#/components/schemas/AssignedTo", - "description": "Current assignment target for the incident." - }, - "channel_id": { - "description": "Channel ID. 0 for standalone incidents.", - "format": "int64", - "type": "integer" + "integration_types": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Plugin types of all contributing integrations (see `integration_type`); `null` when there are none." }, - "channel_name": { - "description": "Channel display name.", - "type": "string" + "dedup_key": { + "type": "string", + "description": "Deduplication key used to coalesce alerts." }, - "channel_status": { - "description": "Channel status.", - "type": "string" + "equals_md5": { + "type": "string", + "description": "MD5 hash used for content-equality checks." }, - "close_time": { - "description": "Unix timestamp (seconds) when the incident was closed. 0 if still open.", + "start_time": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp (seconds) when the incident started." }, - "closer": { - "$ref": "#/components/schemas/PersonShort", - "description": "Closer member info." + "end_time": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp (seconds) when the incident ended. 0 if still active." }, - "closer_id": { - "description": "Member ID that closed the incident. 0 if auto-closed.", + "last_time": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp (seconds) of the most recent update." }, - "created_at": { - "description": "Creation timestamp (seconds).", + "ack_time": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp (seconds) when the incident was first acknowledged. 0 if unacknowledged." }, - "creator": { - "$ref": "#/components/schemas/PersonShort", - "description": "Creator member info." + "close_time": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp (seconds) when the incident was closed. 0 if still open." }, "creator_id": { - "description": "Member ID that created the incident. 0 if auto-created by the system.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Member ID that created the incident. 0 if auto-created by the system." }, - "data_source_id": { - "deprecated": true, - "description": "Deprecated. Use `integration_id` instead.", + "closer_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Member ID that closed the incident. 0 if auto-closed." }, - "data_source_ids": { - "deprecated": true, - "description": "Deprecated. Use `integration_ids` instead.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "owner_id": { + "type": "integer", + "format": "int64", + "description": "Primary owner member ID. 0 if none." }, - "data_source_type": { - "deprecated": true, - "description": "Deprecated. Use `integration_type` instead.", - "type": "string" + "incident_status": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ], + "description": "Current incident status, derived from alert statuses." }, - "data_source_types": { - "deprecated": true, - "description": "Deprecated. Use `integration_types` instead.", - "items": { - "type": "string" - }, - "type": "array" + "incident_severity": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ], + "description": "Configured incident severity." }, - "dedup_key": { - "description": "Deduplication key used to coalesce alerts.", - "type": "string" + "progress": { + "type": "string", + "enum": [ + "Triggered", + "Processing", + "Closed" + ], + "description": "Incident progress. `Triggered` means fired and unacknowledged; `Processing` means acknowledged and being handled (un-acknowledging moves it back to `Triggered`); `Closed` means resolved." }, - "deleted_at": { - "description": "Soft-delete timestamp (seconds). Zero if not deleted.", - "format": "int64", - "type": "integer" + "title": { + "type": "string", + "description": "Incident title." }, "description": { - "description": "Incident description.", - "type": "string" + "type": "string", + "description": "Incident description." }, - "detail_url": { - "description": "Web console URL for the incident.", - "type": "string" + "ai_summary": { + "type": "string", + "description": "AI-generated summary of the incident." }, - "end_time": { - "description": "Unix timestamp (seconds) when the incident ended. 0 if still active.", - "format": "int64", - "type": "integer" + "impact": { + "type": "string", + "description": "Impact description." }, - "equals_md5": { - "description": "MD5 hash used for content-equality checks.", - "type": "string" + "root_cause": { + "type": "string", + "description": "Root cause analysis." }, - "ever_muted": { - "description": "Whether the incident has ever been silenced.", - "type": "boolean" + "resolution": { + "type": "string", + "description": "Resolution notes." }, - "fields": { - "additionalProperties": true, - "description": "Custom field values keyed by field name.", - "type": "object" + "num": { + "type": "string", + "description": "Short display identifier; not guaranteed unique." }, "frequency": { + "type": "string", "description": "Frequency bucket for recurrence analysis: `frequent` or `rare`.", "enum": [ "frequent", "rare" - ], - "type": "string" + ] + }, + "deleted_at": { + "type": "integer", + "format": "int64", + "description": "Soft-delete timestamp (seconds). Zero if not deleted." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation timestamp (seconds)." + }, + "updated_at": { + "type": "integer", + "format": "int64", + "description": "Last update timestamp (seconds)." + }, + "snoozed_before": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp (seconds) until which notifications are snoozed. 0 if not snoozed." }, "group_method": { + "type": "string", "description": "Alert grouping method: `i` intelligent, `p` pattern, `n` none.", "enum": [ "i", "p", "n" - ], - "type": "string" - }, - "images": { - "description": "Attached images.", - "items": { - "$ref": "#/components/schemas/Image" - }, - "type": "array" + ] }, - "impact": { - "description": "Impact description.", - "type": "string" + "ever_muted": { + "type": "boolean", + "description": "Whether the incident has ever been silenced." }, - "incident_id": { - "description": "Incident ID (MongoDB ObjectID).", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "has_unfinished_work_item": { + "type": "boolean", + "description": "`true` when the incident still has at least one action item or follow-up that is neither `done` nor `cancelled`." }, - "incident_severity": { - "description": "Configured incident severity.", - "enum": [ - "Critical", - "Warning", - "Info", - "Ok" + "labels": { + "type": [ + "object", + "null" ], - "type": "string" + "additionalProperties": { + "type": "string" + }, + "description": "Labels propagated from alerts." }, - "incident_status": { - "description": "Current incident status, derived from alert statuses.", - "enum": [ - "Critical", - "Warning", - "Info", - "Ok" - ], - "type": "string" + "fields": { + "type": "object", + "additionalProperties": true, + "description": "Custom field values keyed by field name." }, - "integration_id": { - "description": "First integration associated with the incident.", + "assigned_to": { + "$ref": "#/components/schemas/AssignedTo", + "description": "Current assignment target. Always present; for an incident that was never assigned, `type` and `id` are empty and `assigned_at` is `0`." + }, + "reporter_email": { + "type": "string", + "description": "Reporter email for manually created incidents." + }, + "alert_cnt": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Total count of alerts merged into this incident." }, - "integration_ids": { - "description": "All integration IDs contributing alerts to this incident.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "active_alert_cnt": { + "type": "integer", + "format": "int64", + "description": "Count of alerts currently in Critical/Warning/Info state." }, - "integration_type": { - "description": "First alert's integration type string, used by the detail page for label mappings.", - "type": "string" + "alert_event_cnt": { + "type": "integer", + "format": "int64", + "description": "Total raw alert event count across all merged alerts." }, - "integration_types": { - "description": "Integration type strings for all contributing integrations.", + "alerts": { + "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/AlertInfo" }, - "type": "array" + "description": "Not returned by the incident endpoints; present only in notification template and custom action payloads." }, - "labels": { - "additionalProperties": { - "type": "string" - }, - "description": "Labels propagated from alerts.", - "type": "object" + "closer": { + "$ref": "#/components/schemas/PersonShort", + "description": "Closer member info." }, - "last_time": { - "description": "Unix timestamp (seconds) of the most recent update.", - "format": "int64", - "type": "integer" + "creator": { + "$ref": "#/components/schemas/PersonShort", + "description": "Creator member info." }, - "links": { - "description": "Channel-level link integrations rendered for this incident.", - "items": { - "$ref": "#/components/schemas/LinkItem" - }, - "type": "array" + "owner": { + "$ref": "#/components/schemas/PersonShort", + "description": "Owner member info. May be deprecated.", + "deprecated": true }, - "manual_overrides": { - "description": "Fields that were manually overridden after auto-population.", + "responders": { + "type": "array", "items": { - "type": "string" + "$ref": "#/components/schemas/Responder" }, - "type": "array" + "description": "Current responders with assignment/acknowledgement state." }, - "num": { - "description": "Short display identifier; not guaranteed unique.", - "type": "string" + "account_name": { + "type": "string", + "description": "Always an empty string in API responses; filled only when the incident is rendered for notifications." }, - "owner": { - "$ref": "#/components/schemas/PersonShort", - "deprecated": true, - "description": "Owner member info. May be deprecated." + "account_locale": { + "type": "string", + "description": "Always an empty string in API responses; filled only when the incident is rendered for notifications." }, - "owner_id": { - "description": "Primary owner member ID. 0 if none.", - "format": "int64", - "type": "integer" + "account_time_zone": { + "type": "string", + "description": "Always an empty string in API responses; filled only when the incident is rendered for notifications." }, - "post_mortem_id": { - "description": "Associated post-mortem ID, if any. One incident can only link to a single post-mortem.", - "type": "string" + "channel_name": { + "type": "string", + "description": "Channel display name." }, - "progress": { - "description": "Incident progress. `Triggered` means fired and unacknowledged; `Processing` means acknowledged and being handled (un-acknowledging moves it back to `Triggered`); `Closed` means resolved.", + "channel_status": { + "type": "string", + "description": "Status of the channel: `enabled`, `disabled`, or `deleted`. Empty string when the record has no channel or the channel no longer exists.", "enum": [ - "Triggered", - "Processing", - "Closed" - ], - "type": "string" + "enabled", + "disabled", + "deleted", + "" + ] }, - "reporter_email": { - "description": "Reporter email for manually created incidents.", - "type": "string" + "detail_url": { + "type": "string", + "description": "Web console URL for the incident." }, - "resolution": { - "description": "Resolution notes.", - "type": "string" + "silence_url": { + "type": "string", + "description": "Quick-silence URL for this incident." }, - "responders": { - "description": "Current responders with assignment/acknowledgement state.", + "links": { + "type": "array", "items": { - "$ref": "#/components/schemas/Responder" + "$ref": "#/components/schemas/LinkItem" }, - "type": "array" + "description": "Channel-level link integrations rendered for this incident." }, - "root_cause": { - "description": "Root cause analysis.", - "type": "string" + "integration_type": { + "type": "string", + "description": "Plugin type of the incident's first integration (see `integration_types` for all). Open set, for example `prometheus.alert` or `monit.alert`; `POST /integration/type/list` returns the full list. Omitted when the incident has no integration or the endpoint does not fill it." }, - "silence_url": { - "description": "Quick-silence URL for this incident.", - "type": "string" + "post_mortem_id": { + "type": "string", + "description": "Associated post-mortem ID, if any. One incident can only link to a single post-mortem." }, - "snoozed_before": { - "description": "Unix timestamp (seconds) until which notifications are snoozed. 0 if not snoozed.", - "format": "int64", - "type": "integer" + "images": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/Image" + }, + "description": "Images attached to the incident; `null` when there are none. Tokens starting with `img_` are returned as download URLs." }, - "start_time": { - "description": "Unix timestamp (seconds) when the incident started.", - "format": "int64", - "type": "integer" + "manual_overrides": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string", + "enum": [ + "title", + "description", + "incident_severity" + ] + }, + "description": "Fields edited manually and therefore no longer overwritten by merged alerts: `title`, `description`, `incident_severity`. `null` when none." }, - "team_id": { - "description": "ID of the team that owns the incident's channel. 0 when the channel has no team.", + "data_source_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Deprecated. Use `integration_id` instead.", + "deprecated": true }, - "title": { - "description": "Incident title.", - "type": "string" + "data_source_ids": { + "type": [ + "array", + "null" + ], + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Deprecated. Use `integration_ids` instead.", + "deprecated": true }, - "updated_at": { - "description": "Last update timestamp (seconds).", - "format": "int64", - "type": "integer" + "data_source_type": { + "type": "string", + "description": "Deprecated; same value as `integration_type`.", + "deprecated": true + }, + "data_source_types": { + "type": [ + "array", + "null" + ], + "items": { + "type": "string" + }, + "description": "Deprecated. Use `integration_types` instead.", + "deprecated": true } - }, - "required": [ - "incident_id", - "account_id", - "channel_id", - "team_id", - "integration_id", - "integration_ids", - "integration_types", - "dedup_key", - "equals_md5", - "start_time", - "end_time", - "last_time", - "ack_time", - "close_time", - "creator_id", - "closer_id", - "owner_id", - "incident_status", - "incident_severity", - "progress", - "title", - "description", - "ai_summary", - "impact", - "root_cause", - "resolution", - "num", - "created_at", - "updated_at", - "snoozed_before", - "group_method", - "ever_muted", - "labels", - "fields", - "assigned_to", - "alert_cnt", - "active_alert_cnt", - "alert_event_cnt", - "responders", - "account_name", - "account_locale", - "account_time_zone", - "channel_name", - "channel_status", - "detail_url", - "silence_url", - "post_mortem_id", - "images", - "manual_overrides" - ], - "type": "object" + } }, "IncidentInfoRequest": { "description": "Lookup parameters for a single incident. Supply either incident_id or num.", @@ -12164,35 +12372,35 @@ "type": "object" }, "IncidentListResponse": { + "type": "object", "description": "Paginated list of incidents.", + "required": [ + "items", + "total", + "has_next_page" + ], "properties": { - "has_next_page": { - "description": "True when more results are available beyond this page.", - "type": "boolean" - }, "items": { - "description": "Incident list for the current page.", + "type": "array", "items": { "$ref": "#/components/schemas/IncidentInfo" }, - "type": "array" - }, - "search_after_ctx": { - "description": "Opaque cursor to pass as `search_after_ctx` on the next request.", - "type": "string" + "description": "Incident list for the current page." }, "total": { - "description": "Total number of matching incidents.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Number of matching incidents, capped at 1,000. For `POST /incident/list-by-ids`, the number of incidents found." + }, + "has_next_page": { + "type": "boolean", + "description": "Whether another page exists. Reflects the real data with both `p`/`limit` and `search_after_ctx` paging, including past the 1,000 cap of `total`. Always `false` for `POST /incident/list-by-ids`." + }, + "search_after_ctx": { + "type": "string", + "description": "Cursor pointing at the last item of this page; pass it as `search_after_ctx` on the next request to continue past the 1,000-item page limit. Returned for every non-empty page in `p`/`limit` mode, and in cursor mode only when `has_next_page` is `true`. Omitted by `POST /incident/list-by-ids`." } - }, - "required": [ - "items", - "total", - "has_next_page" - ], - "type": "object" + } }, "IncidentRawItem": { "description": "Raw incident row returned by the analytics incident list, with per-incident handling metrics attached.", @@ -12485,135 +12693,141 @@ "type": "object" }, "IncidentShort": { + "type": "object", "description": "Brief incident reference embedded in an alert.", "properties": { "incident_id": { - "description": "Incident ID (ObjectID hex string).", - "type": "string" - }, - "progress": { - "description": "Incident progress — one of `Triggered`, `Processing`, `Closed`.", - "type": "string" + "type": "string", + "description": "Incident ID (ObjectID hex string)." }, "title": { - "description": "Incident title.", - "type": "string" + "type": "string", + "description": "Incident title." + }, + "progress": { + "type": "string", + "description": "Incident progress: `Triggered` not yet acknowledged; `Processing` acknowledged and being handled; `Closed` resolved.", + "enum": [ + "Triggered", + "Processing", + "Closed" + ] } - }, - "type": "object" + } }, "InhibitRuleItem": { + "type": "object", + "required": [ + "account_id", + "channel_id", + "rule_name", + "description", + "source_filters", + "target_filters", + "equals", + "is_directly_discard", + "status", + "rule_id", + "updated_by", + "created_at", + "updated_at" + ], "properties": { "account_id": { - "description": "ID of the account the rule belongs to.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the account the rule belongs to." }, "channel_id": { - "description": "ID of the channel the rule belongs to.", - "format": "int64", - "type": "integer" - }, - "created_at": { - "description": "Creation time, Unix timestamp in seconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the channel the rule belongs to." }, - "deleted_at": { - "description": "Deletion time, Unix timestamp in seconds. Omitted unless the rule is soft-deleted; deleted rules are excluded from list responses.", - "format": "int64", - "type": "integer" + "rule_name": { + "type": "string", + "description": "Inhibit rule name, 1–39 characters." }, "description": { - "description": "Rule description.", - "type": "string" + "type": "string", + "description": "Rule description." + }, + "source_filters": { + "$ref": "#/components/schemas/FilterGroup", + "description": "Conditions the source alert must match, evaluated against stored active alerts. Supported keys: `status`, `incident_status`, `alert_status`, `severity`, `incident_severity`, `alert_severity`, `title`, `description`, or any `labels.`. Empty makes the rule inert." + }, + "target_filters": { + "$ref": "#/components/schemas/FilterGroup", + "description": "Conditions the incoming target alert event must match to be inhibited; empty means every incoming event is a target. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`." }, "equals": { - "description": "Field keys whose values must be equal between the source (inhibiting) alert and the target (suppressed) alert, e.g. `data_source_id` or `labels.cluster`.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Keys whose values must be equal on the source alert and the incoming event. Only `title`, `severity` and `labels.` take effect; with any other key the rule never fires." }, "is_directly_discard": { - "description": "When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule.", - "type": "boolean" + "type": "boolean", + "description": "When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule." + }, + "status": { + "type": "string", + "enum": [ + "enabled", + "disabled" + ], + "description": "Rule status: `enabled` or `disabled`; deleted rules never appear in the list." }, "rule_id": { - "description": "Rule ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" - }, - "rule_name": { - "description": "Rule name.", - "type": "string" - }, - "source_filters": { - "$ref": "#/components/schemas/FilterGroup", - "description": "Conditions the source alert must match, evaluated against stored active alerts. Supported keys: `status`, `incident_status`, `alert_status`, `severity`, `incident_severity`, `alert_severity`, `title`, `description`, or any `labels.`. Empty makes the rule inert." + "description": "Rule ID (MongoDB ObjectID)." }, - "status": { - "description": "Rule status: `enabled` or `disabled`; deleted rules never appear in the list.", - "enum": [ - "enabled", - "disabled" - ], - "type": "string" + "updated_by": { + "type": "integer", + "format": "int64", + "description": "ID of the user who last updated the rule." }, - "target_filters": { - "$ref": "#/components/schemas/FilterGroup", - "description": "Conditions the incoming target alert event must match to be suppressed; empty means every event is a target." + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation time, Unix timestamp in seconds." }, "updated_at": { - "description": "Last update time, Unix timestamp in seconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update time, Unix timestamp in seconds." }, - "updated_by": { - "description": "ID of the user who last updated the rule.", + "deleted_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Deletion time, Unix timestamp in seconds. Omitted unless the rule is soft-deleted; deleted rules are excluded from list responses." } - }, - "required": [ - "account_id", - "channel_id", - "rule_name", - "description", - "source_filters", - "target_filters", - "equals", - "is_directly_discard", - "status", - "rule_id", - "updated_by", - "created_at", - "updated_at" - ], - "type": "object" + } }, "InitPostMortemRequest": { + "type": "object", "description": "Parameters for initializing a post-mortem report from incidents.", + "required": [ + "incident_ids", + "template_id" + ], "properties": { "incident_ids": { - "description": "Incident IDs to link to the report. 1-10 incidents.", + "type": "array", + "minItems": 1, + "maxItems": 10, "items": { - "type": "string" + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$" }, - "maxItems": 10, - "minItems": 1, - "type": "array" + "description": "Incident IDs (MongoDB ObjectIDs) to link to the report, 1–10. All must exist in the account. The same set always maps to the same report." }, "template_id": { - "description": "Template ID used to initialize the report.", - "type": "string" + "type": "string", + "description": "Template ID from `POST /incident/post-mortem/template/list`, e.g. the built-in `post_mortem_default_tmpl_en-us` or `post_mortem_default_tmpl_zh-cn`, or a custom template ID." } - }, - "required": [ - "incident_ids", - "template_id" - ], - "type": "object" + } }, "InsightAlertByLabelItem": { "properties": { @@ -12656,150 +12870,150 @@ "type": "object" }, "InsightFilter": { + "type": "object", "description": "Shared filter envelope for insight and export endpoints. Severities accept up to 3 values; team/channel/responder/incident filters accept up to 100 IDs each. The time range cannot exceed one year.", + "required": [ + "start_time", + "end_time" + ], "properties": { - "asc": { - "description": "Sort ascending when `true`, descending otherwise. Only used by `/insight/incident/list`.", - "type": "boolean" + "start_time": { + "type": "integer", + "format": "int64", + "description": "Start time, Unix seconds. Must be greater than 0.", + "exclusiveMinimum": 0 }, - "channel_ids": { - "description": "Filter by channel IDs. At most 100 entries.", + "end_time": { + "type": "integer", + "format": "int64", + "description": "End time, Unix seconds. Must be greater than `start_time`." + }, + "team_ids": { + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "maxItems": 100, - "type": "array" - }, - "description_html_to_text": { - "description": "Strip HTML markup from the description column when exporting.", - "type": "boolean" + "description": "Filter by team IDs. At most 100 entries.", + "maxItems": 100 }, - "end_time": { - "description": "End time, Unix seconds. Must be greater than `start_time`.", - "format": "int64", - "type": "integer" + "channel_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Filter by channel IDs. At most 100 entries.", + "maxItems": 100 }, - "export_fields": { - "description": "CSV column keys to include in the export, in the given order; unknown or duplicate keys are rejected. The valid key set differs per export endpoint — see each export operation's description. Only used by the export endpoints; at most 50 entries.", + "responder_ids": { + "type": "array", "items": { - "type": "string" + "type": "integer", + "format": "int64" }, - "maxItems": 50, - "type": "array" + "description": "Filter by responder member IDs. Used by `/insight/responder` (which responders to return) and the incident list/export (incidents any of them responded to); ignored by the account/team/channel and top-K endpoints. At most 100 entries.", + "maxItems": 100 }, - "fields": { - "additionalProperties": true, - "description": "Custom-field filters (exact match).", - "type": "object" + "severities": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ] + }, + "description": "Filter by severity: `Critical`, `Warning`, `Info`, or `Ok`. At most 3 entries.", + "maxItems": 3 }, "incident_ids": { - "description": "Filter by incident IDs (MongoDB ObjectIDs). At most 100 entries.", + "type": "array", "items": { - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$" }, - "maxItems": 100, - "type": "array" - }, - "include_ever_muted": { - "description": "Include incidents that have ever been muted. By default, they are excluded.", - "type": "boolean" + "description": "Filter by incident IDs (24-character hex). Used only by the incident list and export. At most 100 entries.", + "maxItems": 100 }, - "is_my_team": { - "description": "Restrict results to teams the caller belongs to. When true and the caller has no teams, the result set is empty.", - "type": "boolean" + "query": { + "type": "string", + "description": "Substring match on the incident title (SQL `LIKE %query%`)." }, "labels": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "Label filters (exact match).", - "type": "object" + "description": "Label filters (exact match)." + }, + "fields": { + "type": "object", + "additionalProperties": true, + "description": "Custom-field filters (exact match)." }, "orderby": { - "description": "Sort field of the incident list; only `created_at` (incident creation time) is supported. Used by `/insight/incident/list` only.", + "type": "string", "enum": [ "created_at" ], - "type": "string" + "description": "Sort field of the incident list; only `created_at` (incident creation time, the default). Used by `/insight/incident/list` and `/insight/incident/export`." }, - "query": { - "description": "Substring match on the incident title (SQL `LIKE %query%`).", - "type": "string" - }, - "responder_ids": { - "description": "Filter by responder person IDs. At most 100 entries.", - "items": { - "format": "int64", - "type": "integer" - }, - "maxItems": 100, - "type": "array" + "asc": { + "type": "boolean", + "description": "Sort ascending when `true`, descending (default) otherwise. Used by the incident list and export; `/insight/alert/topk-by-label` has its own `asc`." }, - "seconds_to_ack_from": { - "description": "Lower bound (inclusive) on time-to-acknowledge, in seconds.", - "format": "int64", - "minimum": 0, - "type": "integer" + "is_my_team": { + "type": "boolean", + "description": "Restrict results to the caller's teams (intersected with `team_ids` when both are set). When that intersection is empty, or the caller belongs to no team, the result is empty." }, - "seconds_to_ack_to": { - "description": "Upper bound (exclusive) on time-to-acknowledge, in seconds. Must be greater than `seconds_to_ack_from` when both are set.", - "format": "int64", - "minimum": 0, - "type": "integer" + "time_zone": { + "type": "string", + "description": "IANA time zone (for example `Asia/Shanghai` or `UTC`) used to cut `aggregate_unit` buckets; abbreviations such as `EST` and `Etc/GMT±N` are rejected. Defaults to UTC. `/insight/incident/export` uses it to render times, falling back to the account time zone and then `Asia/Shanghai`." }, "seconds_to_close_from": { - "description": "Lower bound (inclusive) on time-to-close, in seconds.", + "type": "integer", "format": "int64", - "minimum": 0, - "type": "integer" + "description": "Lower bound (inclusive) on time-to-close, in seconds.", + "minimum": 0 }, "seconds_to_close_to": { - "description": "Upper bound (exclusive) on time-to-close, in seconds. Must be greater than `seconds_to_close_from` when both are set.", + "type": "integer", "format": "int64", - "minimum": 0, - "type": "integer" + "description": "Upper bound (exclusive) on time-to-close, in seconds. Must be greater than `seconds_to_close_from` when both are set.", + "minimum": 0 }, - "severities": { - "description": "Filter by severity. At most 3 entries.", - "items": { - "enum": [ - "Critical", - "Warning", - "Info", - "Ok" - ], - "type": "string" - }, - "maxItems": 3, - "type": "array" + "seconds_to_ack_from": { + "type": "integer", + "format": "int64", + "description": "Lower bound (inclusive) on time-to-acknowledge, in seconds.", + "minimum": 0 }, - "start_time": { - "description": "Start time, Unix seconds. Must be greater than 0.", - "exclusiveMinimum": 0, + "seconds_to_ack_to": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Upper bound (exclusive) on time-to-acknowledge, in seconds. Must be greater than `seconds_to_ack_from` when both are set.", + "minimum": 0 }, - "team_ids": { - "description": "Filter by team IDs. At most 100 entries.", + "export_fields": { + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "string" }, - "maxItems": 100, - "type": "array" + "description": "CSV column keys to include in the export, in the given order; unknown or duplicate keys are rejected. The valid key set differs per export endpoint — see each export operation's description. Only used by the export endpoints; at most 50 entries.", + "maxItems": 50 }, - "time_zone": { - "description": "IANA time zone name used to cut day/week/month buckets (e.g. `Asia/Shanghai`). Optional; defaults to UTC, except that `/insight/incident/export` falls back to the account time zone and then `Asia/Shanghai`.", - "type": "string" + "description_html_to_text": { + "type": "boolean", + "description": "Strip HTML markup from the description column when exporting." + }, + "include_ever_muted": { + "type": "boolean", + "description": "Include incidents that have ever been muted. By default, they are excluded." } - }, - "required": [ - "start_time", - "end_time" - ], - "type": "object" + } }, "InsightIncidentExportRequest": { "$ref": "#/components/schemas/InsightFilter" @@ -12844,29 +13058,29 @@ ] }, "InsightIncidentListResponse": { + "type": "object", "properties": { + "total": { + "type": "integer", + "format": "int64", + "description": "Number of matching incidents. When the request carried `search_after_ctx`, only incidents after the cursor are counted." + }, "has_next_page": { - "description": "Whether another page of results is available.", - "type": "boolean" + "type": "boolean", + "description": "Whether another page of results is available." + }, + "search_after_ctx": { + "type": "string", + "description": "Cursor token to fetch the next page — the incident ID of the last row on this page. Present only when `has_next_page` is true." }, "items": { - "description": "Incident items.", + "type": "array", "items": { "$ref": "#/components/schemas/IncidentRawItem" }, - "type": "array" - }, - "search_after_ctx": { - "description": "Cursor token to fetch the next page — the incident ID of the last row on this page. Present only when `has_next_page` is true.", - "type": "string" - }, - "total": { - "description": "Total matching incidents.", - "format": "int64", - "type": "integer" + "description": "Incidents on this page; an empty array when none match." } - }, - "type": "object" + } }, "InsightQueryRequest": { "allOf": [ @@ -12874,23 +13088,23 @@ "$ref": "#/components/schemas/InsightFilter" }, { + "type": "object", "description": "Insight dimension-aggregation request. Extends InsightFilter with aggregation controls.", "properties": { + "split_hours": { + "type": "boolean", + "description": "When `true`, each bucket is further split into `work`, `sleep` and `off` hours, returned as separate rows with `hours` set." + }, "aggregate_unit": { - "description": "Aggregates metrics by time granularity. When set, the time range must be at least 24 hours; with `day` granularity the range must not exceed 31 days. `day` buckets by calendar day, `week` by calendar week, and `month` by calendar month, with boundaries aligned to `time_zone`.", + "type": "string", "enum": [ "day", "week", "month" ], - "type": "string" - }, - "split_hours": { - "description": "When true, metrics are split into `work`/`sleep`/`off` hour buckets.", - "type": "boolean" + "description": "Split the range into time buckets; omit for a single bucket covering the whole range. Requires a range of at least 24 hours, and `day` allows at most 31 days.\n- `day`: calendar days in `time_zone` (the first bucket runs from `start_time` to the next midnight).\n- `week`: consecutive 7-day buckets starting at `start_time` (not aligned to Monday).\n- `month`: calendar months in `time_zone` (the first bucket runs from `start_time` to the 1st of the next month)." } - }, - "type": "object" + } } ] }, @@ -12900,195 +13114,235 @@ "$ref": "#/components/schemas/InsightQueryRequest" }, { + "type": "object", + "required": [ + "label" + ], "properties": { - "asc": { - "description": "Sort ascending when `true`, descending otherwise.", - "type": "boolean" - }, - "k": { - "default": 20, - "description": "Number of top entries to return, between 1 and 100. Defaults to 20.", - "maximum": 100, - "minimum": 1, - "type": "integer" - }, "label": { - "description": "Aggregation dimension. `check` aggregates by the event's `labels.check` label (monitoring check); `resource` aggregates by the `labels.resource` label (monitored resource identifier).", + "type": "string", "enum": [ "check", "resource" ], - "type": "string" + "description": "Aggregation dimension. `check` aggregates by the event's `labels.check` label (monitoring check); `resource` aggregates by the `labels.resource` label (monitored resource identifier)." + }, + "k": { + "type": "integer", + "description": "Number of label values to return, between 1 and 100 (default 20). With `split_hours`, applied per hour bucket.", + "minimum": 1, + "maximum": 100, + "default": 20 }, "orderby": { - "description": "Sort field. `total_alert_cnt` sorts by alert count; `total_alert_event_cnt` sorts by raw alert event count (default).", + "type": "string", "enum": [ "total_alert_cnt", "total_alert_event_cnt" ], - "type": "string" + "description": "Sort field. `total_alert_cnt` sorts by alert count; `total_alert_event_cnt` sorts by raw alert event count (default)." + }, + "asc": { + "type": "boolean", + "description": "Sort ascending when `true`, descending otherwise." } - }, - "required": [ - "label" - ], - "type": "object" + } } ] }, "InviteMemberItem": { + "type": "object", "description": "A member to invite. Identify the invitee by `email` alone, or by `member_name` + `phone` together.", "properties": { - "country_code": { - "description": "ISO 3166-1 alpha-2 region code for `phone` (e.g. \"CN\"). Validated and normalized to upper case before storage; invalid values are rejected with a 400. Also the parsing hint when `phone` has no \"+\" prefix (defaults to \"CN\").", - "type": "string" - }, - "email": { - "description": "Email address. Required when `phone` is not provided.", - "type": "string" - }, - "locale": { - "description": "Locale. One of: `zh-CN` (Simplified Chinese), `en-US` (English); other values are rejected with a 400.", - "enum": [ - "zh-CN", - "en-US" - ], - "type": "string" - }, "member_name": { - "description": "Display name, 2–39 characters. Required when `email` is not provided; derived from the email prefix when omitted.", - "maxLength": 39, + "type": "string", "minLength": 2, - "type": "string" + "maxLength": 39, + "description": "Display name, 2–39 characters. Required when `email` is not provided; derived from the email prefix when omitted." + }, + "email": { + "type": "string", + "description": "Email address, stored in lower case. Required when `phone` is not provided." }, "phone": { - "description": "Phone number. Required when `email` is not provided.", - "type": "string" + "type": "string", + "description": "Phone number. Required when `email` is not provided." }, - "ref_id": { - "description": "External reference ID", - "type": "string" + "country_code": { + "type": "string", + "description": "ISO 3166-1 alpha-2 region code for `phone` (e.g. \"CN\"). Validated and normalized to upper case before storage; invalid values are rejected with a 400. Also the parsing hint when `phone` has no \"+\" prefix (defaults to \"CN\")." }, "role_ids": { - "description": "Role IDs to assign", + "type": "array", "items": { - "format": "uint64", - "type": "integer" + "type": "integer", + "format": "uint64" }, - "type": "array" + "description": "Role IDs to assign: built-in `2` (Admin), `6` (Responder), `8` (Viewer), or custom role IDs from `POST /role/list`. Defaults to Viewer (`8`) when omitted; an ID that does not exist returns `400`." + }, + "locale": { + "type": "string", + "enum": [ + "zh-CN", + "en-US" + ], + "description": "Locale: `zh-CN` (Simplified Chinese) or `en-US` (English); other values are rejected with a 400. Defaults to the account's locale when omitted." }, "time_zone": { - "description": "Time zone", - "type": "string" + "type": "string", + "description": "IANA time zone name such as `Asia/Shanghai`. Omit it to have the member follow the account's time zone; an invalid name returns `400`." + }, + "ref_id": { + "type": "string", + "description": "External reference ID (for example an employee ID in an HR system), usable later as a lookup key in `POST /member/delete` and `POST /member/info/reset`." } - }, - "type": "object" + } }, "KnowledgeFileDeleteRequest": { + "type": "object", "description": "Knowledge file to remove.", "properties": { - "force": { - "description": "Delete even when other knowledge files reference this file; the referrers are then returned as warnings instead of blocking the delete.", - "type": "boolean" - }, "pack_id": { - "description": "Knowledge ID; defaults to the caller's account-scope knowledge.", - "type": "string" + "type": "string", + "description": "Knowledge ID; defaults to the caller's account-scope knowledge." }, "rel_path": { - "description": "Path of the file relative to the knowledge root.", - "type": "string" + "type": "string", + "description": "Path of the file relative to the knowledge root. Same path rules as `POST /safari/knowledge/file/put`." + }, + "force": { + "type": "boolean", + "description": "Delete even when other knowledge files reference this file; the referrers are then returned as warnings instead of blocking the delete." + }, + "expected_version": { + "type": "integer", + "minimum": 0, + "default": 0, + "description": "Optimistic-concurrency guard. `0` or omitted: delete unconditionally. A positive value: delete only if the knowledge's current `version` equals it; otherwise nothing is deleted and the call returns HTTP 200 with `status` = `conflict` and the current `version`." } }, "required": [ "rel_path" - ], - "type": "object" + ] }, "KnowledgeFileDeleteResponse": { - "description": "Deletion result; empty unless warnings were raised.", + "type": "object", + "description": "Delete result.", "properties": { + "status": { + "type": "string", + "enum": [ + "ok", + "conflict" + ], + "description": "Outcome of the delete.\n- `ok`: the file was deleted, or did not exist.\n- `conflict`: `expected_version` did not match the current knowledge version, so nothing was deleted." + }, "warnings": { - "description": "Non-blocking warnings after deletion; `code=still_referenced_by` means the (force-)deleted file is still @ref-referenced by other files in the knowledge (`refs` lists the referrers). Absent when there are no warnings (omitempty).", + "type": "array", "items": { "$ref": "#/components/schemas/KnowledgeWarning" }, - "type": "array" + "description": "Non-blocking warnings; `still_referenced_by` means `force` deleted a file that other files still reference (`refs` lists them). Omitted when there are no warnings." + }, + "version": { + "type": "integer", + "description": "Knowledge `version` after the delete (unchanged if the file did not exist). When the file did not exist and `expected_version` was not sent, this is `0`. On `conflict`, the current version." + }, + "message": { + "type": "string", + "description": "Explanation of the conflict. Present only when `status` is `conflict`." } }, - "type": "object" + "required": [ + "status", + "version" + ] }, "KnowledgeFileGetRequest": { + "type": "object", "description": "Which file to fetch.", "properties": { "pack_id": { - "description": "Knowledge ID; defaults to the caller's account-scope knowledge.", - "type": "string" + "type": "string", + "description": "Knowledge ID; defaults to the caller's account-scope knowledge." }, "rel_path": { - "description": "Path of the file relative to the knowledge root.", - "type": "string" + "type": "string", + "description": "Path of the file relative to the knowledge root. If no file exists at this path, the call still succeeds with `file` set to `null` and an empty `content_b64`." } }, "required": [ "rel_path" - ], - "type": "object" + ] }, "KnowledgeFileGetResponse": { - "description": "File metadata plus its base64-encoded content.", + "type": "object", + "description": "File metadata, its base64-encoded content, and the current knowledge version.", "properties": { + "file": { + "description": "Metadata of the file; `null` when no file exists at `rel_path`.", + "oneOf": [ + { + "$ref": "#/components/schemas/KnowledgeFileItem" + }, + { + "type": "null" + } + ] + }, "content_b64": { - "description": "Base64-encoded file content; decodes to UTF-8 text.", - "type": "string" + "type": "string", + "description": "Base64-encoded file content. Empty string when the file does not exist (or is empty)." }, - "file": { - "$ref": "#/components/schemas/KnowledgeFileItem" + "version": { + "type": "integer", + "description": "Current `version` of the knowledge. Pass it as `expected_version` to `POST /safari/knowledge/file/put` or `POST /safari/knowledge/file/delete` to reject the write if someone else changed the knowledge in between." } }, "required": [ "file", - "content_b64" - ], - "type": "object" + "content_b64", + "version" + ] }, "KnowledgeFileItem": { + "type": "object", "description": "Metadata of one knowledge file. Content is fetched separately via file/get.", "properties": { - "checksum": { - "description": "SHA-256 hex digest of the file content.", - "type": "string" - }, - "content_type": { - "description": "MIME type; inferred from the file extension when not set on upload.", - "type": "string" - }, "file_id": { - "description": "File ID (`kfl_` prefix).", - "type": "string" + "type": "string", + "description": "File ID (`kfl_` prefix)." }, "pack_id": { - "description": "ID of the knowledge that contains the file.", - "type": "string" + "type": "string", + "description": "ID of the knowledge that contains the file." }, "rel_path": { - "description": "Path relative to the knowledge root, e.g. `runbooks/restart.md`.", - "type": "string" + "type": "string", + "description": "Path relative to the knowledge root, using `/` separators, e.g. `runbooks/restart.md`. Unique within the knowledge." + }, + "content_type": { + "type": "string", + "description": "MIME type stored with the file. Open set: when `content_type` is omitted on write it is derived from the extension of `rel_path` — `.md` → `text/markdown`, `.yaml`/`.yml` → `text/yaml`, `.json` → `application/json`, `.sh` → `text/x-sh`, anything else → `text/plain`; a value passed explicitly is stored as given." }, "size_bytes": { + "type": "integer", "description": "File size in bytes.", - "format": "int64", - "type": "integer" + "format": "int64" }, - "updated_at_ms": { - "description": "Unix timestamp in milliseconds when the file was last modified.", - "format": "int64", - "type": "integer" + "checksum": { + "type": "string", + "description": "SHA-256 hex digest of the file content." }, "updated_by": { + "type": "integer", "description": "Person ID of the member who last modified the file.", - "format": "int64", - "type": "integer" + "format": "int64" + }, + "updated_at_ms": { + "type": "integer", + "description": "Unix timestamp in milliseconds when the file was last modified.", + "format": "int64" } }, "required": [ @@ -13100,8 +13354,7 @@ "checksum", "updated_by", "updated_at_ms" - ], - "type": "object" + ] }, "KnowledgeFileListRequest": { "description": "Which knowledge's files to list.", @@ -13122,70 +13375,99 @@ "type": "object" }, "KnowledgeFileListResponse": { - "description": "Files in the knowledge.", + "type": "object", + "description": "All files in the knowledge plus the current knowledge version.", "properties": { "files": { - "description": "Array of files in the specified knowledge; empty array when it has no files.", + "type": "array", "items": { "$ref": "#/components/schemas/KnowledgeFileItem" }, - "type": "array" + "description": "Array of files in the specified knowledge; empty array when it has no files." }, "total": { - "description": "Total number of files in the knowledge.", - "format": "int64", - "type": "integer" + "type": "integer", + "description": "Number of files in `files` — always the full file count of the knowledge, since this endpoint does not paginate.", + "format": "int64" + }, + "version": { + "type": "integer", + "description": "Current `version` of the knowledge; usable as `expected_version` for file writes." } }, "required": [ "files", - "total" - ], - "type": "object" + "total", + "version" + ] }, "KnowledgeFilePutRequest": { + "type": "object", "description": "File to create or overwrite. The body is base64 text in `content_b64`, not a multipart upload.", "properties": { + "pack_id": { + "type": "string", + "description": "Knowledge ID; defaults to the caller's account-scope knowledge." + }, + "rel_path": { + "type": "string", + "description": "Destination path relative to the knowledge root; an existing file at this path is overwritten. Must use `/` separators, must not start with `/`, must already be in normalized form, and no segment may be empty, `.`, `..`, or start with `.` (dotfiles are rejected)." + }, "content_b64": { - "description": "Base64-encoded file content; must decode to valid UTF-8 text (binary is rejected). Per-file limit 1 MiB.", - "type": "string" + "type": "string", + "description": "Base64-encoded (standard alphabet) file content. The decoded bytes must be UTF-8 text with no NUL bytes and at most 1 MiB (`DUTY.md`: at most 32 KiB). Omit or send an empty string to write an empty file." }, "content_type": { - "description": "MIME type; inferred from the file extension when omitted.", - "type": "string" - }, - "pack_id": { - "description": "Knowledge ID; defaults to the caller's account-scope knowledge.", - "type": "string" + "type": "string", + "description": "MIME type to store with the file. Optional: when omitted it is derived from the extension of `rel_path` (`.md` → `text/markdown`, `.yaml`/`.yml` → `text/yaml`, `.json` → `application/json`, `.sh` → `text/x-sh`, otherwise `text/plain`). Any value passed is stored as given." }, - "rel_path": { - "description": "Destination path relative to the knowledge root; existing files are overwritten.", - "type": "string" + "expected_version": { + "type": "integer", + "minimum": 0, + "default": 0, + "description": "Optimistic-concurrency guard. `0` or omitted: write unconditionally. A positive value: write only if the knowledge's current `version` equals it; otherwise nothing is written and the call returns HTTP 200 with `status` = `conflict` and the current `version`." } }, "required": [ "rel_path" - ], - "type": "object" + ] }, "KnowledgeFilePutResponse": { - "description": "The written file plus any non-blocking warnings.", + "type": "object", + "description": "Write result. On success carries the written file; on a version conflict carries only `status`, `version` and `message`.", "properties": { + "status": { + "type": "string", + "enum": [ + "ok", + "conflict" + ], + "description": "Outcome of the write.\n- `ok`: the change was committed.\n- `conflict`: `expected_version` did not match the current knowledge version, so nothing was changed; re-read the file and retry with the returned `version`." + }, "file": { - "$ref": "#/components/schemas/KnowledgeFileItem" + "$ref": "#/components/schemas/KnowledgeFileItem", + "description": "The file as stored after the write. Omitted when `status` is `conflict`." }, "warnings": { - "description": "Non-blocking warnings after a successful write; `code=unresolved_reference` means an @ref in the file content points to a file that does not exist in the knowledge. Absent when there are no warnings (omitempty).", + "type": "array", "items": { "$ref": "#/components/schemas/KnowledgeWarning" }, - "type": "array" + "description": "Non-blocking warnings; `unresolved_reference` means an @ref in the written content points to a path that does not exist in the knowledge. Omitted when there are no warnings." + }, + "version": { + "type": "integer", + "description": "Knowledge `version` produced by this write when `status` is `ok`; the current version when `status` is `conflict`. Use it as `expected_version` for the next write." + }, + "message": { + "type": "string", + "description": "Explanation of the conflict (`this knowledge was updated by someone else`). Present only when `status` is `conflict`." } }, "required": [ - "file" - ], - "type": "object" + "status", + "version" + ] }, "KnowledgeGetRequest": { "description": "No request fields — the account-scope knowledge is always targeted.", @@ -13226,105 +13508,106 @@ "type": "object" }, "KnowledgePackDeleteResponse": { + "type": "object", "description": "Deletion result.", "properties": { "ok": { - "description": "True when the knowledge was deleted.", - "type": "boolean" + "type": "boolean", + "description": "Always `true` on success; a failed delete returns an error instead." } }, "required": [ "ok" - ], - "type": "object" + ] }, "KnowledgePackEnsureRequest": { + "type": "object", "description": "Scope at which to ensure knowledge exists.", "properties": { "scope": { - "description": "Scope of the knowledge to ensure. One of: `account` (account-level knowledge; scope_id is forced to the caller's account ID and only account admins may create it; first creation seeds a default DUTY.md), `team` (team-level knowledge; the `scope_id` team ID is required and the caller must belong to that team).", + "type": "string", + "description": "Scope of the knowledge to ensure.\n- `account`: the account knowledge. `scope_id` is replaced by the caller's account ID; only the account owner and admins may call this, even when the knowledge already exists. If the knowledge has no `DUTY.md`, a default one is written.\n- `team`: the knowledge of the team in `scope_id`. `scope_id` is required and the caller must be a member of that team.", "enum": [ "account", "team" - ], - "type": "string" + ] }, "scope_id": { - "description": "Team ID; required for `team` scope, ignored for `account` scope.", - "format": "int64", - "type": "integer" + "type": "integer", + "description": "Team ID. Required (non-zero) for `team` scope, otherwise the request fails with `InvalidParameter`; ignored for `account` scope.", + "format": "int64" } }, "required": [ "scope" - ], - "type": "object" + ] }, "KnowledgePackItem": { + "type": "object", "description": "Knowledge — a versioned file tree staged into every AI SRE sandbox at session start. One knowledge exists per (account, scope, scope_id).", "properties": { + "pack_id": { + "type": "string", + "description": "Knowledge ID (`kpk_` prefix)." + }, "account_id": { + "type": "integer", "description": "Account that owns the knowledge.", - "format": "int64", - "type": "integer" - }, - "can_edit": { - "description": "Whether the caller can edit this knowledge.", - "type": "boolean" - }, - "created_at_ms": { - "description": "Unix timestamp in milliseconds when the knowledge was created.", - "format": "int64", - "type": "integer" - }, - "created_by": { - "description": "Person ID of the member who created the knowledge.", - "format": "int64", - "type": "integer" - }, - "duty_version": { - "description": "Knowledge version at which DUTY.md was last authored or re-affirmed. When `version` is greater, DUTY.md no longer reflects every file in the knowledge.", - "type": "integer" - }, - "file_count": { - "description": "Number of files in the knowledge.", - "type": "integer" - }, - "pack_id": { - "description": "Knowledge ID (`kpk_` prefix).", - "type": "string" + "format": "int64" }, "scope": { - "description": "Knowledge scope. `channel` is a legacy scope; new knowledge is `account` or `team` scope.", + "type": "string", + "description": "Knowledge scope.\n- `account`: account-level knowledge shared by the whole account; `scope_id` is the account ID.\n- `team`: knowledge owned by one team; `scope_id` is the team ID.\n- `channel`: legacy scope. It cannot be created or moved into through this API and is never returned by `POST /safari/knowledge/pack/list`; it can only appear when such knowledge is addressed directly by `pack_id`.", "enum": [ "account", "team", "channel" - ], - "type": "string" + ] }, "scope_id": { + "type": "integer", "description": "Scope owner: the account ID for `account` scope, the team ID for `team` scope.", - "format": "int64", - "type": "integer" + "format": "int64" }, "team_name": { - "description": "Display name of the owning team (team scope only). Omitted when empty (account scope, or the team name could not be resolved).", - "type": "string" + "type": "string", + "description": "Display name of the owning team (team scope only). Omitted when empty (account scope, or the team name could not be resolved)." + }, + "file_count": { + "type": "integer", + "description": "Number of files currently in the knowledge." }, "total_bytes": { - "description": "Total size of all files in bytes.", - "format": "int64", - "type": "integer" + "type": "integer", + "description": "Total size of all files in bytes. Capped at 5 MiB per knowledge.", + "format": "int64" + }, + "version": { + "type": "integer", + "description": "Knowledge version. Starts at 0 and increases by 1 on every file write or file deletion. Moving the knowledge to another scope does not change it." + }, + "duty_version": { + "type": "integer", + "description": "The `version` at which `DUTY.md` was last written. Writing `DUTY.md` sets it to the new `version`; when `version` is greater, files were added, changed or deleted after `DUTY.md` was last updated, so `DUTY.md` may no longer index every file." + }, + "created_by": { + "type": "integer", + "description": "Person ID of the member whose request created the knowledge. Account knowledge is created automatically by the first request that needs it, so this can be any member of the account.", + "format": "int64" + }, + "created_at_ms": { + "type": "integer", + "description": "Unix timestamp in milliseconds when the knowledge was created.", + "format": "int64" }, "updated_at_ms": { + "type": "integer", "description": "Unix timestamp in milliseconds when the knowledge was last modified.", - "format": "int64", - "type": "integer" + "format": "int64" }, - "version": { - "description": "Knowledge version, incremented on every file change.", - "type": "integer" + "can_edit": { + "type": "boolean", + "description": "Whether the caller can change this knowledge and its files: for `account` scope, `true` only for the account owner and admins; for `team` scope, `true` only when the caller is a member of that team (owners and admins are not exempt)." } }, "required": [ @@ -13340,51 +13623,50 @@ "created_at_ms", "updated_at_ms", "can_edit" - ], - "type": "object" + ] }, "KnowledgePackListRequest": { + "type": "object", "description": "Filter and pagination for the knowledge list.", "properties": { - "include_account": { - "description": "Include the account-scope knowledge; defaults to true.", - "type": [ - "boolean", - "null" - ] - }, - "limit": { - "description": "Page size.", - "type": "integer" - }, "p": { - "description": "Page number, 1-based; returns all results when both `p` and `limit` are unset.", - "type": "integer" + "type": "integer", + "description": "Page number, 1-based. When both `p` and `limit` are omitted (or ≤ 0), all matching knowledge is returned without paging; when only `limit` is set, `p` defaults to 1." }, - "query": { - "description": "Case-insensitive substring filter over knowledge ID, scope, scope ID/account ID, and team name.", - "maxLength": 128, - "type": "string" + "limit": { + "type": "integer", + "description": "Page size. Defaults to 20 when `p` is set and `limit` is omitted; no upper bound is enforced." }, "scope": { - "description": "Restrict to one scope; `all` (default) overrides `include_account`. One of: `all` (account scope plus visible team scopes), `account` (account-level knowledge only), `team` (team-level knowledge only, can be combined with `team_ids`).", + "type": "string", + "description": "Which scopes to return:\n- `all` (default): account knowledge (unless `include_account` is `false`) plus the visible team knowledge.\n- `account`: only the account knowledge; `include_account` and `team_ids` are ignored.\n- `team`: only team knowledge, optionally narrowed by `team_ids`; `include_account` is ignored.", "enum": [ "all", "account", "team" - ], - "type": "string" + ] + }, + "query": { + "type": "string", + "description": "Case-insensitive substring filter over knowledge ID, scope, scope ID, account ID and team name. Account knowledge also matches `账户`/`账号` and team knowledge also matches `团队`. Leading and trailing spaces are ignored.", + "maxLength": 128 }, "team_ids": { - "description": "Restrict to these team IDs; for non-admins the list is intersected with their own teams.", + "type": "array", + "description": "Restrict team knowledge to these team IDs. IDs of teams the caller does not belong to are silently dropped — this applies to every caller, including owners and admins.", "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "type": "integer", + "format": "int64" + } + }, + "include_account": { + "type": [ + "boolean", + "null" + ], + "description": "Whether to include the account knowledge when `scope` is `all` or omitted. Defaults to `true`." } - }, - "type": "object" + } }, "KnowledgePackListResponse": { "description": "Visible knowledge and the total after filtering.", @@ -13409,64 +13691,64 @@ "type": "object" }, "KnowledgePackUpdateRequest": { + "type": "object", "description": "Move knowledge to a different scope.", "properties": { "pack_id": { - "description": "Knowledge ID to update.", - "type": "string" + "type": "string", + "description": "Knowledge ID to update." }, "scope": { - "description": "Destination scope; omit for a no-op that returns the current knowledge.", - "enum": [ - "account", - "team" - ], "type": [ "string", "null" + ], + "description": "Destination scope. Omit to leave the knowledge unchanged and get it back.\n- `account`: make it the account knowledge (only the account owner and admins).\n- `team`: move it to the team in `scope_id` (the caller must be a member of that team).\nAny other value returns `InvalidParameter`. If the destination already has knowledge, the request fails with `ReferenceExist`.", + "enum": [ + "account", + "team" ] }, "scope_id": { - "description": "Destination team ID; required when `scope` is `team`, set automatically for `account`.", - "format": "int64", "type": [ "integer", "null" - ] + ], + "description": "Destination team ID. Required (non-zero) when `scope` is `team`; ignored when `scope` is `account` (the account ID is used).", + "format": "int64" } }, "required": [ "pack_id" - ], - "type": "object" + ] }, "KnowledgeWarning": { + "type": "object", "description": "Non-blocking annotation returned by file uploads and deletions, e.g. references that point at a removed file.", "properties": { "code": { + "type": "string", "description": "Warning code. One of: `unresolved_reference` (an @ref in the written file's content points to a file that does not exist in the knowledge; `ref` carries it), `still_referenced_by` (the deleted file is still @ref-referenced by other files in the knowledge; `refs` lists the referrers).", "enum": [ "unresolved_reference", "still_referenced_by" - ], - "type": "string" + ] }, "ref": { - "description": "Single reference related to the warning.", - "type": "string" + "type": "string", + "description": "Set only for `unresolved_reference`: the referenced path that does not exist in the knowledge." }, "refs": { - "description": "Multiple references related to the warning.", + "type": "array", + "description": "Set only for `still_referenced_by`: `rel_path` of every other file that still references the deleted file.", "items": { "type": "string" - }, - "type": "array" + } } }, "required": [ "code" - ], - "type": "object" + ] }, "LicenseListResponse": { "description": "People with active fixed or temporary On-call licenses.", @@ -13569,171 +13851,155 @@ "type": "object" }, "ListChangeRequest": { + "type": "object", "properties": { - "asc": { - "description": "Sort in ascending order when true; default is descending.", - "type": "boolean" + "start_time": { + "type": "integer", + "format": "int64", + "description": "Start of the query window, Unix seconds. Required in practice: it must be less than `end_time`, and the window can span at most 31 days. A change matches when its [start_time, last_time] range overlaps the window.", + "minimum": 0 }, - "channel_ids": { - "description": "Filter by channel IDs.", - "items": { - "description": "", - "format": "int64", - "type": "integer" - }, - "type": "array" + "end_time": { + "type": "integer", + "format": "int64", + "description": "End of the query window, Unix seconds. Required in practice; see `start_time`.", + "minimum": 0 }, - "data_source_id": { - "deprecated": true, - "description": "Deprecated: use `integration_ids` instead. Single integration ID to filter by.", + "p": { + "type": "integer", + "description": "Page number, starting at 1. Defaults to 1.", "format": "int64", "minimum": 1, - "type": "integer" - }, - "data_source_ids": { - "deprecated": true, - "description": "Deprecated: use `integration_ids` instead. At least 1 entry when provided.", - "items": { - "description": "Integration ID.", - "format": "int64", - "type": "integer" - }, - "minItems": 1, - "type": "array" + "default": 1 }, - "end_time": { - "description": "End of the query window, Unix epoch seconds. See `start_time` for defaults and constraints.", + "limit": { + "type": "integer", + "description": "Number of items per page, 1-100. Defaults to 10.", "format": "int64", - "minimum": 0, - "type": "integer" + "minimum": 1, + "maximum": 100, + "default": 10 }, - "filters": { - "description": "Structured filters ANDed onto the query (e.g. on labels). Keys prefixed with `incident` are ignored.", + "channel_ids": { + "type": "array", "items": { - "$ref": "#/components/schemas/FilterCondition" + "type": "integer", + "description": "Channel ID.", + "format": "int64" }, - "type": "array" - }, - "include_events": { - "description": "Include the underlying change events for each change when true.", - "type": "boolean" - }, - "integration_id": { - "deprecated": true, - "description": "Deprecated: use `integration_ids` instead. Single integration ID to filter by.", - "format": "int64", - "minimum": 1, - "type": "integer" + "description": "Filter by channel IDs." }, "integration_ids": { - "description": "Filter by reporting integration IDs. At least 1 entry when provided.", + "type": "array", "items": { - "description": "", - "format": "int64", - "type": "integer" + "type": "integer", + "description": "Integration ID.", + "format": "int64" }, - "minItems": 1, - "type": "array" - }, - "limit": { - "default": 10, - "description": "Number of items per page.", - "format": "int64", - "maximum": 100, - "minimum": 1, - "type": "integer" + "description": "Filter by reporting integration IDs. At least 1 entry when provided.", + "minItems": 1 }, "orderby": { + "type": "string", "description": "Sort field: `start_time` or `last_time`. Defaults to `start_time`.", "enum": [ "start_time", "last_time" - ], - "type": "string" + ] }, - "p": { - "description": "Page number, starting at 1.", - "format": "int64", - "minimum": 1, - "type": "integer" + "asc": { + "type": "boolean", + "description": "Sort in ascending order when true; default is descending." + }, + "include_events": { + "type": "boolean", + "description": "Include the underlying change events for each change when true." }, "query": { - "description": "Case-insensitive substring or regular-expression match over the change title, change_key, and description. An invalid regular expression falls back to a literal match.", - "type": "string" + "type": "string", + "description": "Case-insensitive substring or regular-expression match over the change title, change_key, and description. An invalid regular expression falls back to a literal match." }, - "start_time": { - "description": "Start of the query window, Unix epoch seconds. Optional — when both `start_time` and `end_time` are omitted or 0, the window defaults to the last hour. Must be less than `end_time`, with a span of at most 31 days. A change matches when its [start_time, last_time] window overlaps the query window.", + "filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/FilterCondition" + }, + "description": "Structured filters ANDed onto the query (e.g. on labels). Keys prefixed with `incident` are ignored." + }, + "data_source_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64", + "description": "Integration ID." + }, + "description": "Deprecated: use `integration_ids` instead. At least 1 entry when provided.", + "deprecated": true, + "minItems": 1 + }, + "data_source_id": { + "type": "integer", "format": "int64", - "minimum": 0, - "type": "integer" + "minimum": 1, + "deprecated": true, + "description": "Deprecated: use `integration_ids` instead. Single integration ID to filter by." + }, + "integration_id": { + "type": "integer", + "format": "int64", + "minimum": 1, + "deprecated": true, + "description": "Deprecated: use `integration_ids` instead. Single integration ID to filter by." } }, - "type": "object" + "required": [ + "start_time", + "end_time" + ] }, "ListChangeResponse": { + "type": "object", "properties": { + "total": { + "type": "integer", + "description": "Total number of matching changes.", + "format": "int64" + }, "has_next_page": { - "description": "Whether more pages are available after this one.", - "type": "boolean" + "type": "boolean", + "description": "Whether more pages are available after this one." }, "items": { - "description": "Changes on the current page.", + "type": "array", "items": { "$ref": "#/components/schemas/ChangeItem" }, - "type": "array" - }, - "total": { - "description": "Total number of matching changes.", - "format": "int64", - "type": "integer" + "description": "Changes on the current page." } }, - "type": "object" + "required": [ + "total", + "has_next_page", + "items" + ] }, "ListChannelsRequest": { + "type": "object", "properties": { - "asc": { - "description": "When true, sort ascending; defaults to false (descending).", - "type": "boolean" - }, - "channel_ids": { - "description": "Filter by explicit channel IDs.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "channel_name": { - "description": "Exact-match filter on channel name. Takes priority over `query` for name filtering. Must be valid UTF-8 — invalid byte sequences are rejected with `InvalidParameter`.", - "type": "string" - }, - "is_brief": { - "description": "When true, return only `channel_id`, `channel_name`, `description` and `status`, and return all matches without pagination.", - "type": "boolean" - }, - "is_my_managed": { - "description": "When true, return only channels the caller manages.", - "type": "boolean" - }, - "is_my_starred": { - "description": "When true, return only channels the caller has starred. Mutually exclusive with `is_my_team`.", - "type": "boolean" - }, - "is_my_team": { - "description": "When true, return channels owned by the caller's teams. Mutually exclusive with `is_my_starred`.", - "type": "boolean" + "p": { + "type": "integer", + "minimum": 1, + "description": "Page number, starting at 1. Always pass it: when omitted the first page is returned but `has_next_page` is unreliable." }, "limit": { - "default": 100, - "description": "Page size. Defaults to 100 when omitted.", - "maximum": 100, + "type": "integer", "minimum": 1, - "type": "integer" + "maximum": 100, + "default": 100, + "description": "Page size. Defaults to 100 when omitted." }, "orderby": { - "description": "Field used to order results. Defaults to `created_at`.", + "type": "string", "enum": [ "ranking", "created_at", @@ -13741,53 +14007,79 @@ "channel_name", "last_incident_at" ], - "type": "string" + "description": "Sort field, default `created_at`. `ranking` uses the caller's own channel order saved in the console and falls back to creation order when none is saved; `channel_name` sorts case-insensitively." }, - "p": { - "description": "Page number (1-based).", - "minimum": 1, - "type": "integer" + "asc": { + "type": "boolean", + "description": "When true, sort ascending; defaults to false (descending)." }, - "query": { - "description": "Case-insensitive regular expression matched against channel name and description; invalid regex syntax falls back to a literal match. Must be valid UTF-8 — invalid byte sequences are rejected with `InvalidParameter`.", - "type": "string" + "is_my_managed": { + "type": "boolean", + "description": "When true, return only channels owned by one of the caller's teams or created by the caller. Takes precedence over `is_my_team` and `is_my_starred`." + }, + "is_my_starred": { + "type": "boolean", + "description": "When true, return only channels the caller has starred. Cannot be combined with `is_my_team`." + }, + "is_brief": { + "type": "boolean", + "description": "When true, return only `channel_id`, `channel_name`, `description`, `status` and `is_starred` for each channel, with all matches in one page." + }, + "is_my_team": { + "type": "boolean", + "description": "When true, return only channels whose owning team is one of the caller's teams. Cannot be combined with `is_my_starred`." }, "team_ids": { - "description": "Filter by team IDs.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Return only channels owned by these teams. Ignored when `is_my_managed` or `is_my_team` is true." + }, + "query": { + "type": "string", + "description": "Case-insensitive regular expression matched against channel name and description; invalid regex syntax falls back to a literal match. Must be valid UTF-8 — invalid byte sequences are rejected with `InvalidParameter`." + }, + "channel_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Filter by explicit channel IDs." + }, + "channel_name": { + "type": "string", + "description": "Exact-match filter on channel name. Takes priority over `query` for name filtering. Must be valid UTF-8 — invalid byte sequences are rejected with `InvalidParameter`." } - }, - "type": "object" + } }, "ListChannelsResponse": { + "type": "object", + "required": [ + "items", + "total", + "has_next_page" + ], "properties": { - "has_next_page": { - "description": "Whether more pages are available.", - "type": "boolean" - }, "items": { - "description": "Channels on the current page.", + "type": "array", "items": { "$ref": "#/components/schemas/ChannelItem" }, - "type": "array" + "description": "Channels on the current page." }, "total": { - "description": "Total matching channels.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Total number of matching channels across all pages." + }, + "has_next_page": { + "type": "boolean", + "description": "Whether more pages follow. Reliable only when `p` is passed." } - }, - "required": [ - "items", - "total", - "has_next_page" - ], - "type": "object" + } }, "ListDropRulesResponse": { "properties": { @@ -13805,19 +14097,19 @@ "type": "object" }, "ListEscalationRulesResponse": { + "type": "object", + "required": [ + "items" + ], "properties": { "items": { - "description": "All escalation rules of the channel, excluding deleted ones, ordered by priority ascending.", + "type": "array", "items": { "$ref": "#/components/schemas/EscalateRuleItem" }, - "type": "array" + "description": "Escalation rules of the channel, excluding deleted ones, in evaluation order: ascending `priority`, then creation time." } - }, - "required": [ - "items" - ], - "type": "object" + } }, "ListIncidentAlertsRequest": { "description": "Filters for alerts belonging to an incident.", @@ -13860,26 +14152,26 @@ "type": "object" }, "ListIncidentAlertsResponse": { + "type": "object", "description": "Paginated list of alerts merged into an incident.", + "required": [ + "items", + "total" + ], "properties": { "items": { - "description": "Alert list.", + "type": "array", "items": { "$ref": "#/components/schemas/AlertInfo" }, - "type": "array" + "description": "Alerts on the requested page; an empty array when no alert matches." }, "total": { - "description": "Total matching alerts.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Total matching alerts." } - }, - "required": [ - "items", - "total" - ], - "type": "object" + } }, "ListIncidentCommentTypesRequest": { "description": "No parameters. The operation always returns every comment type of the calling account.", @@ -13887,56 +14179,60 @@ "type": "object" }, "ListIncidentCommentTypesResponse": { + "type": "object", "description": "Full list of the account's comment types, ordered by position.", "properties": { "items": { - "description": "All comment types of the account, ordered by position.", + "type": "array", "items": { "$ref": "#/components/schemas/IncidentCommentTypeItem" }, - "type": "array" + "description": "All comment types of the account, ordered by position." } }, - "type": "object" + "required": [ + "items" + ] }, "ListIncidentFeedRequest": { + "type": "object", "description": "Filters for the incident timeline query.", + "required": [ + "incident_id" + ], "properties": { - "asc": { - "description": "Ascending chronological order when true.", - "type": "boolean" - }, "incident_id": { - "description": "Incident ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Incident ID (MongoDB ObjectID)." }, - "limit": { - "default": 20, - "description": "Page size, at most 100.", + "p": { + "type": "integer", "format": "int64", - "maximum": 100, "minimum": 1, - "type": "integer" - }, - "p": { "description": "Page number starting at 1.", + "default": 1 + }, + "limit": { + "type": "integer", "format": "int64", "minimum": 1, - "type": "integer" + "maximum": 100, + "default": 20, + "description": "Page size, at most 100." + }, + "asc": { + "type": "boolean", + "description": "Ascending chronological order when true." }, "types": { - "description": "Optional filter restricting the returned entries to specific types.", + "type": "array", "items": { "$ref": "#/components/schemas/IncidentFeedType" }, - "type": "array" + "description": "Return only entries of these types; omit to return all types." } - }, - "required": [ - "incident_id" - ], - "type": "object" + } }, "ListIncidentFeedResponse": { "description": "Page of incident timeline entries.", @@ -13977,140 +14273,144 @@ "type": "object" }, "ListIncidentsRequest": { + "type": "object", "description": "Filters for the incident list query. `start_time` and `end_time` are required; the window must not exceed 31 days.", + "required": [ + "start_time", + "end_time" + ], "properties": { - "acker_ids": { - "description": "Filter by acker member IDs; obtain member IDs from `POST /member/list`.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "start_time": { + "type": "integer", + "format": "int64", + "description": "Start of the time window (Unix timestamp in seconds). The window with `end_time` may span at most 31 days and filters by incident start time." + }, + "end_time": { + "type": "integer", + "format": "int64", + "description": "Window end, Unix seconds. Must be greater than `start_time` and within 31 days." }, "asc": { - "description": "Ascending order when true.", - "type": "boolean" + "type": "boolean", + "description": "Ascending order when true." }, - "channel_ids": { - "description": "Channel IDs to filter by. Use 0 for standalone (global) incidents.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "is_snoozed": { + "type": "boolean", + "description": "When true, include only snoozed incidents." }, - "closer_ids": { - "description": "Closer member IDs. Use 0 for automatically closed incidents.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "is_my_team": { + "type": "boolean", + "description": "When true, restrict to incidents in channels owned by the user's teams." }, - "creator_ids": { - "description": "Creator member IDs. Use 0 for automatically created incidents.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "end_time": { - "description": "Window end, Unix seconds. Must be greater than `start_time` and within 31 days.", - "format": "int64", - "type": "integer" + "is_my_channel": { + "type": "boolean", + "description": "When true, restrict to incidents in channels the user personally owns." }, "ever_muted": { - "description": "When true, include only incidents that were ever silenced.", - "type": "boolean" + "type": "boolean", + "description": "When true, include only incidents that were ever silenced." }, - "incident_ids": { - "description": "Restrict to the given incident IDs.", + "is_rare": { + "type": "boolean", + "description": "When true, include only outlier (rare) incidents." + }, + "has_unfinished_work_item": { + "type": "boolean", + "description": "When true, include only incidents that still have an action item or follow-up that is neither `done` nor `cancelled`. `false` applies no filter." + }, + "progress": { + "type": "string", + "description": "Comma-separated progress states to match, for example `Triggered,Processing`. Values: `Triggered` not yet acknowledged; `Processing` acknowledged and being handled; `Closed` resolved. Omit to match every state." + }, + "query": { + "type": "string", + "description": "Full-text search query." + }, + "incident_severity": { + "type": "string", + "description": "Comma-separated severities to match, for example `Critical,Warning`. Values: `Critical` most severe, `Warning`, `Info` least severe." + }, + "channel_ids": { + "type": "array", "items": { - "type": "string" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Channel IDs to filter by. Use 0 for standalone (global) incidents." }, - "incident_severity": { - "description": "Comma-separated list of severities (`Critical,Warning,Info`).", - "type": "string" + "team_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Team IDs; resolved to channels via channel ownership." }, - "is_my_channel": { - "description": "When true, restrict to incidents in channels the user personally owns.", - "type": "boolean" + "responder_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Filter by responder member IDs; obtain member IDs from `POST /member/list`." }, - "is_my_team": { - "description": "When true, restrict to incidents in channels owned by the user's teams.", - "type": "boolean" + "acker_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Filter by acker member IDs; obtain member IDs from `POST /member/list`." }, - "is_rare": { - "description": "When true, include only outlier (rare) incidents.", - "type": "boolean" + "creator_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Creator member IDs. Use 0 for automatically created incidents." }, - "is_snoozed": { - "description": "When true, include only snoozed incidents.", - "type": "boolean" + "closer_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Closer member IDs. Use 0 for automatically closed incidents." }, - "limit": { - "default": 20, - "description": "Page size, at most 100.", - "format": "int64", - "maximum": 100, - "minimum": 0, - "type": "integer" + "incident_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Restrict to the given incident IDs." }, "nums": { - "description": "Filter by incident short numbers (the numbers shown before incident titles in the console).", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Filter by incident short numbers (the numbers shown before incident titles in the console)." }, "p": { - "description": "Page number starting at 1.", + "type": "integer", "format": "int64", "minimum": 0, - "type": "integer" - }, - "progress": { - "description": "Comma-separated list of progress states to match (e.g. `Triggered,Processing`).", - "type": "string" - }, - "query": { - "description": "Full-text search query.", - "type": "string" - }, - "responder_ids": { - "description": "Filter by responder member IDs; obtain member IDs from `POST /member/list`.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "search_after_ctx": { - "description": "Cursor from a previous response for forward pagination.", - "type": "string" + "description": "Page number starting at 1." }, - "start_time": { - "description": "Start of the time window (Unix timestamp in seconds). The window with `end_time` may span at most 31 days and filters by incident start time.", + "limit": { + "type": "integer", "format": "int64", - "type": "integer" + "minimum": 0, + "maximum": 100, + "default": 20, + "description": "Page size, at most 100." }, - "team_ids": { - "description": "Team IDs; resolved to channels via channel ownership.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "search_after_ctx": { + "type": "string", + "description": "Cursor from the previous response's `search_after_ctx`; when set, `p` is ignored." } - }, - "required": [ - "start_time", - "end_time" - ], - "type": "object" + } }, "ListInhibitRulesResponse": { "properties": { @@ -14169,142 +14469,139 @@ "type": "object" }, "ListPostMortemTemplatesRequest": { + "type": "object", "description": "Pagination and ordering options for post-mortem templates.", "properties": { - "asc": { - "description": "Ascending order when true.", - "type": "boolean" - }, - "limit": { - "default": 20, - "description": "Page size, at most 100.", - "format": "int64", - "maximum": 100, - "minimum": 0, - "type": "integer" - }, "order_by": { - "description": "Field used to order results.", + "type": "string", "enum": [ "created_at_seconds" ], - "type": "string" + "description": "Sort field for custom templates. Only `created_at_seconds` is supported, which is also the default." + }, + "asc": { + "type": "boolean", + "description": "Sort custom templates in ascending order when true; default false (newest first)." }, "p": { - "description": "Page number starting at 1.", + "type": "integer", "format": "int64", "minimum": 0, - "type": "integer" + "description": "Page number starting at 1; 0 or omitted means 1." + }, + "limit": { + "type": "integer", + "format": "int64", + "minimum": 0, + "maximum": 100, + "default": 20, + "description": "Page size, 1–100; 0 or omitted means 20." }, "search_after_ctx": { - "description": "Cursor from a previous response for forward pagination.", - "type": "string" + "type": "string", + "description": "Not supported by this operation; leave it unset and paginate with `p`. If sent, it must be an integer string, and `p` is then ignored (results start from the first page)." } - }, - "type": "object" + } }, "ListPostMortemTemplatesResponse": { + "type": "object", "description": "Paginated list of post-mortem templates.", + "required": [ + "items", + "total", + "has_next_page" + ], "properties": { - "has_next_page": { - "description": "True when another page is available.", - "type": "boolean" - }, "items": { - "description": "Templates in the current page.", + "type": "array", "items": { "$ref": "#/components/schemas/PostMortemTemplate" }, - "type": "array" - }, - "search_after_ctx": { - "description": "Cursor for forward pagination.", - "type": "string" + "description": "Templates on this page; the built-in template is first on page 1." }, "total": { - "description": "Total matching templates.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Total number of templates, including the built-in one." + }, + "has_next_page": { + "type": "boolean", + "description": "True when another page is available." } - }, - "required": [ - "items", - "total", - "has_next_page" - ], - "type": "object" + } }, "ListPostMortemsRequest": { + "type": "object", "description": "Filters for the post-mortem report list.", "properties": { - "asc": { - "description": "Ascending order when true.", - "type": "boolean" + "status": { + "type": "string", + "enum": [ + "drafting", + "published" + ], + "description": "Optional status filter: `drafting` returns only drafts, `published` returns only published post-mortems. When omitted, post-mortems in all statuses are returned." }, - "channel_ids": { - "description": "Channel IDs to restrict the query to.", + "team_ids": { + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Team IDs to restrict the query to." }, - "created_at_end_seconds": { - "description": "Upper bound of post-mortem creation time (Unix timestamp in seconds).", - "format": "int64", - "minimum": 0, - "type": "integer" + "channel_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Channel IDs to restrict the query to." }, "created_at_start_seconds": { - "description": "Lower bound of post-mortem creation time (Unix timestamp in seconds).", + "type": "integer", "format": "int64", "minimum": 0, - "type": "integer" + "description": "Lower bound of post-mortem creation time (Unix timestamp in seconds)." }, - "limit": { - "default": 20, - "description": "Page size, at most 100.", + "created_at_end_seconds": { + "type": "integer", "format": "int64", - "maximum": 100, "minimum": 0, - "type": "integer" + "description": "Upper bound of post-mortem creation time (Unix timestamp in seconds)." }, "order_by": { - "description": "Field used to order results.", + "type": "string", "enum": [ "created_at_seconds", "updated_at_seconds" ], - "type": "string" + "description": "Sort field: `created_at_seconds` creation time, `updated_at_seconds` last update time.", + "default": "created_at_seconds" + }, + "asc": { + "type": "boolean", + "description": "Ascending order when true." }, "p": { - "description": "Page number starting at 1.", + "type": "integer", "format": "int64", "minimum": 0, - "type": "integer" + "description": "Page number starting at 1." }, - "search_after_ctx": { - "description": "Cursor from a previous response for forward pagination.", - "type": "string" - }, - "status": { - "description": "Optional status filter: `drafting` returns only drafts, `published` returns only published post-mortems. When omitted, post-mortems in all statuses are returned.", - "enum": [ - "drafting", - "published" - ], - "type": "string" + "limit": { + "type": "integer", + "format": "int64", + "minimum": 0, + "maximum": 100, + "default": 20, + "description": "Page size, at most 100." }, - "team_ids": { - "description": "Team IDs to restrict the query to.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "search_after_ctx": { + "type": "string", + "description": "Cursor from a previous response for forward pagination." } - }, - "type": "object" + } }, "ListPostMortemsResponse": { "description": "Paginated list of post-mortem reports.", @@ -14341,7 +14638,7 @@ "description": "Remote configuration history request. Newest first by default.", "properties": { "application_id": { - "description": "RUM application ID.", + "description": "RUM application ID. Get application IDs via `POST /rum/application/list`.", "type": "string" }, "asc": { @@ -14350,13 +14647,12 @@ }, "limit": { "default": 20, - "description": "Page size. Default 20, max 100.", - "maximum": 100, + "description": "Page size. `0` or a negative value means 20; values above 100 are treated as 100.", "type": "integer" }, "orderby": { "default": "updated_at", - "description": "Sort field. Default: `updated_at`.", + "description": "Sort field:\n\n- `updated_at`: publish time (default).\n- `version`: version number.\n\nAny other value falls back to `updated_at`.", "enum": [ "updated_at", "version" @@ -14380,40 +14676,45 @@ "description": "Remote configuration history page.", "properties": { "has_next_page": { - "description": "Whether more pages remain.", + "description": "`true` when more versions remain after this page.", "type": "boolean" }, "items": { - "description": "Version items, newest first by default.", + "description": "Versions on this page, newest first by default. Empty array when the application has never been configured.", "items": { "$ref": "#/components/schemas/RemoteConfigHistoryItem" }, "type": "array" }, "total": { - "description": "Total number of versions.", + "description": "Number of retained versions (at most 50).", "type": "integer" } }, - "type": "object" + "type": "object", + "required": [ + "total", + "has_next_page", + "items" + ] }, "ListRoutesRequest": { + "type": "object", "description": "Parameters for listing routing rules across multiple integrations.", + "required": [ + "integration_ids" + ], "properties": { "integration_ids": { - "description": "Integration IDs to fetch routing rules for.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "minItems": 1, - "type": "array" + "description": "Shared integration IDs to fetch routing rules for, at least one; obtain them from `POST /integration/list`.", + "minItems": 1 } - }, - "required": [ - "integration_ids" - ], - "type": "object" + } }, "ListRoutesResponse": { "description": "Response wrapper for the routing rule list.", @@ -14536,111 +14837,129 @@ "type": "object" }, "ListWebhookHistoryRequest": { + "type": "object", "description": "Filter parameters for listing outbound webhook delivery history. The query is bounded by a required millisecond time window; use `search_after_ctx` for cursor-based pagination.", + "required": [ + "limit", + "start_time", + "end_time" + ], "properties": { - "asc": { - "description": "Ascending order by `event_time` when true; otherwise descending.", - "type": "boolean" - }, - "end_time": { - "description": "Window end time in Unix milliseconds. Must be greater than `start_time`.", - "format": "int64", - "maximum": 9999999999999, - "minimum": 1000000000000, - "type": "integer" - }, - "event_types": { - "description": "Filter by event type codes (e.g. `i_new` incident created, `a_new` alert triggered).", - "items": { - "type": "string" - }, - "type": "array" - }, - "integration_id": { - "description": "Filter by webhook integration ID.", - "format": "int64", - "minimum": 0, - "type": "integer" + "search_after_ctx": { + "type": "string", + "description": "Opaque cursor returned by a previous call for fetching the next page." }, "limit": { - "description": "Page size.", - "maximum": 100, + "type": "integer", "minimum": 1, - "type": "integer" + "maximum": 100, + "description": "Number of records per page, 1–100." + }, + "asc": { + "type": "boolean", + "description": "Ascending order by `event_time` when true; otherwise descending." }, "orderby": { - "description": "Sort field. Currently only `event_time` is supported.", + "type": "string", "enum": [ "event_time" ], - "type": "string" + "description": "Sort field. Currently only `event_time` is supported." }, "ref_id": { - "description": "Reference ID filter (incident or alert ID).", + "type": "string", "maxLength": 128, - "type": "string" - }, - "search_after_ctx": { - "description": "Opaque cursor returned by a previous call for fetching the next page.", - "type": "string" + "description": "Reference ID filter (incident or alert ID)." }, - "start_time": { - "description": "Window start time in Unix milliseconds.", + "integration_id": { + "type": "integer", "format": "int64", - "maximum": 9999999999999, - "minimum": 1000000000000, - "type": "integer" + "minimum": 0, + "description": "Filter by webhook integration ID; `0` or omitted returns all integrations." + }, + "event_types": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Filter by event type codes (e.g. `i_new` incident created, `a_new` alert triggered)." }, "status": { - "description": "Filter by delivery status: `success` or `failed`.", + "type": "string", "enum": [ "success", "failed" ], - "type": "string" + "description": "Filter by delivery status: `success` or `failed`." + }, + "start_time": { + "type": "integer", + "format": "int64", + "minimum": 1000000000000, + "maximum": 9999999999999, + "description": "Window start time in Unix milliseconds." + }, + "end_time": { + "type": "integer", + "format": "int64", + "minimum": 1000000000000, + "maximum": 9999999999999, + "description": "Window end time in Unix milliseconds. Must be greater than `start_time`." } - }, - "required": [ - "limit", - "start_time", - "end_time" - ], - "type": "object" + } }, "ListWebhookHistoryResponse": { + "type": "object", "description": "Paginated webhook delivery history.", + "required": [ + "items", + "total", + "search_after_ctx" + ], "properties": { "items": { - "description": "Webhook delivery records on the current page.", + "type": "array", "items": { "$ref": "#/components/schemas/WebhookHistoryItem" }, - "type": "array" - }, - "search_after_ctx": { - "description": "Cursor to pass as `search_after_ctx` to fetch the next page. Empty when no further pages are available.", - "type": "string" + "description": "Webhook delivery records on the current page." }, "total": { - "description": "Total number of matching records.", - "format": "int64", - "type": "integer" + "type": "integer", + "description": "Total number of records matching the filters, not capped.", + "format": "int64" + }, + "search_after_ctx": { + "type": "string", + "description": "Cursor to pass as `search_after_ctx` to fetch the next page. Empty when no further pages are available." } - }, - "required": [ - "items", - "total", - "search_after_ctx" - ], - "type": "object" + } }, "ListWorkItemRequest": { + "type": "object", "description": "Filters for listing work items. At least one of `incident_id`, `post_mortem_id`, `assignee_id`, or `assignee_type` = `ai_sre` is required.", "properties": { + "incident_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Incident ID (MongoDB ObjectID). Also returns follow-ups anchored on the incident's post-mortem." + }, + "post_mortem_id": { + "type": "string", + "description": "Post-mortem ID (32-character hex string). Returns follow-ups bound to this post-mortem." + }, + "item_type": { + "type": "string", + "enum": [ + "action", + "follow_up" + ], + "description": "Filter by work item type: `action` action item, `follow_up` post-mortem follow-up." + }, "assignee_id": { - "description": "Restrict results to items assigned to this member ID. Listing by assignee alone requires being that assignee or an account admin. Ignored when `assignee_type` is `ai_sre`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Restrict results to items assigned to this member ID. Listing by assignee alone requires being that member or an account owner or admin. Ignored when `assignee_type` is `ai_sre`." }, "assignee_type": { "description": "Filter by assignee type: `person` or `ai_sre`. `ai_sre` returns items assigned to AI SRE (an AI caller uses this to list its own tasks) and does not require `assignee_id`. `person` together with `assignee_id` restricts results to that member. Omitted with a positive `assignee_id` means `person`.", @@ -14651,150 +14970,136 @@ "type": "string" }, "cursor": { - "description": "Pagination cursor from a previous response's `next_cursor`.", - "type": "string" - }, - "incident_id": { - "description": "Incident ID (MongoDB ObjectID). Also returns follow-ups anchored on the incident's post-mortem.", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" - }, - "item_type": { - "description": "Filter by work item type: `action` action item, `follow_up` post-mortem follow-up.", - "enum": [ - "action", - "follow_up" - ], - "type": "string" + "type": "string", + "description": "Opaque cursor from a previous response's `next_cursor`. An invalid cursor returns `InvalidParameter`." }, "limit": { - "default": 50, - "description": "Page size, at most 200. Defaults to 50.", + "type": "integer", "format": "int64", - "maximum": 200, - "minimum": 0, - "type": "integer" - }, - "post_mortem_id": { - "description": "Post-mortem ID (32-character hex string). Returns follow-ups bound to this post-mortem.", - "type": "string" + "default": 50, + "description": "Page size. 0, negative or omitted means 50; values above 200 are treated as 200." } - }, - "type": "object" + } }, "MCPServerCreateRequest": { + "type": "object", "description": "Configuration for a new MCP server.", "properties": { - "allow_insecure_oauth_http": { - "description": "Allow this server's OAuth token exchange over plaintext HTTP. Testing use only; defaults to false.", - "type": "boolean" + "server_name": { + "type": "string", + "description": "MCP server name: must start with a letter and contain only letters, digits, `-`, or `_` (`@` is reserved); unique within its scope (account-wide or one team).", + "minLength": 1, + "maxLength": 255 }, - "allow_insecure_tls_skip_verify": { - "description": "Skip TLS certificate verification when connecting to this server. Testing use only; defaults to false.", - "type": "boolean" + "description": { + "type": "string", + "description": "Server description.", + "minLength": 1, + "maxLength": 1024 + }, + "transport": { + "type": "string", + "description": "Transport protocol: `stdio` launches a local process via `command`/`args`/`env`, `sse` / `streamable-http` connects to a remote service via `url`/`headers`.", + "enum": [ + "stdio", + "sse", + "streamable-http" + ] + }, + "command": { + "type": "string", + "description": "Executable command (stdio transport)." }, "args": { - "description": "Command arguments (stdio transport).", + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "auth_mode": { - "description": "Authentication mode: shared (default), per_user_secret, or per_user_oauth.", - "type": "string" - }, - "call_timeout": { - "description": "Tool-call timeout in seconds. 0 = default (60s).", - "type": "integer" - }, - "command": { - "description": "Executable command (stdio transport).", - "type": "string" - }, - "connect_timeout": { - "description": "Connection timeout in seconds. 0 = default (10s).", - "type": "integer" - }, - "description": { - "description": "Server description.", - "maxLength": 1024, - "minLength": 1, - "type": "string" + "description": "Command arguments (stdio transport)." }, "env": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "Environment variables (stdio transport).", - "type": "object" + "description": "Environment variables (`stdio` transport). Values under credential-looking names (containing `KEY`, `SECRET`, `TOKEN`, `PASSWORD`, …) are encrypted at rest and masked in responses." }, - "environments": { - "description": "Execution environments this server is callable from: `cloud` and/or BYOC runner environment IDs. Omitted or empty means all environments.", - "items": { - "type": "string" - }, - "type": "array" + "url": { + "type": "string", + "description": "Server URL (sse / streamable-http transport)." }, "headers": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "HTTP headers (sse / streamable-http).", - "type": "object" + "description": "HTTP headers (`sse` / `streamable-http` transport). Values under credential-looking names (containing `KEY`, `TOKEN`, `AUTHORIZATION`, …) are encrypted at rest and masked in responses." }, - "oauth_metadata": { - "description": "JSON OAuth metadata; reserved for per_user_oauth.", - "type": "string" + "connect_timeout": { + "type": "integer", + "description": "Connection timeout in seconds. Omitted or `0` is stored as `0` and means the 10-second default." }, - "secret_schema": { - "description": "JSON secret schema; required when auth_mode=per_user_secret.", - "type": "string" + "call_timeout": { + "type": "integer", + "description": "Tool-call timeout in seconds. Omitted or `0` is stored as `0` and means the 60-second default." }, - "server_name": { - "description": "MCP server name: must start with a letter and contain only letters, digits, `-`, or `_` (`@` is reserved); unique within its scope (account-wide or one team), case-insensitive.", - "maxLength": 255, - "minLength": 1, - "type": "string" + "auth_mode": { + "type": "string", + "description": "Who supplies the credential:\n- `shared` (default; an empty value behaves the same): one credential stored on the server (`env` / `headers`) is used for every caller.\n- `per_user_secret`: each user stores their own secret, sent in the header named by `secret_schema.header_name`.\n- `per_user_oauth`: each user completes their own OAuth authorization; discovery and client registration run on first use.\n\n`per_user_secret` requires `secret_schema` with a non-empty `header_name`; any other value returns `InvalidParameter`.", + "enum": [ + "shared", + "per_user_secret", + "per_user_oauth" + ], + "default": "shared" }, - "source_template_name": { - "description": "Marketplace template name when created from a connector template.", - "type": "string" + "secret_schema": { + "type": "string", + "description": "JSON secret schema; required when auth_mode=per_user_secret." + }, + "oauth_metadata": { + "type": "string", + "description": "JSON OAuth metadata; reserved for per_user_oauth." }, "status": { - "default": "enabled", + "type": "string", "description": "Initial status: `enabled` (default) or `disabled` (created but kept off).", "enum": [ "enabled", "disabled" ], - "type": "string" + "default": "enabled" }, "team_id": { - "description": "Team scope: 0 = account-wide; >0 = team.", - "format": "int64", - "type": "integer" - }, - "transport": { - "description": "Transport protocol: `stdio` launches a local process via `command`/`args`/`env`, `sse` / `streamable-http` connects to a remote service via `url`/`headers`.", - "enum": [ - "stdio", - "sse", - "streamable-http" - ], - "type": "string" + "type": "integer", + "description": "Team scope: `0` = account-wide (account owner or admin only); `>0` = a team the caller belongs to. Ignored when `source_template_name` is set — marketplace installs are always account-wide.", + "format": "int64" }, - "url": { - "description": "Server URL (sse / streamable-http transport).", - "type": "string" + "environments": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Execution environments this server is callable from: `cloud` and/or BYOC runner environment IDs. Omitted or empty means all environments." + }, + "allow_insecure_oauth_http": { + "type": "boolean", + "description": "Allow this server's OAuth token exchange over plaintext HTTP. Testing use only; defaults to false." + }, + "allow_insecure_tls_skip_verify": { + "type": "boolean", + "description": "Skip TLS certificate verification when connecting to this server. Testing use only; defaults to false." + }, + "source_template_name": { + "type": "string", + "description": "Name of the marketplace template to install. When set, the template must exist, the server is created at account scope, and the connection fields must match the template except for its declared parameter values. Cannot be changed later." } }, "required": [ "server_name", "description", "transport" - ], - "type": "object" + ] }, "MCPServerDeleteRequest": { "description": "MCP server deletion by ID.", @@ -14823,146 +15128,156 @@ "type": "object" }, "MCPServerItem": { + "type": "object", "description": "An MCP server (connector) registered on the account.", "properties": { + "server_id": { + "type": "string", + "description": "Unique MCP server ID (prefix `mcp_`)." + }, "account_id": { + "type": "integer", "description": "Owning account ID.", - "format": "int64", - "type": "integer" - }, - "ai_description": { - "description": "LLM-generated description, preferred over `description` when present. Omitted when not yet generated.", - "type": "string" + "format": "int64" }, - "allow_insecure_oauth_http": { - "description": "Allow this server's OAuth token exchange over plaintext HTTP; testing use only. Omitted when false.", - "type": "boolean" + "team_id": { + "type": "integer", + "description": "Team scope: 0 = account-wide; >0 = the owning team.", + "format": "int64" }, - "allow_insecure_tls_skip_verify": { - "description": "Skip TLS certificate verification when connecting to this server; testing use only. Omitted when false.", - "type": "boolean" + "can_edit": { + "type": "boolean", + "description": "Whether the caller may update, enable, disable, or delete this server: `true` for an account-scoped server only for the account owner or an admin, for a team server only for members of that team. Create and update responses always return `true`." }, - "args": { - "description": "Command arguments (stdio transport).", + "environments": { + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "auth_mode": { - "description": "Authentication mode. One of: `shared` (a single static credential saved on the resource and shared by all callers in the account; the default — an empty value behaves the same), `per_user_secret` (each user stores their own secret per `secret_schema`, injected per user at runtime), `per_user_oauth` (each user completes their own OAuth grant; discovery and registration run lazily on first use).", - "enum": [ - "shared", - "per_user_secret", - "per_user_oauth" - ], - "type": "string" - }, - "call_timeout": { - "description": "Tool-call timeout in seconds (0 = server default, 60s).", - "type": "integer" + "description": "Execution environments this server is callable from (`cloud` and/or BYOC runner environment IDs). Always present; `[]` means all environments (also the value on legacy rows created before this field)." }, - "can_edit": { - "description": "Whether the caller may edit this server.", - "type": "boolean" + "server_name": { + "type": "string", + "description": "MCP server name, unique within its scope (account-wide or one team)." }, - "command": { - "description": "Executable command (stdio transport only).", - "type": "string" + "description": { + "type": "string", + "description": "Server description." }, - "connect_timeout": { - "description": "Connection timeout in seconds (0 = server default, 10s).", - "type": "integer" + "ai_description": { + "type": "string", + "description": "LLM-generated description, preferred over `description` when present. Omitted when not yet generated." }, - "created_at": { - "description": "Creation time. Unix timestamp in milliseconds.", - "format": "int64", - "type": "integer" + "transport": { + "type": "string", + "description": "Transport protocol. One of: `stdio` (standard I/O to a local subprocess), `sse` (standalone SSE, the legacy MCP transport), `streamable-http` (the newer HTTP streaming transport).", + "enum": [ + "stdio", + "sse", + "streamable-http" + ] }, - "created_by": { - "description": "Member ID that created the server.", - "format": "int64", - "type": "integer" + "command": { + "type": "string", + "description": "Executable command (stdio transport only)." }, - "description": { - "description": "Server description.", - "type": "string" + "args": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Command arguments (stdio transport)." }, "env": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "Environment variables (stdio transport). Secret values are masked.", - "type": "object" + "description": "Environment variables (`stdio` transport). Values under credential-looking names, or encrypted at rest, are masked: longer than 8 characters shows the first and last 4 characters around `****`, otherwise `****`. Omitted when empty." }, - "environments": { - "description": "Execution environments this server is callable from (`cloud` and/or BYOC runner environment IDs). Always present; `[]` means all environments (also the value on legacy rows created before this field).", - "items": { - "type": "string" - }, - "type": "array" + "url": { + "type": "string", + "description": "Server URL (sse / streamable-http transport)." }, "headers": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "HTTP headers (sse / streamable-http). Secret values are masked.", - "type": "object" - }, - "oauth_metadata": { - "description": "JSON-encoded OAuth metadata (per_user_oauth mode).", - "type": "string" + "description": "HTTP headers (`sse` / `streamable-http` transport), masked by the same rule as `env`. Omitted when empty." }, "proxy_url": { - "description": "Outbound proxy URL used to reach the server.", - "type": "string" + "type": "string", + "description": "Outbound proxy URL used to reach the server. Not settable through the public API; omitted when empty." }, - "secret_schema": { - "description": "JSON-encoded secret schema (per_user_secret mode).", - "type": "string" + "status": { + "type": "string", + "description": "Whether the server's tools are offered to AI SRE sessions:\n- `enabled`: available (default on create).\n- `disabled`: kept but not offered; re-enable with `POST /safari/mcp/server/enable`.", + "enum": [ + "enabled", + "disabled" + ] }, - "server_id": { - "description": "Unique MCP server ID (prefix `mcp_`).", - "type": "string" + "connect_timeout": { + "type": "integer", + "description": "Connection timeout in seconds as stored; `0` means the 10-second default is used." }, - "server_name": { - "description": "MCP server name, unique within its scope (account-wide or one team), case-insensitive.", - "type": "string" + "call_timeout": { + "type": "integer", + "description": "Tool-call timeout in seconds as stored; `0` means the 60-second default is used." }, - "source_template_name": { - "description": "Marketplace template this connector was installed from; empty for user-authored.", - "type": "string" + "allow_insecure_oauth_http": { + "type": "boolean", + "description": "Allow this server's OAuth token exchange over plaintext HTTP; testing use only. Omitted when false." }, - "status": { - "description": "Server status.", + "allow_insecure_tls_skip_verify": { + "type": "boolean", + "description": "Skip TLS certificate verification when connecting to this server; testing use only. Omitted when false." + }, + "auth_mode": { + "type": "string", + "description": "Who supplies the credential; omitted when empty, which behaves like `shared`:\n- `shared`: one credential stored on the server (`env` / `headers`) is used for every caller.\n- `per_user_secret`: each user stores their own secret, sent in the header named by `secret_schema.header_name`.\n- `per_user_oauth`: each user completes their own OAuth authorization; discovery and client registration run on first use.", "enum": [ - "enabled", - "disabled" - ], - "type": "string" + "shared", + "per_user_secret", + "per_user_oauth" + ] }, - "team_id": { - "description": "Team scope: 0 = account-wide; >0 = the owning team.", + "secret_schema": { + "type": "string", + "description": "JSON-encoded secret schema (per_user_secret mode)." + }, + "oauth_metadata": { + "type": "string", + "description": "JSON-encoded OAuth metadata (per_user_oauth mode)." + }, + "source_template_name": { + "type": "string", + "description": "Marketplace template this server was installed from; omitted for servers created by hand." + }, + "test_error": { + "type": "string", + "description": "Error message from the last connection test; omitted when the last test succeeded or the server was never tested." + }, + "tested_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Time of the last connection test, Unix timestamp in milliseconds; omitted if the server was never tested." }, - "transport": { - "description": "Transport protocol. One of: `stdio` (standard I/O to a local subprocess), `sse` (standalone SSE, the legacy MCP transport), `streamable-http` (the newer HTTP streaming transport).", - "enum": [ - "stdio", - "sse", - "streamable-http" - ], - "type": "string" + "created_by": { + "type": "integer", + "description": "Member ID that created the server.", + "format": "int64" }, - "updated_at": { - "description": "Last update time. Unix timestamp in milliseconds.", + "created_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Creation time. Unix timestamp in milliseconds." }, - "url": { - "description": "Server URL (sse / streamable-http transport).", - "type": "string" + "updated_at": { + "type": "integer", + "format": "int64", + "description": "Last update time. Unix timestamp in milliseconds." } }, "required": [ @@ -14980,53 +15295,53 @@ "created_at", "updated_at", "environments" - ], - "type": "object" + ] }, "MCPServerListRequest": { + "type": "object", "description": "Pagination, scope, and search filters for listing MCP servers.", "properties": { - "include_account": { - "description": "Include account-scoped (team_id=0) rows. Defaults to true.", - "type": [ - "boolean", - "null" - ] - }, - "limit": { - "default": 20, - "description": "Page size.", - "type": "integer" - }, "p": { - "default": 1, - "description": "Page number, 1-based.", - "type": "integer" + "type": "integer", + "description": "Page number, 1-based; values below 1 are treated as 1.", + "default": 1 }, - "query": { - "description": "Case-insensitive substring search across name, description, AI-generated description, server ID, transport, URL, command, and source template name.", - "maxLength": 128, - "type": "string" + "limit": { + "type": "integer", + "description": "Page size; values below 1 fall back to 20. No upper bound is enforced.", + "default": 20 }, "scope": { + "type": "string", "description": "Restrict results to a scope: `account` for account-wide rows only, `team` for the caller's own visible team rows only, or omit (defaults to `all`) for both, subject to team_ids/include_account.", "enum": [ "all", "account", "team" ], - "type": "string" + "default": "all" + }, + "query": { + "type": "string", + "maxLength": 128, + "description": "Case-insensitive substring search across name, description, AI-generated description, server ID, transport, URL, command, and source template name." }, "team_ids": { - "description": "Filter to these team IDs; empty = the caller's visible set.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Restrict to these team IDs. IDs of teams the caller does not belong to are ignored; empty means all of the caller's teams." + }, + "include_account": { + "type": [ + "boolean", + "null" + ], + "description": "Include account-scoped (`team_id=0`) rows. Defaults to `true`; ignored when `scope` is `account` (always included) or `team` (never included)." } - }, - "type": "object" + } }, "MCPServerListResponse": { "description": "Paginated MCP server list.", @@ -15064,119 +15379,124 @@ "type": "object" }, "MCPServerUpdateRequest": { + "type": "object", "description": "Partial update of an MCP server. Omit a field to leave it unchanged.", "properties": { - "allow_insecure_oauth_http": { - "description": "Allow OAuth token exchange over plaintext HTTP. Omit to leave unchanged.", - "type": [ - "boolean", - "null" - ] + "server_id": { + "type": "string", + "description": "Target MCP server ID, from the list returned by `POST /safari/mcp/server/list`." }, - "allow_insecure_tls_skip_verify": { - "description": "Skip TLS certificate verification. Omit to leave unchanged.", - "type": [ - "boolean", - "null" + "server_name": { + "type": "string", + "description": "New name; omitted or empty leaves it unchanged.", + "minLength": 1, + "maxLength": 255 + }, + "description": { + "type": "string", + "description": "New description; omitted or empty leaves it unchanged.", + "minLength": 1, + "maxLength": 1024 + }, + "transport": { + "type": "string", + "description": "Transport protocol; when switching, also supply the matching fields (`command`/`args`/`env` for `stdio`, `url`/`headers` for `sse` / `streamable-http`); omitted or empty leaves it unchanged.", + "enum": [ + "stdio", + "sse", + "streamable-http" ] }, + "command": { + "type": "string", + "description": "New executable command (`stdio` transport); omitted or empty leaves it unchanged." + }, "args": { - "description": "Command arguments (`stdio` transport); replaces the whole list — pass `[]` to clear, omit to leave unchanged.", + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "auth_mode": { - "description": "Authentication mode: shared (default), per_user_secret, or per_user_oauth.", - "type": "string" - }, - "call_timeout": { - "description": "Tool-call timeout in seconds. 0 = default (60s).", - "type": "integer" - }, - "command": { - "description": "Executable command (stdio transport).", - "type": "string" - }, - "connect_timeout": { - "description": "Connection timeout in seconds. 0 = default (10s).", - "type": "integer" - }, - "description": { - "description": "New description; omitted or empty leaves it unchanged.", - "maxLength": 1024, - "minLength": 1, - "type": "string" + "description": "Command arguments (`stdio` transport); replaces the whole list — pass `[]` to clear, omit to leave unchanged." }, "env": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "Environment variables (`stdio` transport); replaces the whole map, but a sensitive key sent back masked or as an empty string keeps its stored value; omit to leave unchanged.", - "type": "object" + "description": "Environment variables (`stdio` transport); replaces the whole map, so keys left out are removed. For a protected key (see the masking rule on get), sending the masked value or an empty string keeps the stored value. Omit to leave unchanged." }, - "environments": { - "description": "Execution environments this server is callable from: `cloud` and/or BYOC runner environment IDs. Omit (null) to leave unchanged; send a list to set it — an empty list clears the restriction back to all environments.", - "items": { - "type": "string" - }, - "type": [ - "array", - "null" - ] + "url": { + "type": "string", + "description": "New server URL (`sse` / `streamable-http` transport); omitted or empty leaves it unchanged. A real change also clears `oauth_metadata` unless a new one is sent." }, "headers": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "HTTP headers (`sse` / `streamable-http` transport); replaces the whole map, with the same masked/empty-value preservation as `env`; omit to leave unchanged.", - "type": "object" + "description": "HTTP headers (`sse` / `streamable-http` transport); replaces the whole map, with the same masked/empty-value preservation as `env`; omit to leave unchanged." }, - "oauth_metadata": { - "description": "JSON OAuth metadata; reserved for per_user_oauth.", - "type": "string" + "connect_timeout": { + "type": "integer", + "description": "New connection timeout in seconds; omitted or `0` leaves it unchanged (a stored `0` means the 10-second default)." }, - "secret_schema": { - "description": "JSON secret schema; required when auth_mode=per_user_secret.", - "type": "string" + "call_timeout": { + "type": "integer", + "description": "New tool-call timeout in seconds; omitted or `0` leaves it unchanged (a stored `0` means the 60-second default)." }, - "server_id": { - "description": "Target MCP server ID, from the list returned by `POST /safari/mcp/server/list`.", - "type": "string" + "auth_mode": { + "type": "string", + "description": "New auth mode; omitted or empty leaves it unchanged. Who supplies the credential:\n- `shared` (default; an empty value behaves the same): one credential stored on the server (`env` / `headers`) is used for every caller.\n- `per_user_secret`: each user stores their own secret, sent in the header named by `secret_schema.header_name`.\n- `per_user_oauth`: each user completes their own OAuth authorization; discovery and client registration run on first use.\n\n`per_user_secret` requires `secret_schema` with a non-empty `header_name`; any other value returns `InvalidParameter`.", + "enum": [ + "shared", + "per_user_secret", + "per_user_oauth" + ] }, - "server_name": { - "description": "New name; omitted or empty leaves it unchanged.", - "maxLength": 255, - "minLength": 1, - "type": "string" + "secret_schema": { + "type": "string", + "description": "New JSON secret schema, e.g. `{\"header_name\":\"X-Api-Key\"}`. Applied only together with a non-empty `auth_mode`; sent alone it is ignored." + }, + "oauth_metadata": { + "type": "string", + "description": "New JSON OAuth metadata. A non-empty value is stored as sent. When omitted or empty, the stored value is kept unless `auth_mode` or `url` changes, in which case it is cleared." }, "team_id": { - "description": "Reassign team scope: 0 = account-wide; >0 = team. Omit to leave unchanged.", - "format": "int64", "type": [ "integer", "null" - ] + ], + "description": "Reassign team scope: `0` = account-wide (account owner or admin only); `>0` = a team the caller belongs to. Servers installed from the marketplace can only move to `0`. Omit to leave unchanged.", + "format": "int64" }, - "transport": { - "description": "Transport protocol; when switching, also supply the matching fields (`command`/`args`/`env` for `stdio`, `url`/`headers` for `sse` / `streamable-http`); omitted or empty leaves it unchanged.", - "enum": [ - "stdio", - "sse", - "streamable-http" + "environments": { + "type": [ + "array", + "null" ], - "type": "string" + "items": { + "type": "string" + }, + "description": "Execution environments this server is callable from: `cloud` and/or BYOC runner environment IDs. Omit (null) to leave unchanged; send a list to set it — an empty list clears the restriction back to all environments." }, - "url": { - "description": "Server URL (sse / streamable-http transport).", - "type": "string" + "allow_insecure_oauth_http": { + "type": [ + "boolean", + "null" + ], + "description": "Allow OAuth token exchange over plaintext HTTP. Omit to leave unchanged." + }, + "allow_insecure_tls_skip_verify": { + "type": [ + "boolean", + "null" + ], + "description": "Skip TLS certificate verification. Omit to leave unchanged." } }, "required": [ "server_id" - ], - "type": "object" + ] }, "ManualRunRuleResult": { "description": "Result of manually running an Automation rule outside its schedule.", @@ -15207,73 +15527,75 @@ "type": "object" }, "MappingAPICreateRequest": { + "type": "object", + "required": [ + "api_name", + "url" + ], "properties": { "api_name": { - "description": "Unique API name (max 199 chars).", + "type": "string", "maxLength": 199, - "type": "string" + "description": "Name of the mapping API, unique among non-deleted mapping APIs (max 199 characters)." }, "description": { - "description": "Optional description. Values longer than 500 characters are silently truncated.", - "type": "string" + "type": "string", + "description": "Optional description. Values longer than 500 characters are silently truncated." + }, + "url": { + "type": "string", + "format": "uri", + "maxLength": 500, + "description": "Endpoint called with `POST`. Must be an `http` or `https` URL of at most 500 characters; in SaaS the host must not resolve to an internal IP address." + }, + "insecure_skip_verify": { + "type": "boolean", + "description": "Skip TLS certificate verification. Default `false`." }, "headers": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "Custom HTTP request headers. In SaaS mode, security-sensitive names (`authorization`, `cookie`, `x-forwarded-for`, etc.) are rejected; keys must be RFC 7230 token characters (max 1024 chars) and values max 4096 chars.", - "type": "object" + "description": "Custom HTTP request headers. In SaaS mode, security-sensitive names (`authorization`, `cookie`, `x-forwarded-for`, etc.) are rejected; keys must be RFC 7230 token characters (max 1024 chars) and values max 4096 chars." }, - "insecure_skip_verify": { - "description": "Skip TLS certificate verification. Default `false`.", - "type": "boolean" + "timeout": { + "type": "integer", + "description": "Timeout of the whole request in seconds (1–3). Defaults to 2 when omitted or 0.", + "minimum": 1, + "maximum": 3, + "default": 2 }, "retry_count": { - "description": "Number of retries on failure (0–1). Default 0.", - "maximum": 1, + "type": "integer", + "description": "Number of retries after a failed call (0–1). Defaults to 0.", "minimum": 0, - "type": "integer" + "maximum": 1, + "default": 0 }, "team_id": { - "description": "Owning team ID; obtain it from `POST /team/list`.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "timeout": { - "description": "Request timeout in seconds (1–3). Default 2.", - "maximum": 3, - "minimum": 1, - "type": "integer" - }, - "url": { - "description": "HTTP/HTTPS endpoint URL (max 500 chars).", - "format": "uri", - "maxLength": 500, - "type": "string" + "description": "Owning team ID; obtain it from `POST /team/list`. `0` or omitted means no team. A non-zero ID must be an existing team." } - }, - "required": [ - "api_name", - "url" - ], - "type": "object" + } }, "MappingAPICreateResponse": { + "type": "object", "properties": { "api_id": { - "description": "Created API ID (MongoDB ObjectID hex).", - "type": "string" + "type": "string", + "description": "Created API ID (MongoDB ObjectID hex)." }, "api_name": { - "description": "API name.", - "type": "string" + "type": "string", + "description": "Name of the created mapping API, as sent in the request." } }, "required": [ "api_id", "api_name" - ], - "type": "object" + ] }, "MappingAPIIDRequest": { "properties": { @@ -15288,83 +15610,84 @@ "type": "object" }, "MappingAPIItem": { + "type": "object", "description": "Mapping API configuration.", "properties": { "api_id": { - "description": "API ID (MongoDB ObjectID hex).", - "type": "string" + "type": "string", + "description": "API ID (MongoDB ObjectID hex)." }, "api_name": { - "description": "API name.", - "type": "string" - }, - "created_at": { - "description": "Creation time, Unix seconds. Omitted when 0 (legacy records).", - "format": "int64", - "type": "integer" - }, - "creator_id": { - "description": "Creator member ID.", - "format": "int64", - "type": "integer" - }, - "deleted_at": { - "description": "Deletion time, Unix seconds. Omitted when the API has not been soft-deleted.", - "format": "int64", - "type": "integer" + "type": "string", + "description": "Name of the mapping API, unique among non-deleted mapping APIs." }, "description": { - "description": "Description.", - "type": "string" + "type": "string", + "description": "Free-text description (at most 500 characters); an empty string when none was given." + }, + "url": { + "type": "string", + "description": "Endpoint URL." }, "headers": { - "additionalProperties": { - "type": "string" - }, - "description": "Custom request headers. `null` when none are configured.", "type": [ "object", "null" - ] + ], + "additionalProperties": { + "type": "string" + }, + "description": "Request headers sent with every call, returned in plain text to callers who can edit the API (the account owner or an admin, the API's creator, or a member of its team). `null` when none are configured or the caller cannot edit the API." }, - "insecure_skip_verify": { - "description": "Whether TLS verification is skipped.", - "type": "boolean" + "timeout": { + "type": "integer", + "description": "Timeout of the whole request in seconds (1–3)." }, "retry_count": { - "description": "Retry count.", - "type": "integer" + "type": "integer", + "description": "Number of retries after a failed call: `0` or `1`." + }, + "insecure_skip_verify": { + "type": "boolean", + "description": "Whether TLS verification is skipped." }, "status": { - "description": "API status: `enabled` or `deleted` (soft-deleted). The list endpoint excludes `deleted` items; the info endpoint may return them.", + "type": "string", "enum": [ "enabled", "deleted" ], - "type": "string" + "description": "API status: `enabled` or `deleted` (soft-deleted). The list endpoint excludes `deleted` items; the info endpoint may return them." }, "team_id": { - "description": "Owning team ID.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "timeout": { - "description": "Request timeout in seconds.", - "type": "integer" + "description": "Owning team ID." }, - "updated_at": { - "description": "Last update time, Unix seconds. Omitted when 0 (legacy records).", + "creator_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Creator member ID." }, "updated_by": { - "description": "Last updater member ID.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last updater member ID." }, - "url": { - "description": "Endpoint URL.", - "type": "string" + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation time, Unix seconds. Omitted when 0 (legacy records)." + }, + "updated_at": { + "type": "integer", + "format": "int64", + "description": "Last update time, Unix seconds. Omitted when 0 (legacy records)." + }, + "deleted_at": { + "type": "integer", + "format": "int64", + "description": "Deletion time, Unix seconds. Omitted when the API has not been soft-deleted." } }, "required": [ @@ -15380,340 +15703,348 @@ "team_id", "updated_by", "creator_id" - ], - "type": "object" + ] }, "MappingAPIListResponse": { + "type": "object", "properties": { + "total": { + "type": "integer", + "description": "Number of items returned; the list is not paginated." + }, "items": { - "description": "Mapping APIs.", + "type": "array", "items": { "$ref": "#/components/schemas/MappingAPIItem" }, - "type": "array" - }, - "total": { - "description": "Total API count.", - "type": "integer" + "description": "Mapping APIs." } }, "required": [ "total", "items" - ], - "type": "object" + ] }, "MappingAPIUpdateRequest": { + "type": "object", + "required": [ + "api_id" + ], "properties": { "api_id": { - "description": "Mapping API ID (MongoDB ObjectID hex).", - "type": "string" + "type": "string", + "description": "Mapping API ID (MongoDB ObjectID hex)." }, "api_name": { - "description": "New API name (max 199 chars).", - "maxLength": 199, "type": [ "string", "null" - ] + ], + "maxLength": 199, + "description": "New name, unique among non-deleted mapping APIs (max 199 characters). Omit to keep." }, "description": { - "description": "New description.", "type": [ "string", "null" - ] + ], + "description": "New description; longer than 500 characters is truncated. Omit to keep, send `\"\"` to clear." }, - "headers": { - "additionalProperties": { - "type": "string" - }, - "description": "Custom HTTP request headers. In SaaS mode, security-sensitive names (`authorization`, `cookie`, `x-forwarded-for`, etc.) are rejected; keys must be RFC 7230 token characters (max 1024 chars) and values max 4096 chars.", - "type": "object" + "url": { + "type": [ + "string", + "null" + ], + "format": "uri", + "maxLength": 500, + "description": "New `http`/`https` endpoint (max 500 characters); in SaaS the host must not resolve to an internal IP. Omit to keep." }, "insecure_skip_verify": { - "description": "New TLS skip-verify setting.", "type": [ "boolean", "null" - ] + ], + "description": "New TLS skip-verify setting. Omit to keep." }, - "retry_count": { - "description": "New retry count.", - "maximum": 1, - "minimum": 0, - "type": [ - "integer", - "null" - ] + "headers": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Replaces the whole header map when sent; send `{}` to remove all headers. Omit to keep. In SaaS, sensitive header names (see `/enrichment/mapping/api/create`) are rejected; keys are at most 1,024 characters and values at most 4,096." }, - "team_id": { - "description": "New owning team ID; obtain it from `POST /team/list`.", - "format": "int64", + "timeout": { "type": [ "integer", "null" - ] - }, - "timeout": { - "description": "New timeout in seconds.", - "maximum": 3, + ], + "description": "New whole-request timeout in seconds (1–3). Omit to keep.", "minimum": 1, + "maximum": 3 + }, + "retry_count": { "type": [ "integer", "null" - ] + ], + "description": "New retry count (0–1). Omit to keep.", + "minimum": 0, + "maximum": 1 }, - "url": { - "description": "New endpoint URL (max 500 chars).", - "format": "uri", - "maxLength": 500, + "team_id": { "type": [ - "string", + "integer", "null" - ] + ], + "format": "int64", + "description": "New owning team ID from `POST /team/list`; `0` removes the team. Omit to keep." } - }, - "required": [ - "api_id" - ], - "type": "object" + } }, "MappingDataDeleteRequest": { + "type": "object", + "required": [ + "schema_id", + "keys" + ], "properties": { + "schema_id": { + "type": "string", + "description": "Mapping schema ID (MongoDB ObjectID hex)." + }, "keys": { - "description": "Keys of rows to delete.", + "type": "array", "items": { "type": "string" }, "maxItems": 100, - "type": "array" - }, - "schema_id": { - "description": "Mapping schema ID (MongoDB ObjectID hex).", - "type": "string" + "description": "Row keys to delete (at most 100), as returned in `key` by `/enrichment/mapping/data/list` or in `keys` by `/enrichment/mapping/data/upsert`. Keys that match no row are ignored." } - }, - "required": [ - "schema_id", - "keys" - ], - "type": "object" + } }, "MappingDataItem": { + "type": "object", "description": "A single mapping data row.", "properties": { - "created_at": { - "description": "Creation time, Unix seconds. Omitted when 0.", - "format": "int64", - "type": "integer" + "key": { + "type": "string", + "description": "Composite row key — MD5 of the row's source label values (sorted by label name, joined with `:`). Omitted when empty." }, "fields": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "All label key-value pairs of this row. Omitted when empty.", - "type": "object" + "description": "All label key-value pairs of this row. Omitted when empty." }, - "key": { - "description": "Composite row key — MD5 of the row's source label values (sorted by label name, joined with `:`). Omitted when empty.", - "type": "string" + "created_at": { + "type": "integer", + "format": "int64", + "description": "Time the row was last written, Unix seconds; a replaced row gets a new value. Omitted when 0." }, "updated_at": { - "description": "Last update time, Unix seconds. Omitted when 0.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update time, Unix seconds. Omitted when 0." } - }, - "type": "object" + } }, "MappingDataListRequest": { + "type": "object", + "required": [ + "schema_id" + ], "properties": { - "asc": { - "description": "Sort ascending when `true`.", - "type": "boolean" + "schema_id": { + "type": "string", + "description": "Mapping schema ID (MongoDB ObjectID hex)." }, - "limit": { - "description": "Page size (0–100); defaults to 20 when omitted, `null`, or 0.", - "format": "int64", - "maximum": 100, - "minimum": 0, - "type": [ - "integer", - "null" - ] + "query": { + "type": "object", + "additionalProperties": { + "type": "string" + }, + "description": "Exact-match filter on source label values. Keys that are not source labels of the schema are silently ignored; if any source label is given, all source labels must be provided." }, "orderby": { - "description": "Sort field. Defaults to `updated_at`.", + "type": "string", "enum": [ "created_at", "updated_at" ], - "type": "string" + "description": "Sort field. Defaults to `updated_at`." + }, + "asc": { + "type": "boolean", + "description": "Sort ascending when `true`; defaults to `false` (newest first).", + "default": false }, "p": { - "description": "Page number (1-based) for offset pagination; defaults to 1 when omitted, `null`, or 0. Ignored when `search_after_ctx` is set. Page-based navigation can reach at most 10,000 rows (`p * limit <= 10000`).", - "format": "int64", - "minimum": 0, "type": [ "integer", "null" - ] - }, - "query": { - "additionalProperties": { - "type": "string" - }, - "description": "Exact-match filter on source label values. Keys that are not source labels of the schema are silently ignored; if any source label is given, all source labels must be provided.", - "type": "object" + ], + "format": "int64", + "description": "Page number (1-based) for offset pagination; defaults to 1 when omitted, `null`, or 0. Ignored when `search_after_ctx` is set. Page-based navigation can reach at most 10,000 rows (`p * limit <= 10000`).", + "minimum": 0 }, - "schema_id": { - "description": "Mapping schema ID (MongoDB ObjectID hex).", - "type": "string" + "limit": { + "type": [ + "integer", + "null" + ], + "format": "int64", + "description": "Page size (0–100); defaults to 20 when omitted, `null`, or 0.", + "minimum": 0, + "maximum": 100 }, "search_after_ctx": { - "description": "Opaque cursor for cursor-based pagination — pass the `search_after_ctx` value from the previous response. Must be a MongoDB ObjectID hex string; when set, `p` is ignored.", "type": [ "string", "null" - ] + ], + "description": "Opaque cursor for cursor-based pagination — pass the `search_after_ctx` value from the previous response. Must be a MongoDB ObjectID hex string; when set, `p` is ignored." } - }, - "required": [ - "schema_id" - ], - "type": "object" + } }, "MappingDataListResponse": { + "type": "object", "properties": { - "has_next_page": { - "description": "Whether more pages exist.", - "type": "boolean" - }, "items": { - "description": "Data rows.", + "type": "array", "items": { "$ref": "#/components/schemas/MappingDataItem" }, - "type": "array" - }, - "search_after_ctx": { - "description": "Cursor token (ObjectID hex of this page's last row) for fetching the next page. Omitted when there is no next page.", - "type": "string" + "description": "Data rows of this page, ordered by `orderby`/`asc`. Empty when nothing matches." }, "total": { - "description": "Total matching rows.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Number of rows matching `query`, counted up to 1,000; a value of 1,000 means at least 1,000." + }, + "has_next_page": { + "type": "boolean", + "description": "`true` when more rows follow this page." + }, + "used_cnt": { + "type": "integer", + "format": "int64", + "description": "Total number of rows stored in the schema, regardless of `query`. Compare it with the schema row limit (10,000 by default)." + }, + "search_after_ctx": { + "type": "string", + "description": "Cursor token (ObjectID hex of this page's last row) for fetching the next page. Omitted when there is no next page." } }, "required": [ "items", "total", - "has_next_page" - ], - "type": "object" + "has_next_page", + "used_cnt" + ] }, "MappingDataUpsertRequest": { + "type": "object", + "required": [ + "schema_id", + "docs" + ], "properties": { + "schema_id": { + "type": "string", + "description": "Mapping schema ID (MongoDB ObjectID hex)." + }, "docs": { - "description": "Rows to insert or update. Each row must include all source and result labels; unknown labels are silently dropped; a value longer than 2048 characters is rejected.", + "type": "array", "items": { + "type": "object", "additionalProperties": { "type": "string" - }, - "type": "object" + } }, "maxItems": 1000, - "type": "array" - }, - "schema_id": { - "description": "Mapping schema ID (MongoDB ObjectID hex).", - "type": "string" + "description": "Rows to insert or replace (at most 1,000). Each row maps label names to values and must include every source and result label; other keys are dropped; a value longer than 2,048 bytes is rejected. A row whose source label values match an existing row replaces it." } - }, - "required": [ - "schema_id", - "docs" - ], - "type": "object" + } }, "MappingDataUpsertResponse": { + "type": "object", "properties": { "keys": { - "description": "Composite keys of upserted rows.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Row keys of the written rows (one per distinct row, in no particular order); use them with `/enrichment/mapping/data/delete`." } }, "required": [ "keys" - ], - "type": "object" + ] }, "MappingSchemaCreateRequest": { + "type": "object", + "required": [ + "schema_name", + "source_labels", + "result_labels" + ], "properties": { + "schema_name": { + "type": "string", + "maxLength": 39, + "description": "Schema name, unique among the account's non-deleted schemas (max 39 characters)." + }, "description": { - "description": "Optional description (max 500 chars).", + "type": "string", "maxLength": 500, - "type": "string" - }, - "result_labels": { - "description": "Output label names written on a match (1–10). Each must match `^[a-zA-Z_][a-zA-Z0-9_]*$`; entries must be unique and must not overlap with `source_labels`.", - "items": { - "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", - "type": "string" - }, - "maxItems": 10, - "type": "array", - "uniqueItems": true + "description": "Optional description (max 500 chars)." }, - "schema_name": { - "description": "Unique schema name (max 39 chars).", - "maxLength": 39, - "type": "string" + "team_id": { + "type": "integer", + "format": "int64", + "description": "Owning team ID from `POST /team/list`. `0` or omitted means no team; a non-zero ID must be an existing team." }, "source_labels": { - "description": "Lookup key label names (1–3). Each must match `^[a-zA-Z_][a-zA-Z0-9_]*$`; entries must be unique and must not overlap with `result_labels`.", + "type": "array", "items": { - "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$", - "type": "string" + "type": "string", + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" }, "maxItems": 3, - "type": "array", - "uniqueItems": true + "description": "Lookup key label names (1–3). Each must match `^[a-zA-Z_][a-zA-Z0-9_]*$`; entries must be unique and must not overlap with `result_labels`.", + "uniqueItems": true, + "minItems": 1 }, - "team_id": { - "description": "Owning team ID. `0` means no team.", - "format": "int64", - "type": "integer" + "result_labels": { + "type": "array", + "items": { + "type": "string", + "pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" + }, + "maxItems": 10, + "description": "Output label names written on a match (1–10). Each must match `^[a-zA-Z_][a-zA-Z0-9_]*$`; entries must be unique and must not overlap with `source_labels`.", + "uniqueItems": true, + "minItems": 1 } - }, - "required": [ - "schema_name", - "source_labels", - "result_labels" - ], - "type": "object" + } }, "MappingSchemaCreateResponse": { + "type": "object", "properties": { "schema_id": { - "description": "Created schema ID (MongoDB ObjectID hex).", - "type": "string" + "type": "string", + "description": "Created schema ID (MongoDB ObjectID hex)." }, "schema_name": { - "description": "Schema name.", - "type": "string" + "type": "string", + "description": "Name of the created schema, as sent in the request." } }, "required": [ "schema_id", "schema_name" - ], - "type": "object" + ] }, "MappingSchemaIDRequest": { "properties": { @@ -15728,71 +16059,72 @@ "type": "object" }, "MappingSchemaItem": { + "type": "object", "description": "Mapping schema definition.", "properties": { - "created_at": { - "description": "Creation time, Unix seconds. Omitted when 0 (legacy records).", - "format": "int64", - "type": "integer" - }, - "creator_id": { - "description": "Creator member ID.", - "format": "int64", - "type": "integer" + "schema_id": { + "type": "string", + "description": "Schema ID (MongoDB ObjectID hex)." }, - "deleted_at": { - "description": "Deletion time, Unix seconds. Omitted when the schema has not been soft-deleted.", - "format": "int64", - "type": "integer" + "schema_name": { + "type": "string", + "description": "Schema name, unique among the account's non-deleted schemas." }, "description": { - "description": "Schema description.", - "type": "string" + "type": "string", + "description": "Schema description." }, - "result_labels": { - "description": "Output label names.", + "source_labels": { + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "schema_id": { - "description": "Schema ID (MongoDB ObjectID hex).", - "type": "string" - }, - "schema_name": { - "description": "Schema name.", - "type": "string" + "description": "Label names whose values form the lookup key of a data row (1–3); fixed at creation." }, - "source_labels": { - "description": "Lookup key label names.", + "result_labels": { + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Label names written to the event when a row matches (1–10); fixed at creation." }, "status": { - "description": "Schema status: `enabled` or `deleted` (soft-deleted). The list endpoint excludes `deleted` items; the info endpoint may return them.", + "type": "string", "enum": [ "enabled", "deleted" ], - "type": "string" + "description": "Schema status: `enabled` or `deleted` (soft-deleted). The list endpoint excludes `deleted` items; the info endpoint may return them." }, "team_id": { - "description": "Owning team ID.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Owning team ID; `0` when the schema belongs to no team." }, - "updated_at": { - "description": "Last update time, Unix seconds. Omitted when 0 (legacy records).", + "creator_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Creator member ID." }, "updated_by": { - "description": "Last updater member ID.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last updater member ID." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation time, Unix seconds. Omitted when 0 (legacy records)." + }, + "updated_at": { + "type": "integer", + "format": "int64", + "description": "Last update time, Unix seconds. Omitted when 0 (legacy records)." + }, + "deleted_at": { + "type": "integer", + "format": "int64", + "description": "Deletion time, Unix seconds. Omitted when the schema has not been soft-deleted." } }, "required": [ @@ -15805,66 +16137,99 @@ "team_id", "updated_by", "creator_id" - ], - "type": "object" + ] }, "MappingSchemaListResponse": { + "type": "object", "properties": { + "total": { + "type": "integer", + "description": "Number of items returned; the list is not paginated." + }, "items": { - "description": "Mapping schemas.", + "type": "array", "items": { "$ref": "#/components/schemas/MappingSchemaItem" }, - "type": "array" - }, - "total": { - "description": "Total schema count.", - "type": "integer" + "description": "Mapping schemas." } }, "required": [ "total", "items" - ], - "type": "object" + ] }, "MappingSchemaUpdateRequest": { + "type": "object", + "required": [ + "schema_id" + ], "properties": { - "description": { - "description": "New description (max 500 chars).", - "maxLength": 500, - "type": [ - "string", - "null" - ] - }, "schema_id": { - "description": "Schema ID (MongoDB ObjectID hex).", - "type": "string" + "type": "string", + "description": "Schema ID (MongoDB ObjectID hex)." }, "schema_name": { - "description": "New schema name (max 39 chars).", + "type": [ + "string", + "null" + ], "maxLength": 39, + "description": "New name, unique among non-deleted schemas (max 39 characters). Omit to keep." + }, + "description": { "type": [ "string", "null" - ] + ], + "maxLength": 500, + "description": "New description (max 500 characters). Omit to keep, send `\"\"` to clear." }, "team_id": { - "description": "New owning team ID. `0` removes the team association.", - "format": "int64", "type": [ "integer", "null" - ] + ], + "format": "int64", + "description": "New owning team ID from `POST /team/list`; `0` removes the team. Omit to keep." } - }, - "required": [ - "schema_id" - ], - "type": "object" + } }, "MemberDeleteRequest": { + "type": "object", + "description": "Delete member request (provide one of the lookup fields)", + "properties": { + "member_id": { + "type": "integer", + "format": "uint64", + "description": "Member ID. When several lookup fields are provided, the first non-empty one wins in the order `member_id` > `member_name` > `email` > `phone` > `ref_id`" + }, + "member_name": { + "type": "string", + "description": "Member name. Only used when `member_id` is not provided" + }, + "email": { + "type": "string", + "description": "Email address. Only used when neither `member_id` nor `member_name` is provided" + }, + "phone": { + "type": "string", + "description": "Phone number. Only used when `member_id`, `member_name`, and `email` are all absent" + }, + "country_code": { + "type": "string", + "description": "Region hint for parsing `phone` when it has no \"+\" prefix — an ISO 3166-1 alpha-2 code such as \"CN\" (the default when omitted). Legacy digit calling codes like \"86\" are still accepted in this parsing context." + }, + "ref_id": { + "type": "string", + "description": "External reference ID. Only used when all other lookup fields are absent" + }, + "is_force": { + "type": "boolean", + "description": "Skip the reference check. When false (default), the call fails with `ReferenceExist` if the member belongs to a team, is targeted by an escalation rule, or is in a schedule. A forced delete does not remove those references.", + "default": false + } + }, "anyOf": [ { "required": [ @@ -15891,41 +16256,7 @@ "ref_id" ] } - ], - "description": "Delete member request (provide one of the lookup fields)", - "properties": { - "country_code": { - "description": "Region hint for parsing `phone` when it has no \"+\" prefix — an ISO 3166-1 alpha-2 code such as \"CN\" (the default when omitted). Legacy digit calling codes like \"86\" are still accepted in this parsing context.", - "type": "string" - }, - "email": { - "description": "Email address. Only used when neither `member_id` nor `member_name` is provided", - "type": "string" - }, - "is_force": { - "default": false, - "description": "Force delete. Defaults to false, which checks for references from escalation rules, schedules, etc. Set to true to skip the reference check and delete immediately", - "type": "boolean" - }, - "member_id": { - "description": "Member ID. When several lookup fields are provided, the first non-empty one wins in the order `member_id` > `member_name` > `email` > `phone` > `ref_id`", - "format": "uint64", - "type": "integer" - }, - "member_name": { - "description": "Member name. Only used when `member_id` is not provided", - "type": "string" - }, - "phone": { - "description": "Phone number. Only used when `member_id`, `member_name`, and `email` are all absent", - "type": "string" - }, - "ref_id": { - "description": "External reference ID. Only used when all other lookup fields are absent", - "type": "string" - } - }, - "type": "object" + ] }, "MemberEmptyObject": { "description": "Empty response", @@ -15938,102 +16269,110 @@ "type": "object" }, "MemberInfoResponse": { + "type": "object", "description": "Current member profile", "properties": { - "account_avatar": { - "description": "Account avatar URL", - "type": "string" - }, - "account_email": { - "description": "Account email", - "type": "string" - }, "account_id": { - "description": "Account ID", + "type": "integer", "format": "uint64", - "type": "integer" - }, - "account_locale": { - "description": "Account-level locale preference (e.g. zh-CN or en-US). Omitted when the account has none set.", - "type": "string" + "description": "ID of the account the member belongs to." }, "account_name": { - "description": "Account name", - "type": "string" + "type": "string", + "description": "Name of the account (organization)." + }, + "account_avatar": { + "type": "string", + "description": "Account avatar URL" + }, + "account_email": { + "type": "string", + "description": "Contact email of the account owner." }, "account_role_ids": { - "description": "Assigned role IDs", + "type": "array", "items": { - "format": "uint64", - "type": "integer" + "type": "integer", + "format": "uint64" }, - "type": "array" + "description": "IDs of the roles assigned to the member; resolve them with `POST /role/list`." + }, + "account_locale": { + "type": "string", + "description": "Account-level locale preference (e.g. zh-CN or en-US). Omitted when the account has none set." }, "account_time_zone": { - "description": "Account-level time zone (e.g. Asia/Shanghai). Omitted when the account has none set.", - "type": "string" + "type": "string", + "description": "The account's IANA time zone setting; empty string when the account has none. Always present." }, - "avatar": { - "description": "Member avatar URL", - "type": "string" + "resolved_time_zone": { + "type": "string", + "description": "Effective time zone to render times in: the member's `time_zone` if valid, otherwise the account's, otherwise `Asia/Shanghai`. Always present." }, - "country_code": { - "description": "ISO 3166-1 alpha-2 region code of the member's contact phone (e.g. \"CN\", \"US\", \"HK\").", - "type": "string" + "domain": { + "type": "string", + "description": "Account domain, the subdomain used to sign in to the console." }, - "created_at": { - "description": "Member creation time, Unix timestamp in seconds.", - "format": "int64", - "type": "integer" + "member_id": { + "type": "integer", + "format": "uint64", + "description": "ID of the calling member." }, - "domain": { - "description": "Account domain", - "type": "string" + "member_name": { + "type": "string", + "description": "Member display name" + }, + "phone": { + "type": "string", + "description": "Masked phone number" + }, + "phone_verified": { + "type": "boolean", + "description": "Whether phone is verified" }, "email": { - "description": "Email address", - "type": "string" + "type": "string", + "description": "Email address" }, "email_verified": { - "description": "Whether email is verified", - "type": "boolean" + "type": "boolean", + "description": "Whether email is verified" }, - "is_external": { - "description": "Whether provisioned via SSO", - "type": "boolean" + "country_code": { + "type": "string", + "description": "ISO 3166-1 alpha-2 region code of the member's contact phone (e.g. \"CN\", \"US\", \"HK\")." + }, + "avatar": { + "type": "string", + "description": "Member avatar URL" }, "locale": { - "description": "Member's locale preference. Omitted when the member has none set.", - "type": "string" + "type": "string", + "description": "Member's locale preference. Omitted when the member has none set." }, - "member_id": { - "description": "Member ID", - "format": "uint64", - "type": "integer" + "time_zone": { + "type": "string", + "description": "The member's own IANA time zone setting; empty string when the member follows the account's time zone. Always present." }, - "member_name": { - "description": "Member display name", - "type": "string" + "is_external": { + "type": "boolean", + "description": "Whether provisioned via SSO" }, - "mp_account_id": { - "description": "Account identifier on the marketplace platform. Omitted together with `mp_plat`.", - "type": "string" + "created_at": { + "type": "integer", + "format": "int64", + "description": "Member creation time, Unix timestamp in seconds." }, "mp_plat": { - "description": "Cloud marketplace platform the account was provisioned from. Omitted when the account did not come from a marketplace.", - "type": "string" - }, - "phone": { - "description": "Masked phone number", - "type": "string" - }, - "phone_verified": { - "description": "Whether phone is verified", - "type": "boolean" + "type": "string", + "description": "Cloud marketplace the account was provisioned from: `aws` — AWS Marketplace. Omitted when the account did not come from a marketplace.", + "enum": [ + "aws" + ] }, - "time_zone": { - "description": "Member's IANA time zone. Omitted when the member has none set.", - "type": "string" + "mp_account_id": { + "type": "string", + "description": "Account identifier on the marketplace platform. Omitted together with `mp_plat`." } }, "required": [ @@ -16052,9 +16391,11 @@ "country_code", "avatar", "is_external", - "created_at" - ], - "type": "object" + "created_at", + "time_zone", + "account_time_zone", + "resolved_time_zone" + ] }, "MemberInviteRequest": { "description": "Invite members request", @@ -16078,187 +16419,190 @@ "type": "object" }, "MemberInviteResponse": { + "type": "object", "description": "Invite members response", "properties": { "items": { - "description": "Newly created members", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/components/schemas/NewMemberItem" }, - "type": "array" + "description": "Members created by this call; entries skipped because they already exist are not listed. `null` when no member was created." } - }, - "type": "object" + } }, "MemberItem": { + "type": "object", "description": "Member item", + "required": [ + "account_id", + "member_id", + "member_name", + "country_code", + "phone", + "email", + "phone_verified", + "email_verified", + "avatar", + "status", + "account_role_ids", + "created_at", + "updated_at", + "ref_id", + "is_external" + ], "properties": { "account_id": { - "description": "Account ID", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the account the member belongs to." }, - "account_role_ids": { - "description": "Role IDs", - "items": { - "format": "uint64", - "type": "integer" - }, - "type": "array" + "member_id": { + "type": "integer", + "format": "uint64", + "description": "Member ID; the same value is used as the person ID in other APIs (for example `person_ids`)." }, - "avatar": { - "description": "Avatar URL", - "type": "string" + "member_name": { + "type": "string", + "description": "Display name, unique in the account." }, "country_code": { - "description": "ISO 3166-1 alpha-2 region code of the member's contact phone (e.g. \"CN\", \"US\", \"HK\").", - "type": "string" + "type": "string", + "description": "ISO 3166-1 alpha-2 region code of the member's contact phone (e.g. \"CN\", \"US\", \"HK\")." }, - "created_at": { - "description": "Creation timestamp (Unix seconds)", - "format": "int64", - "type": "integer" + "phone": { + "type": "string", + "description": "Phone number in E.164 form with the middle digits masked (for example `+86151****6519`); empty string when unset." }, "email": { - "description": "Email address", - "type": "string" - }, - "email_verified": { - "description": "Email verified", - "type": "boolean" - }, - "is_external": { - "description": "Provisioned via SSO", - "type": "boolean" + "type": "string", + "description": "Email address in lower case; empty string when unset." }, "locale": { - "description": "Member's locale preference (e.g. `zh-CN`). Omitted when empty — the list endpoint does not populate it.", - "type": "string" - }, - "member_id": { - "description": "Member ID", - "format": "uint64", - "type": "integer" - }, - "member_name": { - "description": "Display name", - "type": "string" + "type": "string", + "description": "Locale preference. Not populated by `POST /member/list`, so it is always omitted there." }, - "phone": { - "description": "Masked phone number", - "type": "string" + "time_zone": { + "type": "string", + "description": "The member's own IANA time zone setting (for example `Asia/Shanghai`). Omitted when unset, which means the member follows the account's time zone; `POST /member/info` returns the effective zone." }, "phone_verified": { - "description": "Phone verified", - "type": "boolean" + "type": "boolean", + "description": "`true` once the member has verified the phone number." }, - "ref_id": { - "description": "External reference ID", - "type": "string" + "email_verified": { + "type": "boolean", + "description": "`true` once the member has verified the email address." + }, + "avatar": { + "type": "string", + "description": "Avatar image URL or path; empty string when unset." }, "status": { - "description": "Member status. `enabled` — active member; `pending` — invited but not yet accepted; `deleted` — removed from the organization.", + "type": "string", "enum": [ "enabled", - "pending", - "deleted" + "pending" ], - "type": "string" + "description": "Member status. `enabled` — active member; `pending` — invited but has not accepted yet. Removed members are not listed." }, - "time_zone": { - "description": "Member's IANA time zone (e.g. `Asia/Shanghai`). Omitted when empty — the list endpoint does not populate it.", - "type": "string" + "account_role_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "uint64" + }, + "description": "IDs of the roles assigned to the member: built-in `2` (Admin), `6` (Responder), `8` (Viewer), or custom role IDs from `POST /role/list`." + }, + "is_external": { + "type": "boolean", + "description": "`true` when the member was provisioned through SSO rather than invited or registered." + }, + "ref_id": { + "type": "string", + "description": "External reference ID (for example an employee ID in an HR system); empty string when unset." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation timestamp (Unix seconds)" }, "updated_at": { - "description": "Update timestamp (Unix seconds)", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Update timestamp (Unix seconds)" } - }, - "required": [ - "account_id", - "member_id", - "member_name", - "country_code", - "phone", - "email", - "phone_verified", - "email_verified", - "avatar", - "status", - "account_role_ids", - "created_at", - "updated_at", - "ref_id", - "is_external" - ], - "type": "object" + } }, "MemberListRequest": { + "type": "object", "description": "List members request", "properties": { - "asc": { - "description": "Ascending order. Default: false (descending)", - "type": "boolean" - }, - "limit": { - "default": 100, - "description": "Page size. Defaults to 100 on the server when omitted or 0", - "maximum": 100, - "minimum": 1, - "type": "integer" + "role_id": { + "type": "integer", + "format": "uint64", + "description": "Filter by role ID. Get role IDs from `POST /role/list` (built-in roles: 2=Admin, 6=Responder, 8=Viewer)" }, "member_id": { - "description": "Filter by member ID. Return only the member with this ID.", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "Filter by member ID. Return only the member with this ID." + }, + "p": { + "type": "integer", + "minimum": 1, + "description": "Page number, starting at 1. Defaults to the first page." + }, + "limit": { + "type": "integer", + "minimum": 1, + "maximum": 100, + "description": "Page size. Defaults to 100 on the server when omitted or 0", + "default": 100 }, "orderby": { - "description": "Sort field. Default: `updated_at`", + "type": "string", "enum": [ "created_at", "updated_at" ], - "type": "string" + "description": "Sort field. Default: `updated_at`" }, - "p": { - "description": "Page number, 1-based", - "minimum": 1, - "type": "integer" + "asc": { + "type": "boolean", + "description": "Ascending order. Default: false (descending)" }, "query": { - "description": "Substring match on member name or email; if the keyword parses as a phone number, an exact phone match is also applied", - "type": "string" - }, - "role_id": { - "description": "Filter by role ID. Get role IDs from `POST /role/list` (built-in roles: 2=Admin, 6=Responder, 8=Viewer)", - "format": "uint64", - "type": "integer" + "type": "string", + "description": "Keyword. Matches a substring of the member name or email; a numeric keyword also matches an exact member ID, and a keyword that parses as a phone number (without `+`, parsed as a Chinese number) also matches the exact phone." } - }, - "type": "object" + } }, "MemberListResponse": { + "type": "object", "description": "Member list response", "properties": { - "items": { - "description": "Member items", - "items": { - "$ref": "#/components/schemas/MemberItem" - }, - "type": "array" + "p": { + "type": "integer", + "description": "Page number from the request; `0` when `p` was omitted (the first page is returned)." }, "limit": { - "description": "Page size", - "type": "integer" - }, - "p": { - "description": "Current page", - "type": "integer" + "type": "integer", + "description": "Page size applied; 100 when `limit` was omitted." }, "total": { - "description": "Total count", - "type": "integer" + "type": "integer", + "description": "Number of members matching the filters, across all pages." + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/MemberItem" + }, + "description": "Members on this page; empty array when none match." } }, "required": [ @@ -16266,33 +16610,32 @@ "limit", "total", "items" - ], - "type": "object" + ] }, "MemberOncallInterval": { + "type": "object", "description": "One on-call shift interval of a member.", "properties": { - "end_at": { - "description": "Unix timestamp in seconds - when the shift ends. Absent while the shift is ongoing.", - "format": "int64", - "type": "integer" - }, "schedule_id": { + "type": "integer", "description": "Owning schedule ID.", - "format": "int64", - "type": "integer" + "format": "int64" }, "schedule_name": { - "description": "Owning schedule name.", - "type": "string" + "type": "string", + "description": "Owning schedule name." }, "start_at": { + "type": "integer", "description": "Unix timestamp in seconds - when the shift starts.", - "format": "int64", - "type": "integer" + "format": "int64" + }, + "end_at": { + "type": "integer", + "description": "Unix timestamp in seconds when the shift ends. Present on `current`; omitted on `next`.", + "format": "int64" } - }, - "type": "object" + } }, "MemberResetInfoRequest": { "anyOf": [ @@ -16364,397 +16707,397 @@ "type": "object" }, "MemberResetInfoUpdates": { + "type": "object", "description": "Member profile fields to write. Omitted fields remain unchanged.", "properties": { - "avatar": { - "description": "New avatar URL.", - "maxLength": 499, + "member_name": { "type": [ "string", "null" - ] + ], + "minLength": 2, + "maxLength": 39, + "description": "New display name, 2–39 characters, unique in the account." }, - "country_code": { - "description": "ISO 3166-1 alpha-2 region code (e.g. \"CN\", \"US\"). Updated independently — `phone` is not required — and also used as the parsing hint for `phone`. Invalid values are rejected with a 400; an explicit empty string is not allowed.", + "password": { "type": [ "string", "null" - ] + ], + "description": "New login password in the encrypted format accepted by the backend." }, - "email": { - "description": "New email address.", + "phone": { "type": [ "string", "null" - ] - }, - "locale": { - "description": "New locale preference. One of: `zh-CN` (Simplified Chinese), `en-US` (English); other values are rejected with a 400.", - "enum": [ - "zh-CN", - "en-US" ], + "description": "New phone number; include `country_code` when it is not in E.164 format. Must not belong to another member; the new number is marked unverified (see `from`)." + }, + "country_code": { "type": [ "string", "null" - ] + ], + "description": "ISO 3166-1 alpha-2 region code (e.g. \"CN\", \"US\"). Updated independently — `phone` is not required — and also used as the parsing hint for `phone`. Invalid values are rejected with a 400; an explicit empty string is not allowed." }, - "member_name": { - "description": "New display name.", - "maxLength": 39, - "minLength": 2, + "email": { "type": [ "string", "null" - ] + ], + "description": "New email address. Must not belong to another member; the new address is marked unverified (see `from`)." }, - "password": { - "description": "New login password in the encrypted format accepted by the backend.", + "avatar": { "type": [ "string", "null" - ] + ], + "maxLength": 499, + "description": "New avatar URL." }, - "phone": { - "description": "New phone number. Include country_code when the number is not in E.164 format.", + "locale": { "type": [ "string", "null" - ] + ], + "enum": [ + "zh-CN", + "en-US" + ], + "description": "New locale preference. One of: `zh-CN` (Simplified Chinese), `en-US` (English); other values are rejected with a 400." }, - "ref_id": { - "description": "New external reference ID.", + "time_zone": { "type": [ "string", "null" - ] + ], + "description": "New IANA time zone name such as `Asia/Shanghai`; an empty string clears it so the member follows the account's time zone. An invalid name returns `400`." }, - "time_zone": { - "description": "New IANA time zone name, such as Asia/Shanghai.", + "ref_id": { "type": [ "string", "null" - ] + ], + "description": "New external reference ID; an empty string clears it." } - }, - "type": "object" + } }, "MemberRoleGrantRequest": { + "type": "object", "description": "Grant role to member request", + "required": [ + "member_id", + "role_ids" + ], "properties": { "member_id": { - "description": "Member ID", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the member whose roles change (from `POST /member/list`)." }, "role_ids": { - "description": "Role IDs to grant; appended to the member's current roles (duplicates are deduplicated).", + "type": "array", "items": { - "format": "uint64", - "type": "integer" + "type": "integer", + "format": "uint64" }, - "type": "array" + "description": "Role IDs to grant; appended to the member's current roles (duplicates are deduplicated)." } - }, + } + }, + "MemberRoleRevokeRequest": { + "type": "object", + "description": "Revoke role from member request", "required": [ "member_id", "role_ids" ], - "type": "object" - }, - "MemberRoleRevokeRequest": { - "description": "Revoke role from member request", "properties": { "member_id": { - "description": "Member ID", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the member whose roles change (from `POST /member/list`)." }, "role_ids": { - "description": "Role IDs to remove from the member.", + "type": "array", "items": { - "format": "uint64", - "type": "integer" + "type": "integer", + "format": "uint64" }, - "type": "array" + "description": "Role IDs to remove from the member." } - }, - "required": [ - "member_id", - "role_ids" - ], - "type": "object" + } }, "MemberRoleUpdateRequest": { + "type": "object", "description": "Update member roles request", + "required": [ + "member_id" + ], "properties": { "member_id": { - "description": "Member ID", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the member whose roles change (from `POST /member/list`)." }, "role_ids": { - "description": "New role ID set. Replaces the member's existing roles entirely (not additive); get IDs from `POST /role/list`. Leave empty to reset to the built-in Viewer role (ID 8)", + "type": "array", "items": { - "format": "uint64", - "type": "integer" + "type": "integer", + "format": "uint64" }, - "type": "array" + "description": "New role ID set; replaces the member's existing roles entirely (not additive). Get IDs from `POST /role/list`." } - }, - "required": [ - "member_id" - ], - "type": "object" + } }, "MemberScheduleItem": { + "type": "object", "description": "An enabled schedule the member participates in.", "properties": { "schedule_id": { - "description": "Schedule ID.", - "format": "int64", - "type": "integer" + "type": "integer", + "description": "ID of a schedule the member participates in; pass it to `/schedule/info`.", + "format": "int64" }, "schedule_name": { - "description": "Schedule name.", - "type": "string" + "type": "string", + "description": "Name of that schedule." } - }, - "type": "object" + } }, "MergeIncidentsRequest": { + "type": "object", "description": "Parameters for merging source incidents into a target.", + "required": [ + "source_incident_ids", + "target_incident_id" + ], "properties": { - "comment": { - "description": "Optional comment recorded on the merge timeline entry.", - "maxLength": 1024, - "type": "string" - }, - "owner_id": { - "description": "Accepted for compatibility but currently ignored by the server; the merge does not change the target incident owner.", - "format": "int64", - "type": "integer" - }, - "remove_source_incidents": { - "description": "When true, soft-delete the source incidents after merging instead of closing them.", - "type": "boolean" - }, "source_incident_ids": { - "description": "Source incident IDs. The target incident is removed from this set automatically.", + "type": "array", "items": { - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$" }, - "maxItems": 100, "minItems": 1, - "type": "array" + "maxItems": 100, + "description": "Source incident IDs. The target incident is removed from this set automatically." }, "target_incident_id": { - "description": "Target incident ID of the merge; obtain it from `POST /incident/list`.", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Target incident ID of the merge; obtain it from `POST /incident/list`." }, "title": { - "description": "Optional new title for the target incident.", + "type": "string", "maxLength": 512, - "type": "string" + "description": "Optional new title for the target incident." + }, + "comment": { + "type": "string", + "maxLength": 1024, + "description": "Optional comment recorded on the merge timeline entry." + }, + "owner_id": { + "type": "integer", + "format": "int64", + "description": "Accepted for compatibility but currently ignored by the server; the merge does not change the target incident owner." + }, + "remove_source_incidents": { + "type": "boolean", + "description": "When true, permanently delete the source incidents after their alerts move to the target. When false, the sources are closed and kept." } - }, - "required": [ - "source_incident_ids", - "target_incident_id" - ], - "type": "object" + } }, "MetricsBase": { + "type": "object", "description": "Shared dimension identifiers attached to every aggregated insight row.", "properties": { - "channel_id": { - "description": "Channel ID, returned only when aggregating by channel (`/insight/channel`).", - "format": "int64", - "type": "integer" - }, - "channel_name": { - "description": "Channel name, returned when aggregating by channel; omitted when the name cannot be resolved.", - "type": "string" - }, "hours": { - "description": "Hour bucket when `split_hours` is enabled. `work` is Mon–Fri 08:00–19:00, `sleep` is daily 23:00–08:00, and `off` is everything else, all evaluated in the account timezone (`sleep` takes precedence over `work`). Omitted when `split_hours` is false.", + "type": "string", "enum": [ "work", "sleep", "off" ], - "type": "string" + "description": "Hour bucket when `split_hours` is enabled. `work` is Mon–Fri 08:00–19:00, `sleep` is daily 23:00–08:00, and `off` is everything else, all evaluated in the account timezone (`sleep` takes precedence over `work`). Omitted when `split_hours` is false." }, - "responder_id": { - "description": "Responder (person) ID, returned only when aggregating by responder (`/insight/responder`).", + "ts": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Start of the time bucket, Unix seconds. Equals `start_time` when `aggregate_unit` is not set." }, - "responder_name": { - "description": "Responder name, returned when aggregating by responder; omitted when the name cannot be resolved.", - "type": "string" + "channel_id": { + "type": "integer", + "format": "int64", + "description": "Channel ID, returned only when aggregating by channel (`/insight/channel`)." }, "team_id": { - "description": "Team ID, returned only when aggregating by team (`/insight/team`).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Team ID, returned only by `/insight/team`. Omitted on the row that aggregates incidents without a team." + }, + "responder_id": { + "type": "integer", + "format": "int64", + "description": "Responder (person) ID, returned only when aggregating by responder (`/insight/responder`)." }, "team_name": { - "description": "Team name, returned when aggregating by team; omitted when the name cannot be resolved (e.g. team deleted).", - "type": "string" + "type": "string", + "description": "Team name, returned when aggregating by team; omitted when the name cannot be resolved (e.g. team deleted)." }, - "ts": { - "description": "Start of the aggregation bucket, Unix epoch seconds. Equals `start_time` when no `aggregate_unit` is given.", - "format": "int64", - "type": "integer" + "channel_name": { + "type": "string", + "description": "Channel name, returned when aggregating by channel; omitted when the name cannot be resolved." + }, + "responder_name": { + "type": "string", + "description": "Responder name, returned when aggregating by responder; omitted when the name cannot be resolved." } - }, - "type": "object" + } }, "MigrateStatusPageEmailSubscribersRequest": { + "type": "object", "description": "Parameters for starting an Atlassian Statuspage email subscriber migration job.", + "required": [ + "api_key", + "source_page_id", + "target_page_id" + ], "properties": { "api_key": { - "description": "Atlassian Statuspage API key with access to the source page.", - "type": "string" + "type": "string", + "description": "Atlassian Statuspage API key with access to the source page." }, "source_page_id": { - "description": "Atlassian Statuspage source page ID.", - "type": "string" + "type": "string", + "description": "Atlassian Statuspage source page ID; only letters, digits, `_`, and `-` are accepted." }, "target_page_id": { - "description": "Flashduty target status page ID that will receive the imported subscribers.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Flashduty target status page ID that will receive the imported subscribers." } - }, - "required": [ - "api_key", - "source_page_id", - "target_page_id" - ], - "type": "object" + } }, "MigrateStatusPageStructureRequest": { + "type": "object", "description": "Parameters for starting an Atlassian Statuspage structure and history migration job.", + "required": [ + "api_key", + "source_page_id" + ], "properties": { "api_key": { - "description": "Atlassian Statuspage API key with access to the source page.", - "type": "string" + "type": "string", + "description": "Atlassian Statuspage API key with access to the source page." }, "source_page_id": { - "description": "Atlassian Statuspage source page ID.", - "type": "string" + "type": "string", + "description": "Atlassian Statuspage source page ID; only letters, digits, `_`, and `-` are accepted." }, "url_name": { - "description": "Target URL name for the new status page, normalized to a URL-safe slug (max 255 characters). Omit or pass null to derive it from the source page name; an explicitly empty string is rejected.", - "maxLength": 255, "type": [ "string", "null" - ] + ], + "description": "Target URL name for the new status page, normalized to a URL-safe slug (max 255 characters). Omit or pass null to derive it from the source page name; an explicitly empty string is rejected.", + "maxLength": 255 } - }, - "required": [ - "api_key", - "source_page_id" - ], - "type": "object" + } }, "NameMessage": { + "type": "object", "description": "Per-item result for batch rule operations.", - "properties": { - "message": { - "description": "Empty on success, error message on failure.", - "type": "string" - }, - "name": { - "description": "Rule name.", - "type": "string" - } - }, "required": [ "name", "message" ], - "type": "object" + "properties": { + "name": { + "type": "string", + "description": "Name of the rule this result belongs to; `id: ` when the rule ID does not exist." + }, + "message": { + "type": "string", + "description": "Outcome for this rule. On success it is empty for `/monit/rule/update/fields` and a localized success text (`Move successfully` / `移动成功`) for `/monit/rule/move`; on failure it carries the error message." + } + } }, "NewMemberItem": { + "type": "object", "description": "Newly created member", "properties": { "member_id": { - "description": "Member ID", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the newly created member." }, "member_name": { - "description": "Member display name", - "type": "string" + "type": "string", + "description": "Display name stored for the member; derived from the email prefix when `member_name` was omitted." } - }, - "type": "object" + } }, "NotifyChat": { + "type": "object", "description": "Notification delivery record for a chat group recipient.", "properties": { + "data_source_id": { + "type": "integer", + "format": "int64", + "description": "Integration data source ID used to send the notification." + }, "chat_id": { - "description": "Chat group identifier.", - "type": "string" + "type": "string", + "description": "Chat group identifier." }, "chat_name": { - "description": "Chat group display name.", - "type": "string" - }, - "data_source_id": { - "description": "Integration data source ID used to send the notification.", - "format": "int64", - "type": "integer" + "type": "string", + "description": "Chat group display name." }, "failed_reason": { - "description": "Failure reason if delivery did not succeed.", - "type": "string" + "type": "string", + "description": "Localized, human-readable reason the delivery failed, as reported by the delivery channel; omitted when delivery succeeded or no failure was reported. The text is not a fixed code set." } - }, - "type": "object" + } }, "NotifyPerson": { + "type": "object", "description": "Notification delivery record for a single person recipient.", "properties": { - "failed_reason": { - "description": "Failure reason if delivery did not succeed.", - "type": "string" - }, "person_id": { - "description": "Recipient member ID.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Recipient member ID." + }, + "failed_reason": { + "type": "string", + "description": "Localized, human-readable reason the delivery failed, as reported by the delivery channel; omitted when delivery succeeded or no failure was reported. The text is not a fixed code set." }, "sms_content": { - "description": "SMS text delivered to the recipient; present on SMS deliveries.", - "type": "string" + "type": "string", + "description": "SMS text delivered to the recipient; present on SMS deliveries." } - }, - "type": "object" + } }, "NotifyRobot": { + "type": "object", "description": "Notification delivery record for a robot webhook recipient.", "properties": { + "token": { + "type": "string", + "description": "Robot token or identifier." + }, "alias": { - "description": "Robot alias.", - "type": "string" + "type": "string", + "description": "Robot alias." }, "failed_reason": { - "description": "Failure reason if delivery did not succeed.", - "type": "string" - }, - "token": { - "description": "Robot token or identifier.", - "type": "string" + "type": "string", + "description": "Localized, human-readable reason the delivery failed, as reported by the delivery channel; omitted when delivery succeeded or no failure was reported. The text is not a fixed code set." } - }, - "type": "object" + } }, "OnceTimeFilter": { "description": "One-off time window defined by unix seconds.", @@ -16991,99 +17334,99 @@ "type": "object" }, "PersonItem": { + "type": "object", "description": "Person profile", + "required": [ + "account_id", + "person_id", + "phone_verified", + "email_verified" + ], "properties": { "account_id": { - "description": "Account ID", + "type": "integer", "format": "uint64", - "type": "integer" - }, - "as": { - "description": "Principal kind: `account` — the account owner principal; `member` — an organization member.", - "enum": [ - "account", - "member" - ], - "type": "string" + "description": "ID of the account the person belongs to." }, - "avatar": { - "description": "Avatar URL. Omitted when empty.", - "type": "string" + "person_id": { + "type": "integer", + "format": "uint64", + "description": "Person ID: the account ID for the account owner, otherwise the member ID." }, - "email": { - "description": "Email address. Omitted when empty.", - "type": "string" + "person_name": { + "type": "string", + "description": "Display name. Omitted when empty." }, - "email_verified": { - "description": "Email verified", - "type": "boolean" + "avatar": { + "type": "string", + "description": "Avatar URL. Omitted when empty." }, "locale": { - "description": "Locale. Omitted when empty.", - "type": "string" + "type": "string", + "description": "Locale preference (`zh-CN` or `en-US`). Omitted when unset." }, - "person_id": { - "description": "Person ID", - "format": "uint64", - "type": "integer" + "time_zone": { + "type": "string", + "description": "IANA time zone setting: the member's own setting, or the account's for the account owner. Omitted when unset (a member without a setting follows the account's time zone)." }, - "person_name": { - "description": "Display name. Omitted when empty.", - "type": "string" + "email": { + "type": "string", + "description": "Email address. Omitted when empty." }, "phone": { - "description": "Phone number. Omitted when empty — this endpoint never populates it.", - "type": "string" + "type": "string", + "description": "Phone number. Omitted when empty — this endpoint never populates it." }, "phone_verified": { - "description": "Whether the phone is verified. Always false in this endpoint's response.", - "type": "boolean" + "type": "boolean", + "description": "Whether the phone is verified. Always false in this endpoint's response." + }, + "email_verified": { + "type": "boolean", + "description": "`true` when the email address is verified; for the account owner, `true` whenever an email is set." + }, + "as": { + "type": "string", + "description": "Principal kind: `account` — the account owner principal; `member` — an organization member.", + "enum": [ + "account", + "member" + ] }, "status": { - "description": "Person status. `enabled` — active; `pending` — invited but not yet accepted; `deleted` — removed. Omitted when empty.", + "type": "string", "enum": [ "enabled", "pending", "deleted" ], - "type": "string" - }, - "time_zone": { - "description": "Time zone. Omitted when empty.", - "type": "string" + "description": "Person status. `enabled` — active; `pending` — invited but not yet accepted; `deleted` — removed. Omitted when empty." } - }, - "required": [ - "account_id", - "person_id", - "phone_verified", - "email_verified" - ], - "type": "object" + } }, "PersonShort": { + "type": "object", "description": "A Flashduty member reference.", "properties": { - "as": { - "description": "Role label for this member in the context of the current object.", - "type": "string" - }, - "email": { - "description": "Member email address.", - "format": "email", - "type": "string" - }, "person_id": { - "description": "Member ID.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Member ID; the same ID that `POST /member/list` returns." }, "person_name": { - "description": "Member display name.", - "type": "string" + "type": "string", + "description": "Member display name." + }, + "email": { + "type": "string", + "format": "email", + "description": "Member email address." + }, + "as": { + "type": "string", + "description": "Role label for this member in the context of the current object." } - }, - "type": "object" + } }, "PlatformEmptyObject": { "additionalProperties": false, @@ -17139,281 +17482,293 @@ "type": "object" }, "PostMortemItem": { + "type": "object", "description": "Full post-mortem report including basics, content and follow-ups.", + "required": [ + "meta", + "basics", + "content", + "follow_ups", + "has_active_incident" + ], "properties": { + "meta": { + "$ref": "#/components/schemas/PostMortemMeta" + }, "basics": { - "description": "Basics aggregated automatically from the linked incidents: highest severity, earliest start / latest close time, total duration, and responders.", + "type": "object", + "required": [ + "incidents_highest_severity", + "incidents_earliest_start_seconds", + "incidents_latest_close_seconds", + "incidents_total_duration_seconds", + "responders" + ], "properties": { + "incidents_highest_severity": { + "type": "string", + "description": "Highest severity among linked incidents: `Critical`, `Warning`, or `Info`; `Ok` only when it was set manually.", + "enum": [ + "Critical", + "Warning", + "Info", + "Ok" + ] + }, "incidents_earliest_start_seconds": { - "description": "Earliest start time among linked incidents (seconds).", + "type": "integer", "format": "int64", - "type": "integer" - }, - "incidents_highest_severity": { - "description": "Highest severity among linked incidents.", - "type": "string" + "description": "Earliest start time among linked incidents (Unix seconds)." }, "incidents_latest_close_seconds": { - "description": "Latest close time among linked incidents (seconds).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Latest close time among linked incidents (Unix seconds); an incident not yet closed contributes its `end_time`." }, "incidents_total_duration_seconds": { - "description": "Cumulative duration in seconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Seconds from the earliest start to the latest close among linked incidents (not the sum of each incident's duration)." }, "responders": { - "description": "Responders involved in the incident(s).", + "type": "array", "items": { "$ref": "#/components/schemas/Responder" }, - "type": "array" + "description": "Responders involved in the incident(s)." } }, - "required": [ - "incidents_highest_severity", - "incidents_earliest_start_seconds", - "incidents_latest_close_seconds", - "incidents_total_duration_seconds", - "responders" - ], - "type": "object" + "description": "Basics aggregated automatically from the linked incidents: highest severity, earliest start / latest close time, total duration, and responders." }, "content": { - "description": "Post-mortem body; the object holds a single `content` field whose value is a BlockNote JSON string.", + "type": "object", + "required": [ + "content" + ], "properties": { "content": { - "description": "Report body content (BlockNote JSON).", - "type": "string" + "type": "string", + "description": "Report body content (BlockNote JSON)." } }, - "required": [ - "content" - ], - "type": "object" + "description": "Post-mortem body; the object holds a single `content` field whose value is a BlockNote JSON string." }, "follow_ups": { - "description": "Follow-up action items rendered as a single string.", - "type": "string" + "type": "string", + "description": "Follow-up action items rendered as a single string." }, - "meta": { - "$ref": "#/components/schemas/PostMortemMeta" + "has_active_incident": { + "type": "boolean", + "description": "`true` when at least one linked incident is not closed yet; follow-ups stay locked until all are closed. Computed per request." } - }, - "required": [ - "meta", - "basics", - "content", - "follow_ups" - ], - "type": "object" + } }, "PostMortemMeta": { + "type": "object", "description": "Post-mortem metadata (lightweight shape used in lists).", + "required": [ + "account_id", + "title", + "status", + "post_mortem_id", + "template_id", + "incident_ids", + "media_count", + "author_ids", + "team_id", + "channel_id", + "is_private", + "generation", + "revision", + "channel_name", + "created_at_seconds", + "updated_at_seconds" + ], "properties": { "account_id": { - "description": "Account ID.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the account that owns this record; the same for every record returned to one `app_key`." }, - "author_ids": { - "description": "Member IDs that contributed to the report.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "channel_id": { - "description": "Owning channel ID. 0 if none.", - "format": "int64", - "type": "integer" + "title": { + "type": "string", + "description": "Report title." }, - "channel_name": { - "description": "Channel name, filled by the server.", - "type": "string" + "status": { + "type": "string", + "enum": [ + "drafting", + "published" + ], + "description": "Post-mortem status. `drafting` means still being edited; `published` means published." }, - "created_at_seconds": { - "description": "Creation timestamp (seconds).", - "format": "int64", - "type": "integer" + "post_mortem_id": { + "type": "string", + "description": "Post-mortem ID: a 32-character hex string derived from the account ID and the linked incident IDs." }, - "generation": { - "description": "Collaboration document generation. Incremented by each full content reset; 0 for legacy documents.", - "format": "int64", - "type": "integer" + "template_id": { + "type": "string", + "description": "Template used to initialize the report." }, "incident_ids": { - "description": "Linked incident IDs.", + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "is_private": { - "description": "When true, only team members and admins can view.", - "type": "boolean" + "description": "Linked incident IDs." }, "media_count": { - "description": "Number of uploaded media files.", - "type": "integer" + "type": "integer", + "description": "Number of uploaded media files." }, - "post_mortem_id": { - "description": "Deterministic post-mortem ID derived from account and incident IDs.", - "type": "string" + "author_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Member IDs that contributed to the report." }, - "revision": { - "description": "Content revision for optimistic concurrency. Monotonically increases on collaborative saves and full content resets.", + "team_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Owning team ID. 0 if none." }, - "status": { - "description": "Post-mortem status. `drafting` means still being edited; `published` means published.", - "enum": [ - "drafting", - "published" - ], - "type": "string" + "channel_id": { + "type": "integer", + "format": "int64", + "description": "Owning channel ID. 0 if none." }, - "team_id": { - "description": "Owning team ID. 0 if none.", + "is_private": { + "type": "boolean", + "description": "When true, only team members and admins can view." + }, + "generation": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Collaboration document generation. Incremented by each full content reset; 0 for legacy documents." }, - "template_id": { - "description": "Template used to initialize the report.", - "type": "string" + "revision": { + "type": "integer", + "format": "int64", + "description": "Content revision for optimistic concurrency. Monotonically increases on collaborative saves and full content resets." }, - "title": { - "description": "Report title.", - "type": "string" + "channel_name": { + "type": "string", + "description": "Channel name, filled by the server." + }, + "created_at_seconds": { + "type": "integer", + "format": "int64", + "description": "Creation timestamp (seconds)." }, "updated_at_seconds": { - "description": "Last update timestamp (seconds).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update timestamp (seconds)." } - }, + } + }, + "PostMortemTemplate": { + "type": "object", + "description": "Post-mortem report template.", "required": [ "account_id", - "title", - "status", - "post_mortem_id", "template_id", - "incident_ids", - "media_count", - "author_ids", + "name", + "description", + "content", + "content_markdown", "team_id", - "channel_id", - "is_private", - "generation", - "revision", - "channel_name", "created_at_seconds", "updated_at_seconds" ], - "type": "object" - }, - "PostMortemTemplate": { - "description": "Post-mortem report template.", "properties": { "account_id": { - "description": "Account ID that owns the template. 0 for built-in templates.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "content": { - "description": "BlockNote JSON content used to initialize the report body.", - "type": "string" + "description": "Account ID that owns the template; 0 for the built-in template." }, - "content_markdown": { - "description": "Markdown version of the template content, used by AI generation.", - "type": "string" + "template_id": { + "type": "string", + "description": "Template ID: `post_mortem_default_tmpl_zh-cn` or `post_mortem_default_tmpl_en-us` for the built-in templates, a server-generated ID for custom ones." }, - "created_at_seconds": { - "description": "Unix timestamp in seconds when the template was created.", - "format": "int64", - "type": "integer" + "name": { + "type": "string", + "description": "Template name shown in the console." }, "description": { - "description": "Template description.", - "type": "string" + "type": "string", + "description": "Template description." }, - "name": { - "description": "Template name shown in the console.", - "type": "string" + "content": { + "type": "string", + "description": "Template body as BlockNote editor JSON (an array of blocks), serialized as a string." + }, + "content_markdown": { + "type": "string", + "description": "Markdown version of the template content, used by AI generation." }, "team_id": { - "description": "Managing team ID. Built-in templates use 0.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Managing team ID; 0 for the built-in template." }, - "template_id": { - "description": "Template ID. Built-in templates use a stable `post_mortem_default_tmpl_*` ID.", - "type": "string" + "created_at_seconds": { + "type": "integer", + "format": "int64", + "description": "Creation time, Unix timestamp in seconds; 0 for the built-in template." }, "updated_at_seconds": { - "description": "Unix timestamp in seconds when the template was last updated.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update time, Unix timestamp in seconds; 0 for the built-in template." } - }, - "required": [ - "account_id", - "template_id", - "name", - "description", - "content", - "content_markdown", - "team_id", - "created_at_seconds", - "updated_at_seconds" - ], - "type": "object" + } }, "PreflightResult": { + "type": "object", "description": "Readiness checks computed before a manual run is allowed to start.", "properties": { - "app_name": { - "description": "App the rule is scoped to. Currently always ai-sre; manual runs are only supported for that app.", - "type": "string" + "ok": { + "type": "boolean", + "description": "Whether all readiness checks passed. Always `true` in a 200 response; a failed preflight returns an error instead." }, "checks": { - "description": "Names of the readiness checks performed, in order. Current fixed set: rule_loaded, actor_authorized, app_allowed, runtime_scope_resolved, rule_config_valid.", + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "ok": { - "description": "Whether all readiness checks passed. Always true in a response that reaches the caller — a failed preflight returns a 400/403 error instead of a payload with ok=false.", - "type": "boolean" - }, - "owner_id": { - "description": "Rule owner person ID.", - "format": "int64", - "type": "integer" + "description": "Names of the readiness checks performed, in order. Current fixed set: rule_loaded, actor_authorized, app_allowed, runtime_scope_resolved, rule_config_valid." }, "scope": { - "description": "Resolved run scope for this run; mirrors the rule's run_scope. One of: `person` (personal rule, runs as its creator), `team` (team rule, runs under the owning team).", + "type": "string", "enum": [ "person", "team" ], - "type": "string" + "description": "Resolved run scope for this run; mirrors the rule's run_scope. One of: `person` (personal rule, runs as its creator), `team` (team rule, runs under the owning team)." + }, + "owner_id": { + "type": "integer", + "format": "int64", + "description": "Rule owner person ID." }, "team_id": { - "description": "Rule's scope team ID; 0 means a personal rule.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Rule's scope team ID; 0 means a personal rule." + }, + "app_name": { + "type": "string", + "description": "App the rule is scoped to. Currently always ai-sre; manual runs are only supported for that app." }, "warnings": { - "description": "Non-fatal warnings surfaced during preflight. Omitted or empty when there are none.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Non-fatal warnings from preflight. Currently never populated, so the field is omitted." } }, "required": [ @@ -17423,54 +17778,29 @@ "owner_id", "team_id", "app_name" - ], - "type": "object" - }, - "PreviewIncidentCardFixedField": { - "description": "Fixed incident-card fields returned for supported IM previews after the requested hiding rules are applied.", - "properties": { - "field": { - "description": "Incident-card field name.\n\n| Value | Meaning |\n|---|---|\n| `channel` | Name of the alert channel that produced the incident; returned only when non-empty. |\n| `snoozed_before` | Snooze-until timestamp formatted as `YYYY-MM-DD HH:MM:SS`; returned only while the incident is snoozed. |\n| `severity` | Incident severity label; returned only when non-empty. |\n| `responders` | Names of the current responders, separated by spaces; returned only when the incident has responders. |\n| `aggregate_alert_count` | Number of alerts aggregated into the incident; returned only when greater than 1. |", - "enum": [ - "channel", - "snoozed_before", - "severity", - "responders", - "aggregate_alert_count" - ], - "type": "string" - }, - "value": { - "description": "Rendered display value for the fixed field.", - "type": "string" - } - }, - "required": [ - "field", - "value" - ], - "type": "object" + ] }, "PreviewRemoteConfigRequest": { "description": "Preview request. Omit `config` to preview the currently live configuration.", "properties": { "app_version": { - "description": "App version the simulated client reports.", + "description": "App version the simulated client reports, compared exactly with rules' `match.app_version` (no range or prefix matching). Omitted = not reported.", "type": "string" }, "application_id": { - "description": "RUM application ID.", + "description": "RUM application ID. Get application IDs via `POST /rum/application/list`.", "type": "string" }, "config": { - "$ref": "#/components/schemas/RemoteConfig" + "$ref": "#/components/schemas/RemoteConfig", + "description": "Draft configuration to evaluate, validated like `POST /rum/application/remote-config/update`. Omit to evaluate the live configuration." }, "env": { - "description": "Environment the simulated client reports.", + "description": "Environment the simulated client reports, compared exactly with rules' `match.env`. Omitted = not reported, so rules that test `env` cannot match.", "type": "string" }, "sdk": { - "description": "SDK name and version the simulated client reports, e.g. `web@2.4.1`.", + "description": "SDK identifier the simulated client reports, e.g. `web@2.4.1`, compared exactly with rules' `match.sdk`. Omitted = not reported.", "type": "string" } }, @@ -17483,173 +17813,348 @@ "description": "Values the simulated client would receive.", "properties": { "hit_rule_index": { - "description": "0-based index of the rule that decided the result, or -1 when only the default applied.", + "description": "0-based index into `config.rules` of the first rule that matched, or `-1` when no rule matched (only `default` applied) or the configuration is disabled or absent.", "type": "integer" }, "values": { - "$ref": "#/components/schemas/RemoteConfigValues" + "$ref": "#/components/schemas/RemoteConfigValues", + "description": "`default` merged with the matching rule's `set`. Fields set by neither are omitted; an empty object means the client keeps all its init values." } }, - "type": "object" + "type": "object", + "required": [ + "values", + "hit_rule_index" + ] }, "PreviewTemplateRequest": { - "description": "Template preview request.", + "type": "object", "properties": { "content": { - "description": "Template content to render.", - "type": "string" + "type": "string", + "description": "Template source to render for the channel `type`. Empty or omitted previews the channel's built-in preset content. Ignored for `push`." }, - "feishu_app_card_v2_enabled": { - "type": "boolean", - "description": "Render the preview as a Feishu app card v2 message." + "type": { + "type": "string", + "description": "Channel to preview; other values return `InvalidParameter`.\n- `email`: email body (HTML template).\n- `sms`, `voice`: SMS text and voice call script.\n- `push`: mobile app push (fixed content; `content` is ignored).\n- `dingtalk`, `wecom`, `feishu`, `zoom`, `telegram`, `slack`: robot (webhook) messages.\n- `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, `teams_app`: IM app cards.", + "enum": [ + "email", + "sms", + "voice", + "push", + "dingtalk", + "wecom", + "feishu", + "zoom", + "telegram", + "slack", + "feishu_app", + "dingtalk_app", + "wecom_app", + "slack_app", + "teams_app" + ] }, - "feishu_app_card_v2_preserve_blank_lines": { - "type": "boolean", - "description": "Keep blank lines in the body of the Feishu app card v2 preview." + "incident_id": { + "type": "string", + "description": "Incident whose data is rendered (24-character hex ID from `/incident/list`); must exist in the account, otherwise `InvalidParameter`. When omitted a mock incident is used.", + "pattern": "^[0-9a-fA-F]{24}$" }, "incident_card_hidden_fields": { "$ref": "#/components/schemas/IncidentCardHiddenFields", "description": "Incident card fields to hide per IM app when previewing." }, - "incident_id": { - "description": "Incident ID whose data is used to render the template; mock data is used when omitted. A MongoDB ObjectID hex string.", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "feishu_app_card_v2_table_enabled": { + "type": "boolean", + "default": false, + "description": "Render Markdown tables in `feishu_app` content as native Feishu card tables, as the template setting of the same name does." }, - "type": { - "description": "Template channel type that selects the rendering engine. `email` renders as Go html/template; other channels render as text/template. Values match the template channel fields, for example `email`, `sms`, `voice`, `dingtalk`, `wecom`, `feishu`, `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, `teams_app`, `telegram`, `slack`, `zoom`.", - "type": "string" + "feishu_app_card_v2_preserve_blank_lines": { + "type": "boolean", + "description": "Keep blank lines in the body of the Feishu app card v2 preview." + }, + "wecom_markdown_v2_enabled": { + "type": "boolean", + "default": false, + "description": "Preview `wecom` content as a `markdown_v2` message, as the template setting of the same name does (size limit 4,096 bytes)." } }, "required": [ - "content", "type" ], - "type": "object" + "description": "Template preview request." }, "PreviewTemplateResponse": { - "description": "Template preview result.", + "type": "object", "properties": { - "content": { - "description": "Rendered template output, present when success is true.", - "type": "string" - }, - "fixed_fields": { - "description": "Fixed incident-card fields returned for supported IM previews after the requested hiding rules are applied.", - "items": { - "$ref": "#/components/schemas/PreviewIncidentCardFixedField" - }, - "type": "array" - }, - "message": { - "description": "Error message describing why rendering failed, present when success is false.", - "type": "string" - }, "success": { - "description": "Whether the template rendered without errors.", - "type": "boolean" - } - }, - "required": [ - "success", - "content", - "message" - ], - "type": "object" - }, - "PublishedArtifactItem": { - "description": "One published artifact in the gallery. Time fields are Unix timestamps in milliseconds.", - "properties": { - "artifact_id": { - "description": "Artifact ID (`art_` prefix). Also the key of the public-share link.", - "type": "string" - }, - "can_edit": { - "description": "Whether the caller may manage this artifact (rename, transfer, delete, share): the creator, any member of the owning team, or a manager of the source session.", - "type": "boolean" - }, - "content_type": { - "description": "MIME type of the file.", - "type": "string" - }, - "created_at": { - "description": "Unix timestamp in milliseconds when the artifact was published.", - "format": "int64", - "type": "integer" + "type": "boolean", + "description": "Whether the template rendered without errors." }, - "creator_name": { - "description": "Creator's display name.", - "type": "string" + "content": { + "type": "string", + "description": "Rendered template output; an empty string when `success` is `false`." }, - "file_id": { - "description": "Presented-file ID (`pf_` prefix) currently holding the artifact's bytes. Changes on every republish.", - "type": "string" + "message": { + "type": "string", + "description": "Why rendering failed, in the caller's language; an empty string when `success` is `true`." }, - "is_mine": { - "description": "Whether the caller is the creator.", - "type": "boolean" + "card": { + "type": "object", + "description": "Message frame around the rendered template, in the account language. Returned for `email`, `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app` and `teams_app`; omitted otherwise.", + "required": [ + "title", + "elements" + ], + "properties": { + "title": { + "type": "string", + "description": "Email subject or card title." + }, + "elements": { + "type": "array", + "description": "Card elements in display order.", + "items": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "template", + "markdown", + "divider", + "actions" + ], + "description": "Element kind.\n- `template`: where the rendered template (`content`) appears.\n- `markdown`: fixed text in the channel's Markdown, in `content`.\n- `divider`: a horizontal rule.\n- `actions`: a row of buttons, in `actions`." + }, + "content": { + "type": "string", + "description": "Markdown text of a `markdown` element; omitted for other kinds." + }, + "actions": { + "type": "array", + "description": "Buttons of an `actions` element; omitted for other kinds.", + "items": { + "type": "object", + "required": [ + "text" + ], + "properties": { + "text": { + "type": "string", + "description": "Button label." + }, + "style": { + "type": "string", + "enum": [ + "primary", + "danger", + "select" + ], + "description": "Button style: `primary` (highlighted), `danger` (destructive), `select` (a drop-down menu). Omitted for a plain button." + } + } + } + } + } + } + } + } }, - "name": { - "description": "Underlying file name including extension.", - "type": "string" + "blocks": { + "type": "array", + "description": "How the recipient's client shows `content`, split into blocks. Omitted for channels that show the text as is.", + "items": { + "type": "object", + "required": [ + "type" + ], + "properties": { + "type": { + "type": "string", + "enum": [ + "markdown", + "table" + ], + "description": "Block kind: `markdown` (text in `content`) or `table` (a table in `columns`/`rows`)." + }, + "content": { + "type": "string", + "description": "Text of a `markdown` block." + }, + "native": { + "type": "boolean", + "description": "`true` when a `table` block is shown as a native card table; omitted otherwise." + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Column headers of a `table` block." + }, + "rows": { + "type": "array", + "items": { + "type": "array", + "items": { + "type": "string" + } + }, + "description": "Cell values of a `table` block, one array per row." + }, + "page_size": { + "type": "integer", + "description": "Rows shown per page in a native table; omitted when not set." + } + } + } + }, + "notices": { + "type": "array", + "description": "Warnings about how the content will be delivered. Omitted when there are none.", + "items": { + "type": "object", + "required": [ + "code" + ], + "properties": { + "code": { + "type": "string", + "enum": [ + "table_not_rendered", + "native_table_fallback", + "content_too_large" + ], + "description": "Warning kind.\n- `table_not_rendered`: the channel cannot show Markdown tables; they are sent as text.\n- `native_table_fallback`: a table cannot be a native card table and is sent as Markdown; `reason` says why (`too_many_tables`, `too_many_columns`, `too_many_rows`, `cell_too_long`, `unsupported_cell`, `card_too_large`).\n- `content_too_large`: the content exceeds `size_limit_bytes`; `reason` is `truncated` (cut to fit), `compact_fallback` (sent in a compact form) or `rejected` (the channel will refuse it)." + }, + "reason": { + "type": "string", + "description": "Detail for `code`, as listed there; omitted for `table_not_rendered`." + } + } + } + }, + "size_bytes": { + "type": "integer", + "description": "Size of the rendered content in bytes, measured before any truncation." + }, + "size_limit_bytes": { + "type": "integer", + "description": "Size limit the channel applies in bytes: 4,000 for robot channels (and `wecom` without `markdown_v2`), 4,096 for `wecom` with `markdown_v2`, 15,000 for `slack_app`, 30,720 for `feishu_app`; `0` when the channel has no limit." + } + }, + "required": [ + "success", + "content", + "message", + "size_bytes", + "size_limit_bytes" + ], + "description": "Template preview result." + }, + "PublishedArtifactItem": { + "type": "object", + "description": "One published artifact in the gallery. Time fields are Unix timestamps in milliseconds.", + "properties": { + "artifact_id": { + "type": "string", + "description": "Artifact ID (`art_` prefix). Also the key of the public-share link." + }, + "title": { + "type": "string", + "description": "Display title in the gallery." + }, + "team_id": { + "type": "integer", + "format": "int64", + "description": "Owning scope. `0` means a personal artifact: it appears only in its creator's list, and can be managed by the creator or by anyone who can manage the source session. A positive value is the owning team ID: the artifact appears in that team's members' lists and any team member can manage it. Set from the source session at first publish; change it with `/safari/artifact/gallery/update`." + }, + "team_name": { + "type": "string", + "description": "Owning team's display name. Omitted for personal artifacts." }, "person_id": { - "description": "Person (member) ID of the creator.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Person ID of the artifact's creator: the owner of the source session at first publish. It never changes on republish or scope transfer." }, - "public_url": { - "description": "Anonymous public link — a console `/share/artifact/` page served entirely from CDN. Present only while shared; anyone with the link can view it, no login required.", - "type": "string" + "creator_name": { + "type": "string", + "description": "Creator's display name." + }, + "is_mine": { + "type": "boolean", + "description": "`true` when the caller (for an `app_key` call, the key owner) is the creator, i.e. `person_id` equals the caller's person ID." + }, + "can_edit": { + "type": "boolean", + "description": "Whether the caller may manage this artifact (rename, transfer, delete, share): the creator, any member of the owning team, or a manager of the source session." }, "session_id": { - "description": "Source session ID (`sess_` prefix) that produced the file.", - "type": "string" + "type": "string", + "description": "Source session ID (`sess_` prefix) that produced the file." }, "session_title": { - "description": "Source session's title. Omitted when the session has been deleted.", - "type": "string" + "type": "string", + "description": "Source session's title. Omitted when the session has been deleted." }, - "share_enabled": { - "description": "Whether anonymous public sharing is on. Omitted when false.", - "type": "boolean" + "file_id": { + "type": "string", + "description": "Presented-file ID (`pf_` prefix) currently holding the artifact's bytes. Changes on every republish." }, - "share_file_id": { - "description": "Presented-file ID the public snapshot was materialized from. When `share_enabled` is true and `file_id` differs from `share_file_id`, the public snapshot is stale — call `/safari/artifact/gallery/share/sync` to refresh it.", - "type": "string" + "name": { + "type": "string", + "description": "Underlying file name including extension. Empty when the underlying file record is missing." }, - "shared_at": { - "description": "Unix timestamp in milliseconds of the last share enable or snapshot sync. Present only while shared.", + "size": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "File size in bytes." }, - "shared_by": { - "description": "Person ID of the member who enabled sharing. Present only while shared.", + "content_type": { + "type": "string", + "description": "MIME type, derived from the file-name extension when the file was produced: `text/html` (.html/.htm), `text/markdown` (.md), `text/plain` (.txt/.log), `text/csv`, `text/yaml` (.yaml/.yml), `text/x-python`, `text/x-go`, `text/x-sh`, `application/json`, `application/xml`, `application/pdf`, `image/png`, `image/jpeg`, `image/gif`, `image/svg+xml`, `image/webp`, `application/zip`, `application/gzip` (.tar/.gz/.tgz); any other extension is `application/octet-stream`. Empty when the underlying file record is missing." + }, + "created_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp in milliseconds when the artifact was published." }, - "size": { - "description": "File size in bytes.", + "updated_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp in milliseconds of the last change to the artifact row (rename, transfer, republish, or share state change)." }, - "team_id": { - "description": "Owning team ID. `0` means a personal artifact (creator-only management); a positive value means team-owned.", + "pinned_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp in milliseconds when the caller pinned this artifact in the console gallery. Pins are per member; omitted when the caller has not pinned it. Pinned artifacts are listed first by `/safari/artifact/gallery/list`." }, - "team_name": { - "description": "Owning team's display name. Omitted for personal artifacts.", - "type": "string" + "share_enabled": { + "type": "boolean", + "description": "Whether anonymous public sharing is on. Omitted when false." }, - "title": { - "description": "Display title in the gallery.", - "type": "string" + "public_url": { + "type": "string", + "description": "Anonymous public link — a console `/share/artifact/` page served entirely from CDN. Present only while shared; anyone with the link can view it, no login required." }, - "updated_at": { - "description": "Unix timestamp in milliseconds when the artifact was last updated (rename, transfer, or republish).", + "shared_by": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Person ID of the member who enabled sharing; a later snapshot sync does not change it. Present only while shared." + }, + "shared_at": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in milliseconds of the last share enable or snapshot sync. Present only while shared." + }, + "share_file_id": { + "type": "string", + "description": "Presented-file ID the public snapshot was materialized from. When `share_enabled` is true and `file_id` differs from `share_file_id`, the public snapshot is stale — call `/safari/artifact/gallery/share/sync` to refresh it." } }, "required": [ @@ -17667,16 +18172,15 @@ "content_type", "created_at", "updated_at" - ], - "type": "object" + ] }, "QueryDataRequest": { + "description": "Request body of the structured query endpoint.", "allOf": [ { "$ref": "#/components/schemas/QueryRowsRequest" } - ], - "description": "Request for the stable structured query endpoint. It accepts the same query fields as the retired rows endpoint." + ] }, "QueryDataResponse": { "description": "Stable, Edge-version-independent structured query response.", @@ -17848,43 +18352,59 @@ ] }, "QueryRowsRequest": { + "type": "object", + "required": [ + "ds_type", + "ds_name", + "expr" + ], "properties": { "account_id": { - "description": "Optional consistency check. Must equal the authenticated account when supplied; mismatched values are rejected. Business execution always uses the authenticated account.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "args": { - "additionalProperties": { - "type": "string" - }, - "description": "Polymorphic key/value extension parameters forwarded verbatim to monit-edge. All values must be strings, and keys are always namespaced by source (e.g. `sls.project`, `loki.type`). Validation depends on `ds_type`: SLS requires `sls.project` + `sls.logstore`. Elasticsearch accepts `es.type` of `sql`, or omitted — any other value is rejected. Loki and VictoriaLogs accept `.type` of `stats`, `raw`, or omitted; `raw` additionally requires a time range, either `.start` + `.end` or `.timespan.value` + `.timespan.unit` (unit one of `s`, `m`, `h`, `d`). Prometheus and the remaining SQL sources ignore `args` entirely.", - "type": "object" + "description": "Optional consistency check. When supplied it must equal the authenticated account, otherwise the request fails with `AccessDenied`. The query always runs as the authenticated account." }, - "delay_seconds": { - "default": 0, - "description": "Look-back offset in seconds applied to point-in-time queries (Prometheus, Loki stats, VictoriaLogs stats). Ignored for raw / detail queries.", - "type": "integer" + "ds_type": { + "type": "string", + "description": "Data source type. Together with `ds_name` it must match an enabled data source of the account.\n\n- `prometheus`: Prometheus-compatible data source; `expr` is PromQL.\n- `loki`: Grafana Loki; `expr` is LogQL.\n- `victorialogs`: VictoriaLogs.\n- `sls`: Alibaba Cloud Log Service (SLS).\n- `tencent_cls`: Tencent Cloud Log Service (CLS); requires monit-edge v0.66.0 or later.\n- `elasticsearch`: Elasticsearch.\n- `mysql`: MySQL; `expr` is SQL.\n- `postgres`: PostgreSQL; `expr` is SQL.\n- `oracle`: Oracle Database; `expr` is SQL.\n- `clickhouse`: ClickHouse; `expr` is SQL.\n\nOther data source types (for example MongoDB, Redis, or Kafka) are rejected.", + "enum": [ + "clickhouse", + "elasticsearch", + "loki", + "mysql", + "oracle", + "postgres", + "prometheus", + "sls", + "tencent_cls", + "victorialogs" + ] }, "ds_name": { - "description": "Data source name; must match a configured data source under the tenant.", - "type": "string" - }, - "ds_type": { - "description": "Data source type; must match a configured data source under the tenant. Examples: `prometheus`, `loki`, `victorialogs`, `sls`, `elasticsearch`, `mysql`, `postgres`, `oracle`, `clickhouse`.", - "type": "string" + "type": "string", + "description": "Data source name, as returned by `/monit/datasource/list`. The data source must be enabled; a name that matches no data source of the account returns HTTP 400." }, "expr": { - "description": "Query expression. Syntax depends on `ds_type` and is interpreted by the corresponding monit-edge client (PromQL for Prometheus, LogQL for Loki, SQL for SQL sources, etc.).", - "type": "string" + "type": "string", + "description": "Query expression in the language of `ds_type` (PromQL for `prometheus`, LogQL for `loki`, SQL for SQL sources, and so on). Required, at most 64 KiB (12 KiB for `tencent_cls`). Loki's `$__auto` is not supported here; use a fixed duration such as `[5m]`. Prometheus expressions are syntax-checked before dispatch.", + "minLength": 1 + }, + "delay_seconds": { + "type": "integer", + "description": "Look-back offset in seconds, from 0 to 86400. Applied to point-in-time queries (Prometheus, Loki stats, VictoriaLogs stats); ignored for raw and detail queries. When `args` carries an absolute `.time` and the Edge is v0.74.0 or later, the absolute time takes precedence and this offset is not applied.", + "default": 0, + "minimum": 0, + "maximum": 86400 + }, + "args": { + "type": "object", + "description": "Extra query parameters as string key/value pairs; keys are namespaced by data source (for example `sls.project`, `loki.type`). At most 128 entries, keys up to 256 bytes, values up to 64 KiB, and 128 KiB in total. What is accepted depends on `ds_type`:\n\n- `prometheus`: optional `prometheus.time`, the evaluation time as Unix seconds, not in the future.\n- `loki`, `victorialogs`: `.type` is `stats` (default) or `raw`. `stats` accepts an optional `.time` (Unix seconds, not in the future). `raw` requires a time range, either `.start` + `.end` (Unix seconds) or `.timespan.value` + `.timespan.unit` (`s`, `m`, `h`, or `d`), spanning at most 6 hours, and accepts `.limit` from 1 to 1001.\n- `sls`: `sls.project` and `sls.logstore` are required. Optional: `sls.lines` (1 to 100), `sls.offset` (0 or more), and a time range of at most 6 hours given as `sls.from` + `sls.to` (Unix seconds) or `sls.timespan.value` + `sls.timespan.unit`.\n- `tencent_cls`: `tencent_cls.region`, `tencent_cls.topic_id`, `tencent_cls.query_mode` (`raw` or `analysis`), and `tencent_cls.syntax` (`cql` or `lucene`) are required. Optional: `tencent_cls.limit` (1 to 100, `raw` mode only, needs monit-edge v0.67.0 or later) and a time range given as `tencent_cls.from` + `tencent_cls.to` (Unix seconds) or `tencent_cls.timespan.value` + `tencent_cls.timespan.unit`, at most 6 hours in `raw` mode and 24 hours in `analysis` mode. Any other key is rejected.\n- `elasticsearch`: `es.type` may be `sql` or omitted; any other value is rejected.\n- `mysql`, `postgres`, `oracle`, `clickhouse`: no arguments are defined.\n\nAn absolute `.time` is only valid for its own data source type. Edges older than v0.74.0 approximate it with a look-back offset and accept only times within the last 86,400 seconds.", + "additionalProperties": { + "type": "string" + } } }, - "required": [ - "ds_type", - "ds_name", - "expr" - ], - "type": "object" + "description": "Query to run. `ds_type` and `ds_name` together select the data source; `expr` and `args` are interpreted by that data source type." }, "QuerySample": { "properties": { @@ -17954,29 +18474,35 @@ "type": "string" }, "custom": { - "additionalProperties": {}, - "description": "Application-defined pass-through values handed to the host app verbatim. At most 5 keys, each key up to 64 bytes, each value up to 4 KB of JSON nested at most 3 levels, 16 KB in total. Anyone holding the public client token can read it.", + "additionalProperties": { + "description": "Any JSON value: string, number, boolean, array or object." + }, + "description": "Free-form key/value map that SDKs hand to the host app verbatim; the platform does not interpret it. At most 5 keys, each key 1–64 bytes, each value valid JSON of at most 4 KB nested at most 3 levels, 16 KB in total. Anyone holding the public client token can read it. Omitted from responses when empty.", "maxProperties": 5, "type": "object" }, "default": { - "$ref": "#/components/schemas/RemoteConfigValues" + "$ref": "#/components/schemas/RemoteConfigValues", + "description": "Values every client receives unless a matching rule overrides them." }, "enabled": { - "description": "Kill switch. When false the engine reports no values at all and SDKs fall back to their init values.", + "description": "Kill switch. When `false` the SDK config endpoint returns no values and SDKs fall back to their init values; `default` and `rules` are kept. Treated as `false` when omitted.", "type": "boolean" }, "refresh_on_foreground": { - "description": "Let clients re-check the configuration when they return to the foreground instead of waiting for the next poll.", + "description": "If `true`, clients re-check the configuration when they return to the foreground instead of waiting for the next poll. Default `false`; omitted from responses when `false`.", "type": "boolean" }, "rules": { - "description": "Targeting rules, evaluated in order; at most 20 per application.", + "description": "Targeting rules, evaluated in order; the first match wins. At most 20. Can be `null` when the configuration was saved without rules.", "items": { "$ref": "#/components/schemas/RemoteConfigRule" }, "maxItems": 20, - "type": "array" + "type": [ + "array", + "null" + ] } }, "type": "object" @@ -17985,18 +18511,19 @@ "description": "One published remote configuration version.", "properties": { "config": { - "$ref": "#/components/schemas/RemoteConfig" + "$ref": "#/components/schemas/RemoteConfig", + "description": "The configuration content that went live under this version." }, "content_hash": { - "description": "Hash of the configuration content; lets the console identify versions with identical content.", + "description": "Fingerprint of the stored configuration: the first 16 hex characters of its SHA-256. Versions with equal hashes have identical content. Can be empty for older versions.", "type": "string" }, "equivalent_to": { - "description": "Earliest version carrying the same content, when that is not this version itself.", + "description": "Earliest retained version with the same `content_hash`, e.g. the version a revert restored. Omitted when this version is itself the earliest.", "type": "integer" }, "reason": { - "description": "Operator's note left when the version was published. Empty when none was given.", + "description": "Free-text note (not an enum) sent as `reason` when the version was published or reverted; `\"\"` when none was given.", "type": "string" }, "updated_at": { @@ -18010,7 +18537,7 @@ "type": "integer" }, "updated_by_name": { - "description": "Name of the member who published the version.", + "description": "Name of the member who published the version at publish time, truncated to 128 characters.", "type": "string" }, "version": { @@ -18018,18 +18545,35 @@ "type": "integer" } }, - "type": "object" + "type": "object", + "required": [ + "config", + "version", + "content_hash", + "reason", + "updated_by", + "updated_by_name", + "updated_at" + ] }, "RemoteConfigRule": { - "description": "One targeting rule: when `match` holds, `set` overrides `default`. The first matching rule wins and evaluation stops there - rule order is the priority.", + "description": "One targeting rule: when every `match` condition holds, `set` overrides `default`. The first matching rule wins and evaluation stops there; rule order is the priority. `set` must set at least one value.", "properties": { "match": { "additionalProperties": { "maxLength": 256, + "minLength": 1, "type": "string" }, - "description": "Key/value conditions the SDK's config request must equal. Keys are limited to `env`, `app_version` and `sdk`; values are at most 256 bytes.", + "description": "Conditions on what the SDK reports in its config request, combined with AND and compared as exact strings. Keys are limited to `env`, `app_version` and `sdk`; values are 1–256 bytes. A key the SDK does not report never matches.", "minProperties": 1, + "propertyNames": { + "enum": [ + "env", + "app_version", + "sdk" + ] + }, "type": "object" }, "set": { @@ -18046,7 +18590,7 @@ "description": "The SDK knobs a configuration can set. Every field is optional: a value absent from both rule and default is omitted from the SDK response, which tells the SDK to keep its init value.", "properties": { "defaultPrivacyLevel": { - "description": "How Session Replay masks a page by default.", + "description": "How Session Replay masks a page by default:\n\n- `mask`: replaces text and hides input values.\n- `mask-user-input`: keeps page text but hides what users type.\n- `allow`: records the page as it is; content already uploaded cannot be masked later.", "enum": [ "mask", "mask-user-input", @@ -18072,7 +18616,7 @@ ] }, "sessionReplaySampleRate": { - "description": "Session Replay sampling rate (0-100).", + "description": "Percentage of sessions that record Session Replay (0–100).", "maximum": 100, "minimum": 0, "type": [ @@ -18081,7 +18625,7 @@ ] }, "sessionSampleRate": { - "description": "Session sampling rate (0-100).", + "description": "Percentage of sessions collected (0–100).", "maximum": 100, "minimum": 0, "type": [ @@ -18090,7 +18634,7 @@ ] }, "traceSampleRate": { - "description": "Trace sampling rate (0-100): which sessions inject trace headers into their requests.", + "description": "Percentage of sessions that inject trace headers into their requests (0–100). Decided per session: a session traces all of its requests or none.", "maximum": 100, "minimum": 0, "type": [ @@ -18121,28 +18665,28 @@ "type": "object" }, "ReopenIncidentRequest": { + "type": "object", "description": "Parameters for reopening one or more closed incidents.", + "required": [ + "incident_ids" + ], "properties": { "incident_ids": { - "description": "Incident IDs to reopen. At most 100 per call.", + "type": "array", "items": { - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$" }, "maxItems": 100, - "minItems": 1, - "type": "array" + "description": "Incident IDs to reopen. At most 100 per call.", + "minItems": 1 }, "reason": { - "description": "Optional reason recorded on the timeline.", + "type": "string", "maxLength": 1024, - "type": "string" + "description": "Optional free-text reason, recorded on the `i_reopen` timeline entry. At most 1,024 characters." } - }, - "required": [ - "incident_ids" - ], - "type": "object" + } }, "ReorderIncidentCommentTypesRequest": { "description": "Parameters for reordering comment types.", @@ -18163,77 +18707,77 @@ "type": "object" }, "ResetIncidentFieldRequest": { + "type": "object", "description": "Parameters for updating a custom field value on an incident.", + "required": [ + "incident_id", + "field_name" + ], "properties": { + "incident_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Incident ID (MongoDB ObjectID)." + }, "field_name": { - "description": "Custom field name; must match a field defined on the account.", - "type": "string" + "type": "string", + "description": "Custom field name (the field's `field_name`, not its display name). The field must exist and be enabled; list fields with `POST /field/list`." }, "field_value": { - "description": "New field value. Type must match the field definition." - }, - "incident_id": { - "description": "Incident ID (MongoDB ObjectID).", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "New value. Its type must match the field: `checkbox` takes a boolean, `single_select` one of the options, `multi_select` an array of options, `text` a string. Omit it or send `null` to clear the field." } - }, - "required": [ - "incident_id", - "field_name" - ], - "type": "object" + } }, "ResetPostMortemBasicsRequest": { + "type": "object", "description": "Basic incident facts to write back to a post-mortem report.", + "required": [ + "post_mortem_id", + "incidents_highest_severity", + "incidents_earliest_start_seconds" + ], "properties": { - "incidents_earliest_start_seconds": { - "description": "Unix timestamp in seconds for the earliest linked incident start time.", - "format": "int64", - "minimum": 1, - "type": "integer" + "post_mortem_id": { + "type": "string", + "description": "Post-mortem ID; obtain it from `POST /incident/post-mortem/list`." }, "incidents_highest_severity": { - "description": "Highest severity among linked incidents: `Critical`, `Warning`, `Info`, or `Ok`.", + "type": "string", + "description": "Highest severity among the linked incidents.\n- `Critical`: critical.\n- `Warning`: warning.\n- `Info`: informational.\n- `Ok`: recovered.", "enum": [ "Critical", "Warning", "Info", "Ok" - ], - "type": "string" + ] + }, + "incidents_earliest_start_seconds": { + "type": "integer", + "format": "int64", + "minimum": 1, + "description": "Unix timestamp in seconds for the earliest linked incident start time." }, "incidents_latest_close_seconds": { - "description": "Unix timestamp in seconds for the latest linked incident close time. 0 when still open.", + "type": "integer", "format": "int64", "minimum": 0, - "type": "integer" + "description": "Latest close time among the linked incidents, Unix timestamp in seconds. 0 (also when omitted) means still open." }, "incidents_total_duration_seconds": { - "description": "Total incident duration in seconds.", + "type": "integer", "format": "int64", "minimum": 0, - "type": "integer" - }, - "post_mortem_id": { - "description": "Post-mortem ID; obtain it from `POST /incident/post-mortem/list`.", - "type": "string" + "description": "Total incident duration in seconds; 0 when omitted." }, "responder_ids": { - "description": "Responder member IDs to store on the report.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Member IDs to store as the report's responders. Replaces the stored list; omit or send `[]` to clear it. IDs that do not resolve to a person are dropped." } - }, - "required": [ - "post_mortem_id", - "incidents_highest_severity", - "incidents_earliest_start_seconds" - ], - "type": "object" + } }, "ResetPostMortemContentRequest": { "description": "Parameters for fully replacing a drafting post-mortem report body.", @@ -18271,72 +18815,88 @@ "type": "object" }, "ResetPostMortemFollowUpsRequest": { + "type": "object", "description": "Parameters for replacing post-mortem follow-up action items.", - "properties": { - "follow_ups": { - "description": "Follow-up action items as free text.", - "type": "string" - }, - "post_mortem_id": { - "description": "Post-mortem ID; obtain it from `POST /incident/post-mortem/list`.", - "type": "string" - } - }, "required": [ "post_mortem_id" ], - "type": "object" + "properties": { + "post_mortem_id": { + "type": "string", + "description": "Post-mortem ID; obtain it from `POST /incident/post-mortem/list`." + }, + "follow_ups": { + "type": "string", + "description": "Follow-ups as free text, replacing the stored string. A JSON array in the console's follow-up format (objects with `title`, `status`, `priority`, `assignee_ids`, …) is also synced into structured follow-up work items." + } + } }, "ResetPostMortemStatusRequest": { + "type": "object", "description": "Parameters for changing a post-mortem report status.", + "required": [ + "post_mortem_id", + "status" + ], "properties": { "post_mortem_id": { - "description": "Post-mortem ID; obtain it from `POST /incident/post-mortem/list`.", - "type": "string" + "type": "string", + "description": "Post-mortem ID; obtain it from `POST /incident/post-mortem/list`." }, "status": { - "description": "Target report status: `drafting` draft, `published` published.", + "type": "string", "enum": [ "drafting", "published" ], - "type": "string" + "description": "Target report status.\n- `drafting`: being edited; the body can still be replaced with a content reset.\n- `published`: published; media files no longer referenced by the body are deleted." } - }, - "required": [ - "post_mortem_id", - "status" - ], - "type": "object" + } }, "ResetPostMortemTitleRequest": { + "type": "object", "description": "Parameters for changing a post-mortem report title.", + "required": [ + "post_mortem_id", + "title" + ], "properties": { "post_mortem_id": { - "description": "Post-mortem ID; obtain it from `POST /incident/post-mortem/list`.", - "type": "string" + "type": "string", + "description": "Post-mortem ID; obtain it from `POST /incident/post-mortem/list`." }, "title": { - "description": "New report title.", - "type": "string" + "type": "string", + "maxLength": 256, + "description": "New report title, at most 256 characters." } - }, - "required": [ - "post_mortem_id", - "title" - ], - "type": "object" + } }, "ResetWorkItemAssigneesRequest": { - "description": "Full replacement of a work item's assignee set.", + "type": "object", + "description": "Full replacement of a work item's assignee set. Exactly one of `assignees` or `assignee_ids` must be sent.", + "required": [ + "work_item_id", + "version" + ], "properties": { + "work_item_id": { + "type": "string", + "maxLength": 128, + "description": "Work item ID (opaque string, max 128 characters)." + }, + "version": { + "type": "integer", + "format": "int64", + "description": "The item's current `version` (≥ 1) for optimistic locking." + }, "assignee_ids": { - "description": "Legacy alias for the replacement assignee set. Equivalent to `assignees` with every entry `type` `person`. Mutually exclusive with `assignees`: sending both returns an error. An empty array clears all assignees.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Legacy alias for the replacement assignee set. Equivalent to `assignees` with every entry `type` `person`. Mutually exclusive with `assignees`: sending both returns an error. An empty array clears all assignees." }, "assignees": { "description": "Replacement assignee set. Each entry is `{type, id?}`. `type` is `person` or `ai_sre`; an `ai_sre` entry omits `id`. Mutually exclusive with `assignee_ids`: sending both returns an error. `assignee_ids` is the legacy alias and is equivalent to an all-`person` list. At most 20 entries. An empty array clears all assignees.", @@ -18345,23 +18905,8 @@ }, "maxItems": 20, "type": "array" - }, - "version": { - "description": "Current item version for optimistic locking. Must match the stored version.", - "format": "int64", - "type": "integer" - }, - "work_item_id": { - "description": "Work item ID (opaque string, max 128 characters).", - "maxLength": 128, - "type": "string" } - }, - "required": [ - "work_item_id", - "version" - ], - "type": "object" + } }, "ResolveIncidentRequest": { "description": "Parameters for resolving one or more incidents.", @@ -18534,51 +19079,51 @@ ] }, "ResponderInsightResponse": { + "type": "object", "properties": { "items": { - "description": "Incident response metric rows aggregated by responder; further split by hour bucket or time bucket when `split_hours` or `aggregate_unit` is enabled.", + "type": "array", "items": { "$ref": "#/components/schemas/ResponderInsightItem" }, - "type": "array" + "description": "Per-responder metric rows, newest bucket first. Responders without incidents in a bucket produce no row." } - }, - "type": "object" + } }, "ResponseEnvelope": { + "type": "object", "description": "Standard response envelope used by every Flashduty public API. On success `data` contains the endpoint-specific payload and `error` is absent. On failure `error` is present and `data` is absent. `request_id` is always present and is also mirrored in the `Flashcat-Request-Id` response header.", "properties": { - "data": { - "description": "Endpoint-specific payload. See each operation's 200 response schema." + "request_id": { + "type": "string", + "description": "Unique ID for this request. Mirrored in the Flashcat-Request-Id header. Include it when reporting issues.", + "example": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" }, "error": { "$ref": "#/components/schemas/DutyError" }, - "request_id": { - "description": "Unique ID for this request. Mirrored in the Flashcat-Request-Id header. Include it when reporting issues.", - "example": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "type": "string" + "data": { + "description": "Operation-specific payload, documented in each operation's 200 response. Operations without a payload return `{}` or omit `data` entirely." } }, "required": [ "request_id" - ], - "type": "object" + ] }, "RevertRemoteConfigRequest": { "description": "Republish an earlier version's content under a new version number.", "properties": { "application_id": { - "description": "RUM application ID.", + "description": "RUM application ID. Get application IDs via `POST /rum/application/list`.", "type": "string" }, "reason": { - "description": "Operator's note. The console fills in `rolled back to vN` when left empty.", + "description": "Optional free-text note (not an enum), at most 255 characters, stored verbatim and returned as `reason` by `POST /rum/application/remote-config/history/list`. The server does not fill it in when omitted.", "maxLength": 255, "type": "string" }, "version": { - "description": "History version to republish.", + "description": "Version to restore. Must be one of the retained versions listed by `POST /rum/application/remote-config/history/list`.", "minimum": 1, "type": "integer" } @@ -18593,53 +19138,53 @@ "description": "Version created by the revert.", "properties": { "version": { - "description": "New version number created by the revert.", + "description": "New version number created by the revert (previous highest version + 1).", "type": "integer" } }, "type": "object" }, "RoleDeleteRequest": { + "type": "object", + "required": [ + "role_id" + ], "description": "Request to delete a role.", "properties": { - "is_force": { - "default": false, - "description": "When false (default), deletion fails with a `ReferenceExist` error listing the members that still hold the role in `data.refs`. When true, the role is first revoked from all holders and then deleted.", - "type": "boolean" - }, "role_id": { - "description": "Role ID to delete. Get IDs from `POST /role/list` (built-in roles: 2=Admin, 6=Responder, 8=Viewer).", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "Role ID to delete. Get IDs from `POST /role/list` (built-in roles: 2=Admin, 6=Responder, 8=Viewer)." + }, + "is_force": { + "type": "boolean", + "default": false, + "description": "When false (default), deletion fails with `ReferenceExist` while members still hold the role, listing them in `data.refs`. When true, the role is first revoked from all holders and then deleted. Does not bypass the SSO default-role check." } - }, + } + }, + "RoleGrantRequest": { + "type": "object", "required": [ + "member_ids", "role_id" ], - "type": "object" - }, - "RoleGrantRequest": { "description": "Request to grant or revoke a role from members.", "properties": { "member_ids": { - "description": "Member IDs to grant/revoke the role.", + "type": "array", "items": { - "format": "uint64", - "type": "integer" + "type": "integer", + "format": "uint64" }, - "type": "array" + "description": "IDs of the members to grant the role to or revoke it from (from `POST /member/list`). All must be members of the account; duplicates are rejected." }, "role_id": { - "description": "Role ID to grant or revoke. Get IDs from `POST /role/list`.", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "Role ID to grant or revoke. Get IDs from `POST /role/list`." } - }, - "required": [ - "member_ids", - "role_id" - ], - "type": "object" + } }, "RoleIDRequest": { "properties": { @@ -18668,63 +19213,63 @@ "type": "object" }, "RoleItem": { + "type": "object", "description": "A role and its permission set.", + "required": [ + "role_id", + "role_name", + "description", + "status", + "permission_ids", + "editable", + "created_at", + "updated_at" + ], "properties": { - "created_at": { - "description": "Unix epoch seconds the role was created.", - "format": "int64", - "type": "integer" - }, - "description": { - "description": "Role description.", - "type": "string" - }, - "editable": { - "description": "False for built-in roles which cannot be modified.", - "type": "boolean" - }, - "permission_ids": { - "description": "IDs of permissions granted by this role.", - "items": { - "format": "uint64", - "type": "integer" - }, - "type": "array" - }, "role_id": { - "description": "Unique role ID.", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "Role ID. Built-in roles use the fixed IDs `2` (Admin), `6` (Responder), and `8` (Viewer)." }, "role_name": { - "description": "Role display name.", - "type": "string" + "type": "string", + "description": "Role name, unique in the account. The built-in roles are named `Admin`, `Responder`, and `Viewer` in every language." + }, + "description": { + "type": "string", + "description": "Role description. For built-in roles it is localized by the request language." }, "status": { - "description": "Role status.", + "type": "string", "enum": [ "enabled", "disabled" ], - "type": "string" + "description": "Role status. `enabled` — active; `disabled` — turned off with `POST /role/disable`; it grants no permissions to the members who hold it. Built-in roles are always `enabled`; deleted roles are never returned." + }, + "permission_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "uint64" + }, + "description": "IDs of the permissions the role grants, in ascending order; resolve them with `POST /role/permission/list`. Empty array when none." + }, + "editable": { + "type": "boolean", + "description": "`false` for the built-in roles (Admin, Responder, Viewer); `true` for custom roles." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Time the role was created, Unix timestamp in seconds. Built-in roles carry a fixed timestamp." }, "updated_at": { - "description": "Unix epoch seconds the role was last updated.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix epoch seconds the role was last updated." } - }, - "required": [ - "role_id", - "role_name", - "description", - "status", - "permission_ids", - "editable", - "created_at", - "updated_at" - ], - "type": "object" + } }, "RoleListRequest": { "description": "Filters for listing roles.", @@ -18749,43 +19294,43 @@ "type": "object" }, "RoleListResponse": { + "type": "object", "description": "Role list result.", + "required": [ + "total", + "items" + ], "properties": { + "total": { + "type": "integer", + "description": "Number of roles returned: custom roles plus the 3 built-in roles unless `no_global` is true." + }, "items": { - "description": "Array of roles; includes account roles plus built-in global roles unless `no_global=true`; empty array when no results.", + "type": "array", "items": { "$ref": "#/components/schemas/RoleItem" }, - "type": "array" - }, - "total": { - "description": "Total role count.", - "type": "integer" + "description": "Array of roles; includes account roles plus built-in global roles unless `no_global=true`; empty array when no results." } - }, - "required": [ - "total", - "items" - ], - "type": "object" + } }, "RolePermissionListRequest": { + "type": "object", "description": "Filters for listing permissions.", "properties": { "role_ids": { - "description": "Filter to permissions granted to these roles.", + "type": "array", "items": { - "format": "uint64", - "type": "integer" + "type": "integer", + "format": "uint64" }, - "type": "array" + "description": "Role IDs (built-in or custom) whose granted permissions to return or mark. IDs that do not exist are ignored." }, "with_all": { - "description": "If true, return all permissions with is_granted set to indicate which are granted.", - "type": "boolean" + "type": "boolean", + "description": "When true, return every permission and use `is_granted` to mark the ones granted by `role_ids`. When false (default), return only the granted permissions." } - }, - "type": "object" + } }, "RolePermissionListResponse": { "description": "Permission list result.", @@ -18804,37 +19349,37 @@ "type": "object" }, "RoleUpsertRequest": { + "type": "object", + "required": [ + "role_name" + ], "description": "Parameters for creating or updating a custom role.", "properties": { + "role_id": { + "type": "integer", + "format": "uint64", + "description": "ID of the custom role to update. Omit or set to 0 to create a new role. Do not pass the built-in role IDs `2`, `6`, or `8`." + }, + "role_name": { + "type": "string", + "minLength": 1, + "maxLength": 39, + "description": "Role display name. 1–39 characters." + }, "description": { - "description": "Role description.", + "type": "string", "maxLength": 499, - "type": "string" + "description": "Role description, up to 499 characters. Omitting it on update clears the stored description." }, "permission_ids": { - "description": "Permission IDs to grant. Replaces the existing set.", + "type": "array", "items": { - "format": "uint64", - "type": "integer" + "type": "integer", + "format": "uint64" }, - "type": "array" - }, - "role_id": { - "description": "Role ID. Omit or set to 0 to create.", - "format": "uint64", - "type": "integer" - }, - "role_name": { - "description": "Role display name. 1–39 characters.", - "maxLength": 39, - "minLength": 1, - "type": "string" + "description": "IDs of the permissions the role grants (from `POST /role/permission/list`). Replaces the existing set; omitting it or sending an empty array leaves the role with no permissions." } - }, - "required": [ - "role_name" - ], - "type": "object" + } }, "RoleUpsertResponse": { "description": "Role create/update result.", @@ -18856,177 +19401,177 @@ "type": "object" }, "RouteCase": { + "type": "object", "description": "A single case branch in the routing rule. When all of its conditions match, the alert is dispatched to the configured channels.", + "required": [ + "if" + ], "properties": { - "channel_ids": { - "description": "Target channel IDs. Required when `routing_mode` is `standard` (or empty); returned as `null` for `name_mapping`.", + "if": { + "type": "array", + "description": "Conditions joined with AND; an empty list matches every event. Required.", "items": { - "format": "int64", - "type": "integer" - }, + "$ref": "#/components/schemas/RouteMatchCondition" + } + }, + "channel_ids": { "type": [ "array", "null" - ] - }, - "fallthrough": { - "description": "If `true`, evaluation continues to the next case after this one matches; otherwise matching stops at the first hit.", - "type": "boolean" - }, - "if": { - "description": "List of match conditions that are AND-ed together.", + ], "items": { - "$ref": "#/components/schemas/RouteMatchCondition" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Target channel IDs. Required when `routing_mode` is `standard` (or empty); returned as `null` for `name_mapping`." }, - "name_mapping_label": { - "description": "Label key whose value is used as the target channel name. Required when `routing_mode` is `name_mapping`.", - "type": "string" + "fallthrough": { + "type": "boolean", + "description": "When `true`, evaluation continues with the next case after this one matches and the channels of all matched cases are combined; when `false`, evaluation stops at this case." }, "routing_mode": { - "description": "Routing mode. `standard` (default, also used when left empty) routes to the fixed channel IDs; `name_mapping` resolves channels by reading a label value from the alert event.", + "type": "string", "enum": [ "standard", "name_mapping" ], - "type": "string" + "description": "Routing mode. `standard` routes to the fixed `channel_ids`; `name_mapping` routes to the enabled channel whose name equals the value of `name_mapping_label` on the event. An empty value is treated as `standard` and is omitted in responses." + }, + "name_mapping_label": { + "type": "string", + "description": "Event field whose value is used as the target channel name, for example `labels.service`. Required when `routing_mode` is `name_mapping`; if no enabled channel has that name, the case adds no channel." } - }, - "required": [ - "if" - ], - "type": "object" + } }, "RouteDefault": { + "type": "object", "description": "Default branch used when no case matches (or all matched cases yield no valid channels).", "properties": { "channel_ids": { - "description": "Channel IDs to fall back to.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Channels used when no case yields a channel. An empty list is treated as no default branch." } - }, - "type": "object" + } }, "RouteInfoRequest": { + "type": "object", "description": "Parameters for retrieving the routing rule of one integration.", + "required": [ + "integration_id" + ], "properties": { "integration_id": { - "description": "Integration ID. Must be greater than 0.", - "exclusiveMinimum": 0, + "type": "integer", "format": "int64", - "type": "integer" + "description": "Shared integration ID, greater than 0; obtain it from `POST /integration/list`.", + "exclusiveMinimum": 0 } - }, - "required": [ - "integration_id" - ], - "type": "object" + } }, "RouteItem": { - "description": "Routing rule of an integration. Alerts are evaluated against `cases` in order; unmatched alerts fall through to `default`. Returns `null` when the integration has no configured rule.", + "type": "object", + "description": "Routing rule of a shared integration. Alerts are evaluated against `cases` in order; when no case yields a channel, `default` is used.", + "required": [ + "version", + "updated_by", + "creator_id" + ], "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "description": "Integration the rule belongs to." + }, "cases": { - "description": "Ordered list of case branches.", + "type": "array", "items": { "$ref": "#/components/schemas/RouteCase" }, - "type": "array" - }, - "created_at": { - "description": "Creation time, Unix timestamp in seconds.", - "format": "int64", - "type": "integer" - }, - "creator_id": { - "description": "ID of the person who created the rule.", - "format": "int64", - "type": "integer" - }, - "default": { - "$ref": "#/components/schemas/RouteDefault" - }, - "deleted_at": { - "description": "Soft-delete timestamp, Unix seconds. Omitted when the rule is active.", - "format": "int64", - "type": "integer" - }, - "integration_id": { - "description": "Integration the rule belongs to.", - "format": "int64", - "type": "integer" + "description": "Ordered list of case branches." }, "sections": { - "description": "Optional sections that visually group cases.", + "type": "array", "items": { "$ref": "#/components/schemas/RouteSection" }, - "type": "array" + "description": "Optional sections that visually group cases." + }, + "default": { + "$ref": "#/components/schemas/RouteDefault" }, "status": { - "description": "Route status. `enabled` means active; `deleted` means removed, visible only in historical versions.", + "type": "string", "enum": [ "enabled", "deleted" ], - "type": "string" + "description": "Rule status. These endpoints return only `enabled` rules; `deleted` rules (for example of a deleted integration) are not returned." }, - "updated_at": { - "description": "Last update time, Unix timestamp in seconds.", + "version": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Version number, increased on every `POST /route/upsert`. The server does not use it for concurrency checks." }, "updated_by": { - "description": "ID of the person who performed the last update.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the person who performed the last update." }, - "version": { - "description": "Monotonic version number, incremented on each update. Use it for optimistic concurrency control.", + "creator_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the person who created the rule." + }, + "deleted_at": { + "type": "integer", + "format": "int64", + "description": "Soft-delete time, Unix timestamp in seconds. Not returned by these endpoints, which return only active rules." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation time, Unix timestamp in seconds." + }, + "updated_at": { + "type": "integer", + "format": "int64", + "description": "Last update time, Unix timestamp in seconds." } - }, - "required": [ - "version", - "updated_by", - "creator_id" - ], - "type": "object" + } }, "RouteMatchCondition": { + "type": "object", "description": "A single match condition. All conditions inside one case form an AND group.", + "required": [ + "key", + "oper", + "vals" + ], "properties": { "key": { - "description": "Field key to match against the alert event (e.g. `alert_severity`, `labels.service`).", - "type": "string" + "type": "string", + "description": "Alert or change event field to match: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `change_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`. An unknown key returns `InvalidParameter`." }, "oper": { - "description": "Match operator. `IN` matches when the field value is one of `vals`; `NOTIN` matches when it is not.", + "type": "string", "enum": [ "IN", "NOTIN" ], - "type": "string" + "description": "Match operator. `IN` matches when the field value matches any entry in `vals`; `NOTIN` matches when it matches none. A missing field never matches `IN` and always matches `NOTIN`." }, "vals": { - "description": "Values to compare against. Each value may be a literal string, a wildcard (`*`, `?`), a regular expression wrapped in slashes (`/pattern/`), a CIDR (`cidr:10.0.0.0/8`), or a numeric comparison (`num:lt:100`).", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Values to compare, at least one. Each entry is matched as: an exact string; a wildcard pattern when it contains `*` or `?` (must match the whole value); a regular expression when wrapped in slashes, such as `/^db-/` (may match anywhere in the value); an IP range written `cidr:`, such as `cidr:203.0.113.0/24`; or a numeric comparison `num::` with `lt`, `le`, `gt` or `ge`, such as `num:gt:90`." } - }, - "required": [ - "key", - "oper", - "vals" - ], - "type": "object" + } }, "RouteSection": { "description": "A logical section that groups consecutive cases for display purposes.", @@ -19346,75 +19891,24 @@ "type": "object" }, "RuleFieldsUpdateRequest": { + "type": "object", + "required": [ + "ids", + "fields" + ], "properties": { - "annotations": { - "additionalProperties": { - "type": "string" - }, - "description": "Annotation key-value pairs delivered with alert events; keys must not start with `$` (reserved for query fields). Effective only when `fields` includes `annotations`.", - "type": "object" - }, - "annotations_patch": { - "$ref": "#/components/schemas/StringMapPatch", - "description": "Partial annotation update. Effective only when `fields` includes `annotations`; takes precedence over `annotations` when both are sent." - }, - "channel_ids": { - "description": "IDs of the collaboration spaces alerts are sent to; may be empty. Effective only when `fields` includes `channel_ids`.", - "items": { - "format": "uint64", - "type": "integer" - }, - "type": "array" - }, - "cron_pattern": { - "description": "Schedule expression: a 6-field cron (with seconds) or an `@every 30s` interval descriptor; `CRON_TZ=`/`TZ=` prefixes are not allowed. Effective only when `fields` includes `cron_pattern`.", - "type": "string" - }, - "debug_log_enabled": { - "description": "Whether to enable debug logging; the edge emits detailed evaluation logs for troubleshooting. Effective only when `fields` includes `debug_log_enabled`.", - "type": "boolean" - }, - "delay_seconds": { - "description": "Seconds to shift the evaluation query window backward, compensating for data ingestion latency. Effective only when `fields` includes `delay_seconds`.", - "type": "integer" - }, - "description": { - "description": "Rule description (Markdown). Effective only when `fields` includes `description`.", - "type": "string" - }, - "ds_ids": { - "description": "Datasource IDs, merged with `ds_list` to decide which datasources the rule monitors; IDs survive datasource renames. Effective only when `fields` includes `ds_ids`.", - "items": { - "format": "uint64", - "type": "integer" - }, - "type": "array" - }, - "ds_list": { - "description": "Datasource name match patterns; wildcards supported. Effective only when `fields` includes `ds_list`.", - "items": { - "type": "string" - }, - "type": "array" - }, - "ds_type": { - "description": "Datasource type identifier. Effective only when `fields` includes `ds_type`.", - "type": "string" - }, - "enabled": { - "description": "Whether the rule is enabled. Setting it to `false` makes the server clean up the rule's active alerts. Effective only when `fields` includes `enabled`.", - "type": "boolean" - }, - "enabled_times": { - "description": "Time windows during which the rule is in effect; element structure see `EnabledTime`. Effective only when `fields` includes `enabled_times`.", + "ids": { + "type": "array", "items": { - "$ref": "#/components/schemas/EnabledTime" + "type": "integer", + "format": "uint64" }, - "type": "array" + "description": "IDs of the rules to update; must contain at least one ID." }, "fields": { - "description": "Field names to update. Only listed fields are updated, taking new values from the same-named request fields; values for unlisted fields are silently ignored.", + "type": "array", "items": { + "type": "string", "enum": [ "labels", "ds_type", @@ -19431,51 +19925,102 @@ "channel_ids", "repeat_interval", "repeat_total" - ], + ] + }, + "description": "Names of the fields to update. Each listed field takes the value of the same-named request field, and is set to its zero value when that value is omitted; values sent for unlisted fields are ignored. An unknown name fails the whole call with `InvalidParameter`." + }, + "labels": { + "type": "object", + "additionalProperties": { "type": "string" }, - "type": "array" + "description": "Custom label key-value pairs; replaces existing labels as a whole. Effective only when `fields` includes `labels`; cannot be sent together with `labels_patch`." }, - "ids": { - "description": "Rule IDs to update.", + "ds_type": { + "type": "string", + "description": "Datasource type identifier. Enabled rules must use a type that supports alerting: `prometheus`, `elasticsearch`, `loki`, `clickhouse`, `mysql`, `oracle`, `postgres`, `sls`, `tencent_cls`, `victorialogs`. Effective only when `fields` includes `ds_type`." + }, + "ds_list": { + "type": "array", "items": { - "format": "uint64", - "type": "integer" + "type": "string" }, - "type": "array" + "description": "Datasource name match patterns; wildcards supported. Effective only when `fields` includes `ds_list`." }, - "labels": { + "ds_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "uint64" + }, + "description": "Datasource IDs, merged with `ds_list` to decide which datasources the rule monitors; IDs survive datasource renames. Effective only when `fields` includes `ds_ids`." + }, + "enabled": { + "type": "boolean", + "description": "Whether the rule is enabled. Setting it to `false` makes the server clean up the rule's active alerts. Effective only when `fields` includes `enabled`." + }, + "debug_log_enabled": { + "type": "boolean", + "description": "Whether to enable debug logging; the edge emits detailed evaluation logs for troubleshooting. Effective only when `fields` includes `debug_log_enabled`." + }, + "cron_pattern": { + "type": "string", + "description": "Schedule expression: a 6-field cron (with seconds) or an `@every 30s` interval descriptor; `CRON_TZ=`/`TZ=` prefixes are not allowed. Effective only when `fields` includes `cron_pattern`." + }, + "timezone": { + "type": "string", + "description": "Timezone the rule runs in, as an IANA name (e.g. `Asia/Shanghai`, `UTC`); empty falls back to `Asia/Shanghai`. Effective only when `fields` includes `timezone`.", + "default": "Asia/Shanghai" + }, + "delay_seconds": { + "type": "integer", + "description": "Seconds to shift the evaluation query window backward, compensating for data ingestion latency. Effective only when `fields` includes `delay_seconds`." + }, + "enabled_times": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EnabledTime" + }, + "description": "Time windows during which the rule is in effect; element structure see `EnabledTime`. Effective only when `fields` includes `enabled_times`." + }, + "annotations": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "Custom label key-value pairs; replaces existing labels as a whole. Effective only when `fields` includes `labels`.", - "type": "object" + "description": "Annotation key-value pairs delivered with alert events; replaces existing annotations as a whole, and keys must not start with `$` (reserved for query fields). Effective only when `fields` includes `annotations`; cannot be sent together with `annotations_patch`." }, - "labels_patch": { - "$ref": "#/components/schemas/StringMapPatch", - "description": "Partial label update. Effective only when `fields` includes `labels`; takes precedence over `labels` when both are sent." + "description": { + "type": "string", + "description": "Rule description, rendered according to the rule's existing `description_type` (which this endpoint cannot change). Effective only when `fields` includes `description`." + }, + "channel_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "uint64" + }, + "description": "IDs of the collaboration spaces alerts are sent to; may be empty. Effective only when `fields` includes `channel_ids`." }, "repeat_interval": { - "description": "Interval in seconds between repeated alert notifications. Effective only when `fields` includes `repeat_interval`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Interval in seconds between repeated alert notifications; values below 1 fall back to 3600, maximum 2147483647. Effective only when `fields` includes `repeat_interval`." }, "repeat_total": { - "description": "Maximum number of repeated notifications. Effective only when `fields` includes `repeat_total`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Maximum number of repeated notifications; values below 1 fall back to 3, maximum 2147483647. Effective only when `fields` includes `repeat_total`." }, - "timezone": { - "default": "Asia/Shanghai", - "description": "Timezone in which the rule executes. IANA timezone name; defaults to `Asia/Shanghai`.", - "type": "string" + "labels_patch": { + "$ref": "#/components/schemas/StringMapPatch", + "description": "Partial label update that keeps unmentioned labels. Requires `labels` in `fields` and cannot be sent together with `labels`; otherwise the call returns `InvalidParameter`." + }, + "annotations_patch": { + "$ref": "#/components/schemas/StringMapPatch", + "description": "Partial annotation update that keeps unmentioned annotations. Requires `annotations` in `fields` and cannot be sent together with `annotations`; otherwise the call returns `InvalidParameter`." } - }, - "required": [ - "ids", - "fields" - ], - "type": "object" + } }, "RuleIDRequest": { "properties": { @@ -19491,20 +20036,20 @@ "type": "object" }, "RuleIDsRequest": { + "type": "object", + "required": [ + "ids" + ], "properties": { "ids": { - "description": "Rule IDs.", + "type": "array", "items": { - "format": "uint64", - "type": "integer" + "type": "integer", + "format": "uint64" }, - "type": "array" + "description": "IDs of the alert rules to delete; must contain at least one ID. Get them from `POST /monit/rule/list/basic`." } - }, - "required": [ - "ids" - ], - "type": "object" + } }, "RuleImportRequest": { "description": "Array of alert rule export objects to import.", @@ -19521,51 +20066,51 @@ "type": "array" }, "RuleListRequest": { + "type": "object", "description": "Filter parameter for listing rules in a folder.", "properties": { "folder_id": { - "description": "Folder ID. Must be an existing folder; `0` is rejected with a `folder_not_found` error.", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "ID of the folder to list. Must be an existing folder the caller can manage; `0` or an unknown ID returns `InvalidParameter`." }, "include_descendants": { - "description": "Also include rules from all descendant folders. When `true`, each returned item carries only `id`, `folder_id` and `name`; combine with `query` / `limit` for rule-picker scenarios.", - "type": "boolean" + "type": "boolean", + "description": "Also search all descendant folders. When `true`, results are sorted by name, capped by `limit`, and each item fills only `id`, `folder_id` and `name` (other fields carry zero values); combine with `query` for rule-picker scenarios." + }, + "query": { + "type": "string", + "description": "Filter by rule name substring; a numeric value also matches the rule with that ID. Only effective when `include_descendants` is `true`." }, "limit": { + "type": "integer", "default": 50, - "description": "Max number of rules returned; only effective when `include_descendants` is `true`. Defaults to 50, capped at 100.", "maximum": 100, - "type": "integer" - }, - "query": { - "description": "Rule name fuzzy filter; only effective when `include_descendants` is `true`.", - "type": "string" + "description": "Max number of rules returned; only effective when `include_descendants` is `true`. Defaults to 50, capped at 100." } - }, - "type": "object" + } }, "RuleMoveRequest": { + "type": "object", + "required": [ + "ids", + "dest_folder_id" + ], "properties": { - "dest_folder_id": { - "description": "Destination folder ID. Obtainable via `POST /monit/folder/list`.", - "format": "uint64", - "type": "integer" - }, "ids": { - "description": "Rule IDs to move.", + "type": "array", "items": { - "format": "uint64", - "type": "integer" + "type": "integer", + "format": "uint64" }, - "type": "array" + "description": "IDs of the rules to move; must contain at least one ID." + }, + "dest_folder_id": { + "type": "integer", + "format": "uint64", + "description": "Destination folder ID, from `POST /monit/folder/list`. Must be non-zero; a folder that does not exist or that the caller cannot manage fails the whole call with `AccessDenied`." } - }, - "required": [ - "ids", - "dest_folder_id" - ], - "type": "object" + } }, "RuleNameMessageListResponse": { "description": "Per-rule batch-operation results.", @@ -19578,12 +20123,15 @@ "description": "Alert settings for the application.", "properties": { "channel_ids": { - "description": "Channel IDs to send alerts to. Used only when `delivery_mode` is `oncall`.", + "description": "On-call channel IDs that receive the alerts; used only when `delivery_mode` is `oncall`. Kept as a draft in `webhook` mode. Can be `null` when never set.", "items": { "format": "int64", "type": "integer" }, - "type": "array" + "type": [ + "array", + "null" + ] }, "delivery_mode": { "description": "Alert delivery channel: `oncall` routes alert events through Flashduty On-call, `webhook` POSTs them directly to `webhook_url`. An empty value is treated as `oncall`, and on create/update it is persisted as the deployment default (`webhook` on RUM-only on-premises deployments, `oncall` otherwise). Omitted when empty (legacy rows).", @@ -19594,7 +20142,7 @@ "type": "string" }, "enabled": { - "description": "Whether alerting is enabled.", + "description": "Whether alerting is on. `false` turns alerting off; with `false`, `webhook_url` is not checked.", "type": "boolean" }, "integration_id": { @@ -19603,7 +20151,7 @@ "type": "integer" }, "webhook_url": { - "description": "URL that receives alert events when `delivery_mode` is `webhook`; required in that mode, ignored otherwise. Omitted when empty.", + "description": "URL that receives alert events when `delivery_mode` is `webhook`. Required in that mode while `enabled` is `true`; must use `http` or `https`, and on Flashduty cloud must not resolve to a private, loopback, link-local or reserved address. Ignored in `oncall` mode. Omitted from responses when empty.", "format": "uri", "type": "string" } @@ -19627,7 +20175,7 @@ "type": "string" }, "is_private": { - "description": "Restrict access to team members only.", + "description": "If `true`, only the account owner, account admins, the creator and members of the owning team can see or edit the application. Default `false`.", "type": "boolean" }, "links": { @@ -19643,11 +20191,11 @@ "description": "Source code repositories to link, in order; the first entry is the primary repository. At most 10 entries." }, "no_geo": { - "description": "Do not infer geographic location.", + "description": "If `true`, geographic location is not inferred from the client IP. Default `false`.", "type": "boolean" }, "no_ip": { - "description": "Do not collect IP addresses.", + "description": "If `true`, client IP addresses are not collected. Default `false`.", "type": "boolean" }, "team_id": { @@ -19658,7 +20206,7 @@ }, "tracing": { "$ref": "#/components/schemas/RumApplicationTracing", - "description": "Optional APM tracing integration configuration." + "description": "Optional APM tracing integration configuration. Stored as empty (`enabled: false`, empty `open_type` and `endpoint`) when omitted." }, "type": { "description": "Platform identifier:\n\n| Value | Meaning |\n|---|---|\n| `browser` | Web browser application (JavaScript SDK) |\n| `ios` | Apple iOS application |\n| `android` | Android application |\n| `react-native` | React Native application |\n| `flutter` | Flutter application |\n| `kotlin-multiplatform` | Kotlin Multiplatform application |\n| `roku` | Roku channel application |\n| `unity` | Unity application |\n| `miniprogram` | WeChat mini program |\n| `harmony` | HarmonyOS application |\n| `electron` | Electron desktop application |", @@ -19689,7 +20237,7 @@ "description": "Result of creating a RUM application.", "properties": { "application_id": { - "description": "Auto-generated unique application ID.", + "description": "Server-generated application ID (22-character short UUID); pass it as `application_id` to the other application operations.", "type": "string" }, "application_name": { @@ -19697,11 +20245,16 @@ "type": "string" }, "client_token": { - "description": "Token for RUM SDK initialization.", + "description": "Token used to initialize the RUM SDK. Also returned by `POST /rum/application/info`.", "type": "string" } }, - "type": "object" + "type": "object", + "required": [ + "application_id", + "application_name", + "client_token" + ] }, "RumApplicationIDRequest": { "description": "Request with a single application ID.", @@ -19720,7 +20273,7 @@ "description": "Batch application info request.", "properties": { "application_ids": { - "description": "Up to 200 application IDs. Get IDs via `POST /rum/application/list`.", + "description": "Up to 200 application IDs. Duplicates are collapsed, and unknown or deleted IDs are skipped. Get IDs via `POST /rum/application/list`.", "items": { "type": "string" }, @@ -19737,26 +20290,29 @@ "description": "Batch application info response.", "properties": { "items": { - "description": "Application info items matching the requested `application_ids` (max 200, deduplicated).", + "description": "Applications found among the requested `application_ids`, in no guaranteed order. Empty array when none match.", "items": { "$ref": "#/components/schemas/RumApplicationItem" }, "type": "array" } }, - "type": "object" + "type": "object", + "required": [ + "items" + ] }, "RumApplicationItem": { "description": "A RUM application.", "properties": { "account_id": { - "description": "Account ID.", + "description": "ID of the Flashduty account that owns the application.", "format": "int64", "type": "integer" }, "alerting": { "$ref": "#/components/schemas/RumApplicationAlerting", - "description": "Alerting configuration of the application." + "description": "Alerting configuration of the application. Always an object." }, "application_id": { "description": "Unique application ID.", @@ -19776,17 +20332,17 @@ "type": "integer" }, "created_by": { - "description": "Creator member ID.", + "description": "Member ID of the creator. The creator can always edit the application.", "format": "int64", "type": "integer" }, "is_private": { - "description": "If `true`, the application is only accessible to team members.", + "description": "If `true`, only the account owner, account admins, the creator and members of the owning team can see or edit the application.", "type": "boolean" }, "links": { "$ref": "#/components/schemas/RumApplicationLinks", - "description": "External-link integration configuration." + "description": "External-link integration configuration. Always an object; `systems` can be `null` when no system was ever saved." }, "repositories": { "type": "array", @@ -19794,7 +20350,7 @@ "$ref": "#/components/schemas/RumApplicationRepository" }, "maxItems": 10, - "description": "Linked source code repositories, in order; the first entry is the primary repository. Linking grants no access by itself: AI sessions can only read repositories granted to the account's GitHub App installations." + "description": "Linked source code repositories, in order; the first entry is the primary repository. Empty array when none are linked. Linking grants no access by itself: AI sessions can only read repositories granted to the account's GitHub App installations." }, "no_geo": { "description": "If `true`, geographic location is not inferred from IP.", @@ -19805,7 +20361,7 @@ "type": "boolean" }, "status": { - "description": "Application status. One of `enabled` (active, receiving data), `disabled` (deactivated), `deleted` (soft-delete marker; every query filters it out, so it never actually appears in responses).", + "description": "Application status:\n\n- `enabled`: the SDK `client_token` is accepted and data is collected. Every application created through the API starts in this state.\n- `disabled`: the `client_token` is rejected, so no new data is collected. No public operation sets this status.\n- `deleted`: soft-delete marker; deleted applications are filtered out of every response, so this value is never returned.", "enum": [ "enabled", "disabled", @@ -19814,13 +20370,13 @@ "type": "string" }, "team_id": { - "description": "Owning team ID.", + "description": "Owning team ID. Members of this team can edit the application and, when it is private, see it.", "format": "int64", "type": "integer" }, "tracing": { "$ref": "#/components/schemas/RumApplicationTracing", - "description": "APM tracing integration configuration." + "description": "APM tracing integration configuration. Always an object; when tracing was never configured it is `enabled: false` with empty `open_type` and `endpoint`." }, "type": { "description": "Platform identifier:\n\n| Value | Meaning |\n|---|---|\n| `browser` | Web browser application (JavaScript SDK) |\n| `ios` | Apple iOS application |\n| `android` | Android application |\n| `react-native` | React Native application |\n| `flutter` | Flutter application |\n| `kotlin-multiplatform` | Kotlin Multiplatform application |\n| `roku` | Roku channel application |\n| `unity` | Unity application |\n| `miniprogram` | WeChat mini program |\n| `harmony` | HarmonyOS application |\n| `electron` | Electron desktop application |", @@ -19850,13 +20406,33 @@ "type": "integer" } }, - "type": "object" + "type": "object", + "required": [ + "account_id", + "application_id", + "application_name", + "type", + "client_token", + "team_id", + "is_private", + "no_ip", + "no_geo", + "alerting", + "tracing", + "links", + "repositories", + "status", + "created_by", + "updated_by", + "created_at", + "updated_at" + ] }, "RumApplicationLink": { "description": "External system link rendered on matching RUM event detail pages.", "properties": { "enabled": { - "description": "Whether this external system link is enabled.", + "description": "Whether this external system link is shown. Treated as `false` when omitted.", "type": "boolean" }, "event_types": { @@ -19877,15 +20453,15 @@ "type": "array" }, "icon_color": { - "description": "Display color for the link icon.", + "description": "Display color for the link icon, e.g. `#0F766E`. Omitted from responses when empty.", "type": "string" }, "icon_text": { - "description": "Short text shown in the link icon.", + "description": "Short text shown in the link icon, e.g. `S3`. Omitted from responses when empty.", "type": "string" }, "id": { - "description": "Stable client-side identifier for this external system.", + "description": "Client-chosen identifier for this external system, kept as sent; the server does not validate it.", "type": "string" }, "name": { @@ -19910,7 +20486,7 @@ "description": "External link integration settings for the application.", "properties": { "enabled": { - "description": "Whether external link integration is enabled.", + "description": "Master switch for the external-link integration. Treated as `false` when omitted.", "type": "boolean" }, "systems": { @@ -19933,11 +20509,11 @@ "description": "Filters for listing RUM applications.", "properties": { "asc": { - "description": "Sort ascending if `true`.", + "description": "Sort ascending if `true`; default `false` (descending).", "type": "boolean" }, "is_my_team": { - "description": "If `true`, return only applications belonging to the current user's teams.", + "description": "If `true`, return only applications owned by teams the caller belongs to. When the caller belongs to no team, the list is empty.", "type": "boolean" }, "limit": { @@ -19960,7 +20536,7 @@ "type": "integer" }, "query": { - "description": "Substring match on the application name.", + "description": "Substring match on the application name (SQL `LIKE`, so `%` and `_` act as wildcards).", "type": "string" }, "team_id": { @@ -19979,7 +20555,7 @@ "type": "boolean" }, "items": { - "description": "RUM applications of the current page.", + "description": "RUM applications on the current page. Empty array when nothing matches.", "items": { "$ref": "#/components/schemas/RumApplicationItem" }, @@ -19990,24 +20566,30 @@ "type": "integer" } }, - "type": "object" + "type": "object", + "required": [ + "has_next_page", + "total", + "items" + ] }, "RumApplicationTracing": { "description": "APM tracing integration settings.", "properties": { "enabled": { - "description": "Whether tracing integration is enabled.", + "description": "Whether trace links are shown on RUM events.", "type": "boolean" }, "endpoint": { - "description": "Trace endpoint URL (http or https).", + "description": "Trace endpoint URL; must start with `http` or `https`. Required whenever `tracing` is sent, even with `enabled: false`. Empty in responses when tracing was never configured.", "type": "string" }, "open_type": { - "description": "How to open the trace link. One of `popup` (open trace details in a popup) or `tab` (open in a new browser tab).", + "description": "How the trace link opens:\n\n- `popup`: open trace details in a popup.\n- `tab`: open them in a new browser tab.\n- `\"\"` (empty): returned only when tracing was never configured; rejected in requests.", "enum": [ "popup", - "tab" + "tab", + "" ], "type": "string" } @@ -20024,7 +20606,7 @@ "properties": { "alerting": { "$ref": "#/components/schemas/RumApplicationAlerting", - "description": "Alerting configuration. Omit to leave unchanged.", + "description": "Alerting configuration. When sent, it replaces the stored alerting object (except `integration_id`, which the server manages). Omit to leave unchanged.", "x-flashduty-preserve-absence": true }, "application_id": { @@ -20041,7 +20623,7 @@ ] }, "is_private": { - "description": "Restrict access to members of the owning team; `false` explicitly makes the application public. Omit to leave unchanged.", + "description": "`true` limits access to the account owner, account admins, the creator and members of the owning team; `false` makes the application visible to everyone in the account. Omit to leave unchanged.", "type": [ "boolean", "null" @@ -20049,7 +20631,7 @@ }, "links": { "$ref": "#/components/schemas/RumApplicationLinks", - "description": "External-link integration configuration. Omit to leave unchanged.", + "description": "External-link integration configuration. When sent, it replaces the stored object, including the whole `systems` list. Omit to leave unchanged.", "x-flashduty-preserve-absence": true }, "repositories": { @@ -20076,7 +20658,7 @@ ] }, "team_id": { - "description": "Owning team ID. Get team IDs via `POST /team/list`. Omit to leave unchanged.", + "description": "New owning team ID. Get team IDs via `POST /team/list`. Omit to leave unchanged. Moving the application to another team changes who can edit it.", "exclusiveMinimum": 0, "format": "int64", "type": [ @@ -20086,7 +20668,7 @@ }, "tracing": { "$ref": "#/components/schemas/RumApplicationTracing", - "description": "APM tracing integration configuration. Omit to leave unchanged." + "description": "APM tracing integration configuration. When sent, it replaces the stored object and must carry a valid `open_type` and `endpoint`. Omit to leave unchanged." }, "type": { "description": "Application type. Omit to leave unchanged. Platform identifier:\n\n| Value | Meaning |\n|---|---|\n| `browser` | Web browser application (JavaScript SDK) |\n| `ios` | Apple iOS application |\n| `android` | Android application |\n| `react-native` | React Native application |\n| `flutter` | Flutter application |\n| `kotlin-multiplatform` | Kotlin Multiplatform application |\n| `roku` | Roku channel application |\n| `unity` | Unity application |\n| `miniprogram` | WeChat mini program |\n| `harmony` | HarmonyOS application |\n| `electron` | Electron desktop application |", @@ -20118,15 +20700,15 @@ "description": "Metadata for one returned column.", "properties": { "name": { - "description": "Column name.", + "description": "Column name or alias as written in `sql`; `ts` for the bucket column of `time_series` queries.", "type": "string" }, "nullable": { - "description": "Whether values in this column may be null.", + "description": "Whether values in this column may be `null`. `true` when the driver cannot tell.", "type": "boolean" }, "type": { - "description": "Backend database type name for this column.", + "description": "Column type name as reported by the database driver, such as `VARCHAR`, `BIGINT`, `DOUBLE` or `DATETIME`. It depends on the selected column or expression, so the set is open; use it as a hint for parsing `values`.", "type": "string" } }, @@ -20141,11 +20723,11 @@ "description": "One RUM data query definition.", "properties": { "disable_sampling": { - "description": "When true, asks the query engine to avoid sampling when possible.", + "description": "When `true`, the query always runs on the full data and the response never carries `sampling`. When `false` (default), the server may sample aggregate queries over large time windows.", "type": "boolean" }, "dql": { - "description": "Optional RUM DQL filter expression used together with SQL validation.", + "description": "Optional RUM DQL filter. It is translated and `AND`-ed into the `WHERE` clause of `sql`. A DQL parse error is reported in this query's `error` entry.", "type": "string" }, "format": { @@ -20163,28 +20745,28 @@ }, "interval": { "default": 3600, - "description": "Time bucket interval in seconds for `time_series` queries.", + "description": "Minimum time-bucket width in **milliseconds** for `time_series` queries. Default 3600 (3.6 seconds). The effective width is the smallest step of a fixed ladder that is at least this value and at least the window length divided by `max_points`; it is returned as `interval`. Ignored for `table` queries.", "exclusiveMinimum": 0, "format": "int64", "type": "integer" }, "max_points": { "default": 1226, - "description": "Maximum number of points for `time_series` queries.", + "description": "Upper bound on the number of buckets for `time_series` queries. Default 1226. The bucket width grows so that the window holds at most this many buckets. Ignored for `table` queries.", "exclusiveMinimum": 0, "format": "int64", "type": "integer" }, "search_after_ctx": { - "description": "Opaque cursor returned by a previous table query for continuing pagination.", + "description": "Cursor from a previous response's `search_after_ctx`, to fetch the next page of the same `table` query. Only used by non-aggregate queries with `ORDER BY` and no `OFFSET`. An invalid value makes this query fail.", "type": "string" }, "sql": { - "description": "RUM SQL query to execute.", + "description": "RUM SQL `SELECT` statement. `FROM` names a scope table (`sessions`, `views`, `actions`, `errors`, `resources`, `long_tasks`, `vitals`, `issues`, `sourcemaps`); columns are `field_key` values from `POST /rum/field/list`. The server adds the account and time-range filters.", "type": "string" }, "time_zone": { - "description": "IANA time zone name used when evaluating time functions, such as `Asia/Shanghai`.", + "description": "IANA time zone name, such as `Asia/Shanghai`, used to align `time_series` bucket boundaries to local time. Defaults to UTC alignment. Ignored for `table` queries; an unknown name fails the request with `InvalidParameter`.", "type": "string" } }, @@ -20204,7 +20786,7 @@ }, "error": { "$ref": "#/components/schemas/DutyError", - "description": "Subquery failure details. Omitted when the query succeeded." + "description": "Set when this query failed after request validation (unknown table or column, invalid `dql` or `search_after_ctx`, database error). The code is always `InternalError`. Omitted when the query succeeded." } }, "type": "object" @@ -20252,14 +20834,14 @@ "description": "Rows and metadata returned by one RUM data query.", "properties": { "fields": { - "description": "Column metadata for the values matrix.", + "description": "Column metadata, one entry per returned column, in the same order as `values`. For `time_series` queries the first column is `ts`.", "items": { "$ref": "#/components/schemas/RumDataFieldMeta" }, "type": "array" }, "interval": { - "description": "Effective time bucket interval in seconds. Omitted for `table`-format queries.", + "description": "Effective time-bucket width in **milliseconds** used by a `time_series` query. Omitted for `table` queries.", "format": "int64", "type": "integer" }, @@ -20268,14 +20850,17 @@ "description": "Sampling metadata. Omitted when the query did not use sampling." }, "search_after_ctx": { - "description": "Opaque cursor for continuing paginated table queries. Omitted when the query is not a cursor-paginated table query or no further pages exist.", + "description": "Cursor for the next page of a non-aggregate `table` query with `ORDER BY` and no `OFFSET`. Present only when this page returned as many rows as the `LIMIT`; omitted otherwise.", "type": "string" }, "values": { - "description": "Rows returned by the query. Each row aligns with `fields` by index.", + "description": "Result values in column-major order: `values[i]` is the list of every row's value for column `fields[i]`. A column is `null` when the query returned no rows. Datetime values are returned as RFC 3339 strings.", "items": { "items": {}, - "type": "array" + "type": [ + "array", + "null" + ] }, "type": "array" } @@ -20294,7 +20879,7 @@ "type": "boolean" }, "scale_factor": { - "description": "Multiplier used to scale sampled counts back to estimated full counts.", + "description": "Multiplier applied to scale sampled results back to estimated full values. `COUNT`, `SUM` and `COUNT(DISTINCT)` columns in `values` are already multiplied by it; other aggregates are returned as computed on the sample.", "type": "number" } }, @@ -20312,13 +20897,13 @@ "type": "string" }, "description": { - "description": "Rule description, up to 512 characters.", + "description": "Rule description, up to 512 characters. Defaults to an empty string.", "maxLength": 512, "type": "string" }, "filters": { "$ref": "#/components/schemas/RumErrorIngestionOrFilters", - "description": "Filter conditions (OR-of-ANDs) to match errors; matched errors are dropped and not ingested." + "description": "Conditions (OR-of-ANDs) that select errors. A matched error is still stored but is not grouped into any issue." }, "rule_name": { "description": "Rule name, 1-128 characters.", @@ -20361,11 +20946,11 @@ "description": "A single filter condition matched against one error field.", "properties": { "key": { - "description": "Field key. One of `error.usr_id`, `error.usr_email`, `error.error_type`, `error.error_message`, `error.error_stack`, `error.view_url`, `error.env`, `error.version`, `error.service`, `error.browser_name`, `error.browser_version`, `error.fingerprint`, `error.is_crash`, or a `context.`-prefixed custom context path (up to 3 levels deep).", + "description": "Field to match. One of `error.usr_id`, `error.usr_email`, `error.error_type`, `error.error_message`, `error.error_stack`, `error.view_url`, `error.env`, `error.version`, `error.service`, `error.browser_name`, `error.browser_version`, `error.fingerprint`, `error.is_crash` (value `true` or `false`), or a `context.`-prefixed path into the error's custom context. Context objects are flattened with dots up to 3 levels (`context.a.b.c`); a deeper object is compared as its JSON text, and array values can't be matched.", "type": "string" }, "oper": { - "description": "Match mode: `IN` matches when the field value matches any entry in `vals`; `NOTIN` matches when it matches none.", + "description": "Match mode:\n- `IN`: matches when the field value matches any entry in `vals`. A context field the error doesn't carry never matches.\n- `NOTIN`: matches when the field value matches none of `vals`. A context field the error doesn't carry always matches.", "enum": [ "IN", "NOTIN" @@ -20373,7 +20958,7 @@ "type": "string" }, "vals": { - "description": "Values to match against, at least 1 entry. Each entry is an exact string, or a special pattern using wildcards (`*`/`?`), a regexp wrapped in `/`, a `cidr:`-prefixed CIDR match, or a `num:lt|le|gt|ge:`-prefixed numeric comparison.", + "description": "Values to match against, at least 1 entry. Each entry is one of: an exact, case-sensitive string; a wildcard pattern using `*`/`?` that must match the whole value; a regexp wrapped in `/` (matches anywhere in the value unless anchored); `cidr:` (the value is parsed as an IP); or `num:lt|le|gt|ge:` (the value is parsed as a number, non-numeric values don't match).", "items": { "type": "string" }, @@ -20392,28 +20977,28 @@ "description": "A snapshot of every rule for the application at one history version.", "properties": { "rules": { - "description": "The application's complete rule list as of this version.", + "description": "The application's complete non-deleted rule list as it was just before the change that created this version. Empty for the version created by the application's first rule.", "items": { "$ref": "#/components/schemas/RumErrorIngestionRuleSnapshotItem" }, "type": "array" }, "updated_at": { - "description": "Unix timestamp in milliseconds when this snapshot was recorded.", + "description": "Time of the change that created this version, as a Unix timestamp in milliseconds.", "format": "int64", "type": "integer" }, "updated_by": { - "description": "Member ID whose action triggered this snapshot.", + "description": "Member ID of the person who made the change that created this version.", "format": "int64", "type": "integer" }, "updated_by_name": { - "description": "Display name of the member whose action triggered this snapshot.", + "description": "Display name of that member at the time of the change.", "type": "string" }, "version": { - "description": "History version number, incrementing from 1.", + "description": "History version number, starting at 1 and incremented by every write. Pass it to `POST /rum/error-ingestion/rules/history/revert`.", "type": "integer" } }, @@ -20435,20 +21020,23 @@ }, "asc": { "default": false, - "description": "Sort ascending instead of the default descending order.", + "description": "`true` sorts ascending; `false` (default) sorts descending, newest first.", "type": "boolean" }, "limit": { "default": 20, - "description": "Page size. Default 20, capped at 100; values ≤ 0 fall back to the default.", + "description": "Page size. Default 20; values above 100 are clamped to 100, and values of 0 or below fall back to 20.", "format": "int64", - "maximum": 100, "type": "integer" }, "orderby": { "default": "updated_at", - "description": "Sort column: `updated_at` or `version`. Unrecognized values fall back to `updated_at`.", - "type": "string" + "description": "Sort column:\n- `updated_at`: time of the change that created the version (default).\n- `version`: version number.\nAny other value falls back to `updated_at`.", + "type": "string", + "enum": [ + "updated_at", + "version" + ] }, "p": { "default": 0, @@ -20467,7 +21055,7 @@ "description": "Paginated error ingestion rule history.", "properties": { "has_next_page": { - "description": "Whether another page of history exists after this one.", + "description": "`true` when more versions exist after this page.", "type": "boolean" }, "items": { @@ -20478,7 +21066,7 @@ "type": "array" }, "total": { - "description": "Total number of history versions for the application.", + "description": "Total number of history versions for the application, across all pages.", "format": "int64", "type": "integer" } @@ -20520,7 +21108,7 @@ "type": "object" }, "RumErrorIngestionOrFilters": { - "description": "OR-of-ANDs filter set. The outer array is OR — an error matches the rule if it matches at least one inner AND-group.", + "description": "OR-of-ANDs filter set. The outer array is OR: an error matches the rule if it matches at least one inner AND-group. An empty outer array never matches; an empty inner group matches every error.", "items": { "description": "AND-group. The group only matches when every condition inside it matches.", "items": { @@ -20553,20 +21141,20 @@ "description": "An error ingestion rule.", "properties": { "created_at": { - "description": "Unix timestamp in milliseconds when the rule was created.", + "description": "Unix timestamp in milliseconds when the rule was created; reset to the revert time when the rule is restored by a history revert.", "format": "int64", "type": "integer" }, "description": { - "description": "Rule description, up to 512 characters.", + "description": "Rule description, up to 512 characters; empty string when none was given.", "type": "string" }, "filters": { "$ref": "#/components/schemas/RumErrorIngestionOrFilters", - "description": "The rule's filter conditions." + "description": "The rule's conditions. An error that matches them is stored but not grouped into any issue." }, "rule_id": { - "description": "Rule ID.", + "description": "Rule ID, generated by the server on `create`. It stays the same across updates and history reverts.", "type": "string" }, "rule_name": { @@ -20574,7 +21162,7 @@ "type": "string" }, "status": { - "description": "Current status of the rule.", + "description": "Rule status:\n- `enabled`: the rule is applied to newly ingested errors.\n- `disabled`: the rule is kept but not applied.", "enum": [ "enabled", "disabled" @@ -20582,7 +21170,7 @@ "type": "string" }, "updated_at": { - "description": "Unix timestamp in milliseconds when the rule was last updated.", + "description": "Unix timestamp in milliseconds of the last update, enable, or disable; reset to the revert time when the rule is restored by a history revert.", "format": "int64", "type": "integer" } @@ -20620,7 +21208,7 @@ "description": "One rule record inside a history snapshot. Carries the raw storage fields, a superset of the fields returned by `list`.", "properties": { "account_id": { - "description": "Account ID.", + "description": "ID of the account that owns the rule.", "format": "int64", "type": "integer" }, @@ -20639,12 +21227,12 @@ "type": "integer" }, "deleted_at": { - "description": "Unix timestamp in milliseconds when the row was soft-deleted; `0` when not deleted.", + "description": "Soft-delete time as a Unix timestamp in milliseconds. Always `0` here, because snapshots contain only non-deleted rules.", "format": "int64", "type": "integer" }, "description": { - "description": "Rule description.", + "description": "Rule description as of this snapshot version; empty string when none was given.", "type": "string" }, "filters": { @@ -20652,20 +21240,20 @@ "description": "The rule's filter conditions as of this snapshot version." }, "id": { - "description": "Internal row ID.", + "description": "Internal storage row ID. Not accepted by any endpoint; use `rule_id` instead. Changes when the rule is restored by a history revert.", "format": "int64", "type": "integer" }, "rule_id": { - "description": "Rule ID.", + "description": "Rule ID, the same value `list` returns for this rule.", "type": "string" }, "rule_name": { - "description": "Rule name.", + "description": "Rule name as of this snapshot version.", "type": "string" }, "status": { - "description": "The rule's status as of this snapshot version.", + "description": "The rule's status as of this snapshot version:\n- `enabled`: applied to newly ingested errors.\n- `disabled`: kept but not applied.", "enum": [ "enabled", "disabled" @@ -20678,7 +21266,7 @@ "type": "integer" }, "updated_by": { - "description": "Member ID who last updated the rule.", + "description": "Member ID who last updated the rule before this snapshot.", "format": "int64", "type": "integer" } @@ -20743,7 +21331,7 @@ "description": "Parameters for counting facet value distribution.", "properties": { "dql": { - "description": "RUM DQL filter expression applied before counting.", + "description": "RUM DQL filter expression applied before counting. Fields in it are validated against the `scope`.", "type": "string" }, "end_time": { @@ -20753,11 +21341,11 @@ "type": "integer" }, "facet_key": { - "description": "Field key whose value distribution to count; must be a registered field of the given `scope`. List available fields via `POST /rum/field/list`.", + "description": "Field key whose value distribution to count, such as `error_type`. Must be a facet field of the given `scope` with `show_type: list` and a non-array `value_type`. List candidates with `POST /rum/field/list`.", "type": "string" }, "facet_value": { - "description": "When set, filter events where `facet_key` equals this value before counting. Accepts string, number, or boolean." + "description": "When set, count only events whose `facet_key` equals this value. The JSON type must match the field's `value_type` (string, number or boolean); a mismatch returns `InvalidParameter`. When omitted, events with a `null` value are excluded." }, "kind": { "description": "Symbol kind, used only when `scope` is `sourcemap` and only meaningful for `android`/`harmony`: `mapping` (default) selects ProGuard/R8 mappings or ArkTS sourcemaps, `native` selects native .so symbols.", @@ -20789,7 +21377,7 @@ "type": "string" }, "sql": { - "description": "SQL WHERE clause (no SELECT) for additional filtering.", + "description": "Bare SQL `WHERE` condition (without the `WHERE` keyword) for extra filtering, such as `env = 'prod'`. Any occurrence of `SELECT` is rejected.", "type": "string" }, "start_time": { @@ -20881,7 +21469,7 @@ "type": "string" }, "group": { - "description": "Display group for this field.", + "description": "Display group used to cluster fields in the console, such as `error`, `action` or `device`. Empty when the field has no group.", "type": "string" }, "is_facet": { @@ -20893,7 +21481,7 @@ "type": "boolean" }, "scopes": { - "description": "RUM scopes this field appears in.", + "description": "RUM scopes this field appears in, using the same values as the request `scopes` (for example `error`, `issue`).", "items": { "type": "string" }, @@ -20908,15 +21496,34 @@ "type": "string" }, "status": { - "description": "Field status, e.g. `active`.", + "description": "Field status. `enabled`: the field is in use. `disabled`: the field is defined but switched off. Deleted fields are never returned.", + "enum": [ + "enabled", + "disabled" + ], "type": "string" }, "unit_family": { - "description": "Measurement unit family, e.g. `time`, `bytes`. Empty for dimensionless fields.", + "description": "Measurement unit family. `time`: a duration or timestamp (see `unit_name`). `bytes`: a size in bytes. Empty string for dimensionless fields.", + "enum": [ + "", + "time", + "bytes" + ], "type": "string" }, "unit_name": { - "description": "Specific measurement unit, e.g. `millisecond`, `byte`.", + "description": "Unit of the stored value. Durations: `nanosecond`, `microsecond`, `millisecond`, `second`. Timestamps: `unix_millisecond`, `unix_second`. Sizes: `byte`. Empty string for dimensionless fields. Most built-in duration fields are in `nanosecond`.", + "enum": [ + "", + "nanosecond", + "microsecond", + "millisecond", + "second", + "unix_millisecond", + "unix_second", + "byte" + ], "type": "string" }, "value_type": { @@ -21017,11 +21624,11 @@ "type": "boolean" }, "console_origin": { - "description": "Console origin used to build the `issue_url` column, e.g. `https://console.flashcat.cloud`. The service cannot infer it (SaaS, on-premises and dev releases answer on different origins).", + "description": "Console origin used to build the `issue_url` column, e.g. `https://console.flashcat.cloud`; a trailing `/` is trimmed. The service cannot infer it. When omitted, `issue_url` holds only the path `/rum/error-tracking/issue/`.", "type": "string" }, "dql": { - "description": "DQL query for advanced filtering. Cannot be used with `sql`.", + "description": "DQL query for advanced filtering. Field names must be fields of the `issue` scope (see `POST /rum/field/list` with `scopes: [\"issue\"]`); a bare full-text term searches the error message. Cannot be used with `sql`.", "type": "string" }, "end_time": { @@ -21034,7 +21641,7 @@ "type": "boolean" }, "export_fields": { - "description": "CSV columns to export, in the order they appear. Unknown keys are rejected with a parameter error; an empty array uses the default column set.\n\n| Value | Column content |\n|---|---|\n| `issue_id` | Issue ID |\n| `issue_url` | Console URL of the issue detail page (built from `console_origin`) |\n| `application_name` | Owning application name |\n| `service` | Service name |\n| `error_type` | Error type |\n| `error_message` | Error message |\n| `status` | Triage status |\n| `severity` | Severity |\n| `is_crash` | Whether the error caused a crash |\n| `error_count` | Error occurrence count |\n| `session_count` | Affected session count |\n| `first_seen_at` | First occurrence time (rendered in `time_zone`) |\n| `first_seen_version` | Application version at first occurrence |\n| `last_seen_at` | Most recent occurrence time (rendered in `time_zone`) |\n| `last_seen_version` | Application version at the most recent occurrence |\n| `versions` | All affected versions |\n| `suspected_cause` | Suspected cause category |\n| `resolved_at` | Resolution time (rendered in `time_zone`) |", + "description": "CSV columns to export, in the order they appear. Unknown keys are rejected with a parameter error and duplicates are dropped. Empty or omitted: every column below except the `sample_first_*` group.\n\n| Value | Column content |\n|---|---|\n| `issue_id` | Issue ID |\n| `issue_url` | Console URL of the issue detail page (built from `console_origin`) |\n| `application_name` | Owning application name |\n| `service` | Service name |\n| `error_type` | Error type |\n| `error_message` | Error message |\n| `status` | Triage status |\n| `severity` | Severity |\n| `is_crash` | Whether the error caused a crash |\n| `error_count` | Error occurrence count |\n| `session_count` | Affected session count |\n| `first_seen_at` | First occurrence time (rendered in `time_zone`) |\n| `first_seen_version` | Application version at first occurrence |\n| `last_seen_at` | Most recent occurrence time (rendered in `time_zone`) |\n| `last_seen_version` | Application version at the most recent occurrence |\n| `versions` | All affected versions |\n| `suspected_cause` | Suspected cause category |\n| `resolved_at` | Resolution time (rendered in `time_zone`); empty while unresolved |\n| `sample_time` | Latest error event in the time window: time of the event (rendered in `time_zone`) |\n| `sample_version` | Latest error event in the time window: application version |\n| `sample_view` | Latest error event in the time window: view name, or the view URL when the name is empty |\n| `sample_session_id` | Latest error event in the time window: session ID |\n| `sample_device` | Latest error event in the time window: device brand and model |\n| `sample_os` | Latest error event in the time window: OS name and version |\n| `sample_browser` | Latest error event in the time window: browser name and version |\n| `sample_stack` | Latest error event in the time window: error stack, truncated to the first 20 lines |\n| `sample_first_time` | Earliest error event in the time window: time of the event (rendered in `time_zone`) |\n| `sample_first_version` | Earliest error event in the time window: application version |\n| `sample_first_view` | Earliest error event in the time window: view name, or the view URL when the name is empty |\n| `sample_first_session_id` | Earliest error event in the time window: session ID |\n| `sample_first_device` | Earliest error event in the time window: device brand and model |\n| `sample_first_os` | Earliest error event in the time window: OS name and version |\n| `sample_first_browser` | Earliest error event in the time window: browser name and version |\n| `sample_first_stack` | Earliest error event in the time window: error stack, truncated to the first 20 lines |", "items": { "enum": [ "issue_id", @@ -21054,7 +21661,23 @@ "last_seen_version", "versions", "suspected_cause", - "resolved_at" + "resolved_at", + "sample_time", + "sample_version", + "sample_view", + "sample_session_id", + "sample_device", + "sample_os", + "sample_browser", + "sample_stack", + "sample_first_time", + "sample_first_version", + "sample_first_view", + "sample_first_session_id", + "sample_first_device", + "sample_first_os", + "sample_first_browser", + "sample_first_stack" ], "type": "string" }, @@ -21083,11 +21706,11 @@ "type": "integer" }, "sql": { - "description": "SQL-style query for advanced filtering. Cannot be used with `dql`.", + "description": "SQL-style WHERE condition for advanced filtering, without the `WHERE` keyword (for example `error_count > 100`). Field names must be fields of the `issue` scope; any text containing `SELECT` is rejected. Cannot be used with `dql`.", "type": "string" }, "start_time": { - "description": "Start of the time range, Unix epoch milliseconds.", + "description": "Start of the time range, Unix timestamp in milliseconds (a value that looks like seconds is rejected). Issues are matched by creation time unless `by_intersection` is `true`.", "format": "int64", "type": "integer" }, @@ -21128,7 +21751,7 @@ "type": "array" }, "time_zone": { - "description": "IANA time zone used to render timestamps in the CSV, e.g. `Asia/Shanghai` or `UTC`. Default: `Asia/Shanghai`.", + "description": "IANA time zone used to render the CSV time columns and the file name, e.g. `Asia/Shanghai` or `UTC`. Default: `Asia/Shanghai`. An unknown zone name returns `InvalidParameter`.", "type": "string" } }, @@ -21179,7 +21802,7 @@ "type": "string" }, "type": { - "description": "Error type, from the error event's `error_type` field as reported by the SDK.", + "description": "Error type reported by the SDK in the error event's `error_type` field — free-form, not a fixed set. Browser errors carry the JavaScript exception name, e.g. `Error`, `TypeError`, `ReferenceError`.", "type": "string" } }, @@ -21229,7 +21852,7 @@ "type": "object" }, "regression": { - "description": "Regression metadata. Present only when a previously resolved issue re-occurred.", + "description": "Regression record. Present only after a resolved issue was reopened because its error recurred; cleared when the issue is resolved again.", "properties": { "regressed_at": { "description": "Time the regression was detected, Unix timestamp in milliseconds.", @@ -21249,15 +21872,23 @@ "type": "object" }, "resolved_at": { - "description": "Time the issue was marked resolved, Unix timestamp in milliseconds; 0 while unresolved.", + "description": "Time the issue was marked resolved (by a user or automatically), Unix timestamp in milliseconds; `0` while unresolved.", "format": "int64", "type": "integer" }, "resolved_by": { - "description": "Person ID of the user who marked the issue resolved; 0 while unresolved.", + "description": "Person ID of the user who marked the issue resolved; `0` while unresolved or when the issue was resolved automatically.", "format": "int64", "type": "integer" }, + "resolve_mode": { + "description": "How the issue reacts when its error recurs after being resolved: `any` reopens it on any recurrence; `version` reopens it only when the error recurs in an application version the issue has not been seen in (errors without a version always reopen it). New issues and automatic resolution use `version`; resolving through `POST /rum/issue/update` without `resolve_mode` sets `any`.", + "enum": [ + "any", + "version" + ], + "type": "string" + }, "service": { "description": "Name of the service that produced this issue, taken from the error event's `service` field.", "type": "string" @@ -21268,7 +21899,7 @@ "type": "integer" }, "severity": { - "description": "Issue severity: `Critical`, `Warning`, or `Info`. Empty string on legacy issues created before severity existed.", + "description": "Issue severity, fixed when the issue is created: the first matching enabled preset severity rule (see `POST /rum/issue/preset-severity/rules/list`) decides it, otherwise a built-in rule (crashes are `Critical`; other errors are scored by environment and message keywords). An error only joins an existing issue of equal or higher severity, so the same error can produce separate issues per severity. Empty string on legacy issues created before severity existed.", "enum": [ "Critical", "Warning", @@ -21277,7 +21908,7 @@ "type": "string" }, "status": { - "description": "Triage status of the issue; soft-deleted (`deleted`) issues are never returned.\n\n| Value | Meaning |\n|---|---|\n| `for_review` | Pending triage |\n| `reviewed` | Reviewed |\n| `ignored` | Ignored |\n| `resolved` | Resolved |", + "description": "Triage status of the issue; soft-deleted (`deleted`) issues are never returned. The system resolves an issue automatically when its error has not been seen for 14 days, or when a newer application version reports no such error, and reopens a resolved issue as `for_review` when the error recurs (see `resolve_mode`).\n\n| Value | Meaning |\n|---|---|\n| `for_review` | Pending triage |\n| `reviewed` | Reviewed |\n| `ignored` | Ignored |\n| `resolved` | Resolved |", "enum": [ "for_review", "reviewed", @@ -21295,7 +21926,7 @@ "type": "integer" }, "reason": { - "description": "Explanation for the cause determination, generated only by AI analysis; empty string when AI is disabled or analysis has not run.", + "description": "Free-text explanation of the cause, written only by AI analysis; empty string when AI analysis is disabled, has not run yet, or the cause was set by a user.", "type": "string" }, "source": { @@ -21332,14 +21963,40 @@ "type": "integer" }, "versions": { - "description": "Deduplicated list of application versions in which this issue has occurred; may contain an empty string for events without version info.", + "description": "Deduplicated list of application versions in which this issue has occurred; may contain an empty string for events without version info. `null` on issues that never recorded a version list.", "items": { "type": "string" }, - "type": "array" + "type": [ + "array", + "null" + ] } }, - "type": "object" + "type": "object", + "required": [ + "team_id", + "issue_id", + "application_id", + "application_name", + "service", + "status", + "error_count", + "session_count", + "is_crash", + "age", + "resolved_at", + "resolved_by", + "resolve_mode", + "created_at", + "updated_at", + "first_seen", + "last_seen", + "error", + "suspected_cause", + "versions", + "severity" + ] }, "RumIssueListRequest": { "description": "Filters for listing issues.", @@ -21360,7 +22017,7 @@ "type": "boolean" }, "dql": { - "description": "DQL query for advanced filtering. Cannot be used with `sql`.", + "description": "DQL query for advanced filtering. Field names must be fields of the `issue` scope (see `POST /rum/field/list` with `scopes: [\"issue\"]`); a bare full-text term searches the error message. Cannot be used with `sql`.", "type": "string" }, "end_time": { @@ -21395,11 +22052,11 @@ "type": "integer" }, "sql": { - "description": "SQL-style query for advanced filtering. Cannot be used with `dql`.", + "description": "SQL-style WHERE condition for advanced filtering, without the `WHERE` keyword (for example `error_count > 100`). Field names must be fields of the `issue` scope; any text containing `SELECT` is rejected. Cannot be used with `dql`.", "type": "string" }, "start_time": { - "description": "Start of the time range, Unix epoch milliseconds.", + "description": "Start of the time range, Unix timestamp in milliseconds (a value that looks like seconds is rejected). Issues are matched by creation time unless `by_intersection` is `true`.", "format": "int64", "type": "integer" }, @@ -21474,7 +22131,7 @@ "type": "string" }, "status": { - "description": "New status. Setting `resolved` records the resolution time and operator; switching away from `resolved` clears them.\n\n| Value | Meaning |\n|---|---|\n| `for_review` | Pending triage |\n| `reviewed` | Reviewed |\n| `ignored` | Ignored |\n| `resolved` | Resolved |", + "description": "New status. Setting `resolved` on an unresolved issue records the resolution time and operator and clears `regression`; switching away from `resolved` clears the resolution time and operator. Omit to keep the current status.\n\n| Value | Meaning |\n|---|---|\n| `for_review` | Pending triage |\n| `reviewed` | Reviewed |\n| `ignored` | Ignored |\n| `resolved` | Resolved |", "enum": [ "for_review", "reviewed", @@ -21483,6 +22140,14 @@ ], "type": "string" }, + "resolve_mode": { + "description": "How the issue reacts when its error recurs after being resolved. Applied only together with `status: resolved`; defaults to `any` there when omitted, and is ignored with any other status.\n\n| Value | Meaning |\n|---|---|\n| `any` | Reopen the issue on any recurrence |\n| `version` | Reopen only when the error recurs in an application version the issue has not been seen in; errors without a version always reopen it |", + "enum": [ + "any", + "version" + ], + "type": "string" + }, "suspected_cause": { "description": "New suspected cause; setting it marks the cause source as `user`, overriding the automatic classification. One of:\n\n| Value | Meaning |\n|---|---|\n| `api.failed_request` | API request failure |\n| `network.error` | Network connectivity error |\n| `code.exception` | Code exception |\n| `code.invalid_object_access` | Invalid object access |\n| `code.invalid_argument` | Invalid argument |\n| `unknown` | Unknown cause |", "enum": [ @@ -21514,7 +22179,7 @@ "type": "string" }, "filters": { - "description": "OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches.", + "description": "OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches. An empty outer array never matches; an empty inner group matches every error.", "items": { "items": { "$ref": "#/components/schemas/RumPresetSeverityRuleFilterCondition" @@ -21573,7 +22238,7 @@ "description": "One filter condition within an AND group.", "properties": { "key": { - "description": "Filter attribute key. Only these Error-level attributes are supported for preset severity rules.\n\n| Value | Meaning |\n|---|---|\n| `error.usr_id` | User ID |\n| `error.usr_email` | User email |\n| `error.view_url` | Full URL of the page where the error occurred |\n| `error.view_url_path` | URL path of the page where the error occurred |\n| `error.error_type` | Error type |\n| `error.error_message` | Error message |\n| `error.env` | Environment (e.g. production/staging) |\n| `error.service` | Service name |\n| `error.device_type` | Device type |\n| `error.os_name` | Operating system name |\n| `error.browser_name` | Browser name |\n| `error.is_crash` | Whether the error is a crash (boolean) |", + "description": "Filter attribute key. Only these Error-level attributes are supported for preset severity rules.\n\n| Value | Meaning |\n|---|---|\n| `error.usr_id` | User ID |\n| `error.usr_email` | User email |\n| `error.view_url` | Full URL of the page where the error occurred |\n| `error.view_url_path` | URL path of the page where the error occurred |\n| `error.error_type` | Error type |\n| `error.error_message` | Error message |\n| `error.env` | Environment (e.g. production/staging) |\n| `error.service` | Service name |\n| `error.device_type` | Device type |\n| `error.os_name` | Operating system name |\n| `error.browser_name` | Browser name |\n| `error.is_crash` | Whether the error is a crash, compared as the string `true` or `false` |", "enum": [ "error.usr_id", "error.usr_email", @@ -21591,7 +22256,7 @@ "type": "string" }, "oper": { - "description": "Match semantics: `IN` matches when the field's value matches any of `vals`; `NOTIN` matches when it matches none of them (and matches when the field is absent).", + "description": "Match semantics: `IN` matches when the attribute value matches any of `vals`; `NOTIN` matches when it matches none of them. An attribute the error does not carry is compared as an empty string.", "enum": [ "IN", "NOTIN" @@ -21599,7 +22264,7 @@ "type": "string" }, "vals": { - "description": "Values to match against. Each entry supports exact string match, wildcard (`*`/`?`), regex (wrap in `/.../`), CIDR (`cidr:10.0.0.0/8`) for IP-shaped values, or numeric comparison (`num:gt:100`, `num:le:50`, etc.).", + "description": "Values to match against; at least one, none empty. Each entry is one of: an exact, case-sensitive whole-value match; a wildcard pattern with `*`/`?` (whole value); a regular expression wrapped in `/.../` (matches anywhere in the value unless anchored with `^`/`$`); `cidr:` for IP-shaped values, e.g. `cidr:10.0.0.0/8`; or a numeric comparison `num::` with `op` one of `lt`, `le`, `gt`, `ge`, e.g. `num:gt:100`. For `error.is_crash`, use `true` or `false`.", "items": { "type": "string" }, @@ -21769,7 +22434,7 @@ "type": "string" }, "filters": { - "description": "OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches.", + "description": "OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches. An empty outer array never matches; an empty inner group matches every error.", "items": { "items": { "$ref": "#/components/schemas/RumPresetSeverityRuleFilterCondition" @@ -21873,7 +22538,7 @@ "type": "string" }, "filters": { - "description": "OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches.", + "description": "OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches. An empty outer array never matches; an empty inner group matches every error.", "items": { "items": { "$ref": "#/components/schemas/RumPresetSeverityRuleFilterCondition" @@ -21997,7 +22662,7 @@ ] }, "filters": { - "description": "OR-of-ANDs filter structure: the outer array is OR'd, each inner array is AND'd. A rule matches an error when at least one inner AND-group fully matches.", + "description": "New OR-of-ANDs filter structure; replaces the whole current structure. Omit or pass `null` to leave unchanged. The outer array is OR'd, each inner array is AND'd; an empty outer array never matches, an empty inner group matches every error.", "items": { "items": { "$ref": "#/components/schemas/RumPresetSeverityRuleFilterCondition" @@ -22057,15 +22722,15 @@ "type": "object" }, "RumReplayForegroundPeriod": { - "description": "A time span during which the app was in the foreground (mobile sessions).", + "description": "A span during which a view was in the foreground (focused).", "properties": { "end": { - "description": "Unix timestamp in milliseconds when the foreground period ended.", + "description": "End of the foreground period, in **nanoseconds** since the start of the view identified by `view_id` (not a Unix timestamp).", "format": "int64", "type": "integer" }, "start": { - "description": "Unix timestamp in milliseconds when the foreground period started.", + "description": "Start of the foreground period, in **nanoseconds** since the start of the view identified by `view_id` (not a Unix timestamp).", "format": "int64", "type": "integer" }, @@ -22079,7 +22744,7 @@ "RumReplaySession": { "properties": { "end": { - "description": "Unix timestamp in milliseconds when the session ended (or was last updated, if still active).", + "description": "Unix timestamp in milliseconds of the session end: the later of the session's recorded end and the end of its last returned view.", "format": "int64", "type": "integer" }, @@ -22088,7 +22753,7 @@ "type": "boolean" }, "server_time_delta": { - "description": "Clock skew in milliseconds between the client and Flashduty's servers, added to client timestamps for correction.", + "description": "Always `0`: timestamps are returned as recorded by the client, without clock-skew correction.", "format": "int64", "type": "integer" }, @@ -22120,7 +22785,20 @@ "RumReplayView": { "properties": { "container_source": { - "description": "SDK platform of the container app, when this view is embedded (e.g. a WebView inside a native app). Omitted when the view is not embedded.", + "description": "SDK platform of the app that embeds this view (for example a WebView inside a native app). Omitted when the view is not embedded.\n\n| Value | Meaning |\n|---|---|\n| `browser` | Web browser application |\n| `ios` | Apple iOS application |\n| `android` | Android application |\n| `react-native` | React Native application |\n| `flutter` | Flutter application |\n| `kotlin-multiplatform` | Kotlin Multiplatform application |\n| `roku` | Roku channel application |\n| `unity` | Unity application |\n| `miniprogram` | WeChat mini program |\n| `harmony` | HarmonyOS application |\n| `electron` | Electron desktop application |", + "enum": [ + "browser", + "ios", + "android", + "react-native", + "flutter", + "kotlin-multiplatform", + "roku", + "unity", + "miniprogram", + "harmony", + "electron" + ], "type": "string" }, "container_view_id": { @@ -22137,7 +22815,7 @@ "type": "boolean" }, "loading_type": { - "description": "How the view was entered, e.g. `initial_load`, `route_change`.", + "description": "How the view was entered, as reported by the SDK. Web: `initial_load`, `route_change`. Mobile: `activity_display`, `activity_redisplay`, `fragment_display`, `fragment_redisplay`, `view_controller_display`, `view_controller_redisplay`. Empty when not reported.", "type": "string" }, "name": { @@ -22145,7 +22823,7 @@ "type": "string" }, "server_time_delta": { - "description": "Clock skew in milliseconds between the client and Flashduty's servers, added to client timestamps for correction.", + "description": "Always `0`: timestamps are returned as recorded by the client, without clock-skew correction.", "format": "int64", "type": "integer" }, @@ -22261,7 +22939,7 @@ "type": "integer" }, "session_investigate.free_cnt": { - "description": "Free quota for investigate sessions per application, per billing window.", + "description": "Free quota of investigate (error tracking) sessions per application, per billing window. A negative value means unlimited.", "format": "int64", "type": "integer" }, @@ -22271,11 +22949,11 @@ "type": "integer" }, "session_limit_reached": { - "description": "`true` when a `version=free` account has exceeded its combined free session quota across all applications. Always `false` for non-free plans.", + "description": "`true` when a `version=free` account's investigate or replay sessions in the current window have reached the per-application free quota multiplied by the number of applications. Always `false` for non-free plans and for accounts without applications.", "type": "boolean" }, "session_measure.free_cnt": { - "description": "Free quota for measure sessions per application, per billing window.", + "description": "Free quota of measure (performance) sessions per application, per billing window. A negative value means unlimited.", "format": "int64", "type": "integer" }, @@ -22285,7 +22963,7 @@ "type": "integer" }, "session_replay.free_cnt": { - "description": "Free quota for session-replay sessions per application, per billing window.", + "description": "Free quota of session-replay sessions per application, per billing window. A negative value means unlimited.", "format": "int64", "type": "integer" }, @@ -22372,7 +23050,7 @@ "description": "Device that recorded the session." }, "foreground_periods": { - "description": "Foreground periods across the session (mobile sessions only; empty for web).", + "description": "Periods during which a view was in the foreground (focused), collected from every returned view. Empty when the SDK reported none.", "items": { "$ref": "#/components/schemas/RumReplayForegroundPeriod" }, @@ -22383,7 +23061,7 @@ "description": "Session bounds and state." }, "views": { - "description": "Every view recorded during the session, in chronological order.", + "description": "Views of the session that carry replay data, ordered by start time.", "items": { "$ref": "#/components/schemas/RumReplayView" }, @@ -22400,7 +23078,7 @@ "type": "string" }, "ts": { - "description": "Unix timestamp in milliseconds of the session start time. Optional; disambiguates when a session ID has been reused across different time windows.", + "description": "Session start time, Unix milliseconds. Optional. When set, it must match the session's start exactly; use it to pick one session when a `session_id` was reused.", "exclusiveMinimum": 0, "format": "int64", "type": "integer" @@ -22430,7 +23108,7 @@ "type": "string" }, "ts": { - "description": "Unix timestamp in milliseconds. When set (and `search_after_ctx` is empty), seeks to the most recent full-snapshot segment at or before this time instead of starting from the beginning.", + "description": "Unix timestamp in milliseconds. When set and `search_after_ctx` is empty, paging starts at the last full-snapshot segment at or before this time (searching up to 4 hours back); if none is found, paging starts from the beginning.", "exclusiveMinimum": 0, "format": "int64", "type": "integer" @@ -22453,14 +23131,14 @@ "description": "Presigned segment URLs, returned only when `url_mode` is `true`.", "properties": { "items": { - "description": "Presigned, time-limited URLs (valid 1 hour) for downloading each segment's raw compressed bytes.", + "description": "Presigned URLs (valid 1 hour) for downloading each segment object. The object body is zlib-compressed; decompress it to get the segment JSON.", "items": { "type": "string" }, "type": "array" }, "search_after_ctx": { - "description": "Pagination cursor to pass as `search_after_ctx` on the next call. Empty when this page was the last one.", + "description": "Cursor to pass as `search_after_ctx` on the next call. Set whenever this page returned `limit` segments (the next page may then be empty); empty string when fewer were returned.", "type": "string" } }, @@ -22470,11 +23148,11 @@ "description": "Parameters for sending a sample RUM alert webhook.", "properties": { "application_id": { - "description": "RUM application ID. Get application IDs via `POST /rum/application/list`.", + "description": "RUM application whose name is put in the sample event's `labels.application_name`. The caller must be able to edit it. Get application IDs via `POST /rum/application/list`.", "type": "string" }, "webhook_url": { - "description": "Webhook URL to receive the sample alert event.", + "description": "Webhook URL to receive the sample alert event; must use `http` or `https`. Not saved: use `POST /rum/application/update` with `alerting.webhook_url` to store it.", "format": "uri", "type": "string" } @@ -22489,15 +23167,15 @@ "description": "Result of the webhook test delivery.", "properties": { "message": { - "description": "`ok` on success, otherwise the delivery error message.", + "description": "`ok` on success. Otherwise `unexpected status ` when the endpoint answered with an error status, or `request failed: ` when no response was received.", "type": "string" }, "ok": { - "description": "Whether the webhook endpoint accepted the sample event.", + "description": "`true` when the endpoint answered with a status below 400 (after following redirects); `false` otherwise.", "type": "boolean" }, "status_code": { - "description": "HTTP status code returned by the webhook endpoint. 0 when the request did not receive a response.", + "description": "HTTP status code of the last delivery attempt. `0` when no response was received (connection error or timeout).", "type": "integer" } }, @@ -22663,108 +23341,135 @@ "type": "object" }, "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": { - "$ref": "#/components/schemas/MemberOncallInterval" + "oneOf": [ + { + "$ref": "#/components/schemas/MemberOncallInterval" + }, + { + "type": "null" + } + ], + "description": "Shift in progress now; `null` when the member is not on call." }, "next": { - "$ref": "#/components/schemas/MemberOncallInterval" + "oneOf": [ + { + "$ref": "#/components/schemas/MemberOncallInterval" + }, + { + "type": "null" + } + ], + "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" - }, - "type": "array" + } } }, "required": [ "schedules" - ], - "type": "object" + ] }, "ScheduleCalculatedLayer": { + "type": "object", "description": "Computed schedule for a single layer.", + "required": [ + "layer_name", + "name", + "mode", + "schedules" + ], "properties": { "layer_name": { - "description": "Layer display name.", - "type": "string" - }, - "mode": { - "description": "Layer mode: 0 = common rotation, 1 = override.", - "type": "integer" + "type": "string", + "description": "Layer name; empty string in `final_schedule`." }, "name": { - "description": "Layer internal name.", - "type": "string" + "type": "string", + "description": "Same as `layer_name`." + }, + "mode": { + "type": "integer", + "enum": [ + 0, + 1 + ], + "description": "Type of the source layer: `0` = rotation layer, `1` = override layer. Always `0` in `final_schedule`." }, "schedules": { - "description": "Computed shifts; null when the layer produces none.", - "items": { - "$ref": "#/components/schemas/ScheduleCalculatedSchedule" - }, "type": [ "array", "null" - ] + ], + "items": { + "$ref": "#/components/schemas/ScheduleCalculatedSchedule" + }, + "description": "Computed shifts; null when the layer produces none." } - }, - "required": [ - "layer_name", - "name", - "mode", - "schedules" - ], - "type": "object" + } }, "ScheduleCalculatedSchedule": { + "type": "object", "description": "Computed shift inside a schedule layer.", + "required": [ + "start", + "end", + "group", + "index" + ], "properties": { + "start": { + "type": "integer", + "format": "int64", + "description": "Shift start timestamp (Unix seconds)." + }, "end": { - "description": "Shift end timestamp (Unix seconds).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Shift end timestamp (Unix seconds)." }, "group": { - "$ref": "#/components/schemas/ScheduleGroup", - "description": "Oncall group covering the shift; null marks a coverage gap." + "oneOf": [ + { + "$ref": "#/components/schemas/ScheduleGroup" + }, + { + "type": "null" + } + ], + "description": "Group on call during the shift; `null` marks a gap with nobody on call." }, "index": { - "description": "Index inside the rotation.", - "type": "integer" - }, - "start": { - "description": "Shift start timestamp (Unix seconds).", - "format": "int64", - "type": "integer" + "type": "integer", + "description": "Zero-based position, in the schedule's layer list, of the layer the shift comes from." } - }, - "required": [ - "start", - "end", - "group", - "index" - ], - "type": "object" + } }, "ScheduleDayMask": { + "type": "object", "description": "Day-of-week mask for a rotation layer.", "properties": { "repeat": { - "description": "Weekday numbers (0 = Sunday) included in the rotation. Conflicts with restrict_mode = 2 (week).", - "items": { - "maximum": 6, - "minimum": 0, - "type": "integer" - }, "type": [ "array", "null" - ] + ], + "items": { + "type": "integer", + "minimum": 0, + "maximum": 6 + }, + "description": "Weekdays on which the layer is on call: `0` = Sunday … `6` = Saturday, in the schedule's time zone. Empty or all seven days means every day. Cannot be combined with `restrict_mode` 2." } - }, - "type": "object" + } }, "ScheduleEmptyObject": { "description": "Empty response.", @@ -22803,45 +23508,45 @@ "type": "object" }, "ScheduleGroup": { + "type": "object", "description": "Oncall group definition within a rotation layer.", + "required": [ + "group_name", + "name", + "members", + "start", + "end" + ], "properties": { - "end": { - "description": "Group end timestamp (Unix seconds).", - "format": "int64", - "type": "integer" - }, "group_name": { - "description": "Group display name. Null when only the legacy name is set.", "type": [ "string", "null" - ] + ], + "description": "Group display name. Null when only the legacy name is set." + }, + "name": { + "type": "string", + "description": "Legacy group name." }, "members": { - "description": "Members of this group.", + "type": "array", "items": { "$ref": "#/components/schemas/ScheduleMember" }, - "type": "array" - }, - "name": { - "description": "Legacy group name.", - "type": "string" + "description": "Members of this group." }, "start": { - "description": "Group start timestamp (Unix seconds).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Start of the group's shift (Unix seconds) in computed results; `0` in layer definitions and ignored on input." + }, + "end": { + "type": "integer", + "format": "int64", + "description": "End of the group's shift (Unix seconds) in computed results; `0` in layer definitions and ignored on input." } - }, - "required": [ - "group_name", - "name", - "members", - "start", - "end" - ], - "type": "object" + } }, "ScheduleIDResponse": { "description": "Schedule ID response returned after create.", @@ -22858,21 +23563,21 @@ "type": "object" }, "ScheduleIDsBodyRequest": { - "description": "Request carrying a list of schedule IDs (used by delete/enable/disable).", + "type": "object", + "description": "Request carrying a list of schedule IDs.", + "required": [ + "schedule_ids" + ], "properties": { "schedule_ids": { - "description": "Schedule IDs to operate on; obtain them from `POST /schedule/list`.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Schedule IDs to operate on; obtain them from `POST /schedule/list`." } - }, - "required": [ - "schedule_ids" - ], - "type": "object" + } }, "ScheduleIDsRequest": { "description": "Request carrying a list of schedule IDs (used by batch info).", @@ -22892,686 +23597,832 @@ "type": "object" }, "ScheduleImNotify": { + "type": "object", "description": "IM webhook notification entry.", + "required": [ + "type", + "settings" + ], "properties": { + "type": { + "type": "string", + "enum": [ + "feishu", + "dingtalk", + "wecom", + "slack", + "telegram", + "zoom", + "feishu_app", + "dingtalk_app", + "slack_app", + "teams_app" + ], + "description": "Where the notification goes:\n- `feishu`, `dingtalk`, `wecom`, `slack`: group robot webhook given by `settings.token`.\n- `telegram`: bot `settings.token` posting to `settings.chat_ids`.\n- `zoom`: Zoom robot with `settings.token` and `settings.verify_token`.\n- `feishu_app`, `dingtalk_app`, `slack_app`, `teams_app`: an IM integration (`settings.data_source_id`) posting to the group chats in `settings.chat_ids`.\nOther values are stored but never sent." + }, "settings": { "$ref": "#/components/schemas/ScheduleImNotifySettings", "description": "Webhook channel settings." - }, - "type": { - "description": "IM provider type (for example feishu_app, dingtalk_app, wecom_app, teams_app, slack_app).", - "type": "string" } - }, - "required": [ - "type", - "settings" - ], - "type": "object" + } }, "ScheduleImNotifySettings": { + "type": "object", "description": "Settings for an IM webhook notification channel.", + "required": [ + "token", + "alias", + "data_source_id", + "chat_ids", + "verify_token", + "sign_secret" + ], "properties": { + "token": { + "type": "string", + "description": "Robot webhook token for `feishu`, `dingtalk`, `wecom`, `slack`, `telegram` and `zoom`; empty for the `*_app` types." + }, "alias": { - "description": "Channel alias.", - "type": "string" + "type": "string", + "description": "Display alias for the entry; not used when sending." + }, + "data_source_id": { + "type": "integer", + "format": "int64", + "description": "ID of the IM integration used by the `*_app` types; `0` for robot types." }, "chat_ids": { - "description": "Chat IDs.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Target chat IDs: group chats of the IM integration for `*_app` types, or Telegram chat IDs for `telegram`." }, - "data_source_id": { - "description": "Data source ID.", - "format": "int64", - "type": "integer" + "verify_token": { + "type": "string", + "description": "Verification token, used by the `zoom` type." }, "sign_secret": { - "description": "Signature secret.", - "type": "string" - }, - "token": { - "description": "Webhook token.", - "type": "string" - }, - "verify_token": { - "description": "Verification token.", - "type": "string" + "type": "string", + "description": "Robot signing secret. Stored with the entry." } - }, - "required": [ - "token", - "alias", - "data_source_id", - "chat_ids", - "verify_token", - "sign_secret" - ], - "type": "object" + } }, "ScheduleInfoRequest": { - "description": "Schedule detail request. start/end define the window for computed layers; the span must be less than 45 days.", + "type": "object", + "description": "Schedule detail request. `start`/`end` set the window for computed shifts; at most 45 days apart.", + "required": [ + "schedule_id", + "start", + "end" + ], "properties": { - "end": { - "description": "Preview end timestamp (Unix seconds, 10 digits).", - "format": "int64", - "type": "integer" - }, "schedule_id": { - "description": "Schedule ID; obtain it from `POST /schedule/list`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Schedule ID; obtain it from `POST /schedule/list`." }, "start": { - "description": "Preview start timestamp (Unix seconds, 10 digits).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Preview start timestamp (Unix seconds, 10 digits)." + }, + "end": { + "type": "integer", + "format": "int64", + "description": "Preview end timestamp (Unix seconds, 10 digits)." } - }, + } + }, + "ScheduleItem": { + "type": "object", + "description": "On-call schedule as returned by info, list, infos, self and preview. Which computed fields are filled depends on the endpoint — see each operation's notes.", "required": [ + "id", + "name", + "account_id", + "group_id", + "time_zone", + "disabled", + "create_at", + "create_by", + "update_at", + "update_by", + "layers", + "schedule_layers", + "final_schedule", + "notify", "schedule_id", - "start", - "end" + "schedule_name", + "team_id", + "description", + "layer_schedules", + "status", + "cur_oncall", + "next_oncall" ], - "type": "object" - }, - "ScheduleItem": { - "description": "Full schedule detail returned by info/preview/list.", "properties": { - "account_id": { - "description": "Account ID.", + "id": { + "type": [ + "integer", + "null" + ], "format": "int64", - "type": "integer" + "description": "Schedule ID. null when returned from /schedule/preview." }, - "create_at": { - "description": "Creation timestamp (Unix seconds).", - "format": "int64", - "type": "integer" + "name": { + "type": [ + "string", + "null" + ], + "description": "Schedule name (legacy field; mirrors schedule_name). null when returned from /schedule/preview." }, - "create_by": { - "description": "Creator person ID.", + "account_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the account that owns the schedule." }, - "cur_oncall": { - "$ref": "#/components/schemas/ScheduleOncallGroup", - "description": "Current on-call group, or null when nobody is on-call." - }, - "description": { - "description": "Schedule description. null when returned from /schedule/preview.", + "group_id": { "type": [ - "string", + "integer", "null" - ] + ], + "format": "int64", + "description": "Legacy team/group ID. null when returned from /schedule/preview." + }, + "time_zone": { + "type": "string", + "description": "IANA time zone (for example `Asia/Shanghai`) in which the schedule's handoffs, restriction windows, weekdays and fixed-time notifications are evaluated. Set at creation and immutable. An empty string means none was set and the schedule is evaluated in `Asia/Shanghai`." }, "disabled": { - "description": "Disabled flag (0 = enabled, 1 = disabled). Deprecated. null when returned from /schedule/preview.", "type": [ "integer", "null" - ] + ], + "enum": [ + 0, + 1, + null + ], + "description": "Whether the schedule is disabled: `0` = enabled, `1` = disabled (disabled schedules send no shift notifications and are skipped by `/schedule/self` and `/schedule/by-person`). Same value as `status`. `null` in `/schedule/preview` unless sent." }, - "end": { - "description": "Window end (Unix seconds). Omitted when 0 (no window requested).", + "create_at": { + "type": "integer", "format": "int64", - "type": "integer" - }, - "field": { - "description": "Field name used by the legacy update-field endpoint.", - "type": "string" + "description": "Creation timestamp (Unix seconds)." }, - "final_schedule": { - "$ref": "#/components/schemas/ScheduleCalculatedLayer", - "description": "Collapsed final schedule across all layers." + "create_by": { + "type": "integer", + "format": "int64", + "description": "Creator person ID." }, - "group_id": { - "description": "Legacy team/group ID. null when returned from /schedule/preview.", + "update_at": { + "type": "integer", "format": "int64", - "type": [ - "integer", - "null" - ] + "description": "Last update timestamp (Unix seconds)." }, - "id": { - "description": "Schedule ID. null when returned from /schedule/preview.", + "update_by": { + "type": "integer", "format": "int64", - "type": [ - "integer", - "null" - ] + "description": "Last updater person ID." }, - "layer_schedules": { - "description": "Alias of schedule_layers returned for compatibility. Null when not computed.", - "items": { - "$ref": "#/components/schemas/ScheduleCalculatedLayer" - }, + "layers": { "type": [ "array", "null" - ] - }, - "layers": { - "description": "Rotation layers defined on the schedule. Null when layers were not loaded (for example by `/schedule/infos`, or by `/schedule/list` without start/end).", + ], "items": { "$ref": "#/components/schemas/ScheduleLayer" }, + "description": "Rotation layers defined on the schedule. Null when layers were not loaded (for example by `/schedule/infos`, or by `/schedule/list` without start/end)." + }, + "schedule_layers": { "type": [ "array", "null" - ] + ], + "items": { + "$ref": "#/components/schemas/ScheduleCalculatedLayer" + }, + "description": "Shifts of each visible (non-hidden) layer in the requested window. `null` when no window was computed (`/schedule/infos`, `/schedule/self`, `/schedule/list` without `start`/`end`)." }, - "name": { - "description": "Schedule name (legacy field; mirrors schedule_name). null when returned from /schedule/preview.", - "type": [ - "string", - "null" - ] + "final_schedule": { + "$ref": "#/components/schemas/ScheduleCalculatedLayer", + "description": "All layers merged into one timeline for the window: where layers overlap, override layers win over rotation layers and later layers win over earlier ones. In `/schedule/self` it keeps only the caller's shifts. Empty (`schedules` is `null`) when nothing was computed." }, - "next_oncall": { - "$ref": "#/components/schemas/ScheduleOncallGroup", - "description": "Next on-call group, or null when unknown." + "start": { + "type": "integer", + "format": "int64", + "description": "Window start (Unix seconds). Only echoed by `/schedule/preview`; omitted elsewhere." + }, + "end": { + "type": "integer", + "format": "int64", + "description": "Window end (Unix seconds). Only echoed by `/schedule/preview`; omitted elsewhere." }, "notify": { - "$ref": "#/components/schemas/ScheduleNotify", - "description": "Notification configuration. Null when the schedule has none." + "oneOf": [ + { + "$ref": "#/components/schemas/ScheduleNotify" + }, + { + "type": "null" + } + ], + "description": "Shift notification configuration; `null` when the schedule has none." }, "schedule_id": { - "description": "Schedule ID. Null when returned from `/schedule/preview`.", - "format": "int64", "type": [ "integer", "null" - ] - }, - "schedule_layers": { - "description": "Computed per-layer schedules for the requested window. Null when not computed.", - "items": { - "$ref": "#/components/schemas/ScheduleCalculatedLayer" - }, - "type": [ - "array", - "null" - ] + ], + "format": "int64", + "description": "Schedule ID. Null when returned from `/schedule/preview`." }, "schedule_name": { - "description": "Schedule display name. null when returned from /schedule/preview.", "type": [ "string", "null" - ] + ], + "description": "Schedule display name. null when returned from /schedule/preview." }, - "start": { - "description": "Window start (Unix seconds). Omitted when 0 (no window requested).", + "team_id": { + "type": [ + "integer", + "null" + ], "format": "int64", - "type": "integer" + "description": "Owning team ID. null when returned from /schedule/preview." }, - "status": { - "description": "Legacy status flag. Deprecated. null when returned from /schedule/preview.", + "description": { "type": [ - "integer", + "string", "null" - ] + ], + "description": "Schedule description. null when returned from /schedule/preview." }, - "team_id": { - "description": "Owning team ID. null when returned from /schedule/preview.", - "format": "int64", + "layer_schedules": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/ScheduleCalculatedLayer" + }, + "description": "Same content as `schedule_layers`, filled by `/schedule/info` and `/schedule/preview` only; `null` elsewhere." + }, + "status": { "type": [ "integer", "null" - ] + ], + "enum": [ + 0, + 1, + null + ], + "description": "Mirror of `disabled`: `0` = enabled, `1` = disabled. Send it on `/schedule/update` to enable or disable a schedule. `null` in `/schedule/preview` unless sent." }, - "update_at": { - "description": "Last update timestamp (Unix seconds).", - "format": "int64", - "type": "integer" + "cur_oncall": { + "oneOf": [ + { + "$ref": "#/components/schemas/ScheduleOncallGroup" + }, + { + "type": "null" + } + ], + "description": "The shift in progress now; `null` when nobody is on call, or when the endpoint does not compute it (`/schedule/infos`, `/schedule/self`, `/schedule/list` without a window)." }, - "update_by": { - "description": "Last updater person ID.", - "format": "int64", - "type": "integer" + "next_oncall": { + "oneOf": [ + { + "$ref": "#/components/schemas/ScheduleOncallGroup" + }, + { + "type": "null" + } + ], + "description": "The next shift with someone on duty after the current one; `null` when none is found within 45 days or the endpoint does not compute it." } - }, + } + }, + "ScheduleLayer": { + "type": "object", + "description": "One layer of a schedule. A rotation layer (`mode` 0) cycles through `groups`; an override layer (`mode` 1) puts its first group on call from `layer_start` to `layer_end`. Response-only fields (`account_id`, `schedule_id`, `create_*`, `update_*`) are ignored in requests.", "required": [ - "id", - "name", "account_id", - "group_id", - "disabled", - "create_at", - "create_by", - "update_at", - "update_by", - "layers", - "schedule_layers", - "final_schedule", - "notify", + "name", "schedule_id", - "schedule_name", - "team_id", - "description", - "layer_schedules", - "status", - "cur_oncall", - "next_oncall" + "hidden", + "mode", + "weight", + "groups", + "rotation_duration", + "handoff_time", + "enable_time", + "expire_time", + "restrict_mode", + "restrict_start", + "restrict_end", + "restrict_periods", + "day_mask", + "create_at", + "create_by", + "update_at", + "update_by", + "fair_rotation", + "rotation_unit", + "rotation_value", + "mask_continuous_enabled" ], - "type": "object" - }, - "ScheduleLayer": { - "description": "One rotation layer inside a schedule.", "properties": { "account_id": { - "description": "Account ID.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the account that owns the layer. Set by the server." }, - "create_at": { - "description": "Creation timestamp (Unix seconds).", + "name": { + "type": "string", + "description": "Layer name. Either `name` or `layer_name` is required; `layer_name` wins when both are set." + }, + "schedule_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the schedule the layer belongs to. Set by the server." }, - "create_by": { - "description": "Creator person ID.", + "hidden": { + "type": "integer", + "enum": [ + 0, + 1 + ], + "description": "`1` leaves the layer out of `schedule_layers`; its shifts still feed `final_schedule`. `0` (default) shows it." + }, + "mode": { + "type": "integer", + "description": "Layer type:\n- `0`: rotation layer — groups take turns according to `rotation_unit`/`rotation_value`.\n- `1`: override layer — the first group in `groups` is on call for the whole `layer_start`–`layer_end` period and takes precedence over rotation layers.", + "enum": [ + 0, + 1 + ] + }, + "weight": { + "type": "integer", + "description": "Stored as sent; not used when computing shifts." + }, + "groups": { + "type": [ + "array", + "null" + ], + "items": { + "$ref": "#/components/schemas/ScheduleGroup" + }, + "description": "On-call groups of the layer, in rotation order. Each group needs `group_name` (or `name`) and members with at least one person. `start`/`end` are ignored on input." + }, + "rotation_duration": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Rotation length in seconds. Legacy alternative to `rotation_unit` + `rotation_value`: when only this is set, the server derives them (whole weeks, days or hours), and when only those are set, it fills this in (a month counts as 30 days)." }, - "day_mask": { - "$ref": "#/components/schemas/ScheduleDayMask", - "description": "Day-of-week mask." + "handoff_time": { + "type": "integer", + "format": "int64", + "description": "Weekly handoff point for weekly rotations, as seconds from Monday 00:00 in the schedule's time zone (`weekday × 86400 + seconds of day`, Monday = 0 … Sunday = 6). Not a Unix timestamp. Easier to set with `handoff`." }, "enable_time": { - "description": "When the layer becomes effective (Unix seconds).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "When the layer takes effect (Unix seconds). For rotations its time of day is also the daily handoff time. `layer_start` overrides it when sent." }, "expire_time": { - "description": "When the layer expires (Unix seconds, 0 means never).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "When the layer stops (Unix seconds); `0` = never. Must not be earlier than `enable_time`. `layer_end` overrides it when sent." }, - "fair_rotation": { - "description": "Whether fair rotation is enabled.", - "type": "boolean" + "restrict_mode": { + "type": "integer", + "description": "Restricts the layer to time windows given in `restrict_periods`:\n- `0`: no restriction.\n- `1`: daily windows; offsets are seconds from 00:00 (0–86400).\n- `2`: weekly windows; offsets are seconds from Monday 00:00 (0–604800). Cannot be combined with `day_mask`.\nWindows use the schedule's time zone.", + "enum": [ + 0, + 1, + 2 + ] }, - "groups": { - "description": "Oncall groups participating in the rotation. Null when not set.", - "items": { - "$ref": "#/components/schemas/ScheduleGroup" - }, + "restrict_start": { + "type": "integer", + "format": "int64", + "description": "Legacy single-window start offset in seconds; prefer `restrict_periods`." + }, + "restrict_end": { + "type": "integer", + "format": "int64", + "description": "Legacy single-window end offset in seconds; prefer `restrict_periods`." + }, + "restrict_periods": { "type": [ "array", "null" - ] + ], + "items": { + "$ref": "#/components/schemas/ScheduleRestrictPeriod" + }, + "description": "Time windows in which the layer is on call, interpreted by `restrict_mode`. Outside them the layer has nobody on call. `null` when not set." }, - "handoff_time": { - "description": "Rotation handoff time as a weekly offset in seconds (weekday x 86400 + seconds since midnight), not an absolute Unix timestamp.", + "day_mask": { + "$ref": "#/components/schemas/ScheduleDayMask", + "description": "Weekdays on which the rotation layer is on call." + }, + "create_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Creation timestamp (Unix seconds)." }, - "hidden": { - "description": "Whether the layer is hidden in the UI (0 = no, 1 = yes).", - "type": "integer" + "create_by": { + "type": "integer", + "format": "int64", + "description": "Creator person ID." }, - "layer_end": { - "description": "Layer end timestamp (Unix seconds). null means open-ended.", + "update_at": { + "type": "integer", "format": "int64", - "type": [ - "integer", - "null" - ] + "description": "Last update timestamp (Unix seconds)." + }, + "update_by": { + "type": "integer", + "format": "int64", + "description": "Last updater person ID." }, "layer_name": { - "description": "User-facing layer name. Null when not set.", "type": [ "string", "null" - ] + ], + "description": "Layer name shown in the console; same value as `name` in responses." + }, + "fair_rotation": { + "type": "boolean", + "description": "When `true`, the group that starts each full round shifts by one, so that no group is always first. `false` (default) always restarts from the first group." }, "layer_start": { - "description": "Layer effective start (Unix seconds). Null when not set.", - "format": "int64", "type": [ "integer", "null" - ] - }, - "mask_continuous_enabled": { - "description": "Whether continuous masking is enabled.", - "type": "boolean" - }, - "mode": { - "description": "Layer mode: 0 = common rotation, 1 = override.", - "enum": [ - 0, - 1 ], - "type": "integer" - }, - "name": { - "description": "Layer internal name.", - "type": "string" - }, - "restrict_end": { - "description": "Legacy end offset inside the restriction window (seconds).", "format": "int64", - "type": "integer" - }, - "restrict_mode": { - "description": "Restriction mode: 0 = none, 1 = day, 2 = week.", - "enum": [ - 0, - 1, - 2 - ], - "type": "integer" + "description": "Same as `enable_time`; takes precedence over it in requests. `null` when `enable_time` is 0." }, - "restrict_periods": { - "description": "Restriction windows inside each rotation cycle. Null when not set.", - "items": { - "$ref": "#/components/schemas/ScheduleRestrictPeriod" - }, + "layer_end": { "type": [ - "array", + "integer", "null" - ] - }, - "restrict_start": { - "description": "Legacy start offset inside the restriction window (seconds).", - "format": "int64", - "type": "integer" - }, - "rotation_duration": { - "description": "Rotation duration in seconds.", + ], "format": "int64", - "type": "integer" + "description": "Same as `expire_time`; takes precedence over it in requests. `null` means the layer never ends." }, "rotation_unit": { + "type": "string", "description": "Rotation unit. On-call assignees rotate in turn by this unit.\n| Value | Meaning |\n|---|---|\n| `hour` | Rotates hourly. |\n| `day` | Rotates daily. |\n| `week` | Rotates weekly. |\n| `month` | Rotates monthly. |", "enum": [ "hour", "day", "week", "month" - ], - "type": "string" + ] }, "rotation_value": { - "description": "Rotation quantity (number of rotation_unit per cycle).", + "type": "integer", "format": "int64", - "minimum": 0, - "type": "integer" + "description": "Number of `rotation_unit`s each group stays on call before handing off. A rotation layer needs either this (with `rotation_unit`) or `rotation_duration`.", + "minimum": 0 }, - "schedule_id": { - "description": "Parent schedule ID.", - "format": "int64", - "type": "integer" + "mask_continuous_enabled": { + "type": "boolean", + "description": "Only applies when `day_mask` selects 1–6 weekdays. When `true`, each on-call day runs from the layer's start time of day to the same time the next day instead of midnight to midnight." }, - "update_at": { - "description": "Last update timestamp (Unix seconds).", - "format": "int64", - "type": "integer" + "starts_at": { + "type": "object", + "writeOnly": true, + "description": "Request only. Layer start as a wall-clock date and time in the schedule's time zone; overrides `layer_start`/`enable_time`.", + "required": [ + "date" + ], + "properties": { + "date": { + "type": "string", + "description": "Calendar date, `YYYY-MM-DD`." + }, + "time": { + "type": "string", + "description": "Time of day, `HH:MM` (24-hour); defaults to `00:00`." + } + } }, - "update_by": { - "description": "Last updater person ID.", - "format": "int64", - "type": "integer" + "ends_at": { + "type": "object", + "writeOnly": true, + "description": "Request only. Layer end as a wall-clock date and time in the schedule's time zone; overrides `layer_end`/`expire_time`. Send `{\"date\": \"\"}` to make the layer never end.", + "properties": { + "date": { + "type": "string", + "description": "Calendar date, `YYYY-MM-DD`." + }, + "time": { + "type": "string", + "description": "Time of day, `HH:MM` (24-hour); defaults to `00:00`." + } + } }, - "weight": { - "description": "Layer weight for ordering.", - "type": "integer" + "handoff": { + "type": "object", + "writeOnly": true, + "required": [ + "weekday", + "time" + ], + "description": "Request only. Handoff weekday and time in the schedule's time zone; sets `handoff_time` and the time of day of `enable_time`.", + "properties": { + "weekday": { + "type": "integer", + "minimum": 1, + "maximum": 7, + "description": "ISO weekday: `1` = Monday … `7` = Sunday." + }, + "time": { + "type": "string", + "description": "Time of day, `HH:MM` (24-hour)." + } + } + }, + "restricts_wall": { + "type": "array", + "writeOnly": true, + "description": "Request only. Restriction windows as wall-clock times in the schedule's time zone; replaces `restrict_periods`. With `restrict_mode` 1 use `from`/`to` (`to` = `00:00` means end of day); with `restrict_mode` 2 also set `from_day`/`to_day`. Rejected when `restrict_mode` is 0.", + "items": { + "type": "object", + "properties": { + "from_day": { + "type": "integer", + "minimum": 1, + "maximum": 7, + "description": "ISO weekday the window starts on (`restrict_mode` 2 only): `1` = Monday … `7` = Sunday." + }, + "from": { + "type": "string", + "description": "Window start, `HH:MM`." + }, + "to_day": { + "type": "integer", + "minimum": 1, + "maximum": 7, + "description": "ISO weekday the window ends on (`restrict_mode` 2 only)." + }, + "to": { + "type": "string", + "description": "Window end, `HH:MM`." + } + } + } } - }, - "required": [ - "account_id", - "name", - "schedule_id", - "hidden", - "mode", - "weight", - "groups", - "rotation_duration", - "handoff_time", - "enable_time", - "expire_time", - "restrict_mode", - "restrict_start", - "restrict_end", - "restrict_periods", - "day_mask", - "create_at", - "create_by", - "update_at", - "update_by", - "fair_rotation", - "rotation_unit", - "rotation_value", - "mask_continuous_enabled" - ], - "type": "object" + } }, "ScheduleListRequest": { - "description": "Schedule list request. limit defaults to 10 and is capped at 100; p defaults to 1. is_my_team and is_my_manage are mutually exclusive.", + "type": "object", + "description": "Schedule list filters. `limit` defaults to 10 and is capped at 100; `p` defaults to 1. `is_my_team` and `is_my_manage` cannot both be true.", "properties": { - "end": { - "description": "Window end timestamp (Unix seconds).", - "format": "int64", - "type": "integer" - }, - "is_my_manage": { - "description": "Only return schedules created by the current user within their teams.", - "type": "boolean" + "query": { + "type": "string", + "description": "Substring matched against the schedule name or description." }, - "is_my_team": { - "description": "Only return schedules whose owning team the current user belongs to.", - "type": "boolean" + "p": { + "type": "integer", + "description": "Page number (1-indexed).", + "default": 1 }, "limit": { + "type": "integer", + "description": "Page size. Default 10; values above 100 are treated as 100.", "default": 10, - "description": "Page size. Default 10, max 100.", - "maximum": 100, - "type": "integer" - }, - "p": { - "default": 1, - "description": "Page number (1-indexed).", - "type": "integer" + "maximum": 100 }, - "query": { - "description": "Search keyword matched against schedule name or description.", - "type": "string" + "is_my_team": { + "type": "boolean", + "description": "Only schedules owned by the caller's teams. When `team_ids` shares no team with the caller, or the caller belongs to no team, the list is empty." }, - "start": { - "description": "When set together with end, computed layer schedules are returned. Span must be less than 45 days.", - "format": "int64", - "type": "integer" + "is_my_manage": { + "type": "boolean", + "description": "Only schedules owned by the caller's teams or created by the caller. `team_ids` narrows the team part; team IDs outside the caller's teams are ignored." }, "team_ids": { - "description": "Filter by team IDs.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Only schedules owned by these teams. With `is_my_team` or `is_my_manage`, only the teams the caller belongs to are kept." + }, + "start": { + "type": "integer", + "format": "int64", + "description": "Window start, 10-digit Unix seconds. Send together with `end` to compute layers and shifts." + }, + "end": { + "type": "integer", + "format": "int64", + "description": "Window end, 10-digit Unix seconds, after `start` and at most 45 days later. Sending `end` without `start` is rejected." } - }, - "type": "object" + } }, "ScheduleListResponse": { + "type": "object", "description": "Schedule list response.", + "required": [ + "items", + "total" + ], "properties": { "items": { - "description": "Schedules on this page; null when no schedule matches.", + "type": "array", "items": { "$ref": "#/components/schemas/ScheduleItem" }, - "type": [ - "array", - "null" - ] + "description": "Schedules on this page; an empty array when none match." }, "total": { - "description": "Total number of schedules matching the filters.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Total number of schedules matching the filters." } - }, - "required": [ - "items", - "total" - ], - "type": "object" + } }, "ScheduleMember": { + "type": "object", "description": "Schedule group member reference.", + "required": [ + "role_id", + "person_ids" + ], "properties": { + "role_id": { + "type": "integer", + "format": "int64", + "description": "On-call role assigned to the people in this slot; `0` = no role.", + "minimum": 0 + }, "person_ids": { - "description": "Person IDs in this slot.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "minItems": 1, - "type": "array" - }, - "role_id": { - "description": "Oncall role ID.", - "format": "int64", - "minimum": 0, - "type": "integer" + "description": "Member IDs in this slot; at least one.", + "minItems": 1 } - }, - "required": [ - "role_id", - "person_ids" - ], - "type": "object" + } }, "ScheduleNotify": { + "type": "object", "description": "Notification configuration attached to a schedule.", + "required": [ + "fixed_time", + "by", + "webhooks" + ], "properties": { "advance_in_time": { - "description": "Advance notification lead time in seconds. `0` notifies exactly at shift start; omitting disables advance notification.", - "format": "int64", "type": [ "integer", "null" - ] - }, - "by": { - "$ref": "#/components/schemas/ScheduleNotifyBy", - "description": "Recipient notification preference; null when not configured." + ], + "format": "int64", + "description": "Lead time in seconds for the shift-change notification: `0` notifies at the start of the shift, `300` five minutes before. Omitted or `null` disables shift-change notifications." }, "fixed_time": { - "$ref": "#/components/schemas/ScheduleFixedTimeNotifyInfo", - "description": "Fixed-time notification config; null when not configured." + "oneOf": [ + { + "$ref": "#/components/schemas/ScheduleFixedTimeNotifyInfo" + }, + { + "type": "null" + } + ], + "description": "Send a shift summary at a fixed time; `null` when not configured." + }, + "by": { + "oneOf": [ + { + "$ref": "#/components/schemas/ScheduleNotifyBy" + }, + { + "type": "null" + } + ], + "description": "Personal notifications sent to the people on call; `null` when not configured." }, "im": { + "type": "object", "additionalProperties": { "type": "string" }, - "description": "Legacy IM-type to token map.", - "type": "object" + "description": "Legacy map of robot type to webhook token. Entries not already in `webhooks` are added to `webhooks` when read; use `webhooks` instead." }, "webhooks": { - "description": "IM webhook notification channels; null when not configured.", - "items": { - "$ref": "#/components/schemas/ScheduleImNotify" - }, "type": [ "array", "null" - ] + ], + "items": { + "$ref": "#/components/schemas/ScheduleImNotify" + }, + "description": "Group chats or robots that receive shift-change notifications; `null` when not configured." } - }, - "required": [ - "fixed_time", - "by", - "webhooks" - ], - "type": "object" + } }, "ScheduleNotifyBy": { + "type": "object", "description": "Per-recipient notification preference.", + "required": [ + "follow_preference", + "personal_channels" + ], "properties": { "follow_preference": { - "description": "Whether to follow each responder's personal notification preference.", - "type": "boolean" + "type": "boolean", + "description": "`true`: notify each person through the channels in their own shift-notification preference, ignoring `personal_channels`. `false`: use `personal_channels`." }, "personal_channels": { - "description": "Personal notification channel keys.", + "type": [ + "array", + "null" + ], "items": { "type": "string" }, - "type": "array" + "description": "Channels used when `follow_preference` is `false`: `email`, `sms`, `push` (mobile app), and the IM apps `feishu_app`, `dingtalk_app`, `wecom_app`, `teams_app`, `slack_app`. An IM app value may carry the integration ID as `:` (for example `feishu_app:5427276014131`). Unknown values are stored but never used. `null` when not set." } - }, - "required": [ - "follow_preference", - "personal_channels" - ], - "type": "object" + } }, "ScheduleOncallGroup": { + "type": "object", "description": "Snapshot of the currently or next on-call group.", + "required": [ + "start", + "end", + "group", + "update_at", + "weight", + "index" + ], "properties": { + "start": { + "type": "integer", + "format": "int64", + "description": "Shift start timestamp (Unix seconds)." + }, "end": { - "description": "Shift end timestamp (Unix seconds).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Shift end timestamp (Unix seconds)." }, "group": { "$ref": "#/components/schemas/ScheduleGroup", "description": "Oncall group on duty for the shift." }, - "index": { - "description": "Index inside the rotation.", - "type": "integer" - }, - "start": { - "description": "Shift start timestamp (Unix seconds).", - "format": "int64", - "type": "integer" - }, "update_at": { - "description": "Update timestamp (Unix seconds).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Update time as a Unix timestamp in seconds; always `0` in these responses." }, "weight": { - "description": "Layer weight the shift comes from.", - "type": "integer" + "type": "integer", + "description": "Always `0` in these responses." + }, + "index": { + "type": "integer", + "description": "Always `0` in these responses." } - }, - "required": [ - "start", - "end", - "group", - "update_at", - "weight", - "index" - ], - "type": "object" + } }, "ScheduleRestrictPeriod": { - "description": "Restrict window inside a rotation cycle. restrict_start and restrict_end are second offsets and cannot be equal unless both are 0.", + "type": "object", + "description": "One on-call window inside a day or week (see `restrict_mode`). A window whose start is later than its end wraps past midnight (or the end of the week). `{0, 0}` means the whole day or week. Start and end may not be equal otherwise.", + "required": [ + "restrict_start", + "restrict_end" + ], "properties": { - "restrict_end": { - "description": "End offset inside the rotation cycle.", + "restrict_start": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Window start in seconds: from 00:00 when `restrict_mode` is 1, from Monday 00:00 when it is 2." }, - "restrict_start": { - "description": "Start offset inside the rotation cycle.", + "restrict_end": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Window end in seconds, same reference point as `restrict_start`." } - }, - "required": [ - "restrict_start", - "restrict_end" - ], - "type": "object" + } }, "ScheduleSelfRequest": { "description": "Query parameters for listing the current user's schedules. start and end are required 10-digit Unix timestamps in seconds, and the window must not exceed 45 days.", @@ -23594,169 +24445,194 @@ "type": "object" }, "ScheduleSelfResponse": { - "description": "Response of /schedule/self and /schedule/infos. Only the items field is populated.", + "type": "object", + "description": "Response of `/schedule/self` and `/schedule/infos`.", + "required": [ + "items" + ], "properties": { "items": { - "description": "Schedules assigned to the current user (or matching the requested IDs); null when none.", + "type": "array", "items": { "$ref": "#/components/schemas/ScheduleItem" }, - "type": [ - "array", - "null" - ] + "description": "Matching schedules; an empty array when none match." } - }, - "required": [ - "items" - ], - "type": "object" + } }, "ScheduleUpsertRequest": { - "description": "Schedule create/update/preview request body. The server accepts the same shape as the schedule detail model; only the key fields are listed here. `schedule_name` (or the legacy `name`) is required on create, `schedule_id` is required on update, and `start`/`end` are required on preview.", + "type": "object", + "description": "Request body of `/schedule/create`, `/schedule/update` and `/schedule/preview`. `schedule_name` (or the legacy `name`) is required on create, `schedule_id` on update, and `start`/`end` on preview.", "properties": { - "description": { - "description": "Schedule description. Max 500 characters.", - "maxLength": 500, + "schedule_id": { "type": [ - "string", + "integer", "null" - ] + ], + "format": "int64", + "description": "Schedule ID, required on update; obtain it from `POST /schedule/list`." }, - "disabled": { - "description": "0 = enabled, 1 = disabled. Defaults to enabled when omitted.", + "schedule_name": { "type": [ - "integer", + "string", "null" - ] - }, - "end": { - "description": "Preview window end (Unix seconds, 10 digits). Required for /schedule/preview. Max 45 days after start.", - "format": "int64", - "type": "integer" - }, - "layers": { - "description": "Rotation layers.", - "items": { - "$ref": "#/components/schemas/ScheduleLayer" - }, - "type": "array" + ], + "description": "Schedule name, at most 40 characters, unique within the account. On update, omitting it keeps the current name.", + "maxLength": 40 }, "name": { - "description": "Legacy schedule name field. Used when schedule_name is empty.", - "maxLength": 40, "type": [ "string", "null" - ] - }, - "notify": { - "$ref": "#/components/schemas/ScheduleNotify", - "description": "Rotation notification configuration." + ], + "description": "Legacy name field, used on create only when `schedule_name` is empty. Ignored on update.", + "maxLength": 40 }, - "schedule_id": { - "description": "Schedule ID, required on update; obtain it from `POST /schedule/list`.", - "format": "int64", + "description": { "type": [ - "integer", + "string", "null" - ] + ], + "description": "Schedule description, at most 500 characters. On update, omitting it keeps the current text and an empty string clears it.", + "maxLength": 500 }, - "schedule_name": { - "description": "Schedule display name. Max 40 characters.", - "maxLength": 40, + "team_id": { "type": [ - "string", + "integer", "null" - ] + ], + "format": "int64", + "description": "ID of the owning team; obtain it from `POST /team/list`. On create, omitting it leaves the schedule without a team (`0`); on update, omitting it keeps the current team." + }, + "time_zone": { + "type": "string", + "description": "IANA time zone in which the schedule's wall-clock rules are evaluated, for example `Asia/Shanghai` or `UTC`; abbreviations such as `EST` and `Etc/GMT±N` are rejected. Set on create (default: evaluated in `Asia/Shanghai`); immutable afterwards — on update send nothing or the current value. On preview it sets the evaluation time zone." + }, + "layers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ScheduleLayer" + }, + "description": "Rotation layers. Required in practice: on update the list replaces all existing layers, so omitting it deletes every layer." + }, + "notify": { + "oneOf": [ + { + "$ref": "#/components/schemas/ScheduleNotify" + }, + { + "type": "null" + } + ], + "description": "Shift notification configuration. On update, omitting it keeps the current configuration; a sent object replaces it entirely." }, "start": { - "description": "Preview window start (Unix seconds, 10 digits). Required for /schedule/preview.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Preview window start, 10-digit Unix seconds. Required for `/schedule/preview`; ignored by create and update." }, - "team_id": { - "description": "Owning team ID; obtain it from `POST /team/list`.", + "end": { + "type": "integer", "format": "int64", + "description": "Preview window end, 10-digit Unix seconds, after `start` and at most 45 days later. Required for `/schedule/preview`; ignored by create and update." + }, + "disabled": { "type": [ "integer", "null" - ] + ], + "enum": [ + 0, + 1, + null + ], + "description": "Create only: `0` = enabled (default), `1` = disabled. Ignored on update — use `status` instead." + }, + "status": { + "type": [ + "integer", + "null" + ], + "enum": [ + 0, + 1, + null + ], + "description": "`0` = enabled, `1` = disabled. On update, omitting it keeps the current state. On create it takes precedence over `disabled`." } - }, - "type": "object" + } }, "ServiceDeskPlusRequestListRequest": { + "type": "object", "description": "Filters for listing ServiceDeskPlus request synchronization records. A time window is optional when querying by incident ID; otherwise provide a Unix-second window no longer than 30 days.", "properties": { - "asc": { - "description": "When `true`, sort by internal record ID ascending; otherwise descending.", - "type": "boolean" + "start_time": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "Window start, Unix seconds. Optional when `incident_id` is provided." + }, + "end_time": { + "type": "integer", + "format": "int64", + "minimum": 0, + "description": "Window end, Unix seconds. Must be greater than or equal to `start_time`. Optional when `incident_id` is provided." + }, + "status": { + "type": "string", + "enum": [ + "success", + "failed" + ], + "description": "Filter by sync status: `success` or `failed`." }, "channel_ids": { - "description": "Channel IDs to filter by.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Channel IDs to filter by." }, - "end_time": { - "description": "Window end, Unix seconds. Must be greater than or equal to `start_time`. Optional when `incident_id` is provided.", + "integration_id": { + "type": "integer", "format": "int64", "minimum": 0, - "type": "integer" + "description": "ServiceDeskPlus integration ID." }, "incident_id": { - "description": "Flashduty incident ID. When set, the time window can be omitted.", + "type": "string", "maxLength": 64, - "type": "string" + "description": "Flashduty incident ID. When set, the time window can be omitted." }, - "integration_id": { - "description": "ServiceDeskPlus integration ID.", - "format": "int64", - "minimum": 0, - "type": "integer" + "request_id": { + "type": "string", + "maxLength": 64, + "description": "ServiceDeskPlus request ID." }, - "limit": { - "default": 20, - "description": "Page size. Defaults to 20; maximum 100.", - "format": "int64", - "maximum": 100, - "minimum": 0, - "type": "integer" + "asc": { + "type": "boolean", + "description": "When `true`, sort by internal record ID ascending; otherwise descending." }, "p": { - "description": "Page number starting at 1. Ignored when `search_after_ctx` is set.", + "type": "integer", "format": "int64", "minimum": 0, - "type": "integer" - }, - "request_id": { - "description": "ServiceDeskPlus request ID.", - "maxLength": 64, - "type": "string" - }, - "search_after_ctx": { - "description": "Pagination cursor: leave empty for the first page, then pass the `search_after_ctx` returned by the previous response.", - "type": "string" + "description": "Not supported; pagination uses only `search_after_ctx`, so this value is ignored." }, - "start_time": { - "description": "Window start, Unix seconds. Optional when `incident_id` is provided.", + "limit": { + "type": "integer", "format": "int64", "minimum": 0, - "type": "integer" + "maximum": 100, + "default": 20, + "description": "Page size. Defaults to 20; maximum 100." }, - "status": { - "description": "Filter by sync status: `success` or `failed`.", - "enum": [ - "success", - "failed" - ], - "type": "string" + "search_after_ctx": { + "type": "string", + "description": "Pagination cursor: leave empty for the first page, then pass the `search_after_ctx` returned by the previous response." } - }, - "type": "object" + } }, "ServiceDeskPlusRequestListResponse": { "description": "Paginated list of ServiceDeskPlus request synchronization records.", @@ -23921,29 +24797,26 @@ "type": "object" }, "SessionGetResponse": { + "type": "object", "description": "A session plus a backward-paged window of its events.", "properties": { + "session": { + "$ref": "#/components/schemas/SessionItem" + }, "events": { - "description": "Recent events, ascending by (created_at, event_id).", + "type": "array", "items": { "$ref": "#/components/schemas/EventItem" }, - "type": "array" + "description": "The newest page of events (older pages via `search_after_ctx`), ascending by (`created_at`, `event_id`). Internal control events are excluded. Always an array." }, "has_more_older": { - "description": "True when older events remain beyond this page.", - "type": "boolean" + "type": "boolean", + "description": "True when older events remain beyond this page." }, "search_after_ctx": { - "description": "Opaque keyset cursor; pass back as search_after_ctx to fetch the next older page. Omitted when has_more_older is false.", - "type": "string" - }, - "session": { - "$ref": "#/components/schemas/SessionItem" - }, - "suggest_init": { - "description": "Account-wide onboarding flag: true when the account has no knowledge in any scope; not specific to this session.", - "type": "boolean" + "type": "string", + "description": "Opaque keyset cursor; pass back as search_after_ctx to fetch the next older page. Omitted when has_more_older is false." }, "pending_messages": { "type": "array", @@ -23957,214 +24830,252 @@ "session", "events", "has_more_older", - "suggest_init", "pending_messages" - ], - "type": "object" + ] }, "SessionItem": { + "type": "object", "description": "One agent session row.", "properties": { - "access_source": { - "description": "How the caller received access to this session. Omitted when no access source is resolved. One of:\n| Value | Meaning |\n| --- | --- |\n| `owner` | Caller is the session creator (full access) |\n| `team_member` | Caller belongs to the session's bound team (full access) |\n| `manager` | Manager grant (reserved; never produced by the current version) |\n| `share_link` | Granted via a valid share link (view/fork only; cannot continue or manage) |\n| `participant` | Same-account non-member granted via a participable team session (view/continue/fork only) |", - "enum": [ - "owner", - "team_member", - "manager", - "share_link", - "participant" - ], - "type": "string" + "session_id": { + "type": "string", + "description": "Session identifier." + }, + "parent_session_id": { + "type": "string", + "description": "Parent session id for subagent (child) sessions; empty otherwise." + }, + "session_name": { + "type": "string", + "description": "Session title; may be empty for untitled sessions." }, "app_name": { - "description": "Agent app that owns the session.", - "type": "string" + "type": "string", + "description": "Agent app that owns the session." }, - "archived_at": { - "description": "Unix timestamp in milliseconds when archived; 0 means not archived.", - "format": "int64", - "type": "integer" + "entry_kind": { + "type": "string", + "description": "Surface that created the session:\n- `web`: web console (also returned for subagent child sessions and for sessions that predate this field)\n- `im`: IM bot or IM H5 client\n- `api`: public API\n- `automation`: automation rule (unattended run)", + "enum": [ + "web", + "im", + "api", + "automation" + ] }, - "bound_environment": { - "$ref": "#/components/schemas/EnvironmentBinding" + "person_id": { + "type": "string", + "description": "Creator person id." }, - "can_continue": { - "description": "True when the caller can add a new turn to this session.", - "type": "boolean" + "ref": { + "type": "string", + "description": "Business object the session is about, as a prefixed reference (for example an incident reference). Omitted when the session is not bound to one." }, - "can_fork": { - "description": "True when the caller can fork this session.", - "type": "boolean" + "creator_name": { + "type": "string", + "description": "Display name of the session creator. Returned by `POST /safari/session/list` only; omitted when the name lookup fails." }, - "can_manage": { - "description": "True when the caller may rename/archive/delete the session; personal sessions are creator-only, team sessions allow the creator, account admin, or team member.", - "type": "boolean" + "team_id": { + "type": "integer", + "format": "int64", + "description": "Owning team id; 0 means no team is bound. Immutable after create." + }, + "team_name": { + "type": "string", + "description": "Resolved team name; empty for unbound rows or deleted teams." + }, + "automation": { + "type": "object", + "description": "Automation rule that produced this session. Returned by `POST /safari/session/get` only, for sessions started by an automation rule.", + "properties": { + "rule_id": { + "type": "string", + "description": "ID of the automation rule." + }, + "rule_name": { + "type": "string", + "description": "Rule name; empty when the rule has since been deleted." + }, + "trigger_kind": { + "type": "string", + "enum": [ + "schedule", + "manual", + "http_post", + "oncall_incident", + "war_room_created", + "" + ], + "description": "How this run was triggered:\n- `schedule`: the rule's schedule fired\n- `manual`: run on demand (console or `POST /safari/automation/rule/run`)\n- `http_post`: the rule's HTTP trigger URL was called\n- `oncall_incident`: an On-call incident event matched the rule\n- `war_room_created`: a war room was created\n- `\"\"`: the run record no longer exists" + }, + "can_edit": { + "type": "boolean", + "description": "True when the caller may open and manage the rule; false when the rule has been deleted." + } + }, + "required": [ + "rule_id", + "rule_name", + "trigger_kind", + "can_edit" + ] + }, + "is_mine": { + "type": "boolean", + "description": "True when the caller created this session." }, "can_view": { - "description": "True when the caller can view this session.", - "type": "boolean" + "type": "boolean", + "description": "True when the caller can read this session: always true for the creator, team members, and other members of the same account on a team session; true through a valid share link otherwise." }, - "context_resolved": { - "$ref": "#/components/schemas/ContextResolvedItem" + "can_continue": { + "type": "boolean", + "description": "True when the caller can add a new turn to this session." }, - "context_window": { - "description": "The bound model's max context size in tokens. 0 means unknown.", - "format": "int64", - "type": "integer" + "can_manage": { + "type": "boolean", + "description": "True when the caller may rename, archive, or delete the session: the creator of a personal session, or the creator or a member of the owning team for a team session. Account owners and admins get no exemption." }, - "created_at": { - "description": "Unix timestamp in milliseconds when the session was created.", - "format": "int64", - "type": "integer" + "can_fork": { + "type": "boolean", + "description": "True when the caller can fork this session." }, - "current_context_tokens": { - "description": "Size in tokens of the LLM context window as of the most recent turn. 0 means no turn has completed.", - "format": "int64", - "type": "integer" + "access_source": { + "type": "string", + "description": "How the caller obtained access. Omitted when the caller has no access. One of:\n| Value | Meaning |\n| --- | --- |\n| `owner` | Caller created the session (full access) |\n| `team_member` | Caller belongs to the session's team (full access) |\n| `manager` | Reserved; not produced by the current version |\n| `share_link` | Granted by a valid share link (view and fork only; view only for subagent child sessions) |\n| `participant` | Another member of the same account on a team session (view, continue, fork; no manage) |", + "enum": [ + "owner", + "team_member", + "manager", + "share_link", + "participant" + ] }, - "current_turn_active_ms": { - "description": "Active working duration in milliseconds for the current or most recent round, excluding time spent waiting on ask_user; resets to 0 at the start of each new round.", - "format": "int64", - "type": "integer" + "share_enabled": { + "type": "boolean", + "description": "True when the session's share link is active." }, - "current_turn_started_at": { - "description": "Unix timestamp in milliseconds when the current or most recent round started; 0 if no round has started yet.", + "share_version": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Revision of the share link; it increases when sharing is revoked." }, - "current_turn_tokens": { - "description": "Total tokens (input+output+reasoning) for the in-flight round across the parent and its subagents; only computed by session/get while the session is running, always 0 in session/list responses and when idle.", + "shared_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp in milliseconds when sharing was last enabled; 0 if never shared." }, - "current_turn_wait_ms": { - "description": "Accumulated ask_user human-wait duration in milliseconds for the current round; resets to 0 at the start of each new round.", + "shared_by": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Person ID that most recently enabled sharing; 0 if never shared." }, - "entry_kind": { - "description": "Surface that created the session. One of:\n| Value | Meaning |\n| --- | --- |\n| `web` | Created from the web console |\n| `im` | Created from an IM client (IM bot / IM H5) |\n| `api` | Created via the public API |\n| `automation` | Created by an automation rule (unattended run) |\n| `subagent` | Child session spawned by a parent's agent_dispatch (audit label; at runtime it executes on the web tool surface) |", + "status": { + "type": "string", + "description": "Lifecycle status. Always `enabled` in responses: deleted sessions are never returned.", "enum": [ - "web", - "im", - "api", - "automation", - "subagent" - ], - "type": "string" - }, - "has_unread": { - "description": "True when there is assistant output the caller has not yet viewed.", - "type": "boolean" + "enabled" + ] }, "incognito": { - "description": "True for incognito (non-persisted-memory) sessions.", - "type": "boolean" - }, - "is_mine": { - "description": "True when the caller created this session.", - "type": "boolean" - }, - "is_running": { - "description": "True when an agent turn is currently in flight for this session.", - "type": "boolean" + "type": "boolean", + "description": "True for incognito (non-persisted-memory) sessions." }, - "standing_tasks": { + "created_at": { "type": "integer", - "description": "Number of process-type tasks (background shell or monitor) still alive when the response was rendered." + "format": "int64", + "description": "Unix timestamp in milliseconds when the session was created." }, - "last_event_at": { - "description": "Unix timestamp in milliseconds of the most recent assistant-side event.", + "updated_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp in milliseconds of the last session update." }, - "parent_session_id": { - "description": "Parent session id for subagent (child) sessions; empty otherwise.", - "type": "string" + "template_staging_round_id": { + "type": "string", + "description": "Current save→validate round id (template-assistant only); empty otherwise." }, - "person_id": { - "description": "Creator person id.", - "type": "string" + "state": { + "type": "object", + "additionalProperties": true, + "description": "Raw session-state key/value map. Returned by `POST /safari/session/get` only; omitted when empty." }, - "creator_name": { - "type": "string", - "description": "Display name of the session creator, resolved when the response is rendered. Omitted when the member lookup fails." + "bound_environment": { + "$ref": "#/components/schemas/EnvironmentBinding" }, - "pinned_at": { - "description": "Caller's per-user pin time as a Unix timestamp in milliseconds; 0 means not pinned.", - "format": "int64", - "type": "integer" + "context_resolved": { + "$ref": "#/components/schemas/ContextResolvedItem" }, - "session_id": { - "description": "Session identifier.", - "type": "string" + "token_usage": { + "$ref": "#/components/schemas/SessionTokenUsage" }, - "session_name": { - "description": "Session title; may be empty for untitled sessions.", - "type": "string" + "current_context_tokens": { + "type": "integer", + "format": "int64", + "description": "Size in tokens of the LLM context window as of the most recent turn. 0 means no turn has completed." }, - "share_enabled": { - "description": "True when the session's share link is active.", - "type": "boolean" + "context_window": { + "type": "integer", + "format": "int64", + "description": "Maximum context size of the session's model, in tokens. Computed by `POST /safari/session/get` only; always 0 in list responses and when the lookup fails." }, - "share_version": { - "description": "Revision of the share link; it increases when sharing is revoked.", + "archived_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp in milliseconds when archived; 0 means not archived." }, - "shared_at": { - "description": "Unix timestamp in milliseconds when sharing was last enabled; 0 if never shared.", + "pinned_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "When the caller pinned this session, as a Unix timestamp in milliseconds; 0 when not pinned. Pins are per user. Filled by `POST /safari/session/list` only; always 0 in `POST /safari/session/get`." }, - "shared_by": { - "description": "Person ID that most recently enabled sharing; 0 if never shared.", + "last_event_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp in milliseconds of the latest assistant-side event; user messages alone do not advance it. Omitted when 0." }, - "state": { - "additionalProperties": true, - "description": "Raw session-state bag (session-scoped keys). Omitted when empty.", - "type": "object" + "is_running": { + "type": "boolean", + "description": "True when an agent turn is currently in flight for this session." }, - "status": { - "description": "Lifecycle status. One of: `enabled` (active), `deleted` (soft-deleted, no longer accessible).", - "enum": [ - "enabled", - "deleted" - ], - "type": "string" + "standing_tasks": { + "type": "integer", + "description": "Number of the session's process-type tasks (background shell commands or monitors) still alive when the response was built; 0 when none or when the count cannot be read." }, - "team_id": { - "description": "Owning team id; 0 means no team is bound. Immutable after create.", - "format": "int64", - "type": "integer" + "has_unread": { + "type": "boolean", + "description": "True when assistant output exists that the caller has not viewed yet; always false while `is_running` is true. Computed by `POST /safari/session/list` only; always false in `POST /safari/session/get`." }, - "team_name": { - "description": "Resolved team name; empty for unbound rows or deleted teams.", - "type": "string" + "has_open_tasks": { + "type": "boolean", + "description": "True when the session still has open tasks (for example running subagents or background processes), which tells a handed-off turn apart from a settled session. Returned by `POST /safari/session/get` only; omitted when false or when the lookup fails, so treat absence as unknown rather than idle." }, - "template_staging_round_id": { - "description": "Current save→validate round id (template-assistant only); empty otherwise.", - "type": "string" + "current_turn_started_at": { + "type": "integer", + "format": "int64", + "description": "Unix timestamp in milliseconds when the current or most recent round started; 0 if no round has started yet." }, - "token_usage": { - "$ref": "#/components/schemas/SessionTokenUsage" + "current_turn_active_ms": { + "type": "integer", + "format": "int64", + "description": "Active working duration in milliseconds for the current or most recent round, excluding time spent waiting on ask_user; resets to 0 at the start of each new round." }, - "updated_at": { - "description": "Unix timestamp in milliseconds of the last session update.", + "current_turn_wait_ms": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Accumulated ask_user human-wait duration in milliseconds for the current round; resets to 0 at the start of each new round." }, - "has_open_tasks": { - "type": "boolean", - "description": "Whether the session still has open tasks, used to tell a handed-off turn from a settled session. Best-effort: when the read fails the field is absent (`omitempty`), which callers must treat as \"unknown\", never as proof the session is idle." + "current_turn_tokens": { + "type": "integer", + "format": "int64", + "description": "Total tokens (input+output+reasoning) for the in-flight round across the parent and its subagents; only computed by session/get while the session is running, always 0 in session/list responses and when idle." } }, "required": [ "session_id", "session_name", "app_name", + "entry_kind", "person_id", "team_id", "is_mine", @@ -24191,14 +25102,15 @@ "current_turn_active_ms", "current_turn_wait_ms", "current_turn_tokens" - ], - "type": "object" + ] }, "SessionListRequest": { + "type": "object", "description": "Filters for listing agent sessions. `all` visibility means the caller's own personal sessions plus accessible team sessions; account admins do not see other users' personal sessions.", "properties": { "app_name": { - "description": "Agent app whose sessions to list. One of:\n| Value | Meaning |\n| --- | --- |\n| `ask-ai` | Ask AI assistant |\n| `support` | Customer-support agent |\n| `support-website` | Website support agent (exposed over A2A, not built into the console) |\n| `support-flashcat` | Flashcat-site support agent (exposed over A2A) |\n| `ai-sre` | The AI SRE main app |\n| `template-assistant` | Notification-template assistant (template editing/validation) |\n| `swe` | Internal benchmarking app (not customer-facing) |", + "type": "string", + "description": "Agent app whose sessions to list. One of:\n| Value | Meaning |\n| --- | --- |\n| `ask-ai` | Ask AI assistant |\n| `support` | Customer-support agent |\n| `support-website` | Website support agent (exposed over A2A, not built into the console) |\n| `support-flashcat` | Flashcat-site support agent (exposed over A2A) |\n| `ai-sre` | The AI SRE main app |\n| `template-assistant` | Notification-template assistant (template editing/validation) |\n| `query-assistant` | Monitors query-writing assistant |\n| `swe` | Software-engineering agent app (not offered in the console) |", "enum": [ "ask-ai", "support", @@ -24206,82 +25118,60 @@ "support-flashcat", "ai-sre", "template-assistant", + "query-assistant", "swe" - ], - "type": "string" - }, - "asc": { - "description": "Ascending order when true, descending when false. Only honored together with `orderby`; when `orderby` is omitted the sort is always `updated_at` descending.", - "type": "boolean" - }, - "entry_kinds": { - "description": "Restrict to sessions produced by these surfaces; empty returns every kind.", - "items": { - "enum": [ - "web", - "im", - "api", - "automation" - ], - "type": "string" - }, - "type": "array" - }, - "include_subagent_sessions": { - "description": "Include subagent-dispatched sessions in the list.", - "type": "boolean" + ] }, - "keyword": { - "description": "Filter by session-name keyword.", - "maxLength": 64, - "type": "string" + "p": { + "type": "integer", + "description": "Page number, 1-based.", + "default": 1, + "minimum": 1 }, "limit": { - "default": 20, + "type": "integer", "description": "Page size, 1–100.", - "maximum": 100, "minimum": 1, - "type": "integer" + "maximum": 100, + "default": 20 }, "orderby": { + "type": "string", "description": "Sort field: `created_at` by creation time, `updated_at` by last update; defaults to `updated_at` when omitted.", "enum": [ "created_at", "updated_at" - ], - "type": "string" + ] }, - "p": { - "default": 1, - "description": "Page number, 1-based.", - "minimum": 1, - "type": "integer" + "asc": { + "type": "boolean", + "description": "Ascending order when true, descending when false. Only honored together with `orderby`; when `orderby` is omitted the sort is always `updated_at` descending." + }, + "include_subagent_sessions": { + "type": "boolean", + "description": "When true, also list child sessions spawned by subagent dispatch. Defaults to false (top-level sessions only)." + }, + "keyword": { + "type": "string", + "description": "Return only sessions whose `session_name` contains this text; leading and trailing spaces are ignored.", + "maxLength": 64 }, "scope": { - "description": "Visibility scope: `all` (own personal + accessible team sessions), `personal`, or `team`; default `all`.", + "type": "string", + "description": "Visibility scope:\n- `all` (default): sessions the caller created plus sessions bound to teams the caller belongs to\n- `personal`: the caller's own sessions with no team (`team_id` = 0)\n- `team`: sessions bound to teams the caller belongs to; empty when the caller is in no team", "enum": [ "all", "personal", "team" - ], - "type": "string" - }, - "status": { - "description": "Archive bucket: active (default) returns un-archived, archived returns archived, all returns both.", - "enum": [ - "active", - "archived", - "all" - ], - "type": "string" + ] }, "team_ids": { - "description": "Optional explicit team filter; intersects with `scope` and never expands access.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Optional explicit team filter; intersects with `scope` and never expands access." }, "person_ids": { "type": "array", @@ -24290,39 +25180,55 @@ "format": "int64" }, "description": "Filter by who started the session: returns only sessions started by these members (a session is kept when `person_id` matches any of them). Intersects with `scope` and `team_ids`, so it never widens what the caller is allowed to see." + }, + "entry_kinds": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "web", + "im", + "api", + "automation" + ] + }, + "description": "Restrict to sessions created from these surfaces: `web` (console), `im` (IM bot or IM H5), `api` (public API), `automation` (automation rule). Empty returns every kind." + }, + "status": { + "type": "string", + "description": "Archive filter:\n- `active` (default): sessions that are not archived\n- `archived`: archived sessions only\n- `all`: both", + "enum": [ + "active", + "archived", + "all" + ] } }, "required": [ "app_name" - ], - "type": "object" + ] }, "SessionListResponse": { + "type": "object", "description": "A page of agent sessions.", "properties": { + "total": { + "type": "integer", + "format": "int64", + "description": "Number of matching sessions, ignoring pagination. Pinned sessions prepended on page 1 are not counted." + }, "sessions": { - "description": "The page of sessions.", + "type": "array", "items": { "$ref": "#/components/schemas/SessionItem" }, - "type": "array" - }, - "suggest_init": { - "description": "Account-wide onboarding flag: true when the account has no knowledge in any scope; not dependent on this call's filters.", - "type": "boolean" - }, - "total": { - "description": "Total number of sessions matching the filter (ignoring pagination).", - "format": "int64", - "type": "integer" + "description": "The page of sessions: on page 1, the caller's matching pinned sessions (newest pin first) followed by up to `limit` other sessions in the requested order." } }, "required": [ "total", - "sessions", - "suggest_init" - ], - "type": "object" + "sessions" + ] }, "SessionTokenUsage": { "description": "Cumulative session-level token rollup across all turns. The account-billing source of truth.", @@ -24357,32 +25263,33 @@ "type": "object" }, "SignedURLs": { + "type": "object", "description": "Short-lived signed URLs for downloading or previewing a file.", "properties": { - "content_type": { - "description": "MIME type of the file.", - "type": "string" - }, "download_url": { - "description": "Relative URL (`/safari/artifact/stream?...`) that serves the file as an attachment. Prepend the API base `https://api.flashcat.cloud` before use; expires with `expires_in`.", - "type": "string" + "type": "string", + "description": "Relative URL (`/safari/artifact/stream?...`) that serves the file as an attachment. Prepend the API base `https://api.flashcat.cloud` before use; expires with `expires_in`." + }, + "preview_url": { + "type": "string", + "description": "Same as `download_url` but served inline for browser preview." }, "expires_in": { - "description": "Validity of both URLs in seconds (300).", - "type": "integer" + "type": "integer", + "description": "Validity of both URLs in seconds. Always `300`." }, "name": { - "description": "File name including extension.", - "type": "string" - }, - "preview_url": { - "description": "Same as `download_url` but served inline for browser preview.", - "type": "string" + "type": "string", + "description": "File name including extension." }, "size": { - "description": "File size in bytes.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "File size in bytes." + }, + "content_type": { + "type": "string", + "description": "MIME type, derived from the file-name extension when the file was produced: `text/html` (.html/.htm), `text/markdown` (.md), `text/plain` (.txt/.log), `text/csv`, `text/yaml` (.yaml/.yml), `text/x-python`, `text/x-go`, `text/x-sh`, `application/json`, `application/xml`, `application/pdf`, `image/png`, `image/jpeg`, `image/gif`, `image/svg+xml`, `image/webp`, `application/zip`, `application/gzip` (.tar/.gz/.tgz); any other extension is `application/octet-stream`." } }, "required": [ @@ -24392,112 +25299,111 @@ "name", "size", "content_type" - ], - "type": "object" + ] }, "SilenceRuleItem": { + "type": "object", + "required": [ + "account_id", + "channel_id", + "rule_name", + "description", + "time_filters", + "time_filter", + "filters", + "is_directly_discard", + "status", + "rule_id", + "updated_by", + "created_at", + "updated_at", + "is_effective" + ], "properties": { "account_id": { - "description": "ID of the account the rule belongs to.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the account the rule belongs to." }, "channel_id": { - "description": "ID of the channel the rule belongs to.", - "format": "int64", - "type": "integer" - }, - "created_at": { - "description": "Creation time, Unix timestamp in seconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the channel the rule belongs to." }, - "deleted_at": { - "description": "Deletion time, Unix timestamp in seconds. Omitted unless the rule is soft-deleted; deleted rules are excluded from list responses.", - "format": "int64", - "type": "integer" + "rule_name": { + "type": "string", + "description": "Silence rule name, 1–39 characters." }, "description": { - "description": "Rule description.", - "type": "string" - }, - "filters": { - "$ref": "#/components/schemas/FilterGroup", - "description": "Alert event match conditions; matching events are silenced within the time window." + "type": "string", + "description": "Rule description." }, "from_incident_id": { - "description": "Incident the rule is attached to. Always present; the zero ObjectID `000000000000000000000000` means the rule was not created from an incident.", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Incident the rule is attached to. Always present; the zero ObjectID `000000000000000000000000` means the rule was not created from an incident." }, - "is_auto_delete": { - "description": "When true, the silence rule is automatically deleted after its time window expires. Defaults to false.", - "type": "boolean" - }, - "is_directly_discard": { - "description": "When true, silenced alerts are dropped instead of suppressed into incidents.", - "type": "boolean" + "time_filters": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TimeFilter" + }, + "description": "Recurring silence windows. Empty when the rule uses a one-off `time_filter`." }, - "is_effective": { - "description": "Whether the rule's time window covers the current moment, evaluated at response time.", - "type": "boolean" + "time_filter": { + "$ref": "#/components/schemas/OnceTimeFilter", + "description": "One-off silence window. Present with zero values when the rule uses recurring `time_filters` instead." }, - "rule_id": { - "description": "Rule ID (MongoDB ObjectID).", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "filters": { + "$ref": "#/components/schemas/FilterGroup", + "description": "Alert event conditions (OR of AND groups); matching events are silenced while the time window is active." }, - "rule_name": { - "description": "Rule name.", - "type": "string" + "is_directly_discard": { + "type": "boolean", + "description": "When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as silenced by this rule." }, "status": { - "description": "Rule status: `enabled` or `disabled`; deleted rules never appear in the list.", + "type": "string", "enum": [ "enabled", "disabled" ], - "type": "string" + "description": "Rule status: `enabled` or `disabled`; deleted rules never appear in the list." }, - "time_filter": { - "$ref": "#/components/schemas/OnceTimeFilter", - "description": "One-off silence window. Present with zero values when the rule uses recurring `time_filters` instead." + "rule_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Rule ID (MongoDB ObjectID)." }, - "time_filters": { - "description": "Recurring silence windows. Empty when the rule uses a one-off `time_filter`.", - "items": { - "$ref": "#/components/schemas/TimeFilter" - }, - "type": "array" + "updated_by": { + "type": "integer", + "format": "int64", + "description": "ID of the user who last updated the rule." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation time, Unix timestamp in seconds." }, "updated_at": { - "description": "Last update time, Unix timestamp in seconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update time, Unix timestamp in seconds." }, - "updated_by": { - "description": "ID of the user who last updated the rule.", + "is_effective": { + "type": "boolean", + "description": "Whether the rule's time window covers the current moment, evaluated at response time." + }, + "is_auto_delete": { + "type": "boolean", + "description": "When true, the rule is permanently removed about 24 hours after its one-off window ends; rules with recurring windows are never removed. Returned only when `true`." + }, + "deleted_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Deletion time, Unix timestamp in seconds. Omitted unless the rule is soft-deleted; deleted rules are excluded from list responses." } - }, - "required": [ - "account_id", - "channel_id", - "rule_name", - "description", - "time_filters", - "time_filter", - "filters", - "is_directly_discard", - "status", - "rule_id", - "updated_by", - "created_at", - "updated_at", - "is_effective" - ], - "type": "object" + } }, "SkillDeleteRequest": { "description": "Skill deletion by ID.", @@ -24526,125 +25432,151 @@ "type": "object" }, "SkillItem": { + "type": "object", "description": "An AI SRE skill — a packaged SKILL.md bundle the agent can load.", "properties": { + "skill_id": { + "type": "string", + "description": "Unique skill ID (prefix `skill_`)." + }, "account_id": { + "type": "integer", "description": "Owning account ID.", - "format": "int64", - "type": "integer" - }, - "author": { - "description": "Skill author.", - "type": "string" + "format": "int64" }, - "can_edit": { - "description": "Whether the caller may edit this skill.", - "type": "boolean" - }, - "checksum": { - "description": "SHA-256 checksum of the skill zip.", - "type": "string" + "team_id": { + "type": "integer", + "description": "Team scope: 0 = account-wide; >0 = the owning team.", + "format": "int64" }, - "content": { - "description": "Full SKILL.md content. Omitted in list responses.", - "type": "string" + "skill_name": { + "type": "string", + "description": "Skill name, unique within its scope (account-wide or within one team)." }, - "created": { - "description": "Set only on install-from-session responses: true = fresh install, false = in-place update.", - "type": "boolean" + "description": { + "type": "string", + "description": "Human-readable description from the SKILL.md frontmatter." }, - "created_at": { - "description": "Creation time. Unix timestamp in milliseconds.", - "format": "int64", - "type": "integer" + "description_en": { + "type": "string", + "description": "Optional English description. English-locale UI responses prefer this over `description`; the skill catalog also uses it as a stable selection signal when `description` is localized for display." }, - "created_by": { - "description": "Member ID that created the skill.", - "format": "int64", - "type": "integer" + "content": { + "type": "string", + "description": "Full SKILL.md content. Omitted in list responses." }, - "description": { - "description": "Human-readable description from the SKILL.md frontmatter.", - "type": "string" + "version": { + "type": "string", + "description": "Skill version from the frontmatter." }, - "description_en": { - "description": "Optional English description. English-locale UI responses prefer this over `description`; the skill catalog also uses it as a stable selection signal when `description` is localized for display.", - "type": "string" + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Tags parsed from the frontmatter." }, - "is_modified": { - "description": "True when a marketplace-sourced skill was edited locally (auto-update skips it).", - "type": "boolean" + "author": { + "type": "string", + "description": "Skill author." }, "license": { - "description": "Skill license.", - "type": "string" - }, - "s3_key": { - "description": "Object-storage key of the skill zip.", - "type": "string" + "type": "string", + "description": "Skill license." }, - "skill_id": { - "description": "Unique skill ID (prefix `skill_`).", - "type": "string" + "tools": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Required tools (builtin or `mcp:server/tool`)." }, - "skill_name": { - "description": "Skill name, unique within its scope (account-wide or within one team).", - "type": "string" + "venues": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "cloud", + "byoc" + ] + }, + "description": "Execution environments the skill is restricted to: `cloud` (managed sandbox) and/or `byoc` (self-hosted runner). Omitted when empty, which means every environment." }, - "source_template_name": { - "description": "Marketplace template this skill was installed from; empty for user-authored.", - "type": "string" + "s3_key": { + "type": "string", + "description": "Object-storage key of the skill zip." }, - "source_template_version": { - "description": "Template version at install time.", - "type": "string" + "checksum": { + "type": "string", + "description": "SHA-256 checksum of the skill zip." }, "status": { - "description": "Skill status. Deleted skills are excluded from every API response, so only these two values are ever returned.", + "type": "string", + "description": "Skill status: `enabled` (agents load it) or `disabled` (kept but not loaded). Deleted skills never appear in responses.", "enum": [ "enabled", "disabled" - ], - "type": "string" + ] }, - "tags": { - "description": "Tags parsed from the frontmatter.", - "items": { - "type": "string" - }, - "type": "array" + "created_by": { + "type": "integer", + "description": "Member ID that created the skill.", + "format": "int64" }, - "team_id": { - "description": "Team scope: 0 = account-wide; >0 = the owning team.", + "created_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Creation time. Unix timestamp in milliseconds." }, - "tools": { - "description": "Required tools (builtin or `mcp:server/tool`).", - "items": { - "type": "string" - }, - "type": "array" + "updated_at": { + "type": "integer", + "format": "int64", + "description": "Last update time. Unix timestamp in milliseconds." + }, + "can_edit": { + "type": "boolean", + "description": "True when the caller may change this skill: account owners and admins for account-scope skills, team members for team skills." + }, + "source_template_name": { + "type": "string", + "description": "Marketplace template this skill was installed from; empty for user-authored." + }, + "source_template_version": { + "type": "string", + "description": "Template version at install time." }, "update_available": { - "description": "True when the marketplace has a newer template version.", - "type": "boolean" + "type": "boolean", + "description": "True when the marketplace template this skill was installed from has a newer version. Computed by `POST /safari/skill/list` only; always false in other responses." }, - "updated_at": { - "description": "Last update time. Unix timestamp in milliseconds.", - "format": "int64", - "type": "integer" + "is_modified": { + "type": "boolean", + "description": "True when a marketplace-installed skill was changed locally (for example by uploading a new archive); automatic marketplace updates skip it." }, - "venues": { - "description": "Execution-environment kinds (EnvironmentKind strings, e.g. `byoc`) the skill is restricted to. Omitted when empty, which means the skill is available in all venues.", - "items": { - "type": "string" - }, - "type": "array" + "created": { + "type": "boolean", + "description": "Not returned by these endpoints; it is set only by the install-from-session flow." }, - "version": { - "description": "Skill version from the frontmatter.", - "type": "string" + "examples": { + "type": "array", + "description": "Example prompts declared in the SKILL.md frontmatter (up to 10), shown as suggested questions. Omitted when none.", + "items": { + "type": "object", + "properties": { + "zh": { + "type": "string", + "description": "Chinese prompt text." + }, + "en": { + "type": "string", + "description": "English prompt text." + } + }, + "required": [ + "zh", + "en" + ] + } } }, "required": [ @@ -24660,53 +25592,52 @@ "can_edit", "update_available", "is_modified" - ], - "type": "object" + ] }, "SkillListRequest": { + "type": "object", "description": "Pagination, search, and team filter for listing skills.", "properties": { - "include_account": { - "description": "Include account-scoped (team_id=0) rows. Defaults to true. Ignored when `scope` is `account` or `team`.", - "type": [ - "boolean", - "null" - ] - }, - "limit": { - "default": 20, - "description": "Page size.", - "type": "integer" - }, "p": { - "default": 1, - "description": "Page number, 1-based.", - "type": "integer" + "type": "integer", + "description": "Page number, 1-based; values below 1 fall back to 1.", + "default": 1 }, - "query": { - "description": "Free-text search across skill name, description, English description, skill ID, marketplace source template name, and author.", - "maxLength": 128, - "type": "string" + "limit": { + "type": "integer", + "description": "Page size; values below 1 fall back to 20.", + "default": 20 }, "scope": { - "description": "Restrict results to `all` (default), `account`-only (team_id=0), or `team`-only (excludes account-scoped rows). Overrides `include_account` when set.", + "type": "string", + "description": "Which skills to return; overrides `include_account` when set:\n- `all` (default): account-scope skills (unless `include_account` is false) plus the caller's team skills\n- `account`: account-scope skills only (`team_id` = 0)\n- `team`: the caller's team skills only", "enum": [ "all", "account", "team" - ], - "type": "string" + ] + }, + "query": { + "type": "string", + "description": "Free-text search across skill name, description, English description, skill ID, marketplace source template name, and author.", + "maxLength": 128 }, "team_ids": { - "description": "Filter to these team IDs; empty = the caller's visible set.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Limit team-scope results to these team IDs; IDs of teams the caller does not belong to are dropped. Empty = all of the caller's teams." + }, + "include_account": { + "type": [ + "boolean", + "null" + ], + "description": "Include account-scoped (team_id=0) rows. Defaults to true. Ignored when `scope` is `account` or `team`." } - }, - "type": "object" + } }, "SkillListResponse": { "description": "Paginated skill list.", @@ -24778,31 +25709,31 @@ "type": "object" }, "SkillUploadRequest": { + "type": "object", "description": "Multipart form for uploading a skill archive.", "properties": { "file": { - "description": "Skill archive (.skill / .zip / .tar.gz / .tgz). Max 100MB; oversized files are rejected before the body is read.", + "type": "string", "format": "binary", - "type": "string" + "description": "Skill archive (`.skill`, `.zip`, `.tar.gz`, or `.tgz`), up to 100 MB, containing `SKILL.md` at its root or inside a single top-level folder." + }, + "team_id": { + "type": "integer", + "description": "Scope for the created or overwritten-by-name skill: 0 = account scope (default), >0 = that team. Ignored when `replace=true` and `skill_id` are both set.", + "format": "int64" }, "replace": { - "description": "When true, overwrite an existing skill instead of failing on a name collision — matched by `skill_id` if provided, otherwise by skill name.", - "type": "boolean" + "type": "boolean", + "description": "When true, overwrite an existing skill instead of failing on a name clash: the skill given by `skill_id`, or else the same-named skill in `team_id`. Accepts `true`, `1`, `yes`, `on` (case-insensitive); anything else is false." }, "skill_id": { - "description": "Existing skill ID to target when replacing a specific skill (requires `replace=true`).", - "type": "string" - }, - "team_id": { - "description": "Team scope for the created/upserted skill: 0 = account-wide. Ignored when replacing a specific skill via `skill_id`.", - "format": "int64", - "type": "integer" + "type": "string", + "description": "ID of the skill to overwrite, from `POST /safari/skill/list`. Used only together with `replace=true`; ignored otherwise." } }, "required": [ "file" - ], - "type": "object" + ] }, "SnoozeIncidentRequest": { "description": "Parameters for snoozing notifications on one or more incidents.", @@ -24875,11 +25806,6 @@ "type": "string" } }, - "required": [ - "uuid", - "name", - "is_system" - ], "type": "object" }, "SourcemapCodeSnippet": { @@ -24951,7 +25877,7 @@ "type": "string" }, "key": { - "description": "Storage key uniquely identifying this sourcemap file.", + "description": "Record identifier: a 32-character MD5 hex digest derived from the uploaded file's identity (storage path, or service/version/build identifiers for native symbols).", "type": "string" }, "metadata": { @@ -25012,7 +25938,7 @@ "type": "boolean" }, "build_id": { - "description": "Android only. Filter by Gradle plugin build identifier. Max 200 characters.", + "description": "Substring filter on the build ID (Android Gradle plugin build identifier, or the build ID of native symbols). Max 200 characters.", "maxLength": 200, "type": "string" }, @@ -25084,7 +26010,7 @@ "type": "string" }, "uuid": { - "description": "iOS only. Filter by dSYM bundle UUID. Max 200 characters.", + "description": "iOS only. Substring filter on the dSYM UUID; upper-cased and stripped of hyphens before matching. Max 200 characters.", "maxLength": 200, "type": "string" }, @@ -25126,7 +26052,7 @@ "description": "Stack trace enrichment request.", "properties": { "arch": { - "description": "Android NDK architecture such as `arm`, `arm64`, `x86`, or `x64`.", + "description": "Native CPU architecture, such as `arm`, `arm64`, `x86` or `x64`. With `type: android` and an empty `source_type`, sending `arch` selects NDK native symbolication.", "type": "string" }, "binary_images": { @@ -25163,7 +26089,7 @@ "type": "string" }, "source_type": { - "description": "Android error source type. Use `ndk` with `arch` for native symbolication.", + "description": "The error's `error.source_type` as reported by the SDK. It reroutes symbolication: for `android`, a value containing `ndk` selects NDK native symbols; for `flutter` and `react-native`, `ios` selects dSYM and `android`/`ndk` selects Android symbols; for `electron`, `macos`, `windows` or `linux` selects Breakpad symbols. Ignored for other types.", "type": "string" }, "stack": { @@ -25281,68 +26207,42 @@ "type": "object" }, "StatusPageChangeItem": { + "type": "object", "description": "A status page event (incident or maintenance).", + "required": [ + "change_id", + "type", + "title" + ], "properties": { - "affected_components": { - "description": "Components currently affected by this event, with their resulting status. Omitted when no components are affected.", - "items": { - "$ref": "#/components/schemas/AffectedStatusPageComponentItem" - }, - "type": "array" - }, - "auto_update_by_schedule": { - "description": "Maintenance only: whether the status advances automatically based on the scheduled window. Omitted when false.", - "type": "boolean" - }, "change_id": { - "description": "Event ID.", - "format": "int64", - "type": "integer" - }, - "close_at_seconds": { - "description": "Event close time in Unix seconds. For maintenances this is the scheduled end time; for closed events, the time the event reached its terminal status (`resolved`/`completed`). Omitted when not set.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "description": { - "description": "Event description (Markdown). Omitted when empty.", - "type": "string" - }, - "is_retrospective": { - "description": "Whether this event is a retrospective (historical) one. Omitted when false.", - "type": "boolean" - }, - "linked_change_ids": { - "description": "Linked event IDs (related incidents, deployments, etc.). Omitted when empty.", - "items": { - "type": "string" - }, - "type": "array" - }, - "notify_subscribers": { - "description": "Whether subscribers were notified about this event. Omitted when false.", - "type": "boolean" + "description": "Event ID, returned by `POST /status-page/change/create`; pass it as `change_id` to the other event endpoints." }, "page_id": { - "description": "Parent status page ID. Omitted when 0 (never for stored events).", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Parent status page ID. Omitted when 0 (never for stored events)." }, - "responder_ids": { - "description": "Member IDs responsible for this event. Omitted when no responders are assigned.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "type": { + "type": "string", + "enum": [ + "incident", + "maintenance" + ], + "description": "Change type. `incident` is an unplanned outage; `maintenance` is a planned maintenance. The type determines which status values are valid." }, - "start_at_seconds": { - "description": "Event start time in Unix seconds, derived from the first timeline update. Omitted when 0.", - "format": "int64", - "type": "integer" + "title": { + "type": "string", + "description": "Event title." + }, + "description": { + "type": "string", + "description": "Event description (Markdown). Omitted when empty." }, "status": { - "description": "Current event status. Incident statuses: `investigating`/`identified`/`monitoring`/`resolved`. Maintenance statuses: `scheduled`/`ongoing`/`completed`. Omitted when empty (never for stored events).", + "type": "string", "enum": [ "investigating", "identified", @@ -25352,34 +26252,60 @@ "ongoing", "completed" ], - "type": "string" + "description": "Current event status. Incident statuses: `investigating`/`identified`/`monitoring`/`resolved`. Maintenance statuses: `scheduled`/`ongoing`/`completed`. Omitted when empty (never for stored events)." }, - "title": { - "description": "Event title.", - "type": "string" + "affected_components": { + "type": "array", + "items": { + "$ref": "#/components/schemas/AffectedStatusPageComponentItem" + }, + "description": "Components currently affected by this event, with their resulting status. Omitted when no components are affected." }, - "type": { - "description": "Change type. `incident` is an unplanned outage; `maintenance` is a planned maintenance. The type determines which status values are valid.", - "enum": [ - "incident", - "maintenance" - ], - "type": "string" + "responder_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Member IDs responsible for this event. Omitted when no responders are assigned." + }, + "linked_change_ids": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Linked event IDs (related incidents, deployments, etc.). Omitted when empty." + }, + "start_at_seconds": { + "type": "integer", + "format": "int64", + "description": "Event start time in Unix seconds. For incidents it is the time of the first timeline entry; for maintenances it is the scheduled start given at creation, or the first entry's time when none was given. Omitted when 0." + }, + "close_at_seconds": { + "type": "integer", + "format": "int64", + "description": "Event close time in Unix seconds. For maintenances this is the scheduled end time; for closed events, the time the event reached its terminal status (`resolved`/`completed`). Omitted when not set." + }, + "is_retrospective": { + "type": "boolean", + "description": "Whether this event is a retrospective (historical) one. Omitted when false." }, "updates": { - "description": "Timeline updates attached to this event, ordered by time. Omitted when the event has no timeline updates.", + "type": "array", "items": { "$ref": "#/components/schemas/StatusPageChangeUpdateItem" }, - "type": "array" + "description": "Timeline updates attached to this event, ordered by time. Omitted when the event has no timeline updates." + }, + "notify_subscribers": { + "type": "boolean", + "description": "Whether subscribers were notified about this event. Omitted when false." + }, + "auto_update_by_schedule": { + "type": "boolean", + "description": "Maintenance only: whether the status advances automatically based on the scheduled window. Omitted when false." } - }, - "required": [ - "change_id", - "type", - "title" - ], - "type": "object" + } }, "StatusPageChangeListResponse": { "description": "List of status page events.", @@ -25411,26 +26337,24 @@ "type": "object" }, "StatusPageChangeUpdateItem": { + "type": "object", "description": "A single timeline update on a status page event.", + "required": [ + "update_id", + "at_seconds" + ], "properties": { + "update_id": { + "type": "string", + "description": "Timeline entry ID (a ULID string), assigned by the server; pass it as `update_id` to edit or delete the entry." + }, "at_seconds": { - "description": "Update timestamp in Unix seconds.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "component_changes": { - "description": "Component status transitions applied by this update. Omitted when the update changes no component statuses.", - "items": { - "$ref": "#/components/schemas/StatusPageComponentChangeItem" - }, - "type": "array" - }, - "description": { - "description": "Update description (Markdown). Omitted when empty.", - "type": "string" + "description": "Update timestamp in Unix seconds." }, "status": { - "description": "Change status after this update. Omitted when the update does not change the overall status. The first four values apply to incident-type changes, the last three to maintenance-type changes.\n| Value | Meaning |\n|---|---|\n| `investigating` | Investigating (incident). |\n| `identified` | Root cause identified (incident). |\n| `monitoring` | Fix deployed, monitoring (incident). |\n| `resolved` | Resolved (incident). |\n| `scheduled` | Scheduled (maintenance). |\n| `ongoing` | In progress (maintenance). |\n| `completed` | Completed (maintenance). |", + "type": "string", "enum": [ "investigating", "identified", @@ -25440,32 +26364,39 @@ "ongoing", "completed" ], - "type": "string" + "description": "Change status after this update. Omitted when the update does not change the overall status. The first four values apply to incident-type changes, the last three to maintenance-type changes.\n| Value | Meaning |\n|---|---|\n| `investigating` | Investigating (incident). |\n| `identified` | Root cause identified (incident). |\n| `monitoring` | Fix deployed, monitoring (incident). |\n| `resolved` | Resolved (incident). |\n| `scheduled` | Scheduled (maintenance). |\n| `ongoing` | In progress (maintenance). |\n| `completed` | Completed (maintenance). |" }, - "update_id": { - "description": "Update ID.", - "type": "string" + "description": { + "type": "string", + "description": "Update description (Markdown). Omitted when empty." + }, + "component_changes": { + "type": "array", + "items": { + "$ref": "#/components/schemas/StatusPageComponentChangeItem" + }, + "description": "Component status transitions applied by this update. Omitted when the update changes no component statuses." } - }, - "required": [ - "update_id", - "at_seconds" - ], - "type": "object" + } }, "StatusPageComponentChangeItem": { + "type": "object", "description": "Component status transition applied in a timeline update.", + "required": [ + "component_id", + "status" + ], "properties": { "component_id": { - "description": "Component ID.", - "type": "string" + "type": "string", + "description": "ID of the component whose status changes; matches `component_id` in `GET /status-page/info`." }, "component_name": { - "description": "Component display name. Populated by the backend on read; ignored on write. Omitted when empty.", - "type": "string" + "type": "string", + "description": "Component display name. Populated by the backend on read; ignored on write. Omitted when empty." }, "status": { - "description": "New component status. Incidents support `operational`/`degraded`/`partial_outage`/`full_outage`; maintenances support `operational`/`under_maintenance`.", + "type": "string", "enum": [ "operational", "degraded", @@ -25473,14 +26404,9 @@ "full_outage", "under_maintenance" ], - "type": "string" + "description": "New component status. Incidents support `operational`/`degraded`/`partial_outage`/`full_outage`; maintenances support `operational`/`under_maintenance`." } - }, - "required": [ - "component_id", - "status" - ], - "type": "object" + } }, "StatusPageComponentItem": { "description": "A status page component.", @@ -25526,23 +26452,23 @@ "type": "object" }, "StatusPageDraftCreateResponse": { + "type": "object", "description": "Result of storing a status page draft.", - "properties": { - "created_at": { - "description": "Creation time in Unix epoch seconds.", - "format": "int64", - "type": "integer" - }, - "draft_id": { - "description": "Draft ID matching `draft_[A-Za-z0-9]{22}`; the console review link carries it.", - "type": "string" - } - }, "required": [ "draft_id", "created_at" ], - "type": "object" + "properties": { + "draft_id": { + "type": "string", + "description": "Draft ID matching `draft_[A-Za-z0-9]{22}`; pass it as `draft_id` to `POST /status-page/change/create` or `POST /status-page/change/timeline/create` to publish." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation time in Unix epoch seconds." + } + } }, "StatusPageInfoResponse": { "allOf": [ @@ -25566,108 +26492,123 @@ "type": "object" }, "StatusPageItem": { + "type": "object", "properties": { - "components": { - "description": "Components tracked on the status page.", - "items": { - "$ref": "#/components/schemas/StatusPageComponentItem" - }, - "type": "array" + "page_id": { + "type": "integer", + "description": "Status page ID.", + "format": "int64" }, - "contact_info": { - "description": "Get-in-touch contact, a mailto or website URL. Omitted when not set.", - "type": "string" + "name": { + "type": "string", + "description": "Display name of the status page." + }, + "url_name": { + "type": "string", + "description": "URL-safe slug of the page, unique among the account's pages of the same type." + }, + "type": { + "type": "string", + "description": "Page visibility type. `public` pages are accessible to anyone and use email subscriptions; `internal` pages are restricted to account members and use IM subscriptions.", + "enum": [ + "public", + "internal" + ] }, "custom_domain": { - "description": "Custom domain pointing to the status page. Omitted when not set.", - "type": "string" + "type": "string", + "description": "Custom domain pointing to the status page. Omitted when not set." }, - "custom_links": { - "description": "Custom navigation links shown on the status page. Omitted when not set.", - "items": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - "type": "array" + "logo": { + "type": "string", + "description": "Logo image of the status page. Omitted when not set." }, "dark_logo": { - "description": "Dark-mode logo image of the status page. Omitted when not set.", - "type": "string" + "type": "string", + "description": "Dark-mode logo image of the status page. Omitted when not set." + }, + "logo_url": { + "type": "string", + "description": "URL opened when the logo is clicked. Omitted when not set." + }, + "favicon": { + "type": "string", + "description": "Favicon of the status page. Omitted when not set." + }, + "page_header": { + "type": "string", + "description": "Header content of the status page. Omitted when not set." + }, + "page_footer": { + "type": "string", + "description": "Footer content of the status page. Omitted when not set." }, "date_view": { + "type": "string", "description": "How the timeline displays change dates. `calendar` uses a calendar view; `list` uses a list view. Omitted when not set.", "enum": [ "calendar", "list" - ], - "type": "string" + ] }, "display_uptime_mode": { + "type": "string", "description": "How uptime is displayed. `chart_and_percentage` shows both the uptime chart and the percentage figure; `chart` shows only the chart; `none` hides uptime entirely. Omitted when not set.", "enum": [ "chart_and_percentage", "chart", "none" - ], - "type": "string" - }, - "favicon": { - "description": "Favicon of the status page. Omitted when not set.", - "type": "string" - }, - "logo": { - "description": "Logo image of the status page. Omitted when not set.", - "type": "string" - }, - "logo_url": { - "description": "URL opened when the logo is clicked. Omitted when not set.", - "type": "string" - }, - "name": { - "description": "Display name of the status page.", - "type": "string" + ] }, - "page_footer": { - "description": "Footer content of the status page. Omitted when not set.", - "type": "string" + "custom_links": { + "type": "array", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Link text shown on the page." + }, + "value": { + "type": "string", + "description": "URL the link text points to, such as `https://www.example.com`." + } + }, + "additionalProperties": { + "type": "string" + } + }, + "description": "Custom navigation links shown on the status page. Omitted when not set." }, - "page_header": { - "description": "Header content of the status page. Omitted when not set.", - "type": "string" + "contact_info": { + "type": "string", + "description": "Get-in-touch contact, a mailto or website URL. Omitted when not set." }, - "page_id": { - "description": "Status page ID.", - "format": "int64", - "type": "integer" + "components": { + "type": "array", + "items": { + "$ref": "#/components/schemas/StatusPageComponentItem" + }, + "description": "Components tracked on the status page." }, "sections": { - "description": "Sections grouping the components.", + "type": "array", "items": { "$ref": "#/components/schemas/StatusPageSectionItem" }, - "type": "array" + "description": "Sections grouping the components." }, "subscription": { "$ref": "#/components/schemas/StatusPageSubscriptionItem", "description": "Subscription channel toggles." }, "template_preference": { - "description": "Preferred event template type: `pre_defined` or `message`. Omitted when never set.", - "type": "string" - }, - "type": { - "description": "Page visibility type. `public` pages are accessible to anyone and use email subscriptions; `internal` pages are restricted to account members and use IM subscriptions.", + "type": "string", + "description": "Event template mode used when publishing events in the console: `message` (status descriptions: per-status texts) or `pre_defined` (full status updates: complete examples with title, status, and description). Omitted when never set; the console then uses `message`.", "enum": [ - "public", - "internal" - ], - "type": "string" - }, - "url_name": { - "description": "URL-safe slug, unique per account.", - "type": "string" + "pre_defined", + "message" + ] } }, "required": [ @@ -25678,8 +26619,7 @@ "components", "sections", "subscription" - ], - "type": "object" + ] }, "StatusPageMessageTemplate": { "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.", @@ -25711,136 +26651,136 @@ "type": "object" }, "StatusPageMigrationJob": { + "type": "object", "description": "A migration job's current state and progress.", + "required": [ + "job_id", + "account_id", + "source_page_id", + "target_page_id", + "phase", + "status", + "progress", + "created_at", + "updated_at" + ], "properties": { - "account_id": { - "description": "Owner account ID.", - "format": "int64", - "type": "integer" + "job_id": { + "type": "string", + "description": "Migration job ID." }, - "created_at": { - "description": "Job creation time as a Unix timestamp in seconds.", + "account_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Owner account ID." }, - "error": { - "description": "Terminal error message when `status` is `failed`. Omitted when the job has not failed.", - "type": "string" + "source_page_id": { + "type": "string", + "description": "Atlassian Statuspage source page ID." }, - "job_id": { - "description": "Migration job ID.", - "type": "string" + "target_page_id": { + "type": "integer", + "format": "int64", + "description": "Flashduty target status page ID. For a structure migration it is 0 until the page is created or reused; for a subscriber migration it is the `target_page_id` from the request." }, "phase": { - "description": "Current migration phase. `structure` imports the page structure (sections and components); `history` imports historical incidents, maintenances, and incident templates; `subscribers` imports email subscribers.", + "type": "string", "enum": [ "structure", "history", "subscribers" ], - "type": "string" - }, - "progress": { - "$ref": "#/components/schemas/StatusPageMigrationProgress", - "description": "Per-entity progress counters." - }, - "source_page_id": { - "description": "Atlassian Statuspage source page ID.", - "type": "string" + "description": "Current migration phase. `structure` imports the page structure (sections and components); `history` imports historical incidents, maintenances, and incident templates; `subscribers` imports email subscribers." }, "status": { - "description": "Current job status.\n| Value | Meaning |\n|---|---|\n| `running` | In progress. |\n| `completed` | Finished successfully. |\n| `failed` | Failed; the `error` field holds the reason. |\n| `cancelled` | Canceled by request. |", + "type": "string", "enum": [ "running", "completed", "failed", "cancelled" ], - "type": "string" + "description": "Current job status.\n| Value | Meaning |\n|---|---|\n| `running` | In progress. |\n| `completed` | Finished successfully. |\n| `failed` | Failed; the `error` field holds the reason. |\n| `cancelled` | Canceled by request. |" }, - "target_page_id": { - "description": "Flashduty target status page ID. Set once the job produces one, or supplied up front for subscriber migration.", + "progress": { + "$ref": "#/components/schemas/StatusPageMigrationProgress", + "description": "Per-entity progress counters." + }, + "error": { + "type": "string", + "description": "Terminal error message when `status` is `failed`. Omitted when the job has not failed." + }, + "created_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Job creation time as a Unix timestamp in seconds." }, "updated_at": { - "description": "Last status update time as a Unix timestamp in seconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last status update time as a Unix timestamp in seconds." } - }, - "required": [ - "job_id", - "account_id", - "source_page_id", - "target_page_id", - "phase", - "status", - "progress", - "created_at", - "updated_at" - ], - "type": "object" + } }, "StatusPageMigrationProgress": { + "type": "object", "description": "Progress counters for a migration job.", + "required": [ + "total_steps", + "completed_steps", + "components_imported", + "sections_imported", + "incidents_imported", + "maintenances_imported", + "subscribers_imported", + "templates_imported", + "subscribers_skipped" + ], "properties": { + "total_steps": { + "type": "integer", + "description": "Total steps of the job: 5 for a structure migration (page, sections, components, incidents and maintenances, templates) and 1 for a subscriber migration." + }, "completed_steps": { - "description": "Steps completed so far.", - "type": "integer" + "type": "integer", + "description": "Steps completed so far." }, "components_imported": { - "description": "Number of components imported from the source status page.", - "type": "integer" + "type": "integer", + "description": "Number of components imported from the source status page." + }, + "sections_imported": { + "type": "integer", + "description": "Number of sections (Atlassian component groups) imported from the source status page." }, "incidents_imported": { - "description": "Number of historical incidents imported.", - "type": "integer" + "type": "integer", + "description": "Number of historical incidents imported." }, "maintenances_imported": { - "description": "Number of scheduled maintenances imported.", - "type": "integer" - }, - "sections_imported": { - "description": "Number of sections (Atlassian component groups) imported from the source status page.", - "type": "integer" + "type": "integer", + "description": "Number of scheduled maintenances imported." }, "subscribers_imported": { - "description": "Number of email subscribers successfully imported.", - "type": "integer" - }, - "subscribers_skipped": { - "description": "Number of subscribers skipped (e.g. because they would create duplicates).", - "type": "integer" + "type": "integer", + "description": "Number of email subscribers successfully imported." }, "templates_imported": { - "description": "Number of incident templates successfully imported; templates that fail are skipped and recorded in `warnings`.", - "type": "integer" + "type": "integer", + "description": "Number of incident templates successfully imported; templates that fail are skipped and recorded in `warnings`." }, - "total_steps": { - "description": "Total steps this job will perform.", - "type": "integer" + "subscribers_skipped": { + "type": "integer", + "description": "Number of source subscribers skipped because they are not email subscribers, have no email address, or are quarantined. Recipients already subscribed on the target page are not counted here." }, "warnings": { - "description": "Non-fatal warnings recorded during the job. Omitted when empty.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Non-fatal warnings recorded during the job. Omitted when empty." } - }, - "required": [ - "total_steps", - "completed_steps", - "components_imported", - "sections_imported", - "incidents_imported", - "maintenances_imported", - "subscribers_imported", - "templates_imported", - "subscribers_skipped" - ], - "type": "object" + } }, "StatusPageMigrationStartResponse": { "description": "Result of starting a migration job.", @@ -25856,14 +26796,27 @@ "type": "object" }, "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": { - "description": { - "description": "Template body text (Markdown).", - "type": "string" + "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": { - "description": "Change status the template maps to. Incidents use `investigating`/`identified`/`monitoring`/`resolved`; maintenances use `scheduled`/`ongoing`/`completed`.", + "type": "string", "enum": [ "investigating", "identified", @@ -25873,26 +26826,13 @@ "ongoing", "completed" ], - "type": "string" - }, - "template_id": { - "description": "Template ID. Omit to create a new template; supply to update an existing one.", - "type": "string" - }, - "title": { - "description": "Template title.", - "type": "string" + "description": "Change status the template maps to. Incidents use `investigating`/`identified`/`monitoring`/`resolved`; maintenances use `scheduled`/`ongoing`/`completed`." }, - "type": { - "description": "Change type the template applies to: `incident` unplanned incident, `maintenance` planned maintenance.", - "enum": [ - "incident", - "maintenance" - ], - "type": "string" + "description": { + "type": "string", + "description": "Template body text (Markdown)." } - }, - "type": "object" + } }, "StatusPageSectionItem": { "properties": { @@ -25980,70 +26920,69 @@ "type": "object" }, "StringMapPatch": { - "description": "Partial update for a map field: keys in `set` are inserted or replaced, keys in `delete` are removed, all other keys are preserved.", + "type": "object", + "description": "Partial update for a map field: keys in `set` are inserted or replaced, keys in `delete` are removed, all other keys are preserved. At least one of `set` / `delete` must be non-empty, keys must not be blank, and a key may not appear in both or twice in `delete`.", "properties": { - "delete": { - "description": "Keys to remove.", - "items": { + "set": { + "type": "object", + "additionalProperties": { "type": "string" }, - "type": "array" + "description": "Keys to insert or replace." }, - "set": { - "additionalProperties": { + "delete": { + "type": "array", + "items": { "type": "string" }, - "description": "Keys to insert or replace.", - "type": "object" + "description": "Keys to remove." } - }, - "type": "object" + } }, "SuccessEnvelope": { + "type": "object", "description": "Success response envelope. On every 2xx response, `request_id` identifies the call (also mirrored in the `Flashcat-Request-Id` header) and `data` holds the endpoint-specific payload. Failure responses use a different shape — see `ErrorResponse`.", "properties": { - "data": { - "description": "Endpoint-specific payload. See each operation's 200 response schema." - }, "request_id": { + "type": "string", "description": "Unique ID for this request. Mirrored in the Flashcat-Request-Id response header. Include it when reporting issues.", - "example": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", - "type": "string" + "example": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" + }, + "data": { + "description": "Operation-specific payload, documented in each operation's 200 response. Operations without a payload return `{}` or omit `data` entirely." } }, "required": [ - "request_id", - "data" - ], - "type": "object" + "request_id" + ] }, "TeamBriefItem": { + "type": "object", "description": "Brief team info for batch responses.", "properties": { - "person_ids": { - "description": "Array of person IDs belonging to the team; empty array (never null) when the team has no members.", - "items": { - "format": "uint64", - "type": "integer" - }, - "type": "array" - }, "team_id": { - "description": "Team ID.", + "type": "integer", "format": "uint64", - "type": "integer" + "description": "Team ID, one of the requested `team_ids`." }, "team_name": { - "description": "Team name.", - "type": "string" - } + "type": "string", + "description": "Team name. Deleted teams are included, so this can be the name of a team that no longer appears in `POST /team/list`." + }, + "person_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "uint64" + }, + "description": "Array of person IDs belonging to the team; empty array (never null) when the team has no members." + } }, "required": [ "team_id", "team_name", "person_ids" - ], - "type": "object" + ] }, "TeamDeleteRequest": { "anyOf": [ @@ -26135,107 +27074,110 @@ "type": "object" }, "TeamInfosResponse": { + "type": "object", "description": "Batch team info result.", + "required": [ + "items" + ], "properties": { "items": { - "description": "Array of brief team info for the matched `team_ids`; may be null when no ID matches.", + "type": [ + "array", + "null" + ], "items": { "$ref": "#/components/schemas/TeamBriefItem" }, - "type": "array" + "description": "Brief info for the matched teams, including deleted ones; `null` when no ID matches." } - }, - "required": [ - "items" - ], - "type": "object" + } }, "TeamItem": { + "type": "object", "description": "A team and its membership.", + "required": [ + "account_id", + "team_id", + "team_name", + "description", + "status", + "updated_by_name", + "updated_by", + "creator_id", + "creator_name", + "created_at", + "updated_at", + "person_ids", + "ref_id" + ], "properties": { "account_id": { - "description": "Owning account ID.", + "type": "integer", "format": "uint64", - "type": "integer" - }, - "created_at": { - "description": "Unix epoch seconds the team was created.", - "format": "int64", - "type": "integer" + "description": "Owning account ID." }, - "creator_id": { - "description": "Member ID of the creator.", + "team_id": { + "type": "integer", "format": "uint64", - "type": "integer" + "description": "Unique team ID." }, - "creator_name": { - "description": "Display name of the creator. Not populated by current endpoints — always an empty string; resolve `creator_id` via `POST /person/infos`.", - "type": "string" + "team_name": { + "type": "string", + "description": "Team display name. 1–39 characters, unique per account." }, "description": { - "description": "Free-form description.", - "type": "string" - }, - "person_ids": { - "description": "Member IDs of team members.", - "items": { - "format": "uint64", - "type": "integer" - }, - "type": "array" - }, - "ref_id": { - "description": "External reference ID for third-party HR system integration.", - "type": "string" + "type": "string", + "description": "Free-form description." }, "status": { - "description": "Team status. `enabled` — active; `deleted` — soft-deleted (only possible when fetching a deleted team by `team_id`; list and name/ref_id lookups exclude deleted teams).", + "type": "string", "enum": [ "enabled", "deleted" ], - "type": "string" + "description": "Team status. `enabled` — active; `deleted` — soft-deleted (only possible when fetching a deleted team by `team_id`; list and name/ref_id lookups exclude deleted teams)." }, - "team_id": { - "description": "Unique team ID.", + "updated_by_name": { + "type": "string", + "description": "Name of the last editor: the member's name, or the account name when the account owner made the change; empty string when unknown." + }, + "updated_by": { + "type": "integer", "format": "uint64", - "type": "integer" + "description": "Member ID of the last editor." }, - "team_name": { - "description": "Team display name. 1–39 characters, unique per account.", - "type": "string" + "creator_id": { + "type": "integer", + "format": "uint64", + "description": "Member ID of the creator." + }, + "creator_name": { + "type": "string", + "description": "Display name of the creator. Not populated by current endpoints — always an empty string; resolve `creator_id` via `POST /person/infos`." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Unix epoch seconds the team was created." }, "updated_at": { - "description": "Unix epoch seconds the team was last updated.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix epoch seconds the team was last updated." }, - "updated_by": { - "description": "Member ID of the last editor.", - "format": "uint64", - "type": "integer" + "person_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "uint64" + }, + "description": "Person IDs of the team's members (member IDs; the account owner's ID when the owner is in the team). Empty array when the team has no members." }, - "updated_by_name": { - "description": "Display name of the last editor.", - "type": "string" + "ref_id": { + "type": "string", + "description": "External reference ID for third-party HR system integration." } - }, - "required": [ - "account_id", - "team_id", - "team_name", - "description", - "status", - "updated_by_name", - "updated_by", - "creator_id", - "creator_name", - "created_at", - "updated_at", - "person_ids", - "ref_id" - ], - "type": "object" + } }, "TeamListRequest": { "description": "Filters for listing teams.", @@ -26279,95 +27221,95 @@ "type": "object" }, "TeamListResponse": { + "type": "object", "description": "Paginated team list.", - "properties": { - "items": { - "description": "Array of teams for the current page, used with `p`, `limit` and `total` for pagination; empty array on an empty page.", - "items": { - "$ref": "#/components/schemas/TeamItem" - }, - "type": "array" - }, - "limit": { - "description": "Page size used.", - "type": "integer" - }, - "p": { - "description": "Current page number.", - "type": "integer" - }, - "total": { - "description": "Total number of teams matching the filter.", - "type": "integer" - } - }, "required": [ "p", "limit", "total", "items" ], - "type": "object" + "properties": { + "p": { + "type": "integer", + "description": "Page number from the request; `0` when `p` was omitted (the first page is returned)." + }, + "limit": { + "type": "integer", + "description": "Page size applied; 20 when `limit` was omitted." + }, + "total": { + "type": "integer", + "description": "Number of non-deleted teams matching the filters, across all pages." + }, + "items": { + "type": "array", + "items": { + "$ref": "#/components/schemas/TeamItem" + }, + "description": "Array of teams for the current page, used with `p`, `limit` and `total` for pagination; empty array on an empty page." + } + } }, "TeamUpsertRequest": { + "type": "object", + "required": [ + "team_name" + ], "description": "Parameters for creating or updating a team.", "properties": { - "countryCode": { - "description": "Default country code applied to any `phones` entries that are not in E.164 format.", - "type": "string" + "team_id": { + "type": "integer", + "format": "uint64", + "description": "ID of the team to update. Omit or set to 0 to create a new team; a non-zero ID must belong to an existing team of the account." + }, + "team_name": { + "type": "string", + "minLength": 1, + "maxLength": 39, + "description": "Team display name. 1–39 characters." }, "description": { - "description": "Free-form description.", + "type": "string", "maxLength": 500, - "type": "string" + "description": "Free-form description, up to 500 characters. On update, omitting it clears the stored description." }, - "emails": { - "description": "Add existing members to the team by email. Addresses that don't match an existing member are silently ignored — no invitation is sent.", + "person_ids": { + "type": "array", "items": { - "format": "email", - "type": "string" + "type": "integer", + "format": "uint64" }, - "type": "array" + "description": "Person IDs to place in the team (member IDs, or the account ID for the account owner). Together with `emails` and `phones` they replace the entire member list; IDs that are not members of the account are ignored." }, - "person_ids": { - "description": "Member IDs to set as team members. Replaces the existing member list.", + "emails": { + "type": "array", "items": { - "format": "uint64", - "type": "integer" + "type": "string", + "format": "email" }, - "type": "array" + "description": "Emails of existing members to place in the team; merged with `person_ids` and `phones`. Addresses that match no member are ignored and no invitation is sent." }, "phones": { - "description": "Add existing members to the team by phone number. Numbers not in E.164 format are parsed with `countryCode`; an unparseable number fails the whole request with a 400. Numbers that parse but match no existing member are silently ignored.", + "type": "array", "items": { "type": "string" }, - "type": "array" + "description": "Phone numbers of existing members to place in the team; merged with `person_ids` and `emails`. Numbers without a `+` prefix are parsed with `countryCode`; an unparseable number fails the whole request with `400`, and numbers that match no member are ignored." + }, + "countryCode": { + "type": "string", + "description": "Region hint for `phones` entries without a `+` prefix: an ISO 3166-1 alpha-2 code such as `CN` (the default when omitted) or a digit calling code such as `86`." }, "ref_id": { - "description": "External reference ID for HR system integration.", - "type": "string" + "type": "string", + "description": "External reference ID (for example a department ID in an HR system), usable as a lookup key in `POST /team/info` and `POST /team/delete`. On update, omitting it clears the stored value." }, "reset_if_name_exist": { - "description": "When true and `team_id` is 0, an existing team with the same `team_name` is updated in place instead of returning a name-conflict error.", - "type": "boolean" - }, - "team_id": { - "description": "Team ID. Omit or set to 0 to create a new team.", - "format": "uint64", - "type": "integer" - }, - "team_name": { - "description": "Team display name. 1–39 characters.", - "maxLength": 39, - "minLength": 1, - "type": "string" + "type": "boolean", + "description": "When true and `team_id` is 0, an existing team with the same `team_name` is updated in place instead of returning a name-conflict error." } - }, - "required": [ - "team_name" - ], - "type": "object" + } }, "TeamUpsertResponse": { "description": "Team create/update result.", @@ -26389,50 +27331,111 @@ "type": "object" }, "TemplateCreateRequest": { + "type": "object", "description": "Create a new notification template.", + "required": [ + "template_name" + ], "properties": { + "team_id": { + "type": "integer", + "format": "int64", + "description": "Owning team ID from `POST /team/list`; `0` (default) means account-wide. A non-zero ID must be an existing team.", + "default": 0 + }, + "template_name": { + "type": "string", + "minLength": 1, + "maxLength": 39, + "description": "Template name, 1–39 characters, unique among the account's non-deleted templates and different from the built-in preset template's name in every supported language.", + "example": "Prod incident default" + }, "description": { - "description": "Free-form description. Up to 500 characters.", + "type": "string", "maxLength": 500, - "type": "string" + "description": "Free-form description. Up to 500 characters." + }, + "email": { + "type": "string", + "description": "Email body template source (Go `html/template` syntax)." + }, + "sms": { + "type": "string", + "description": "SMS template source (Go `text/template` syntax)." + }, + "voice": { + "type": "string", + "description": "Voice call script template source." }, "dingtalk": { - "description": "DingTalk robot message template source.", - "type": "string" + "type": "string", + "description": "DingTalk robot message template source." }, - "dingtalk_app": { - "description": "DingTalk app message template source.", - "type": "string" + "wecom": { + "type": "string", + "description": "WeCom robot message template source." }, - "dingtalk_app_war_room_enabled": { + "wecom_markdown_v2_enabled": { "type": "boolean", - "description": "Show the Create War Room button on DingTalk app cards." - }, - "email": { - "description": "Email body template source (Go `html/template` syntax).", - "type": "string" + "description": "Send WeCom robot notifications as `markdown_v2` messages instead of plain markdown. While enabled, the rendered `wecom` content must be at most 4,096 bytes." }, "feishu": { - "description": "Feishu robot message template source.", - "type": "string" + "type": "string", + "description": "Feishu robot message template source." }, "feishu_app": { - "description": "Feishu app message template source.", - "type": "string" + "type": "string", + "description": "Feishu app message template source." + }, + "feishu_app_card_v2_table_enabled": { + "type": "boolean", + "default": false, + "description": "Render Markdown tables in the `feishu_app` content as native Feishu card tables." }, "feishu_app_card_v2_preserve_blank_lines": { "type": "boolean", "description": "Keep blank lines in the body of Feishu app card v2 messages." }, - "feishu_app_card_v2_table_enabled": { - "default": false, - "description": "Render alert labels as a table in Feishu app cards.", - "type": "boolean" - }, "feishu_app_war_room_enabled": { "type": "boolean", "description": "Show the Create War Room button on Feishu app cards." }, + "dingtalk_app_war_room_enabled": { + "type": "boolean", + "description": "Show the Create War Room button on DingTalk app cards." + }, + "slack_app_war_room_enabled": { + "type": "boolean", + "description": "Show the Create War Room button on Slack app cards." + }, + "dingtalk_app": { + "type": "string", + "description": "DingTalk app message template source." + }, + "wecom_app": { + "type": "string", + "description": "WeCom app message template source." + }, + "slack_app": { + "type": "string", + "description": "Slack app message template source." + }, + "teams_app": { + "type": "string", + "description": "Microsoft Teams app message template source." + }, + "telegram": { + "type": "string", + "description": "Telegram bot message template source." + }, + "slack": { + "type": "string", + "description": "Slack robot message template source." + }, + "zoom": { + "type": "string", + "description": "Zoom bot message template source." + }, "incident_card_closed_action_apps": { "type": "array", "items": { @@ -26449,70 +27452,9 @@ }, "incident_card_hidden_fields": { "$ref": "#/components/schemas/IncidentCardHiddenFields", - "description": "Incident card fields hidden per IM app type." - }, - "slack": { - "description": "Slack robot message template source.", - "type": "string" - }, - "slack_app": { - "description": "Slack app message template source.", - "type": "string" - }, - "slack_app_war_room_enabled": { - "type": "boolean", - "description": "Show the Create War Room button on Slack app cards." - }, - "sms": { - "description": "SMS template source (Go `text/template` syntax).", - "type": "string" - }, - "team_id": { - "default": 0, - "description": "Team scope. 0 for account-wide.", - "format": "int64", - "type": "integer" - }, - "teams_app": { - "description": "Microsoft Teams app message template source.", - "type": "string" - }, - "telegram": { - "description": "Telegram bot message template source.", - "type": "string" - }, - "template_name": { - "description": "Template name, unique per account. 1–39 characters.", - "example": "Prod incident default", - "maxLength": 39, - "minLength": 1, - "type": "string" - }, - "voice": { - "description": "Voice call script template source.", - "type": "string" - }, - "wecom": { - "description": "WeCom robot message template source.", - "type": "string" - }, - "wecom_app": { - "description": "WeCom app message template source.", - "type": "string" - }, - "wecom_markdown_v2_enabled": { - "type": "boolean", - "description": "Send WeCom robot notifications as `markdown_v2` messages instead of plain markdown." - }, - "zoom": { - "description": "Zoom bot message template source.", - "type": "string" + "description": "Incident card fields to hide per IM app type." } - }, - "required": [ - "template_name" - ], - "type": "object" + } }, "TemplateCreateResponse": { "description": "Create template response.", @@ -26551,70 +27493,152 @@ "type": "object" }, "TemplateItem": { + "type": "object", "description": "A notification template. Each channel field holds the template source string for that delivery channel; an empty string means 'no custom template for that channel'.", + "required": [ + "account_id", + "team_id", + "template_id", + "template_name", + "description", + "email", + "sms", + "voice", + "dingtalk", + "wecom", + "feishu", + "feishu_app", + "feishu_app_card_v2_table_enabled", + "wecom_markdown_v2_enabled", + "feishu_app_card_v2_preserve_blank_lines", + "feishu_app_war_room_enabled", + "dingtalk_app_war_room_enabled", + "slack_app_war_room_enabled", + "dingtalk_app", + "wecom_app", + "slack_app", + "teams_app", + "telegram", + "slack", + "zoom", + "status", + "creator_id", + "updated_by", + "created_at", + "updated_at", + "incident_card_closed_action_apps", + "incident_card_hidden_fields" + ], "properties": { "account_id": { - "description": "ID of the owning account.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the owning account." }, - "created_at": { - "description": "Unix epoch seconds the template was created.", + "team_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the team this template is scoped to, or 0 for account-wide." }, - "creator_id": { - "description": "Member ID of the creator.", - "format": "int64", - "type": "integer" + "template_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Template ID (24-character hex). The built-in preset template always has the ID `6321aad26c12104586a88916`.", + "example": "6605a1b2c3d4e5f6a7b8c9d0" }, - "deleted_at": { - "description": "Unix epoch seconds the template was soft-deleted. Absent (omitempty) when the template is live.", - "format": "int64", - "type": "integer" + "template_name": { + "type": "string", + "description": "Unique template name within the account." }, "description": { - "description": "Free-form description.", - "type": "string" + "type": "string", + "description": "Free-form description (up to 500 characters); empty string when none was given." + }, + "email": { + "type": "string", + "description": "Email body template source (Go `html/template` syntax)." + }, + "sms": { + "type": "string", + "description": "SMS template source (Go `text/template` syntax)." + }, + "voice": { + "type": "string", + "description": "Voice call script template source." }, "dingtalk": { - "description": "DingTalk robot message template source.", - "type": "string" + "type": "string", + "description": "DingTalk robot message template source." }, - "dingtalk_app": { - "description": "DingTalk app message template source.", - "type": "string" + "wecom": { + "type": "string", + "description": "WeCom robot message template source." }, - "dingtalk_app_war_room_enabled": { + "wecom_markdown_v2_enabled": { "type": "boolean", - "description": "Whether DingTalk app cards show the Create War Room button. Hidden for closed incidents and when the incident has no responders." - }, - "email": { - "description": "Email body template source (Go `html/template` syntax).", - "type": "string" + "description": "Whether WeCom robot notifications use the `markdown_v2` message format." }, "feishu": { - "description": "Feishu robot message template source.", - "type": "string" + "type": "string", + "description": "Feishu robot message template source." }, "feishu_app": { - "description": "Feishu app message template source.", - "type": "string" + "type": "string", + "description": "Feishu app message template source." + }, + "feishu_app_card_v2_table_enabled": { + "type": "boolean", + "description": "Whether Markdown tables in the `feishu_app` content are rendered as native Feishu card tables." }, "feishu_app_card_v2_preserve_blank_lines": { "type": "boolean", "description": "Whether Feishu app card v2 messages keep blank lines in the body." }, - "feishu_app_card_v2_table_enabled": { - "description": "Whether alert labels use table rendering in Feishu app cards.", - "type": "boolean" - }, "feishu_app_war_room_enabled": { "type": "boolean", "description": "Whether Feishu app cards show the Create War Room button. Hidden when the incident has no responders." }, + "dingtalk_app_war_room_enabled": { + "type": "boolean", + "description": "Whether DingTalk app cards show the Create War Room button. Hidden for closed incidents and when the incident has no responders." + }, + "slack_app_war_room_enabled": { + "type": "boolean", + "description": "Whether Slack app cards show the Create War Room button. Hidden for closed incidents and when the incident has no responders." + }, + "dingtalk_app": { + "type": "string", + "description": "DingTalk app message template source." + }, + "wecom_app": { + "type": "string", + "description": "WeCom app message template source." + }, + "slack_app": { + "type": "string", + "description": "Slack app message template source." + }, + "teams_app": { + "type": "string", + "description": "Microsoft Teams app message template source." + }, + "telegram": { + "type": "string", + "description": "Telegram bot message template source." + }, + "slack": { + "type": "string", + "description": "Slack robot message template source." + }, + "zoom": { + "type": "string", + "description": "Zoom bot message template source." + }, "incident_card_closed_action_apps": { - "type": "array", + "type": [ + "array", + "null" + ], "items": { "type": "string", "enum": [ @@ -26625,185 +27649,106 @@ "teams_app" ] }, - "description": "IM apps whose closed-incident cards keep the custom action buttons. Supported values: `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, `teams_app`. An empty list hides the buttons on every app." + "description": "IM apps whose cards for closed incidents keep the custom action buttons (open incidents always show them). Values: `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, `teams_app`. Empty or `null` hides the buttons on closed-incident cards in every app." }, "incident_card_hidden_fields": { "$ref": "#/components/schemas/IncidentCardHiddenFields", "description": "Incident card fields hidden per IM app type; an empty object when none are configured." }, - "slack": { - "description": "Slack robot message template source.", - "type": "string" - }, - "slack_app": { - "description": "Slack app message template source.", - "type": "string" - }, - "slack_app_war_room_enabled": { - "type": "boolean", - "description": "Whether Slack app cards show the Create War Room button. Hidden for closed incidents and when the incident has no responders." - }, - "sms": { - "description": "SMS template source (Go `text/template` syntax).", - "type": "string" - }, "status": { - "description": "Template lifecycle status. `enabled` templates can be referenced by escalation policies for notifications; `disabled` templates are no longer used for new notifications; `deleted` templates are never returned by list endpoints.", + "type": "string", + "description": "Template status.\n- `enabled`: usable by escalation rules.\n- `disabled`: not used for new notifications; cannot be set through this API.\n- `deleted`: soft-deleted by `/template/delete`; excluded from `/template/list` but still returned by `/template/info`.", "enum": [ "enabled", "disabled", "deleted" - ], - "type": "string" + ] }, - "team_id": { - "description": "ID of the team this template is scoped to, or 0 for account-wide.", + "creator_id": { + "type": "integer", "format": "int64", - "type": "integer" - }, - "teams_app": { - "description": "Microsoft Teams app message template source.", - "type": "string" - }, - "telegram": { - "description": "Telegram bot message template source.", - "type": "string" - }, - "template_id": { - "description": "Template ID.", - "example": "6605a1b2c3d4e5f6a7b8c9d0", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Member ID of the creator." }, - "template_name": { - "description": "Unique template name within the account.", - "type": "string" + "updated_by": { + "type": "integer", + "format": "int64", + "description": "Member ID of the last editor." }, - "updated_at": { - "description": "Unix epoch seconds the template was last updated.", + "deleted_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix epoch seconds the template was soft-deleted. Absent (omitempty) when the template is live." }, - "updated_by": { - "description": "Member ID of the last editor.", + "created_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix epoch seconds the template was created." }, - "voice": { - "description": "Voice call script template source.", - "type": "string" - }, - "wecom": { - "description": "WeCom robot message template source.", - "type": "string" - }, - "wecom_app": { - "description": "WeCom app message template source.", - "type": "string" - }, - "wecom_markdown_v2_enabled": { - "type": "boolean", - "description": "Whether WeCom robot notifications use the `markdown_v2` message format." - }, - "zoom": { - "description": "Zoom bot message template source.", - "type": "string" + "updated_at": { + "type": "integer", + "format": "int64", + "description": "Unix epoch seconds the template was last updated." } - }, - "required": [ - "account_id", - "team_id", - "template_id", - "template_name", - "description", - "email", - "sms", - "voice", - "dingtalk", - "wecom", - "feishu", - "feishu_app", - "feishu_app_card_v2_table_enabled", - "wecom_markdown_v2_enabled", - "feishu_app_card_v2_preserve_blank_lines", - "feishu_app_war_room_enabled", - "dingtalk_app_war_room_enabled", - "slack_app_war_room_enabled", - "dingtalk_app", - "wecom_app", - "slack_app", - "teams_app", - "telegram", - "slack", - "zoom", - "status", - "creator_id", - "updated_by", - "created_at", - "updated_at", - "incident_card_closed_action_apps", - "incident_card_hidden_fields" - ], - "type": "object" + } }, "TemplateListRequest": { + "type": "object", "description": "Paginated list filters. Defaults: p=1, limit=20. Max limit=100.", "properties": { - "asc": { - "default": false, - "description": "Ascending sort order.", - "type": "boolean" - }, - "creator_id": { - "description": "Filter by creator member ID; obtain member IDs from `POST /member/list`.", - "format": "int64", - "type": [ - "integer", - "null" - ] - }, - "is_my_team": { - "default": false, - "description": "When true, only return templates scoped to teams the caller belongs to.", - "type": "boolean" + "p": { + "type": "integer", + "description": "Page number, starting at 1.", + "minimum": 1, + "default": 1, + "example": 1 }, "limit": { - "default": 20, + "type": "integer", "description": "Page size. Capped at 100.", - "example": 20, - "maximum": 100, "minimum": 1, - "type": "integer" + "maximum": 100, + "default": 20, + "example": 20 }, "orderby": { - "description": "Sort field.", + "type": "string", + "description": "Sort field: `created_at` (default, creation time) or `updated_at` (last update time).", "enum": [ "created_at", "updated_at" - ], - "type": "string" + ] }, - "p": { - "default": 1, - "description": "Page number, starting at 1.", - "example": 1, - "minimum": 1, - "type": "integer" + "asc": { + "type": "boolean", + "description": "Sort ascending when `true`; defaults to newest first.", + "default": false }, - "query": { - "description": "Regex or substring match on template_name.", - "type": "string" + "is_my_team": { + "type": "boolean", + "description": "When `true`, only templates of teams the caller belongs to are returned. If `team_ids` is also sent, only teams in both lists are kept. When they share no team, or the caller belongs to no team, the result is empty.", + "default": false }, "team_ids": { - "description": "Filter by specific team IDs.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Return only templates of these team IDs (from `POST /team/list`); `0` selects account-wide templates. Empty or omitted applies no team filter. See `is_my_team` for how the two combine." + }, + "creator_id": { + "type": [ + "integer", + "null" + ], + "format": "int64", + "description": "Filter by creator member ID; obtain member IDs from `POST /member/list`." + }, + "query": { + "type": "string", + "description": "Case-insensitive regular expression matched against `template_name`; an invalid expression is matched as literal text." } - }, - "type": "object" + } }, "TemplateListResponse": { "description": "Paginated template list.", @@ -26835,71 +27780,110 @@ "type": "object" }, "TemplateUpdateRequest": { + "type": "object", "description": "Update an existing template.", + "required": [ + "template_id", + "template_name" + ], "properties": { + "template_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Target template ID; obtain it from `POST /template/list`.", + "example": "6605a1b2c3d4e5f6a7b8c9d0" + }, + "team_id": { + "type": [ + "integer", + "null" + ], + "format": "int64", + "description": "Team scope. 0 for account-wide. Omit to keep the template's current team." + }, + "template_name": { + "type": "string", + "minLength": 1, + "maxLength": 39, + "description": "Template name, 1–39 characters. Required and written on every call; must not be used by another template." + }, "description": { - "description": "Free-form description. Up to 500 characters. Omit to keep the current content; send an empty string to clear it.", + "type": [ + "string", + "null" + ], "maxLength": 500, + "description": "Free-form description. Up to 500 characters. Omit to keep the current content; send an empty string to clear it." + }, + "email": { "type": [ "string", "null" - ] + ], + "description": "Email body template source (Go `html/template` syntax). Omit to keep the current content; send an empty string to clear it." }, - "dingtalk": { - "description": "DingTalk robot message template source. Omit to keep the current content; send an empty string to clear it.", + "sms": { "type": [ "string", "null" - ] + ], + "description": "SMS template source (Go `text/template` syntax). Omit to keep the current content; send an empty string to clear it." }, - "dingtalk_app": { - "description": "DingTalk app message template source. Omit to keep the current content; send an empty string to clear it.", + "voice": { "type": [ "string", "null" - ] + ], + "description": "Voice call script template source. Omit to keep the current content; send an empty string to clear it." }, - "dingtalk_app_war_room_enabled": { + "dingtalk": { "type": [ - "boolean", + "string", "null" ], - "description": "When set, show or hide the Create War Room button on DingTalk app cards. Omit to keep the existing setting." + "description": "DingTalk robot message template source. Omit to keep the current content; send an empty string to clear it." }, - "email": { - "description": "Email body template source (Go `html/template` syntax). Omit to keep the current content; send an empty string to clear it.", + "wecom": { "type": [ "string", "null" - ] + ], + "description": "WeCom robot message template source. Omit to keep the current content; send an empty string to clear it." + }, + "wecom_markdown_v2_enabled": { + "type": [ + "boolean", + "null" + ], + "description": "Send WeCom robot notifications as `markdown_v2` messages instead of plain markdown. While enabled, the rendered `wecom` content must be at most 4,096 bytes. Omit to keep the current setting." }, "feishu": { - "description": "Feishu robot message template source. Omit to keep the current content; send an empty string to clear it.", "type": [ "string", "null" - ] + ], + "description": "Feishu robot message template source. Omit to keep the current content; send an empty string to clear it." }, "feishu_app": { - "description": "Feishu app message template source. Omit to keep the current content; send an empty string to clear it.", "type": [ "string", "null" - ] + ], + "description": "Feishu app message template source. Omit to keep the current content; send an empty string to clear it." }, - "feishu_app_card_v2_preserve_blank_lines": { + "feishu_app_card_v2_table_enabled": { "type": [ "boolean", "null" ], - "description": "When set, keep or drop blank lines in the body of Feishu app card v2 messages. Omit to keep the existing setting." + "description": "Render Markdown tables in the `feishu_app` content as native Feishu card tables. Omit to keep the current setting." }, - "feishu_app_card_v2_table_enabled": { - "description": "When set, enable or disable table rendering for alert labels in Feishu app cards. Omit to keep the existing setting.", + "feishu_app_card_v2_preserve_blank_lines": { "type": [ "boolean", "null" - ] + ], + "description": "When set, keep or drop blank lines in the body of Feishu app card v2 messages. Omit to keep the existing setting." }, "feishu_app_war_room_enabled": { "type": [ @@ -26908,37 +27892,12 @@ ], "description": "When set, show or hide the Create War Room button on Feishu app cards. Omit to keep the existing setting." }, - "incident_card_closed_action_apps": { - "type": "array", - "items": { - "type": "string", - "enum": [ - "feishu_app", - "dingtalk_app", - "wecom_app", - "slack_app", - "teams_app" - ] - }, - "description": "Replaces the retained-app list when sent. Supported values: `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, `teams_app`. Omit the field to leave it unchanged." - }, - "incident_card_hidden_fields": { - "$ref": "#/components/schemas/IncidentCardHiddenFields", - "description": "Incident card fields hidden per IM app type." - }, - "slack": { - "description": "Slack robot message template source. Omit to keep the current content; send an empty string to clear it.", - "type": [ - "string", - "null" - ] - }, - "slack_app": { - "description": "Slack app message template source. Omit to keep the current content; send an empty string to clear it.", + "dingtalk_app_war_room_enabled": { "type": [ - "string", + "boolean", "null" - ] + ], + "description": "When set, show or hide the Create War Room button on DingTalk app cards. Omit to keep the existing setting." }, "slack_app_war_room_enabled": { "type": [ @@ -26947,119 +27906,105 @@ ], "description": "When set, show or hide the Create War Room button on Slack app cards. Omit to keep the existing setting." }, - "sms": { - "description": "SMS template source (Go `text/template` syntax). Omit to keep the current content; send an empty string to clear it.", + "dingtalk_app": { "type": [ "string", "null" - ] - }, - "team_id": { - "description": "Team scope. 0 for account-wide. Omit to keep the template's current team.", - "format": "int64", - "type": [ - "integer", - "null" - ] + ], + "description": "DingTalk app message template source. Omit to keep the current content; send an empty string to clear it." }, - "teams_app": { - "description": "Microsoft Teams app message template source. Omit to keep the current content; send an empty string to clear it.", + "wecom_app": { "type": [ "string", "null" - ] + ], + "description": "WeCom app message template source. Omit to keep the current content; send an empty string to clear it." }, - "telegram": { - "description": "Telegram bot message template source. Omit to keep the current content; send an empty string to clear it.", + "slack_app": { "type": [ "string", "null" - ] - }, - "template_id": { - "description": "Target template ID; obtain it from `POST /template/list`.", - "example": "6605a1b2c3d4e5f6a7b8c9d0", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" - }, - "template_name": { - "description": "Template name. 1–39 characters.", - "maxLength": 39, - "minLength": 1, - "type": "string" + ], + "description": "Slack app message template source. Omit to keep the current content; send an empty string to clear it." }, - "voice": { - "description": "Voice call script template source. Omit to keep the current content; send an empty string to clear it.", + "teams_app": { "type": [ "string", "null" - ] + ], + "description": "Microsoft Teams app message template source. Omit to keep the current content; send an empty string to clear it." }, - "wecom": { - "description": "WeCom robot message template source. Omit to keep the current content; send an empty string to clear it.", + "telegram": { "type": [ "string", "null" - ] + ], + "description": "Telegram bot message template source. Omit to keep the current content; send an empty string to clear it." }, - "wecom_app": { - "description": "WeCom app message template source. Omit to keep the current content; send an empty string to clear it.", + "slack": { "type": [ "string", "null" - ] - }, - "wecom_markdown_v2_enabled": { - "type": [ - "boolean", - "null" ], - "description": "When set, switch WeCom robot notifications between `markdown_v2` and plain markdown. Omit to keep the existing setting." + "description": "Slack robot message template source. Omit to keep the current content; send an empty string to clear it." }, "zoom": { - "description": "Zoom bot message template source. Omit to keep the current content; send an empty string to clear it.", "type": [ "string", "null" - ] + ], + "description": "Zoom bot message template source. Omit to keep the current content; send an empty string to clear it." + }, + "incident_card_closed_action_apps": { + "type": "array", + "items": { + "type": "string", + "enum": [ + "feishu_app", + "dingtalk_app", + "wecom_app", + "slack_app", + "teams_app" + ] + }, + "description": "Replaces the retained-app list when sent. Supported values: `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, `teams_app`. Omit the field to leave it unchanged." + }, + "incident_card_hidden_fields": { + "$ref": "#/components/schemas/IncidentCardHiddenFields", + "description": "Incident card fields to hide per IM app type. When sent, replaces the stored value as a whole; omit to keep." } - }, - "required": [ - "template_id", - "template_name" - ], - "type": "object" + } }, "TimeFilter": { - "description": "Recurring time window. `start`/`end` use 24-hour `HH:MM` format; `repeat` lists ISO-style weekday indices (0=Sunday … 6=Saturday).", + "type": "object", + "description": "Recurring time window. `start` and `end` are `HH:MM` in 24-hour format with `start` not later than `end` (windows cannot cross midnight); `00:00`–`00:00` means the whole day.", "properties": { - "cal_id": { - "description": "Optional calendar ID; restricts the window to days matching the calendar.", - "type": "string" + "start": { + "type": "string", + "description": "Window start, `HH:MM`, inclusive." }, "end": { - "description": "End of the window in `HH:MM`.", - "type": "string" - }, - "is_off": { - "description": "When true, match days marked as days-off in the calendar.", - "type": "boolean" + "type": "string", + "description": "Window end, `HH:MM`, inclusive (`23:59` lasts to midnight)." }, "repeat": { - "description": "Days of the week this window repeats on. Empty means every day.", + "type": "array", "items": { - "maximum": 6, + "type": "integer", "minimum": 0, - "type": "integer" + "maximum": 6 }, - "type": "array" + "description": "Days of the week the window applies on: `0` = Sunday … `6` = Saturday. Empty means every day." }, - "start": { - "description": "Start of the window in `HH:MM`.", - "type": "string" + "cal_id": { + "type": "string", + "description": "Service calendar ID from `POST /calendar/list` (for example `cal.xxxx`). When set, the window applies only on the calendar's workdays or days off, as chosen by `is_off`." + }, + "is_off": { + "type": "boolean", + "description": "Used with `cal_id`: `true` applies the window only on the calendar's days off, `false` only on its workdays." } - }, - "type": "object" + } }, "TryLinkPersonRequest": { "description": "Parameters for attempting automatic IM account linking.", @@ -27076,21 +28021,31 @@ "type": "object" }, "TryLinkPersonResponse": { - "description": "People linked by this attempt. When nobody could be newly linked, the response either carries an empty `new_linked_person_ids` array or omits the `data` field entirely.", + "type": "object", + "description": "Result of one linking run for the integration.", + "required": [ + "new_linked_person_ids", + "unmatched_count", + "no_contact_count" + ], "properties": { "new_linked_person_ids": { - "description": "Person IDs newly linked during this call.", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Person IDs linked to the IM app during this call. Empty when nobody was newly linked." + }, + "unmatched_count": { + "type": "integer", + "description": "Members with an email or phone that were looked up but not newly linked: not found on the IM platform, the IM account is already linked to another member, or the lookup failed for them." + }, + "no_contact_count": { + "type": "integer", + "description": "Unlinked members skipped because they have neither an email nor a phone number." } - }, - "required": [ - "new_linked_person_ids" - ], - "type": "object" + } }, "UnackIncidentRequest": { "description": "Parameters for removing acknowledgement from one or more incidents.", @@ -27112,302 +28067,327 @@ "type": "object" }, "UnsubscribeRuleItem": { + "type": "object", "description": "Drop (unsubscribe) rule record.", + "required": [ + "account_id", + "channel_id", + "rule_name", + "description", + "filters", + "status", + "rule_id", + "updated_by", + "created_at", + "updated_at" + ], "properties": { "account_id": { - "description": "ID of the account the rule belongs to.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the account the rule belongs to." }, "channel_id": { - "description": "ID of the channel the rule belongs to.", - "format": "int64", - "type": "integer" - }, - "created_at": { - "description": "Creation time, Unix timestamp in seconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "ID of the channel the rule belongs to." }, - "deleted_at": { - "description": "Deletion time, Unix timestamp in seconds. Omitted unless the rule is soft-deleted; deleted rules are excluded from list responses.", - "format": "int64", - "type": "integer" + "rule_name": { + "type": "string", + "description": "Drop rule name, 1–39 characters." }, "description": { - "description": "Rule description.", - "type": "string" + "type": "string", + "description": "Rule description." }, "filters": { "$ref": "#/components/schemas/FilterGroup", - "description": "Alert event match conditions (OR-of-AND); matching events are discarded entirely. Empty means the rule matches nothing." - }, - "rule_id": { - "description": "Rule ID (MongoDB ObjectID).", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" - }, - "rule_name": { - "description": "Rule name.", - "type": "string" + "description": "Alert event conditions (OR of AND groups); matching events are discarded entirely. Empty means the rule matches nothing; `null` when the last update omitted `filters`." }, "status": { - "description": "Rule status: `enabled` or `disabled`; deleted rules never appear in the list.", + "type": "string", "enum": [ "enabled", "disabled" ], - "type": "string" + "description": "Rule status: `enabled` or `disabled`; deleted rules never appear in the list." + }, + "rule_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Rule ID (MongoDB ObjectID)." + }, + "updated_by": { + "type": "integer", + "format": "int64", + "description": "ID of the user who last updated the rule." + }, + "created_at": { + "type": "integer", + "format": "int64", + "description": "Creation time, Unix timestamp in seconds." }, "updated_at": { - "description": "Last update time, Unix timestamp in seconds.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Last update time, Unix timestamp in seconds." }, - "updated_by": { - "description": "ID of the user who last updated the rule.", + "deleted_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Deletion time, Unix timestamp in seconds. Omitted unless the rule is soft-deleted; deleted rules are excluded from list responses." } - }, - "required": [ - "account_id", - "channel_id", - "rule_name", - "description", - "filters", - "status", - "rule_id", - "updated_by", - "created_at", - "updated_at" - ], - "type": "object" + } }, "UpdateChannelRequest": { + "type": "object", + "required": [ + "channel_id" + ], "description": "Parameters for updating a channel. Only the fields you pass are updated.", "properties": { - "auto_resolve_mode": { - "description": "Auto-resolve timing mode: `trigger` starts the timer when the incident triggers, `update` restarts it on every alert update. Applied only when `auto_resolve_timeout` is also present in the request.", - "enum": [ - "trigger", - "update" - ], - "type": "string" - }, - "auto_resolve_timeout": { - "description": "Auto-resolve timeout in seconds. 0 disables auto-resolve. Max 30 days.", + "channel_id": { + "type": "integer", "format": "int64", - "maximum": 2592000, - "minimum": 0, + "description": "ID of the channel to update; obtain it from `POST /channel/list`." + }, + "team_id": { "type": [ "integer", "null" - ] - }, - "channel_id": { - "description": "ID of the channel to update; obtain it from `POST /channel/list`.", + ], "format": "int64", - "type": "integer" + "description": "New owning team ID; obtain it from `POST /team/list`. Must exist. Omit or pass `null` to keep the current team." + }, + "managing_team_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "maxItems": 3, + "description": "Replaces the additional managing teams, up to 3; every ID must exist. Pass `[]` to remove them all; omit to keep the current list." }, "channel_name": { - "description": "New channel name. 1 to 59 characters.", - "maxLength": 59, - "minLength": 1, "type": [ "string", "null" - ] + ], + "minLength": 1, + "maxLength": 59, + "description": "New channel name, 1–59 characters, unique within the account. Omit or pass `null` to keep the current name." }, "description": { - "description": "New description. Up to 500 characters.", - "maxLength": 500, "type": [ "string", "null" - ] + ], + "maxLength": 500, + "description": "New description. Up to 500 characters." }, - "disable_auto_close": { - "description": "Disable automatic incident closing.", + "auto_resolve_timeout": { "type": [ - "boolean", + "integer", "null" - ] + ], + "format": "int64", + "minimum": 0, + "maximum": 2592000, + "description": "Auto-resolve timeout in seconds. 0 disables auto-resolve. Max 30 days." }, - "disable_outlier_detection": { - "description": "Disable outlier incident detection.", + "auto_resolve_mode": { + "type": "string", + "enum": [ + "trigger", + "update" + ], + "description": "How the auto-resolve timer runs: `trigger` starts it once when the incident is triggered, `update` restarts it whenever a new alert merges in. Applied only together with `auto_resolve_timeout`; if `auto_resolve_timeout` is sent without it, the mode resets to `trigger`." + }, + "is_private": { "type": [ "boolean", "null" - ] + ], + "description": "When true, the channel is visible only to its managing teams." }, - "event_group": { - "$ref": "#/components/schemas/EventGroup", - "description": "Alert event merge configuration. Updated only when present." + "group": { + "$ref": "#/components/schemas/Group", + "description": "Alert grouping configuration; replaces the stored configuration as a whole when present." }, "flapping": { "$ref": "#/components/schemas/Flapping", - "description": "Flapping detection configuration." - }, - "group": { - "$ref": "#/components/schemas/Group", - "description": "Alert grouping configuration." + "description": "Flapping detection configuration; replaces the stored configuration as a whole when present." }, - "is_external_report_enabled": { - "description": "Allow external reporters to file incidents into this channel.", + "disable_outlier_detection": { "type": [ "boolean", "null" - ] + ], + "description": "Disable outlier incident detection." }, - "is_private": { - "description": "When true, the channel is visible only to its managing teams.", + "disable_auto_close": { "type": [ "boolean", "null" - ] - }, - "managing_team_ids": { - "description": "Additional teams that can manage the channel. Up to 3 entries.", - "items": { - "format": "int64", - "type": "integer" - }, - "maxItems": 3, - "type": "array" + ], + "description": "Disable automatic incident closing." }, - "team_id": { - "description": "New owning team ID; obtain it from `POST /team/list`.", - "format": "int64", + "is_external_report_enabled": { "type": [ - "integer", + "boolean", "null" - ] + ], + "description": "`true` enables external reporting and generates a new token, returned in the response (any previous token stops working); `false` disables it and clears the token." + }, + "event_group": { + "$ref": "#/components/schemas/EventGroup", + "description": "Alert event merge configuration; replaces the stored configuration as a whole when present." } - }, - "required": [ - "channel_id" - ], - "type": "object" + } }, "UpdateChannelResponse": { - "description": "Response from updating a channel. Only populated when `is_external_report_enabled` is set to `true`; otherwise all fields are empty.", + "type": "object", + "description": "Contains `external_report_token` only when the request set `is_external_report_enabled` to `true`; otherwise `data` is an empty object.", "properties": { "external_report_token": { - "description": "Newly generated token for external reporters. Only returned when `is_external_report_enabled` is set to `true` in the request. Callers should store this value; it cannot be retrieved afterwards.", - "type": "string" + "type": "string", + "description": "Newly generated token for external reporters; the previous token stops working. It can be read again later from `external_report_token` in `POST /channel/info`." } - }, - "type": "object" + } }, "UpdateDropRuleRequest": { + "type": "object", "description": "Parameters for updating a channel drop rule.", + "required": [ + "channel_id", + "rule_id", + "rule_name" + ], "properties": { "channel_id": { - "description": "Owning channel ID; obtain it from `POST /channel/list`.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "description": { - "description": "Rule description, up to 500 characters.", - "maxLength": 500, - "type": "string" - }, - "filters": { - "$ref": "#/components/schemas/FilterGroup", - "description": "Alert event match conditions (OR-of-AND); matching events are discarded entirely. When empty, the rule matches nothing." + "description": "Owning channel ID; obtain it from `POST /channel/list`." }, "rule_id": { - "description": "Drop rule ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Drop rule ID (MongoDB ObjectID)." }, "rule_name": { - "description": "Rule name, 1 to 39 characters.", - "maxLength": 39, + "type": "string", "minLength": 1, - "type": "string" + "maxLength": 39, + "description": "Rule name, 1 to 39 characters." + }, + "description": { + "type": "string", + "maxLength": 500, + "description": "Rule description, up to 500 characters. Omitting it clears the stored description." + }, + "filters": { + "$ref": "#/components/schemas/FilterGroup", + "description": "Alert event conditions (OR of AND groups); matching events are discarded entirely. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`. The stored conditions are replaced; omitting this field clears them and the rule then matches nothing." } - }, + } + }, + "UpdateEscalationRuleRequest": { + "type": "object", + "description": "Parameters for updating an escalation rule.", "required": [ "channel_id", "rule_id", - "rule_name" + "template_id", + "rule_name", + "layers" ], - "type": "object" - }, - "UpdateEscalationRuleRequest": { - "description": "Parameters for updating an escalation rule.", "properties": { - "aggr_window": { - "description": "Delay window in seconds. 0 disables delay.", - "type": "integer" - }, "channel_id": { - "description": "Owning channel ID; obtain it from `POST /channel/list`.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "description": { - "description": "Rule description, up to 500 characters.", - "maxLength": 500, - "type": "string" - }, - "filters": { - "$ref": "#/components/schemas/FilterGroup", - "description": "Incident-level match conditions (OR-of-AND tree): the rule is matched against the incident the alert was grouped into, not against the alert itself. Omit or leave empty to apply the rule to all incidents in the channel." + "description": "Owning channel ID; obtain it from `POST /channel/list`." }, - "layers": { - "description": "Escalation levels in order. At least one level is required.", - "items": { - "$ref": "#/components/schemas/EscalateLayer" - }, - "type": "array" + "rule_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Escalation rule ID (MongoDB ObjectID)." }, "priority": { - "description": "Evaluation priority. Lower runs first.", "type": [ "integer", "null" - ] + ], + "description": "Evaluation order; lower values are evaluated first. Omit or pass `null` to keep the current value." }, - "rule_id": { - "description": "Escalation rule ID (MongoDB ObjectID).", + "aggr_window": { + "type": "integer", + "description": "Delay in seconds before the first notification for a newly assigned incident; `0` notifies immediately. Omitting it resets the value to `0`." + }, + "template_id": { + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Notification template ID (24-character hex); obtain it from `POST /template/list`. Must exist." }, "rule_name": { - "description": "Rule name, 1 to 39 characters.", - "maxLength": 39, + "type": "string", "minLength": 1, - "type": "string" + "maxLength": 39, + "description": "Rule name, 1 to 39 characters." }, - "template_id": { - "description": "Notification template ID (MongoDB ObjectID).", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": { + "type": "string", + "maxLength": 500, + "description": "Rule description, up to 500 characters. Omitting it clears the stored description." + }, + "layers": { + "type": "array", + "items": { + "$ref": "#/components/schemas/EscalateLayer" + }, + "description": "Escalation levels in order. At least one level is required." }, "time_filters": { - "description": "Optional recurring time windows during which the rule applies.", + "type": "array", "items": { "$ref": "#/components/schemas/TimeFilter" }, - "type": "array" + "description": "Recurring time windows during which the rule can match. Replaces the stored windows; omit or leave empty to match at any time." + }, + "filters": { + "$ref": "#/components/schemas/FilterGroup", + "description": "Incident conditions (OR of AND groups), matched against the incident the alert was grouped into, not against the alert. Keys: `title`, `description`, `severity` (alias `incident_severity`, `alert_severity`), `status` (alias `incident_status`, `alert_status`), `dedup_key`, `integration_id` (alias `data_source_id`), or any `labels.`. Replaces the stored conditions; omit or leave empty to match every incident in the channel." } - }, - "required": [ - "channel_id", - "rule_id", - "template_id", - "rule_name", - "layers" - ], - "type": "object" + } }, "UpdateFieldRequest": { + "type": "object", + "required": [ + "field_id" + ], "properties": { + "field_id": { + "type": "string", + "pattern": "^[a-f0-9]{24}$", + "description": "Field ID — 24-character hex ObjectID." + }, + "display_name": { + "type": "string", + "maxLength": 39, + "description": "New display name (max 39 characters); must stay unique among non-deleted fields. Always written." + }, + "description": { + "type": "string", + "description": "New description. Always written: omitting it clears the description." + }, + "options": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Replacement options list. Must obey the same per-type rules as create. Note: the update always overwrites `display_name`, `description`, `options`, and `default_value` with the submitted values, so for `single_select`/`multi_select` fields a non-empty `options` list must be sent on every update." + }, "default_value": { - "description": "Replacement default value. Type must match the field's existing `field_type`.", + "description": "New default value; its type must match the field's `field_type`. Always written: omitting it clears the default.", "oneOf": [ { "type": "boolean" @@ -27416,184 +28396,160 @@ "type": "string" }, { + "type": "array", "items": { "type": "string" - }, - "type": "array" + } }, { "type": "null" } ] - }, - "description": { - "description": "New description.", - "type": "string" - }, - "display_name": { - "description": "New display name. Must remain unique within the account.", - "maxLength": 39, - "type": "string" - }, - "field_id": { - "description": "Field ID — 24-character hex ObjectID.", - "pattern": "^[a-f0-9]{24}$", - "type": "string" - }, - "options": { - "description": "Replacement options list. Must obey the same per-type rules as create. Note: the update always overwrites `display_name`, `description`, `options`, and `default_value` with the submitted values, so for `single_select`/`multi_select` fields a non-empty `options` list must be sent on every update.", - "items": { - "type": "string" - }, - "type": "array" } - }, - "required": [ - "field_id" - ], - "type": "object" + } }, "UpdateIncidentCommentTypeRequest": { + "type": "object", "description": "Parameters for updating a comment type. Partial update: at least one of `name` or `color` must be provided.", + "required": [ + "comment_type_id" + ], "properties": { - "color": { - "description": "New label color as a hex value in #RRGGBB format. Normalized to uppercase.", - "pattern": "^#[0-9A-Fa-f]{6}$", - "type": "string" - }, "comment_type_id": { - "description": "ID of the comment type to update (24-character hex ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "ID of the comment type to update (24-character hex ObjectID)." }, "name": { - "description": "New display name. Trimmed before storing; must be unique within the account (case-insensitive). At most 40 characters.", + "type": "string", "maxLength": 40, - "type": "string" + "description": "New display name. Trimmed before storing; must be unique within the account (case-insensitive). At most 40 characters. Must not contain control or text-direction characters." + }, + "color": { + "type": "string", + "pattern": "^#[0-9A-Fa-f]{6}$", + "description": "New label color as a hex value in #RRGGBB format. Normalized to uppercase." } - }, - "required": [ - "comment_type_id" - ], - "type": "object" + } }, "UpdateIncidentFieldsRequest": { - "description": "Parameters for updating user-editable fields of an incident. At least one field must be provided; the handler will update only the fields you supply.", + "type": "object", + "description": "Fields to update on an incident. At least one field besides `incident_id` must be non-empty; omitted or empty fields keep their current values.", + "required": [ + "incident_id" + ], "properties": { + "incident_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Incident ID (MongoDB ObjectID)." + }, + "title": { + "type": "string", + "minLength": 3, + "maxLength": 200, + "description": "New incident title." + }, "description": { - "description": "New description.", - "maxLength": 6144, + "type": "string", "minLength": 3, - "type": "string" + "maxLength": 6144, + "description": "New description." }, "impact": { - "description": "New impact description.", + "type": "string", + "minLength": 3, "maxLength": 6144, + "description": "New impact description." + }, + "root_cause": { + "type": "string", "minLength": 3, - "type": "string" + "maxLength": 6144, + "description": "New root cause analysis." }, - "incident_id": { - "description": "Incident ID (MongoDB ObjectID).", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "resolution": { + "type": "string", + "minLength": 3, + "maxLength": 6144, + "description": "New resolution notes." }, "incident_severity": { - "description": "New severity: `Info`, `Warning` or `Critical` (most severe).", + "type": "string", "enum": [ "Info", "Warning", "Critical" ], - "type": "string" - }, - "resolution": { - "description": "New resolution notes.", - "maxLength": 6144, - "minLength": 3, - "type": "string" - }, - "root_cause": { - "description": "New root cause analysis.", - "maxLength": 6144, - "minLength": 3, - "type": "string" - }, - "title": { - "description": "New incident title.", - "maxLength": 200, - "minLength": 3, - "type": "string" + "description": "New severity: `Info`, `Warning` or `Critical` (most severe)." } - }, - "required": [ - "incident_id" - ], - "type": "object" + } }, "UpdateInhibitRuleRequest": { + "type": "object", "description": "Parameters for updating an inhibit rule.", + "required": [ + "channel_id", + "rule_id", + "rule_name", + "equals" + ], "properties": { "channel_id": { - "description": "Owning channel ID; obtain it from `POST /channel/list`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Owning channel ID; obtain it from `POST /channel/list`." + }, + "rule_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Inhibit rule ID (MongoDB ObjectID)." + }, + "rule_name": { + "type": "string", + "minLength": 1, + "maxLength": 39, + "description": "Rule name, 1 to 39 characters." }, "description": { - "description": "Rule description, up to 500 characters.", + "type": "string", "maxLength": 500, - "type": "string" + "description": "Rule description, up to 500 characters. Omitting it clears the stored description." }, "equals": { - "description": "Field keys whose values must be equal between the source (inhibiting) alert and the target (suppressed) alert, e.g. `data_source_id` or `labels.cluster`.", + "type": "array", "items": { "type": "string" }, - "type": "array" - }, - "is_directly_discard": { - "description": "When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule.", - "type": "boolean" - }, - "rule_id": { - "description": "Inhibit rule ID (MongoDB ObjectID).", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" - }, - "rule_name": { - "description": "Rule name, 1 to 39 characters.", - "maxLength": 39, - "minLength": 1, - "type": "string" + "description": "Keys whose values must be equal on the source alert and the incoming event. Only `title`, `severity` and `labels.` take effect; any other key (for example `data_source_id`) is accepted but makes the rule never fire. Must be present; an empty array also makes the rule inert." }, "source_filters": { "$ref": "#/components/schemas/FilterGroup", - "description": "Conditions the source alert must match, evaluated against stored active alerts. Supported keys: `status`, `incident_status`, `alert_status`, `severity`, `incident_severity`, `alert_severity`, `title`, `description`, or any `labels.`. Empty makes the rule inert." + "description": "Conditions the source (inhibiting) alert must match, evaluated against active alerts already stored in the channel. Keys: `title`, `description`, `severity` (alias `incident_severity`, `alert_severity`), `status` (alias `incident_status`, `alert_status`), or any `labels.`. Empty makes the rule inert. Omitting it clears the stored conditions." }, "target_filters": { "$ref": "#/components/schemas/FilterGroup", - "description": "Conditions the incoming target alert event must match to be suppressed; empty means every event is a target." + "description": "Conditions the incoming target alert event must match to be inhibited; empty means every incoming event is a target. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`. Omitting it clears the stored conditions." + }, + "is_directly_discard": { + "type": "boolean", + "description": "When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule. Omitting it sets it to `false`." } - }, - "required": [ - "channel_id", - "rule_id", - "rule_name", - "equals" - ], - "type": "object" + } }, "UpdateRemoteConfigRequest": { "description": "Publish a whole new remote configuration version. The client sends the complete object, not a patch: rule order carries meaning.", "properties": { "application_id": { - "description": "RUM application ID.", + "description": "RUM application ID. Get application IDs via `POST /rum/application/list`.", "type": "string" }, "config": { - "$ref": "#/components/schemas/RemoteConfig" + "$ref": "#/components/schemas/RemoteConfig", + "description": "The complete configuration to publish." }, "reason": { - "description": "Operator's note on why this version was published. Stored verbatim.", + "description": "Optional free-text note (not an enum) on why this version was published, at most 255 characters; stored verbatim and returned as `reason` by `POST /rum/application/remote-config/history/list`.", "maxLength": 255, "type": "string" } @@ -27608,474 +28564,493 @@ "description": "Version allocated to the published configuration.", "properties": { "version": { - "description": "New published version number.", + "description": "Version number allocated to the published configuration (previous highest version + 1).", "type": "integer" } }, "type": "object" }, "UpdateSilenceRuleRequest": { + "type": "object", "description": "Parameters for updating a silence rule. Exactly one of `time_filter` or `time_filters` must be provided, and `filters` must be non-empty.", + "required": [ + "channel_id", + "rule_id", + "rule_name" + ], "properties": { "channel_id": { - "description": "Owning channel ID; obtain it from `POST /channel/list`.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "description": { - "description": "Rule description, up to 500 characters.", - "maxLength": 500, - "type": "string" - }, - "filters": { - "$ref": "#/components/schemas/FilterGroup", - "description": "Match conditions for the alerts to silence; required and must not be empty." - }, - "is_auto_delete": { - "description": "When true, the silence rule is automatically deleted after its time window expires. Defaults to false.", - "type": "boolean" - }, - "is_directly_discard": { - "description": "When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as muted by this rule.", - "type": "boolean" + "description": "Owning channel ID; obtain it from `POST /channel/list`." }, "rule_id": { - "description": "Silence rule ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Silence rule ID (MongoDB ObjectID)." }, "rule_name": { - "description": "Rule name, 1 to 39 characters.", - "maxLength": 39, + "type": "string", "minLength": 1, - "type": "string" + "maxLength": 39, + "description": "Rule name, 1 to 39 characters." }, - "time_filter": { - "$ref": "#/components/schemas/OnceTimeFilter", - "description": "One-off silence window. Mutually exclusive with `time_filters`; exactly one of the two must be set." + "description": { + "type": "string", + "maxLength": 500, + "description": "Rule description, up to 500 characters. Omitting it clears the stored description." }, "time_filters": { - "description": "Recurring time windows. Mutually exclusive with `time_filter`.", + "type": "array", "items": { "$ref": "#/components/schemas/TimeFilter" }, - "type": "array" + "description": "Recurring time windows. Mutually exclusive with `time_filter`." + }, + "time_filter": { + "$ref": "#/components/schemas/OnceTimeFilter", + "description": "One-off silence window. Mutually exclusive with `time_filters`; exactly one of the two must be set." + }, + "filters": { + "$ref": "#/components/schemas/FilterGroup", + "description": "Alert event conditions (OR of AND groups); matching events are silenced while the time window is active. Required, with at least one condition. Keys: `title`, `description`, `severity` (alias `alert_severity`, `event_severity`), `status`, `alert_key`, `title_rule`, `integration_id` (alias `data_source_id`), or any `labels.`." + }, + "is_directly_discard": { + "type": "boolean", + "description": "When true, matching alert events are discarded entirely; when false, alerts are still recorded but marked as silenced by this rule. Omitting it sets it to `false`." + }, + "is_auto_delete": { + "type": "boolean", + "description": "When true, a rule with a one-off `time_filter` is permanently removed about 24 hours after `end_time` (or after its last update, whichever is later). Rules created with `from_incident_id` are cleaned up the same way. Rules with recurring `time_filters` are never removed automatically. Omitting it sets it to `false`." } - }, - "required": [ - "channel_id", - "rule_id", - "rule_name" - ], - "type": "object" + } }, "UpdateStatusPageChangeRequest": { + "type": "object", "description": "Parameters for updating the editable fields of a status page event.", + "required": [ + "page_id", + "change_id" + ], "properties": { - "change_id": { - "description": "Target change ID; obtain it from `GET /status-page/change/list`.", - "format": "int64", - "type": "integer" - }, - "linked_changes": { - "description": "Linked event IDs. Pass the full replacement list.", - "items": { - "type": "string" - }, - "type": "array" - }, "page_id": { - "description": "Status page ID; obtain it from `GET /status-page/list`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Status page ID; obtain it from `GET /status-page/list`." }, - "responders": { - "description": "Member IDs responsible for this event. Pass the full replacement list.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" + "change_id": { + "type": "integer", + "format": "int64", + "description": "Target change ID; obtain it from `GET /status-page/change/list`." }, "title": { - "description": "New event title, up to 255 characters. Omit to keep the existing value.", - "maxLength": 255, "type": [ "string", "null" - ] + ], + "maxLength": 255, + "description": "New event title, up to 255 characters. Omit to keep the existing value." + }, + "responders": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Member IDs responsible for this event, replacing the current list. An omitted or empty array keeps the current list." + }, + "linked_changes": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Linked event IDs, replacing the current list. An omitted or empty array keeps the current list." } - }, - "required": [ - "page_id", - "change_id" - ], - "type": "object" + } }, "UpdateStatusPageChangeTimelineRequest": { + "type": "object", "description": "Parameters for updating an existing timeline entry on a status page event. At least one of `at_seconds` or `description` must be provided; omitted fields keep their current values.", + "required": [ + "page_id", + "change_id", + "update_id" + ], "properties": { - "at_seconds": { - "description": "New update timestamp in Unix seconds.", + "page_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Status page ID; obtain it from `GET /status-page/list`." }, "change_id": { - "description": "Owning change ID; obtain it from `GET /status-page/change/list`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Owning change ID; obtain it from `GET /status-page/change/list`." }, - "description": { - "description": "New update description (Markdown).", - "type": "string" + "update_id": { + "type": "string", + "description": "Target timeline update ID; obtain it from `GET /status-page/change/info`." }, - "page_id": { - "description": "Status page ID; obtain it from `GET /status-page/list`.", + "at_seconds": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "New update time in Unix seconds; must not be earlier than the previous entry or later than the next one. Omit or pass 0 to keep the current time." }, - "update_id": { - "description": "Target timeline update ID; obtain it from `GET /status-page/change/info`.", - "type": "string" + "description": { + "type": "string", + "description": "New update description (Markdown). Omit or pass an empty string to keep the current text; editing the latest entry also updates the event description." } - }, - "required": [ - "page_id", - "change_id", - "update_id" - ], - "type": "object" + } }, "UpdateStatusPageRequest": { + "type": "object", "description": "Parameters for updating an existing status page. All fields except `page_id` are optional; omit a field or pass null to keep its existing value.", + "required": [ + "page_id" + ], "properties": { - "contact_info": { - "description": "Get-in-touch contact, such as a mailto or website URL. Omit or pass null to keep the existing value.", - "type": [ - "string", - "null" - ] + "page_id": { + "type": "integer", + "format": "int64", + "description": "Status page ID; obtain it from `GET /status-page/list`." }, - "custom_domain": { - "description": "Custom domain for a public status page. Omit or pass null to keep the existing value.", - "maxLength": 255, + "name": { "type": [ "string", "null" - ] - }, - "custom_links": { - "description": "Custom navigation links shown on the status page. Omit or pass an empty array to keep the current links.", - "items": { - "additionalProperties": { - "type": "string" - }, - "type": "object" - }, - "type": "array" + ], + "description": "Display name of the status page. Omit or pass null to keep the existing value.", + "maxLength": 255 }, - "dark_logo": { - "description": "Dark-mode logo image of the status page. Omit or pass null to keep the existing value.", + "url_name": { "type": [ "string", "null" - ] - }, - "date_view": { - "description": "How change dates are displayed. Leave empty to keep the current value. `calendar` uses a calendar view; `list` uses a list view.", - "enum": [ - "calendar", - "list" ], - "type": [ - "string", - "null" - ] + "description": "URL-safe slug; normalized to lowercase with non-alphanumeric characters replaced by hyphens, and must be unique among the account's pages of the same type. Omit or pass null to keep the existing value.", + "maxLength": 255 }, - "display_uptime_mode": { - "description": "How uptime is displayed. Leave empty to keep the current value. `chart_and_percentage` shows both chart and percentage; `chart` shows only the chart; `none` hides uptime.", - "enum": [ - "chart_and_percentage", - "chart", - "none" - ], + "custom_domain": { "type": [ "string", "null" - ] + ], + "description": "Custom domain for a public status page; must not be used by another status page. Rejected for internal pages. Omit or pass null to keep the existing value; an empty string removes the domain.", + "maxLength": 255 }, - "favicon": { - "description": "Favicon of the status page. Omit or pass null to keep the existing value.", + "page_title": { "type": [ "string", "null" - ] + ], + "description": "Accepted for compatibility but not stored; it has no effect." }, "logo": { - "description": "Logo image of the status page. Omit or pass null to keep the existing value.", "type": [ "string", "null" - ] + ], + "description": "Logo image of the status page. Omit or pass null to keep the existing value." }, - "logo_url": { - "description": "URL opened when the logo is clicked. Omit or pass null to keep the existing value.", - "maxLength": 255, + "dark_logo": { "type": [ "string", "null" - ] + ], + "description": "Dark-mode logo image of the status page. Omit or pass null to keep the existing value." }, - "name": { - "description": "Display name of the status page. Omit or pass null to keep the existing value.", - "maxLength": 255, + "logo_url": { "type": [ "string", "null" - ] + ], + "description": "URL opened when the logo is clicked. Omit or pass null to keep the existing value.", + "maxLength": 255 }, - "page_footer": { - "description": "Footer content shown on the status page. Omit or pass null to keep the existing value.", + "favicon": { "type": [ "string", "null" - ] + ], + "description": "Favicon of the status page. Omit or pass null to keep the existing value." }, "page_header": { - "description": "Header content shown on the status page. Omit or pass null to keep the existing value.", "type": [ "string", "null" - ] - }, - "page_id": { - "description": "Status page ID; obtain it from `GET /status-page/list`.", - "format": "int64", - "type": "integer" + ], + "description": "Header content shown on the status page. Omit or pass null to keep the existing value." }, - "page_title": { - "description": "Browser title shown for the status page. Omit or pass null to keep the existing value.", + "page_footer": { "type": [ "string", "null" - ] - }, - "subscription": { - "$ref": "#/components/schemas/StatusPageSubscriptionItem", - "description": "Subscription channel toggles. Omit or pass null to keep the existing value." + ], + "description": "Footer content shown on the status page. Omit or pass null to keep the existing value." }, - "template_preference": { - "description": "Preferred event template type: `pre_defined` or `message`. Omit or pass null to keep the existing value.", + "date_view": { "type": [ "string", "null" + ], + "description": "How event dates are displayed: `calendar` uses a calendar view, `list` uses a list view. Omit or pass null to keep the current value; an empty string clears the setting.", + "enum": [ + "calendar", + "list", + "", + null ] }, - "url_name": { - "description": "URL-safe slug, unique per account and page type. Omit or pass null to keep the existing value.", - "maxLength": 255, + "display_uptime_mode": { "type": [ "string", "null" - ] - } - }, - "required": [ - "page_id" - ], - "type": "object" + ], + "description": "How uptime is displayed: `chart_and_percentage` shows the chart and the percentage, `chart` shows only the chart, `none` hides uptime. Omit or pass null to keep the current value; an empty string clears the setting.", + "enum": [ + "chart_and_percentage", + "chart", + "none", + "", + null + ] + }, + "custom_links": { + "type": "array", + "description": "Custom navigation links shown on the status page. Omit or pass an empty array to keep the current links.", + "items": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Link text shown on the page." + }, + "value": { + "type": "string", + "description": "URL the link text points to, such as `https://www.example.com`." + } + }, + "additionalProperties": { + "type": "string" + } + } + }, + "contact_info": { + "type": [ + "string", + "null" + ], + "description": "Get-in-touch contact, such as a mailto or website URL. Omit or pass null to keep the existing value." + }, + "subscription": { + "$ref": "#/components/schemas/StatusPageSubscriptionItem", + "description": "Subscription channel toggles. A public page can enable only `email` and an internal page only `im`. Omit or pass null to keep the existing value." + }, + "template_preference": { + "type": [ + "string", + "null" + ], + "description": "Event template mode used when publishing events in the console: `message` (status descriptions: per-status texts) or `pre_defined` (full status updates: complete examples with title, status, and description). Omit or pass null to keep the current value; the value is not validated.", + "enum": [ + "pre_defined", + "message", + null + ] + } + } }, "UpdateWorkItemRequest": { - "description": "Partial patch for a work item. Omitted fields stay unchanged; an explicit `null` clears the field.", + "type": "object", + "description": "Partial patch for a work item. Omitted fields and fields sent as `null` stay unchanged.", + "required": [ + "work_item_id", + "version" + ], "properties": { - "description": { - "description": "New description (max 65,535 characters).", - "maxLength": 65535, + "work_item_id": { + "type": "string", + "maxLength": 128, + "description": "Work item ID (opaque string, max 128 characters)." + }, + "version": { + "type": "integer", + "format": "int64", + "description": "The item's current `version` (≥ 1) for optimistic locking." + }, + "title": { "type": [ "string", "null" - ] + ], + "description": "New title, at most 512 characters; trimmed and must not be blank. `null` or omitted keeps the current title.", + "maxLength": 512 }, - "priority": { - "description": "New client-defined priority (max 64 characters).", - "maxLength": 64, + "description": { "type": [ "string", "null" - ] + ], + "description": "New description, at most 65,535 characters; `\"\"` clears it. `null` or omitted keeps the current value.", + "maxLength": 65535 }, "status": { - "description": "New status. One of `open`, `in_progress`, `done`, `cancelled`.", + "type": [ + "string", + "null" + ], "enum": [ "open", "in_progress", "done", - "cancelled" + "cancelled", + null ], - "maxLength": 64, - "type": [ - "string", - "null" - ] + "description": "New status. `null` or omitted keeps the current status.\n- `open`: not started.\n- `in_progress`: being worked on.\n- `done`: finished.\n- `cancelled`: no longer needed." }, - "title": { - "description": "New title (max 512 characters).", - "maxLength": 512, + "priority": { "type": [ "string", "null" - ] - }, - "version": { - "description": "Current item version for optimistic locking. Must match the stored version.", - "format": "int64", - "type": "integer" - }, - "work_item_id": { - "description": "Work item ID (opaque string, max 128 characters).", - "maxLength": 128, - "type": "string" + ], + "description": "New free-form priority, at most 64 characters; `\"\"` clears it. `null` or omitted keeps the current value.", + "maxLength": 64 } - }, - "required": [ - "work_item_id", - "version" - ], - "type": "object" + } }, "UpsertPostMortemTemplateRequest": { + "type": "object", "description": "Parameters for creating or updating a post-mortem template.", + "required": [ + "name", + "content" + ], "properties": { - "content": { - "description": "BlockNote JSON template content.", - "type": "string" - }, - "content_markdown": { - "description": "Markdown version of the template content.", - "type": "string" + "template_id": { + "type": "string", + "description": "ID of the custom template to replace. Omit it to create a new template (the server generates the ID)." }, - "description": { - "description": "Template description.", - "type": "string" + "team_id": { + "type": "integer", + "format": "int64", + "description": "Managing team ID. Required when creating; the team must exist. On update, a different team ID moves the template; omit it or send 0 to keep the current team." }, "name": { - "description": "Template name.", - "type": "string" + "type": "string", + "description": "Template name shown in the console." }, - "team_id": { - "description": "Managing team ID. Required when creating a custom template.", - "format": "int64", - "type": "integer" + "description": { + "type": "string", + "description": "Template description; empty when omitted." }, - "template_id": { - "description": "Template ID. Omit to create a new template; provide it to update an existing template.", - "type": "string" + "content": { + "type": "string", + "description": "Template body as BlockNote editor JSON (an array of blocks), serialized as a string. New reports created from this template start from this body." + }, + "content_markdown": { + "type": "string", + "description": "Markdown version of the body, used as the outline when AI generates a report. Empty when omitted." } - }, - "required": [ - "name", - "content" - ], - "type": "object" + } }, "UpsertRouteRequest": { - "description": "Parameters for creating or updating the routing rule of an integration. The handler creates a rule when none exists for the integration, otherwise it overwrites the existing one. At least one of `cases` or `default` must be provided.", + "type": "object", + "description": "Creates the integration's routing rule, or replaces it entirely when one exists. At least one of `cases` or `default` must be provided.", + "required": [ + "integration_id" + ], "properties": { + "integration_id": { + "type": "integer", + "format": "int64", + "description": "Shared integration ID; obtain it from `POST /integration/list`. Channel-exclusive integrations are rejected with `InvalidParameter`." + }, "cases": { - "description": "Ordered list of case branches. Cases are evaluated top to bottom.", + "type": "array", "items": { "$ref": "#/components/schemas/RouteCase" }, - "type": "array" - }, - "default": { - "$ref": "#/components/schemas/RouteDefault", - "description": "Fallback branch used when no case matches." - }, - "integration_id": { - "description": "Integration the rule belongs to.", - "format": "int64", - "type": "integer" + "description": "Ordered list of case branches. Cases are evaluated top to bottom." }, "sections": { - "description": "Optional sections that group consecutive cases for display.", + "type": "array", "items": { "$ref": "#/components/schemas/RouteSection" }, - "type": "array" + "description": "Optional sections that group consecutive cases for display." + }, + "default": { + "$ref": "#/components/schemas/RouteDefault", + "description": "Fallback branch used when no case yields a channel. Omitting it removes any existing default branch." }, "version": { - "description": "Reserved for optimistic concurrency control; currently ignored — the server increments `version` automatically on every upsert.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Ignored. The server increments `version` on every upsert and does not compare it with this value." } - }, - "required": [ - "integration_id" - ], - "type": "object" + } }, "UpsertStatusPageComponentRequest": { + "type": "object", "description": "Parameters for creating or updating one or more service components on a status page.", + "required": [ + "page_id", + "components" + ], "properties": { + "page_id": { + "type": "integer", + "format": "int64", + "description": "Status page ID; obtain it from `GET /status-page/list`." + }, "components": { + "type": "array", "description": "Components to create or update.", "items": { + "type": "object", + "required": [ + "name" + ], "properties": { - "available_since_seconds": { - "description": "Time the component became (or becomes) available, in Unix seconds. On create, defaults to the current time; on update, replaces the stored value.", - "format": "int64", - "type": "integer" - }, "component_id": { - "description": "Component ID. Omit to create a new component; supply to update an existing one.", - "type": "string" + "type": "string", + "description": "Component ID. Omit to create a new component; supply to update an existing one." + }, + "section_id": { + "type": "string", + "description": "Parent section ID; must be an existing section of the page. Omit to place the component at the top level (on update too)." + }, + "name": { + "type": "string", + "description": "Component display name; must be unique within the page." }, "description": { - "description": "Component description.", - "type": "string" + "type": "string", + "description": "Component description." }, - "hide_all": { - "description": "When true, the component is hidden entirely from summary endpoints.", - "type": "boolean" + "order_id": { + "type": "integer", + "format": "int64", + "description": "Display order within its section; on update an omitted value resets to 0." }, "hide_uptime": { - "description": "When true, uptime data is hidden from summary responses.", - "type": "boolean" + "type": "boolean", + "description": "When true, uptime data is hidden from summary responses." }, - "name": { - "description": "Component display name.", - "type": "string" + "hide_all": { + "type": "boolean", + "description": "When true, the component is hidden entirely from summary endpoints." }, - "order_id": { - "description": "Display order within its section.", + "available_since_seconds": { + "type": "integer", "format": "int64", - "type": "integer" - }, - "section_id": { - "description": "Parent section ID. Omit to place the component at the top level.", - "type": "string" + "description": "Time the component became available, in Unix seconds, used as the start of its uptime history. Applies only on create, defaulting to the current time; ignored on update." } - }, - "required": [ - "name" - ], - "type": "object" + } }, - "minItems": 1, - "type": "array" - }, - "page_id": { - "description": "Status page ID; obtain it from `GET /status-page/list`.", - "format": "int64", - "type": "integer" + "minItems": 1 } - }, - "required": [ - "page_id", - "components" - ], - "type": "object" + } }, "UpsertStatusPageComponentResponse": { "description": "Result of upserting status page components.", @@ -28094,57 +29069,57 @@ "type": "object" }, "UpsertStatusPageSectionRequest": { + "type": "object", "description": "Parameters for creating or updating one or more sections on a status page.", + "required": [ + "page_id", + "sections" + ], "properties": { "page_id": { - "description": "Status page ID; obtain it from `GET /status-page/list`.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Status page ID; obtain it from `GET /status-page/list`." }, "sections": { + "type": "array", "description": "Sections to create or update.", "items": { + "type": "object", + "required": [ + "name" + ], "properties": { - "description": { - "description": "Section description.", - "type": "string" - }, - "hide_all": { - "description": "When true, the entire section is hidden from summary endpoints.", - "type": "boolean" - }, - "hide_uptime": { - "description": "When true, uptime data for all components in this section is hidden.", - "type": "boolean" + "section_id": { + "type": "string", + "description": "Section ID. Omit to create a new section; supply to update an existing one." }, "name": { - "description": "Section display name.", - "type": "string" + "type": "string", + "description": "Section display name; must be unique within the page." + }, + "description": { + "type": "string", + "description": "Section description." }, "order_id": { - "description": "Display order.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Display order of the section; on update an omitted value resets to 0." }, - "section_id": { - "description": "Section ID. Omit to create a new section; supply to update an existing one.", - "type": "string" + "hide_uptime": { + "type": "boolean", + "description": "When true, uptime data for all components in this section is hidden." + }, + "hide_all": { + "type": "boolean", + "description": "When true, the entire section is hidden from summary endpoints." } - }, - "required": [ - "name" - ], - "type": "object" + } }, - "minItems": 1, - "type": "array" + "minItems": 1 } - }, - "required": [ - "page_id", - "sections" - ], - "type": "object" + } }, "UpsertStatusPageSectionResponse": { "description": "Result of upserting status page sections.", @@ -28230,130 +29205,140 @@ "type": "object" }, "WarRoom": { - "description": "Live war room details fetched from the IM side. Returns an empty object if the group was deleted externally.", + "type": "object", + "description": "War room group details read from the IM platform. When the IM lookup fails (for example, the group was dissolved outside Flashduty), all fields are empty strings.", + "required": [ + "chat_id", + "chat_name", + "share_link" + ], "properties": { "chat_id": { - "description": "Chat/group ID on the IM side.", - "type": "string" + "type": "string", + "description": "Chat/group ID on the IM side." }, "chat_name": { - "description": "Chat/group display name.", - "type": "string" + "type": "string", + "description": "Chat/group display name." }, "share_link": { - "description": "Join link for the war room, if provided by the IM.", - "type": "string" + "type": "string", + "description": "Join link for the war room, if provided by the IM." } - }, - "required": [ - "chat_id", - "chat_name", - "share_link" - ], - "type": "object" + } }, "WarRoomDataSourceItem": { - "description": "An IM integration (data source) entry.", + "type": "object", "properties": { - "account_id": { - "description": "Account this integration belongs to.", - "format": "int64", - "type": "integer" - }, - "category": { - "description": "Plugin category; `im` for the IM integrations returned here.", - "type": "string" - }, - "created_at": { - "description": "Unix timestamp in seconds when the integration was created.", - "format": "int64", - "type": "integer" - }, - "creator_id": { - "description": "Person who created the integration.", - "format": "int64", - "type": "integer" - }, "data_source_id": { + "type": "integer", "description": "Integration ID.", - "format": "int64", - "type": "integer" - }, - "description": { - "description": "Integration description.", - "type": "string" + "format": "int64" }, - "exclusive_data_source_id": { - "description": "Legacy exclusive-integration linkage; deprecated.", - "format": "int64", - "type": "integer" - }, - "integration_id": { - "description": "Integration ID, alias of data_source_id.", - "format": "int64", - "type": "integer" + "account_id": { + "type": "integer", + "description": "Account this integration belongs to.", + "format": "int64" }, - "integration_key": { - "description": "Push key used by alert sources to send to this integration.", - "type": "string" + "team_id": { + "type": "integer", + "description": "Team that owns this integration.", + "format": "int64" }, - "last_time": { - "description": "Unix timestamp in seconds of the most recent activity in this datasource. Always `0` — this endpoint does not populate the field.", - "format": "int64", - "type": "integer" + "plugin_id": { + "type": "integer", + "description": "Plugin ID backing this integration.", + "format": "int64" }, "name": { - "description": "Integration name.", - "type": "string" + "type": "string", + "description": "Integration name." }, - "no_editable": { - "description": "Whether the integration is read-only.", - "type": "boolean" + "status": { + "type": "string", + "description": "Integration status: `enabled` or `disabled`. Deleted integrations are never returned.", + "enum": [ + "enabled", + "disabled" + ] }, - "plugin_id": { - "description": "Plugin ID backing this integration.", - "format": "int64", - "type": "integer" + "category": { + "type": "string", + "description": "Plugin category. Always `im`, because this endpoint returns only IM integrations.", + "enum": [ + "im" + ] }, "plugin_type": { - "description": "Plugin type identifier of the IM integration, for example `feishu_app`, `dingtalk_app`, `wecom_app`, `slack_app`, or `teams_app`.", - "type": "string" + "type": "string", + "description": "IM integration type: `feishu_app` Feishu (Lark), `dingtalk_app` DingTalk, `wecom_app` WeCom, `slack_app` Slack, `teams_app` Microsoft Teams.", + "enum": [ + "feishu_app", + "dingtalk_app", + "wecom_app", + "slack_app", + "teams_app" + ] }, "plugin_type_name": { - "description": "Localized display name of the integration plugin type.", - "type": "string" + "type": "string", + "description": "Localized display name of the integration plugin type." + }, + "description": { + "type": "string", + "description": "Integration description." + }, + "integration_key": { + "type": "string", + "description": "Push key used by alert sources to send to this integration." }, "ref_id": { - "description": "External reference ID of the integration.", - "type": "string" + "type": "string", + "description": "External reference ID of the integration." }, "settings": { + "type": "object", "additionalProperties": true, - "description": "Plugin-specific configuration of the integration.", - "type": "object" + "description": "Plugin-specific configuration of the integration; includes `war_room_enabled: true`. Secret values are masked as `******`." }, - "status": { - "description": "Integration status: `enabled` or `disabled`. Deleted integrations are never returned.", - "enum": [ - "enabled", - "disabled" - ], - "type": "string" + "no_editable": { + "type": "boolean", + "description": "Whether the integration is read-only." }, - "team_id": { - "description": "Team that owns this integration.", + "creator_id": { + "type": "integer", + "description": "Person who created the integration.", + "format": "int64" + }, + "updated_by": { + "type": "integer", + "description": "Person who last updated the integration.", + "format": "int64" + }, + "created_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp in seconds when the integration was created." }, "updated_at": { - "description": "Unix timestamp in seconds when the integration was last updated.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp in seconds when the integration was last updated." }, - "updated_by": { - "description": "Person who last updated the integration.", + "last_time": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp in seconds of the most recent activity in this datasource. Always `0` — this endpoint does not populate the field." + }, + "exclusive_data_source_id": { + "type": "integer", + "description": "Deprecated; always `0` in this response.", + "format": "int64" + }, + "integration_id": { + "type": "integer", + "description": "Integration ID; same value as `data_source_id`.", + "format": "int64" } }, "required": [ @@ -28379,51 +29364,69 @@ "exclusive_data_source_id", "integration_id" ], - "type": "object" + "description": "An IM integration (data source) entry." }, "WarRoomItem": { + "type": "object", "description": "Stored war room record.", + "required": [ + "account_id", + "integration_id", + "created_by", + "chat_id", + "incident_id", + "status", + "created_at", + "plugin_type", + "chat_name" + ], "properties": { "account_id": { - "description": "Account ID.", + "type": "integer", "format": "int64", - "type": "integer" - }, - "chat_id": { - "description": "Chat/group ID on the IM side.", - "type": "string" + "description": "ID of the account that owns this record; the same for every record returned to one `app_key`." }, - "created_at": { - "description": "Creation timestamp (seconds).", + "integration_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "IM integration ID." }, "created_by": { - "description": "Member ID that created the war room.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Member ID that created the war room." + }, + "chat_id": { + "type": "string", + "description": "Chat/group ID on the IM side." }, "incident_id": { - "description": "Associated incident ID (MongoDB ObjectID).", + "type": "string", "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Associated incident ID (MongoDB ObjectID)." }, - "integration_id": { - "description": "IM integration ID.", + "status": { + "type": "string", + "description": "Record status. Always `enabled` in this list, because deleted war rooms are not returned.", + "enum": [ + "enabled" + ] + }, + "created_at": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Unix timestamp (seconds) when the war room was created." }, "plugin_type": { - "description": "IM plugin type (e.g. `feishu`, `dingtalk`, `wecom`, `slack`).", - "type": "string" - }, - "status": { - "description": "War room record status: `enabled` active, `deleted` disbanded.", + "type": "string", + "description": "Plugin type of the IM integration: `feishu_app` (Feishu), `dingtalk_app` (DingTalk), `wecom_app` (WeCom), or `slack_app` (Slack). Empty string when the integration no longer exists.", "enum": [ - "enabled", - "deleted" - ], - "type": "string" + "feishu_app", + "dingtalk_app", + "wecom_app", + "slack_app", + "" + ] }, "chat_name": { "type": "string", @@ -28433,161 +29436,175 @@ "type": "boolean", "description": "True when the IM integration behind this war room is disabled or no longer exists." } - }, - "required": [ - "account_id", - "integration_id", - "created_by", - "chat_id", - "incident_id", - "status", - "created_at", - "plugin_type", - "chat_name" - ], - "type": "object" + } }, "WarRoomPersonItem": { + "type": "object", "properties": { "account_id": { + "type": "integer", "description": "Account this person belongs to.", - "format": "int64", - "type": "integer" + "format": "int64" }, - "as": { - "description": "Role the person holds in the related context.", - "type": "string" + "person_id": { + "type": "integer", + "description": "Person ID: a member ID, or the account ID when the person is the account owner (`as` = `account`).", + "format": "int64" + }, + "person_name": { + "type": "string", + "description": "Display name of the person." }, "avatar": { - "description": "URL of the person's avatar image.", - "type": "string" + "type": "string", + "description": "URL of the person's avatar image." }, "email": { - "description": "Email address of the person.", - "type": "string" + "type": "string", + "description": "Email address; omitted when the member has not verified it." + }, + "phone": { + "type": "string", + "description": "Phone number; omitted when the member has not verified it." }, "locale": { - "description": "Preferred language locale of the person.", - "type": "string" + "type": "string", + "description": "Preferred language, e.g. `zh-CN` or `en-US`." }, - "person_id": { - "description": "Person ID.", - "format": "int64", - "type": "integer" + "time_zone": { + "type": "string", + "description": "IANA time zone name, e.g. `Asia/Shanghai`." }, - "person_name": { - "description": "Display name of the person.", - "type": "string" - }, - "phone": { - "description": "Phone number of the person.", - "type": "string" + "as": { + "type": "string", + "enum": [ + "account", + "member" + ], + "description": "Identity type of the person.\n- `account`: the account owner.\n- `member`: a regular member of the account." }, "status": { - "description": "Current status of the person.", - "type": "string" - }, - "time_zone": { - "description": "Time zone of the person.", - "type": "string" + "type": "string", + "enum": [ + "enabled", + "pending", + "deleted" + ], + "description": "Membership status.\n- `enabled`: active.\n- `pending`: invited but has not joined yet.\n- `deleted`: removed from the account." } }, "required": [ "account_id", "person_id" - ], - "type": "object" + ] }, "WebhookHistoryDetail": { + "type": "object", "description": "Full detail for a webhook delivery attempt. Extends `WebhookHistoryItem` with human-friendly reference metadata resolved at query time. When no matching record exists, `data` is an empty object.", + "required": [ + "integration_id", + "event_id", + "webhook_type", + "event_type", + "endpoint", + "attempt", + "duration", + "status", + "status_code", + "event_time" + ], "properties": { - "attempt": { - "description": "Attempt sequence number.", - "type": "integer" - }, - "channel_id": { - "description": "Channel ID when applicable.", + "integration_id": { + "type": "integer", "format": "int64", - "type": "integer" - }, - "channel_name": { - "description": "Name of the associated channel, resolved at query time.", - "type": "string" - }, - "duration": { - "description": "Total elapsed time of the attempt in milliseconds.", - "type": "integer" - }, - "endpoint": { - "description": "Destination URL.", - "type": "string" - }, - "error_message": { - "description": "Error message when delivery failed.", - "type": "string" + "description": "ID of the webhook integration that sent the request." }, "event_id": { - "description": "Event ID.", - "type": "string" + "type": "string", + "description": "ID of this delivery record: the delivery date (`YYYYMMDD`) followed by a random suffix. Pass it to `POST /webhook/history/detail`." }, - "event_time": { - "description": "Event time formatted as `YYYY-MM-DD HH:MM:SS.ffffff`.", - "type": "string" + "webhook_type": { + "type": "string", + "description": "Source object kind: `incident` or `alert`.", + "enum": [ + "incident", + "alert" + ] }, "event_type": { - "description": "Event type code. `i_*` values are incident events (for example `i_new` = incident created); `a_*` values are alert events (for example `a_new` = alert triggered).", - "type": "string" + "type": "string", + "description": "Event type code. `i_*` values are incident events (for example `i_new` = incident created); `a_*` values are alert events (for example `a_new` = alert triggered)." }, - "integration_id": { - "description": "Integration ID.", + "channel_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Channel ID when applicable." }, "ref_id": { - "description": "Source object ID.", - "type": "string" + "type": "string", + "description": "Source object ID." }, - "ref_title": { - "description": "Title of the source incident or alert, resolved at query time.", - "type": "string" + "request_headers": { + "type": "string", + "description": "Serialized outbound request headers." }, "request_body": { - "description": "Outbound request body payload.", - "type": "string" + "type": "string", + "description": "JSON payload sent to the endpoint, truncated to the stored size limit." }, - "request_headers": { - "description": "Serialized outbound request headers.", - "type": "string" + "endpoint": { + "type": "string", + "description": "Destination URL." }, - "response_body": { - "description": "Response body.", - "type": "string" + "attempt": { + "type": "integer", + "description": "Number of HTTP tries made for this delivery; retries happen only on connection errors." }, - "response_headers": { - "description": "Serialized response headers.", - "type": "string" + "duration": { + "type": "integer", + "description": "Total time of the delivery including retries, in milliseconds." }, "status": { - "description": "Delivery outcome.", + "type": "string", "enum": [ "success", "failed" ], - "type": "string" + "description": "Delivery outcome: `success` when the endpoint answered HTTP 200; `failed` on a connection error or any other status code." }, "status_code": { - "description": "HTTP status code.", - "type": "integer" + "type": "integer", + "description": "HTTP status code returned by the endpoint; `0` when no response was received." }, - "webhook_type": { - "description": "Source object kind: `incident` or `alert`.", - "enum": [ - "incident", - "alert" - ], - "type": "string" + "error_message": { + "type": "string", + "description": "Error text when the delivery failed (connection error or unexpected status code), truncated. Omitted on success." + }, + "response_headers": { + "type": "string", + "description": "Serialized response headers." + }, + "response_body": { + "type": "string", + "description": "Body returned by the endpoint, truncated to the stored size limit. Omitted when empty or when no response was received." + }, + "event_time": { + "type": "string", + "description": "Event time formatted as `YYYY-MM-DD HH:MM:SS.ffffff`." + }, + "ref_title": { + "type": "string", + "description": "Title of the source incident or alert, resolved at query time." + }, + "channel_name": { + "type": "string", + "description": "Name of the associated channel, resolved at query time." } - }, + } + }, + "WebhookHistoryItem": { + "type": "object", + "description": "A single webhook delivery attempt. Fields with `omitempty` are absent when zero-valued.", "required": [ "integration_id", "event_id", @@ -28600,103 +29617,86 @@ "status_code", "event_time" ], - "type": "object" - }, - "WebhookHistoryItem": { - "description": "A single webhook delivery attempt. Fields with `omitempty` are absent when zero-valued.", "properties": { - "attempt": { - "description": "Attempt sequence number.", - "type": "integer" - }, - "channel_id": { - "description": "Channel ID associated with the event, when applicable.", + "integration_id": { + "type": "integer", "format": "int64", - "type": "integer" - }, - "duration": { - "description": "Total elapsed time of the attempt in milliseconds.", - "type": "integer" - }, - "endpoint": { - "description": "Destination URL.", - "type": "string" - }, - "error_message": { - "description": "Error message when delivery failed.", - "type": "string" + "description": "ID of the webhook integration that sent the request." }, "event_id": { - "description": "Unique event identifier for the delivery attempt.", - "type": "string" + "type": "string", + "description": "ID of this delivery record: the delivery date (`YYYYMMDD`) followed by a random suffix. Pass it to `POST /webhook/history/detail`." }, - "event_time": { - "description": "Event time formatted as `YYYY-MM-DD HH:MM:SS.ffffff`.", - "type": "string" + "webhook_type": { + "type": "string", + "description": "Source object kind: `incident` or `alert`.", + "enum": [ + "incident", + "alert" + ] }, "event_type": { - "description": "Event type code. `i_*` values are incident events (for example `i_new` = incident created); `a_*` values are alert events (for example `a_new` = alert triggered).", - "type": "string" + "type": "string", + "description": "Event type code. `i_*` values are incident events (for example `i_new` = incident created); `a_*` values are alert events (for example `a_new` = alert triggered)." }, - "integration_id": { - "description": "Integration ID that triggered the webhook.", + "channel_id": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Channel ID associated with the event, when applicable." }, "ref_id": { - "description": "Source object ID (incident ID or alert ID).", - "type": "string" + "type": "string", + "description": "Source object ID (incident ID or alert ID)." + }, + "request_headers": { + "type": "string", + "description": "Serialized outbound request headers." }, "request_body": { - "description": "Outbound request body payload.", - "type": "string" + "type": "string", + "description": "JSON payload sent to the endpoint, truncated to the stored size limit." }, - "request_headers": { - "description": "Serialized outbound request headers.", - "type": "string" + "endpoint": { + "type": "string", + "description": "Destination URL." }, - "response_body": { - "description": "Response body returned by the destination.", - "type": "string" + "attempt": { + "type": "integer", + "description": "Number of HTTP tries made for this delivery; retries happen only on connection errors." }, - "response_headers": { - "description": "Serialized response headers from the destination.", - "type": "string" + "duration": { + "type": "integer", + "description": "Total time of the delivery including retries, in milliseconds." }, "status": { - "description": "Delivery outcome.", + "type": "string", "enum": [ "success", "failed" ], - "type": "string" + "description": "Delivery outcome: `success` when the endpoint answered HTTP 200; `failed` on a connection error or any other status code." }, "status_code": { - "description": "HTTP status code returned by the destination.", - "type": "integer" + "type": "integer", + "description": "HTTP status code returned by the endpoint; `0` when no response was received." }, - "webhook_type": { - "description": "Source object kind: `incident` or `alert`.", - "enum": [ - "incident", - "alert" - ], - "type": "string" + "error_message": { + "type": "string", + "description": "Error text when the delivery failed (connection error or unexpected status code), truncated. Omitted on success." + }, + "response_headers": { + "type": "string", + "description": "Serialized response headers from the destination." + }, + "response_body": { + "type": "string", + "description": "Body returned by the endpoint, truncated to the stored size limit. Omitted when empty or when no response was received." + }, + "event_time": { + "type": "string", + "description": "Event time formatted as `YYYY-MM-DD HH:MM:SS.ffffff`." } - }, - "required": [ - "integration_id", - "event_id", - "webhook_type", - "event_type", - "endpoint", - "attempt", - "duration", - "status", - "status_code", - "event_time" - ], - "type": "object" + } }, "WorkItemAssignee": { "description": "One assignee on a work item.", @@ -28721,165 +29721,165 @@ "type": "object" }, "WorkItemCreateResult": { + "type": "object", "description": "Result of creating a work item.", + "required": [ + "item" + ], "properties": { + "item": { + "$ref": "#/components/schemas/WorkItemItem" + }, "added_assignee_ids": { - "description": "Assignee member IDs that were newly added (and notified).", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Member IDs of the person assignees added by this call (and notified); AI SRE is not included. Omitted when none." }, "idempotent_replay": { - "description": "True when the call replayed an earlier request with the same idempotency key and no new item was created.", - "type": "boolean" - }, - "item": { - "$ref": "#/components/schemas/WorkItemItem" + "type": "boolean", + "description": "True when the call replayed an earlier request with the same idempotency key and no new item was created." } - }, - "required": [ - "item" - ], - "type": "object" + } }, "WorkItemItem": { + "type": "object", "description": "A structured incident work item (action or post-mortem follow-up) with its assignees.", + "required": [ + "work_item_id", + "item_type", + "incident_id", + "title", + "status", + "source_kind", + "version", + "assignee_ids", + "assignees", + "created_by", + "updated_by", + "created_at_seconds", + "updated_at_seconds" + ], "properties": { - "agent_session_id": { - "description": "ID of the AI SRE session executing this item. Omitted when no session is recorded.", - "type": "string" + "work_item_id": { + "type": "string", + "maxLength": 128, + "description": "Work item ID (opaque string, max 128 characters)." }, - "agent_session_venue": { - "description": "Where that AI SRE session runs: `web` or `im`. Omitted when no session is recorded.", + "item_type": { + "type": "string", "enum": [ - "web", - "im" + "action", + "follow_up" ], - "type": "string" + "description": "Work item type.\n- `action`: a to-do on an incident that is not closed yet.\n- `follow_up`: a post-mortem follow-up, created on a closed incident or converted from an action." }, - "assignee_ids": { - "description": "Member IDs of the current person assignees. AI SRE is not included. Never null; an empty array means no person assignee.", - "items": { - "format": "int64", - "type": "integer" - }, - "type": "array" - }, - "assignees": { - "description": "Current assignees. Each entry is `{type, id?}`. `type` is `person` or `ai_sre`; an `ai_sre` entry omits `id`. Never null; an empty array means unassigned. `assignee_ids` is the person-only subset of this list.", - "items": { - "$ref": "#/components/schemas/WorkItemAssignee" - }, - "type": "array" - }, - "converted_at_seconds": { - "description": "Conversion time as a Unix timestamp in seconds. Present only after conversion.", - "format": "int64", - "type": "integer" - }, - "converted_by": { - "description": "Member ID of the operator who converted the action into a follow-up. Present only after conversion.", - "format": "int64", - "type": "integer" + "incident_id": { + "type": "string", + "pattern": "^[0-9a-fA-F]{24}$", + "description": "Incident ID (MongoDB ObjectID) the item is anchored to." }, - "created_at_seconds": { - "description": "Creation time as a Unix timestamp in seconds.", - "format": "int64", - "type": "integer" + "post_mortem_id": { + "type": "string", + "description": "Post-mortem ID (32-character hex string). Present only on follow-ups bound to a report; omitted otherwise." }, - "created_by": { - "description": "Member ID of the creator.", - "format": "int64", - "type": "integer" + "title": { + "type": "string", + "maxLength": 512, + "description": "Item title (max 512 characters)." }, "description": { - "description": "Optional longer description (max 65,535 characters).", + "type": "string", "maxLength": 65535, - "type": "string" - }, - "incident_id": { - "description": "Incident ID (MongoDB ObjectID) the item is anchored to.", - "pattern": "^[0-9a-fA-F]{24}$", - "type": "string" + "description": "Optional longer description (max 65,535 characters)." }, - "item_type": { - "description": "`action` for an item anchored to an active incident; `follow_up` for a post-mortem follow-up.", - "enum": [ - "action", - "follow_up" - ], - "type": "string" - }, - "legacy_source_id": { - "description": "Original identifier of the legacy follow-up this item was migrated from. Present only when `source_kind` is `legacy_follow_up`.", - "type": "string" - }, - "post_mortem_id": { - "description": "Post-mortem ID (32-character hex string). Present on follow-up items once bound to a post-mortem.", - "type": "string" + "status": { + "type": "string", + "maxLength": 64, + "description": "Item status: `open` (not started), `in_progress` (being worked on), `done` (finished) or `cancelled` (no longer needed). `done` and `cancelled` count as finished. Older items may still hold other free text, which counts as unfinished." }, "priority": { - "description": "Optional client-defined priority (max 64 characters).", + "type": "string", "maxLength": 64, - "type": "string" + "description": "Free-form priority, at most 64 characters; omitted when empty. The console uses `high`, `medium` and `low`, but any string set through the API is returned as-is." }, "source_kind": { - "description": "`native` for items created through this API; `legacy_follow_up` for items migrated from legacy post-mortem follow-ups.", + "type": "string", "enum": [ "native", "legacy_follow_up" ], - "type": "string" + "description": "`native` for items created through this API; `legacy_follow_up` for items migrated from legacy post-mortem follow-ups." }, - "status": { - "description": "Client-defined status (max 64 characters). There is no fixed state machine.", - "maxLength": 64, + "legacy_source_id": { + "type": "string", + "description": "Original identifier of the legacy follow-up this item was migrated from. Present only when `source_kind` is `legacy_follow_up`." + }, + "version": { + "type": "integer", + "format": "int64", + "description": "Optimistic-locking version, incremented on every mutation." + }, + "assignee_ids": { + "type": "array", + "items": { + "type": "integer", + "format": "int64" + }, + "description": "Member IDs of the current person assignees. AI SRE is not included. Never null; an empty array means no person assignee." + }, + "assignees": { + "description": "Current assignees. Each entry is `{type, id?}`. `type` is `person` or `ai_sre`; an `ai_sre` entry omits `id`. Never null; an empty array means unassigned. `assignee_ids` is the person-only subset of this list.", + "items": { + "$ref": "#/components/schemas/WorkItemAssignee" + }, + "type": "array" + }, + "agent_session_id": { + "description": "ID of the AI SRE session executing this item. Omitted when no session is recorded.", "type": "string" }, - "title": { - "description": "Item title (max 512 characters).", - "maxLength": 512, + "agent_session_venue": { + "description": "Where that AI SRE session runs: `web` or `im`. Omitted when no session is recorded.", + "enum": [ + "web", + "im" + ], "type": "string" }, - "updated_at_seconds": { - "description": "Last update time as a Unix timestamp in seconds.", + "created_by": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Member ID of the creator." }, "updated_by": { - "description": "Member ID of the last updater.", + "type": "integer", "format": "int64", - "type": "integer" + "description": "Member ID of the last updater." }, - "version": { - "description": "Optimistic-locking version, incremented on every mutation.", + "converted_by": { + "type": "integer", "format": "int64", - "type": "integer" + "description": "Member ID of the operator who converted the action into a follow-up. Present only after conversion." }, - "work_item_id": { - "description": "Work item ID (opaque string, max 128 characters).", - "maxLength": 128, - "type": "string" + "converted_at_seconds": { + "type": "integer", + "format": "int64", + "description": "Conversion time as a Unix timestamp in seconds. Present only after conversion." + }, + "created_at_seconds": { + "type": "integer", + "format": "int64", + "description": "Creation time as a Unix timestamp in seconds." + }, + "updated_at_seconds": { + "type": "integer", + "format": "int64", + "description": "Last update time as a Unix timestamp in seconds." } - }, - "required": [ - "work_item_id", - "item_type", - "incident_id", - "title", - "status", - "source_kind", - "version", - "assignee_ids", - "assignees", - "created_by", - "updated_by", - "created_at_seconds", - "updated_at_seconds" - ], - "type": "object" + } }, "WorkItemListResult": { "description": "Cursor-paginated list of work items.", @@ -28911,33 +29911,33 @@ "type": "object" }, "WorkItemMutationResult": { - "description": "Result of mutating a work item.", + "type": "object", + "description": "Result of mutating a work item. `item` is absent for delete.", "properties": { + "item": { + "$ref": "#/components/schemas/WorkItemItem" + }, "added_assignee_ids": { - "description": "Assignee member IDs that were newly added (and notified).", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" - }, - "idempotent_replay": { - "description": "True when the call replayed an earlier request with the same idempotency key.", - "type": "boolean" - }, - "item": { - "$ref": "#/components/schemas/WorkItemItem" + "description": "Member IDs of the person assignees added by this call (and notified); AI SRE is not included. Omitted when none." }, "removed_assignee_ids": { - "description": "Assignee member IDs that were removed (never notified).", + "type": "array", "items": { - "format": "int64", - "type": "integer" + "type": "integer", + "format": "int64" }, - "type": "array" + "description": "Member IDs of the person assignees removed by this call (never notified). Omitted when none." + }, + "idempotent_replay": { + "type": "boolean", + "description": "True when the call replayed an earlier request with the same idempotency key." } - }, - "type": "object" + } }, "AlertRuleV2": { "type": "object", @@ -28967,11 +29967,11 @@ "additionalProperties": { "type": "string" }, - "description": "Custom labels." + "description": "Custom labels added to every alert event of the rule. Keys are trimmed, must not be empty and must not start with `__alert_rule_` (reserved); values containing `{{` are rendered as templates when events are delivered; `job` and `instance` values are limited to 255 characters. The serialized object may not exceed 1024 characters." }, "ds_type": { "type": "string", - "description": "Datasource type identifier (e.g. `prometheus`, `elasticsearch`)." + "description": "Datasource type the rule queries. When the rule is enabled it must be a type that supports alerting: `prometheus`, `elasticsearch`, `loki`, `clickhouse`, `mysql`, `oracle`, `postgres`, `sls`, `tencent_cls`, `victorialogs`." }, "ds_list": { "type": "array", @@ -29002,7 +30002,7 @@ }, "cron_pattern": { "type": "string", - "description": "Schedule expression: a 6-field cron (with seconds) or an `@every 30s` interval. Must not start with `CRON_TZ=` or `TZ=`; set the timezone in the `timezone` field instead." + "description": "Schedule expression: a 6-field cron with seconds (e.g. `0 * * * * *`), a descriptor such as `@hourly`, or `@every ` with a whole number of seconds of at least `1s` (e.g. `@every 30s`). Must not start with `CRON_TZ=` or `TZ=`; set the timezone in the `timezone` field instead." }, "timezone": { "type": "string", @@ -29039,15 +30039,15 @@ "items": { "type": "integer" }, - "description": "Days of week (0=Sunday)." + "description": "Days of week the window applies to, `0` = Sunday through `6` = Saturday; non-empty, no duplicates." }, "stime": { "type": "string", - "description": "Start time, e.g. `09:00`." + "description": "Start time in 24-hour `HH:MM` format, e.g. `09:00`." }, "etime": { "type": "string", - "description": "End time, e.g. `18:00`." + "description": "End time in 24-hour `HH:MM` format, e.g. `18:00`." } } } @@ -29070,7 +30070,7 @@ }, "description": { "type": "string", - "description": "Rule description, Markdown format." + "description": "Rule description; rendered as plain text or Markdown according to `description_type`." }, "channel_ids": { "type": "array", @@ -29083,12 +30083,12 @@ "repeat_interval": { "type": "integer", "format": "int64", - "description": "Notification repeat interval in seconds. Values below 1 fall back to the default 3600." + "description": "Notification repeat interval in seconds. Values below 1 fall back to the default 3600; maximum 2147483647." }, "repeat_total": { "type": "integer", "format": "int64", - "description": "Maximum number of repeat notifications. Values below 1 fall back to the default 3." + "description": "Maximum number of repeat notifications. Values below 1 fall back to the default 3; maximum 2147483647." }, "investigation_targets": { "type": "array", @@ -29096,7 +30096,7 @@ "$ref": "#/components/schemas/InvestigationTarget" }, "maxItems": 20, - "description": "Drill-down entries linked from the alert event detail page; at most 20 items, duplicates rejected. On update the field is presence-based: omit it to keep the current value, pass `[]` to clear.", + "description": "Drill-down entries linked from the alert event detail page; at most 20 items, duplicates rejected, and at most 32 KiB once serialized. On update the field is presence-based: omit it to keep the current value, pass `[]` to clear; `null` is rejected.", "x-flashduty-preserve-absence": true }, "creator_id": { @@ -29181,7 +30181,7 @@ }, "relate_queries": { "type": "array", - "description": "Optional auxiliary queries whose results attach to alert events as context. Each entry needs a unique `name` (not colliding with any query name) and a non-empty `expr`.", + "description": "Optional auxiliary queries whose results attach to alert events as context. Each entry needs a unique `name` (not colliding with any query name) and a non-empty `expr`. Always returned, as `[]` when there are none.", "items": { "type": "object", "properties": { @@ -29500,7 +30500,7 @@ }, "DashboardQuery": { "type": "object", - "description": "Query payload shared by dashboards and drill-down entries.", + "description": "Query payload shared by dashboard panels and alert rule drill-down entries. Template syntax differs by context: dashboard panels use dashboard variables (`${name}`), drill-down entries use event labels (`{{ }}`).", "properties": { "mode": { "type": "string", @@ -29509,18 +30509,18 @@ "range", "window" ], - "description": "Evaluation mode: `instant` evaluates at a single timestamp, `range` evaluates a stepped series, `window` returns raw rows inside a time window." + "description": "Evaluation mode: `instant` = evaluate at a single timestamp; `range` = evaluate a stepped series over the time range; `window` = return raw rows inside the time range. Dashboard panels on Prometheus and Loki accept `instant` or `range` (Loki `logs` panels need `range`); MySQL panels need `window`." }, "expr": { "type": "string", - "description": "Query expression in the target data source's language. May reference event labels through `{{ }}` templates." + "description": "Query expression in the datasource's language. In dashboard panels it may reference variables as `${name}`, `${name:raw}` (one value inserted as is) or `${name:regex}` (values joined as a regex alternation), or as `$name` in Prometheus and Loki; write `$${...}` for a literal. Without a formatter, multi-value or `all` variables and values inside `=~`/`!~` are inserted in regex form, so they cannot be used with `=` or `!=`. MySQL queries do not support variables. In drill-down entries the expression may reference event labels through `{{ }}` templates." }, "args": { "type": "object", "additionalProperties": { "type": "string" }, - "description": "Named query arguments; defaults to an empty object. Values are passed through verbatim and must not contain `{{ }}` templates." + "description": "Named query arguments; defaults to an empty object. In dashboard panels values may use `${name}` templates except for Loki and MySQL datasources. In drill-down entries keys and values must not contain `{{ }}` templates." }, "min_step_seconds": { "type": [ @@ -29530,7 +30530,7 @@ "format": "int64", "minimum": 1, "maximum": 9007199254740, - "description": "Minimum step, in seconds. Only accepted when `mode` is `range`, and must be greater than zero; omit or pass null to let the server decide." + "description": "Minimum step, in seconds; must be greater than zero. In drill-down entries it is only accepted when `mode` is `range`. Omit or pass null to let the server decide." } }, "required": [ @@ -29647,7 +30647,7 @@ }, "DashboardDefinition": { "type": "object", - "description": "Complete dashboard payload stored as a portable `dashboard.v1` document. Unknown keys, duplicate keys, NaN/Inf, over-range numbers and trailing values are rejected; the serialized form must stay within 1 MiB.", + "description": "Complete dashboard payload stored as a portable `dashboard.v1` document. Unknown keys, duplicate keys, trailing values and nesting deeper than 32 levels are rejected, and the serialized form must stay within 1 MiB. Limits: 10 tabs, 10 sections per tab, 30 panels and 100 queries per tab, 100 panels and 300 queries per dashboard, 20 variables.", "properties": { "title": { "type": "string", @@ -29679,7 +30679,7 @@ "$ref": "#/components/schemas/DashboardVariable" }, "maxItems": 20, - "description": "Dashboard variables, at most 20. Names must be unique within the definition and match the variable-name pattern." + "description": "Dashboard variables, at most 20, with unique names. Variables may reference other variables but not in a cycle." }, "tabs": { "type": "array", @@ -29688,7 +30688,7 @@ }, "minItems": 1, "maxItems": 10, - "description": "Tabs, 1–10. Every tab title is unique and every tab or section ID must be a canonical UUIDv7 used only once across the definition." + "description": "Tabs, 1–10. Every tab, section and panel `id` must be a canonical UUIDv7 used only once across the definition. Tab titles do not need to be unique." } }, "required": [ @@ -29743,7 +30743,7 @@ "type": "string", "minLength": 1, "maxLength": 189, - "description": "Tab title, 1–189 Unicode code points. Unique among tabs." + "description": "Tab title, 1–189 Unicode code points after trimming." }, "description": { "type": "string", @@ -29756,7 +30756,7 @@ "$ref": "#/components/schemas/DashboardPanel" }, "maxItems": 30, - "description": "Panels placed directly on the tab, at most 30." + "description": "Panels placed directly on the tab. A tab holds at most 30 panels in total, counting top panels and section panels, and at most 100 queries." }, "sections": { "type": "array", @@ -29804,7 +30804,7 @@ "$ref": "#/components/schemas/DashboardPanel" }, "maxItems": 30, - "description": "Panels in the section, at most 30." + "description": "Panels in the section; they count toward the tab's 30-panel limit." } }, "required": [ @@ -29816,7 +30816,7 @@ }, "DashboardPanel": { "type": "object", - "description": "A single visualization. Panels must not overlap inside the same container; the 24-column grid is validated on save.", + "description": "A single visualization. `datasource_ref` is required for every kind except `text`, where it is forbidden. Panels must not overlap inside the same container; the 24-column grid is validated on save.", "properties": { "id": { "type": "string", @@ -29911,17 +30911,18 @@ "type": "integer", "format": "uint64", "minimum": 1, - "description": "Datasource ID. Required when `kind` is `fixed`, forbidden when `kind` is `variable`." + "description": "Datasource ID. Required when `kind` is `fixed`, forbidden when `kind` is `variable`.", + "maximum": 9007199254740991 }, "name": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", - "description": "Datasource variable name. Required when `kind` is `variable`, forbidden when `kind` is `fixed`." + "description": "Name of a `datasource` variable in the same definition. Required when `kind` is `variable`, forbidden when `kind` is `fixed`." }, "datasource_type": { "type": "string", "pattern": "^[a-z][a-z0-9_]{0,63}$", - "description": "Datasource type identifier, e.g. `prometheus` or `victorialogs`." + "description": "Datasource type identifier: lowercase letters, digits and underscores, starting with a letter. The set is open, so saving accepts any such value, but the dashboard runtime only runs `prometheus`, `mysql` and `loki` datasources; panels on other types fail when run. With `kind` = `variable` it must equal the referenced datasource variable's `datasource_type`." } }, "required": [ @@ -29944,7 +30945,7 @@ "legend_alias": { "type": "string", "maxLength": 1024, - "description": "Optional legend label; supports the same variable templates as `expr`." + "description": "Optional legend label, at most 1024 Unicode code points. The console replaces `{{label}}` with that series label's value (for example `{{env}} requests`); dashboard variables are not substituted here." } }, "required": [ @@ -29988,7 +30989,7 @@ "name": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", - "description": "Variable name used in `{{ }}` templates, at most 64 characters. Names starting with `__` are reserved for built-in time variables." + "description": "Variable name, unique within the definition. Queries reference it as `${name}` (or `$name` inside Prometheus and Loki expressions). Names starting with `__` are reserved for the built-in variables `__interval`, `__rate_interval`, `__range` and `__auto`." }, "label": { "type": "string", @@ -29998,7 +30999,7 @@ "datasource_type": { "type": "string", "pattern": "^[a-z][a-z0-9_]{0,63}$", - "description": "Datasource type the candidates are drawn from." + "description": "Type of datasource offered as candidates; candidates are the account's enabled datasources of this type. The set is open, so saving accepts any such value, but the dashboard runtime only runs `prometheus`, `mysql` and `loki` datasources; panels on other types fail when run. " }, "name_patterns": { "type": "array", @@ -30013,7 +31014,8 @@ "default_datasource_id": { "type": "integer", "format": "uint64", - "description": "Default datasource ID. Without a usable default the runtime picks the first candidate by name, then ID." + "description": "Default datasource ID. Without a usable default the runtime picks the first candidate by name, then ID.", + "maximum": 9007199254740991 } }, "required": [ @@ -30036,7 +31038,7 @@ "name": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", - "description": "Variable name used in `{{ }}` templates, at most 64 characters. Names starting with `__` are reserved for built-in time variables." + "description": "Variable name, unique within the definition. Queries reference it as `${name}` (or `$name` inside Prometheus and Loki expressions). Names starting with `__` are reserved for the built-in variables `__interval`, `__rate_interval`, `__range` and `__auto`." }, "label": { "type": "string", @@ -30080,7 +31082,7 @@ "name": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", - "description": "Variable name used in `{{ }}` templates, at most 64 characters. Names starting with `__` are reserved for built-in time variables." + "description": "Variable name, unique within the definition. Queries reference it as `${name}` (or `$name` inside Prometheus and Loki expressions). Names starting with `__` are reserved for the built-in variables `__interval`, `__rate_interval`, `__range` and `__auto`." }, "label": { "type": "string", @@ -30141,7 +31143,7 @@ }, "DashboardSelection": { "type": "object", - "description": "A concrete selection of variable values. An empty `values` array is valid wire input and means unresolved — the server never substitutes a default for it.", + "description": "A concrete selection of variable values. As a saved variable `default`, `values` must be non-empty and hold exactly one value in `single` mode. In runtime requests an empty `values` array is valid and means unresolved — the server never substitutes a default for it.", "properties": { "kind": { "type": "string", @@ -30228,7 +31230,7 @@ }, "metric": { "type": "string", - "description": "Optional metric used to restrict the series considered." + "description": "Optional metric selector that restricts the series considered; may reference other variables as `${name}` or `$name`." }, "label_filters": { "type": "array", @@ -30250,7 +31252,7 @@ "label": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_:.\\-]{0,189}$", - "description": "Label name." + "description": "Prometheus label name to match, e.g. `job`; letters, digits, `_`, `:`, `.` and `-`, starting with a letter or `_`." }, "op": { "type": "string", @@ -30265,7 +31267,7 @@ "value": { "type": "string", "minLength": 1, - "description": "Matcher value; may reference other variables through `{{ }}`." + "description": "Matcher value; may reference other variables as `${name}`. A multi-value or `all` variable needs `=~` or `!~`." } }, "required": [ @@ -30287,7 +31289,7 @@ }, "expr": { "type": "string", - "description": "SQL statement; may reference other variables through `{{ }}`." + "description": "SQL statement whose result supplies the candidates. SQL variable queries run only on MySQL datasources, and MySQL queries do not support variable references." }, "args": { "type": "object", @@ -30326,7 +31328,7 @@ }, "expr": { "type": "string", - "description": "Logs query expression; may reference other variables through `{{ }}`. May be empty for a Loki datasource, which then lists the field's values across all streams." + "description": "Logs query expression; may reference other variables as `${name}`. Logs variable queries run only on Loki datasources, where `expr` may be empty to list the field's values across all streams." }, "args": { "type": "object", @@ -30349,7 +31351,7 @@ ] }, "DashboardVizConfig": { - "description": "Visualization configuration. `kind` selects the arm and therefore which sibling config object is required; `time_series` also carries the shared numeric options.", + "description": "Visualization configuration. `kind` selects the arm and therefore which sibling fields are allowed; `time_series`, `stat`, `bar` and `gauge` also carry the shared numeric fields `unit`, `decimals` and `threshold`. Fields of another kind are rejected.", "oneOf": [ { "$ref": "#/components/schemas/DashboardTimeSeriesViz" @@ -30416,7 +31418,7 @@ "bytes_per_second", "bits_per_second" ], - "description": "Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second." + "description": "Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. Defaults to `unitless` when omitted." }, "decimals": { "type": [ @@ -30424,7 +31426,8 @@ "null" ], "minimum": 0, - "description": "Fixed decimal places; omit or send null to let the renderer decide." + "description": "Fixed number of decimal places, 0–15; omit or send null to let the console decide.", + "maximum": 15 }, "threshold": { "$ref": "#/components/schemas/DashboardThreshold" @@ -30456,15 +31459,14 @@ "additionalProperties": { "$ref": "#/components/schemas/DashboardColumnOption" }, - "description": "Per-column display overrides keyed by field name, at most 100 entries." + "description": "Per-column display overrides keyed by result field name, at most 100 entries. Keys must be non-empty, at most 1024 Unicode code points and not `frame_index` or `field_index`." }, "sort": { "type": "array", "items": { "$ref": "#/components/schemas/DashboardFieldSort" }, - "maxItems": 2, - "description": "Initial sort keys; fields must be unique." + "description": "Initial sort keys, applied in order; each field may appear once." }, "link_columns": { "type": "array", @@ -30510,7 +31512,7 @@ "bytes_per_second", "bits_per_second" ], - "description": "Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second." + "description": "Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. Defaults to `unitless` when omitted." }, "decimals": { "type": [ @@ -30518,7 +31520,8 @@ "null" ], "minimum": 0, - "description": "Fixed decimal places; omit or send null to let the renderer decide." + "description": "Fixed number of decimal places, 0–15; omit or send null to let the console decide.", + "maximum": 15 }, "threshold": { "$ref": "#/components/schemas/DashboardThreshold" @@ -30528,7 +31531,9 @@ "items": { "type": "string" }, - "description": "Fields reduced to the displayed values." + "description": "Result fields reduced to the displayed values; at least one, each listed once. Names are matched exactly and must not be `frame_index` or `field_index`.", + "minItems": 1, + "uniqueItems": true }, "reducer": { "type": "string", @@ -30579,7 +31584,7 @@ "bytes_per_second", "bits_per_second" ], - "description": "Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second." + "description": "Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. Defaults to `unitless` when omitted." }, "decimals": { "type": [ @@ -30587,21 +31592,25 @@ "null" ], "minimum": 0, - "description": "Fixed decimal places; omit or send null to let the renderer decide." + "description": "Fixed number of decimal places, 0–15; omit or send null to let the console decide.", + "maximum": 15 }, "threshold": { "$ref": "#/components/schemas/DashboardThreshold" }, "category_field": { "type": "string", - "description": "Field supplying the category axis." + "description": "Result field supplying the category axis; required, at most 1024 Unicode code points, not `frame_index` or `field_index`.", + "minLength": 1 }, "value_fields": { "type": "array", "items": { "type": "string" }, - "description": "Fields supplying the bar values." + "description": "Result fields supplying the bar values; at least one, each listed once. Names must not be `frame_index` or `field_index`.", + "minItems": 1, + "uniqueItems": true }, "data_link": { "$ref": "#/components/schemas/DashboardDataLink" @@ -30644,7 +31653,7 @@ "bytes_per_second", "bits_per_second" ], - "description": "Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second." + "description": "Display unit for the panel's numeric values: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. Defaults to `unitless` when omitted." }, "decimals": { "type": [ @@ -30652,7 +31661,8 @@ "null" ], "minimum": 0, - "description": "Fixed decimal places; omit or send null to let the renderer decide." + "description": "Fixed number of decimal places, 0–15; omit or send null to let the console decide.", + "maximum": 15 }, "threshold": { "$ref": "#/components/schemas/DashboardThreshold" @@ -30662,7 +31672,9 @@ "items": { "type": "string" }, - "description": "Fields reduced to the gauge value." + "description": "Result fields reduced to the gauge value; at least one, each listed once. Names are matched exactly and must not be `frame_index` or `field_index`.", + "minItems": 1, + "uniqueItems": true }, "reducer": { "type": "string", @@ -30745,7 +31757,7 @@ "markdown": { "type": "string", "maxLength": 65536, - "description": "Markdown body, at most 64 KiB. Only a restricted node set (headings, lists, tables, links, code) survives validation." + "description": "Markdown body, at most 64 KiB. Allowed: paragraphs, headings, lists, block quotes, code blocks and spans, emphasis, tables, horizontal rules and links. Links must be `https://` URLs or site-relative paths starting with `/`. Images, raw HTML and `${` templates are rejected with `InvalidParameter`, not stripped." } }, "required": [ @@ -30823,7 +31835,7 @@ "bytes_per_second", "bits_per_second" ], - "description": "Unit override for the column: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second." + "description": "Unit override for the column: `unitless` = raw number; `ratio` = fraction of 1; `percent` = percentage; `milliseconds` = duration in milliseconds; `seconds` = duration in seconds; `bytes` = size in bytes; `bits` = size in bits; `count_per_second` = per-second count; `bytes_per_second` = bytes per second; `bits_per_second` = bits per second. Defaults to `unitless` when omitted." }, "threshold": { "$ref": "#/components/schemas/DashboardThreshold" @@ -30848,7 +31860,7 @@ "field": { "type": "string", "minLength": 1, - "description": "Field name to sort by." + "description": "Result field name to sort by; at most 1024 Unicode code points, not `frame_index` or `field_index`." }, "direction": { "type": "string", @@ -30866,12 +31878,12 @@ }, "DashboardDataLink": { "type": "object", - "description": "Drill-down link from a table column or bar panel into another dashboard. The target dashboard must exist and the mapping sources must match the source panel's shape.", + "description": "Drill-down link from a table or bar panel into another dashboard. Only the ID format is checked on save; a link to a dashboard that does not exist is accepted. The mapping sources allowed depend on the source panel kind.", "properties": { "dashboard_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Target dashboard ID." + "description": "ID of the dashboard to open; must be a canonical UUIDv7." }, "target_id": { "type": "string", @@ -30887,7 +31899,7 @@ "additionalProperties": { "$ref": "#/components/schemas/DashboardLinkMapping" }, - "description": "Maps target variable names to a source value such as a column or a source variable." + "description": "Values to set in the target dashboard, keyed by target variable name (must match `^[A-Za-z_][A-Za-z0-9_]{0,63}$`); each entry says where the value comes from. Send `{}` for none." } }, "required": [ @@ -30909,15 +31921,15 @@ "series", "value" ], - "description": "Where the value comes from: `variable` = a dashboard variable; `row_column` = a table column (requires `column`); `category` = the bar category; `series` = the series name; `value` = the value itself. `category`, `series` and `value` are only valid for bar panels." + "description": "Where the value comes from: `variable` = the current value of a variable of the source dashboard (requires `name`), allowed on table and bar panels; `row_column` = the clicked row's value in a table column (requires `column`), table panels only; `category` = the clicked bar's category, `series` = its series name, `value` = its value — these three are bar panels only and take no extra fields." }, "column": { "type": "string", - "description": "Source column name; required when `source` is `row_column`." + "description": "Table column (result field) to read; required when `source` is `row_column` and forbidden otherwise." }, "name": { "type": "string", - "description": "Source dashboard variable name; required when `source` is `variable`." + "description": "Variable of the source dashboard to read; required when `source` is `variable` and must exist in the same definition; forbidden for other sources." } }, "required": [ @@ -30931,11 +31943,11 @@ "id": { "type": "integer", "format": "uint64", - "description": "Member ID." + "description": "Member ID of the person who performed the action." }, "name": { "type": "string", - "description": "Member display name." + "description": "Member display name, recorded at the time of the action." } }, "required": [ @@ -31018,13 +32030,13 @@ "dashboard_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Dashboard ID." + "description": "Dashboard ID; pass it to `POST /monit/dashboard/get` for the full definition." }, "folder_id": { "type": "integer", "format": "uint64", "minimum": 1, - "description": "Folder ID." + "description": "ID of the folder the dashboard is stored in." }, "folder_breadcrumb": { "type": "array", @@ -31039,7 +32051,7 @@ }, "description": { "type": "string", - "description": "Dashboard description; empty when unset." + "description": "Dashboard description; omitted when unset." }, "revision": { "type": "integer", @@ -31095,7 +32107,7 @@ "dashboard_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Dashboard ID." + "description": "ID of the trashed dashboard; pass it to `POST /monit/dashboard/restore`." }, "folder_id": { "type": "integer", @@ -31116,13 +32128,13 @@ }, "description": { "type": "string", - "description": "Dashboard description; empty when unset." + "description": "Dashboard description; omitted when unset." }, "revision": { "type": "integer", "format": "uint64", "minimum": 1, - "description": "Revision the dashboard had when deleted." + "description": "Current revision of the trashed dashboard (the deletion bumped it); send it as `expected_revision` to restore." }, "deleted_by": { "$ref": "#/components/schemas/DashboardActor" @@ -31157,7 +32169,7 @@ "total": { "type": "integer", "format": "int64", - "description": "Total number of deleted dashboards." + "description": "Total number of trashed dashboards visible to the caller, across all pages." } }, "required": [ @@ -31167,11 +32179,11 @@ }, "DashboardUpdateOutput": { "type": "object", - "description": "Result of an update or move. `changed` is false when the write was a no-op — the canonical serialized definition matched the stored one byte for byte, in which case `resource` still describes the unchanged dashboard.", + "description": "Result of an update or move. `changed` is false when nothing was written — for update, the normalized definition and `schema_version` equal the stored ones; for move, the dashboard is already in the target folder. `revision` then stays the same and `resource` describes the unchanged dashboard.", "properties": { "changed": { "type": "boolean", - "description": "Whether the stored dashboard actually changed." + "description": "Whether the dashboard was written and its `revision` incremented." }, "resource": { "$ref": "#/components/schemas/DashboardResource" @@ -31189,13 +32201,13 @@ "dashboard_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Dashboard ID." + "description": "ID of the dashboard moved to the trash." }, "revision": { "type": "integer", "format": "uint64", "minimum": 1, - "description": "Revision recorded for the deletion." + "description": "Revision after the deletion; send it as `expected_revision` to restore." } }, "required": [ @@ -31210,7 +32222,7 @@ "dashboard_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Dashboard ID." + "description": "ID of the dashboard this revision belongs to." }, "revision": { "type": "integer", @@ -31227,7 +32239,7 @@ "message": { "type": "string", "maxLength": 1024, - "description": "Optional commit message; at most 1024 Unicode code points." + "description": "Message passed to `POST /monit/dashboard/update`; omitted when none was given and on revisions written by create, move, delete and restore." }, "actor": { "$ref": "#/components/schemas/DashboardActor" @@ -31269,7 +32281,7 @@ "dashboard_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Dashboard ID." + "description": "ID of the dashboard this revision belongs to." }, "schema_version": { "type": "string", @@ -31296,7 +32308,7 @@ "message": { "type": "string", "maxLength": 1024, - "description": "Optional commit message." + "description": "Message passed to `POST /monit/dashboard/update`; omitted when none was given." }, "actor": { "$ref": "#/components/schemas/DashboardActor" @@ -31356,7 +32368,7 @@ "dashboard_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Dashboard ID." + "description": "Dashboard ID, as passed in the request." }, "title": { "type": "string", @@ -31364,7 +32376,7 @@ }, "description": { "type": "string", - "description": "Dashboard description; empty when unset." + "description": "Dashboard description; omitted when unset." }, "revision": { "type": "integer", @@ -31393,7 +32405,7 @@ "type": "integer", "format": "uint64", "minimum": 1, - "description": "Folder ID." + "description": "ID of the folder the dashboard is stored in." }, "breadcrumb": { "type": "array", @@ -31419,7 +32431,7 @@ }, "label": { "type": "string", - "description": "Display label; empty when unset." + "description": "Display label; omitted when unset." }, "kind": { "type": "string", @@ -31446,15 +32458,15 @@ "id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Tab ID." + "description": "Tab ID; pass it as `target_id` to narrow the outline to this tab." }, "title": { "type": "string", - "description": "Tab title." + "description": "Tab title as stored in the definition." }, "description": { "type": "string", - "description": "Tab description; empty when unset." + "description": "Tab description; omitted when unset." }, "breadcrumb": { "type": "array", @@ -31493,7 +32505,7 @@ "id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Section ID." + "description": "Section ID; pass it as `target_id` to narrow the outline to this section." }, "title": { "type": "string", @@ -31501,7 +32513,7 @@ }, "description": { "type": "string", - "description": "Section description; empty when unset." + "description": "Section description; omitted when unset." }, "breadcrumb": { "type": "array", @@ -31532,7 +32544,7 @@ "id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Panel ID." + "description": "Panel ID; use it as `panel_id` for `POST /monit/dashboard/panel/run` or as `target_id` here." }, "title": { "type": "string", @@ -31540,7 +32552,7 @@ }, "description": { "type": "string", - "description": "Panel description; empty when unset." + "description": "Panel description; omitted when unset." }, "breadcrumb": { "type": "array", @@ -31554,7 +32566,7 @@ }, "datasource_type": { "type": "string", - "description": "Datasource type the panel queries; empty when the panel has no datasource (text panels)." + "description": "Datasource type from the panel's `datasource_ref`, such as `prometheus`, `mysql` or `loki`; omitted for text panels, which have no datasource. The set is open: it echoes whatever type was saved." } }, "required": [ @@ -31620,7 +32632,7 @@ "dashboard_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Canonical UUIDv7 of the dashboard." + "description": "Lowercase canonical UUIDv7 generated by the caller; it becomes the dashboard's permanent ID." }, "schema_version": { "type": "string", @@ -31633,7 +32645,7 @@ "type": "integer", "format": "uint64", "minimum": 1, - "description": "Folder the dashboard is created in. Must be a folder the caller can write." + "description": "Folder to create the dashboard in; must exist and be accessible to the `app_key` owner, otherwise `FolderNotFound`." }, "definition": { "$ref": "#/components/schemas/DashboardDefinition" @@ -31736,7 +32748,7 @@ "type": "integer", "format": "uint64", "minimum": 1, - "description": "Destination folder ID." + "description": "Destination folder ID; must exist and be accessible to the caller, otherwise `FolderNotFound`." } }, "required": [ @@ -31747,7 +32759,7 @@ }, "DashboardDeleteRequest": { "type": "object", - "description": "Move a dashboard to the trash. The definition is retained for 30 days so the delete can be undone with the restore endpoint.", + "description": "Move a dashboard to the trash. It is purged permanently 30 days after deletion; until then the restore endpoint can undo the delete.", "properties": { "dashboard_id": { "type": "string", @@ -31779,7 +32791,7 @@ "type": "integer", "format": "uint64", "minimum": 1, - "description": "Revision the caller last read. The write fails with `DashboardRevisionConflict` unless it still matches the stored revision." + "description": "Current revision of the trashed dashboard, as returned by the delete call or listed in the trash. The restore fails with `DashboardRevisionConflict` if it does not match." }, "folder_id": { "type": [ @@ -31788,7 +32800,7 @@ ], "format": "uint64", "minimum": 1, - "description": "Destination folder. Omit to restore to the original folder; when the original folder is no longer writable the call fails with `RestoreFolderRequired` and you must pass one." + "description": "Destination folder. Omit or send null to restore into the original folder; if that folder no longer exists the call fails with `RestoreFolderRequired` and a destination must be passed." } }, "required": [ @@ -31825,12 +32837,12 @@ "type": "integer", "format": "uint64", "minimum": 1, - "description": "Folder whose dashboards are listed." + "description": "Folder whose directly contained dashboards are listed; subfolders are not included." }, "query": { "type": "string", "maxLength": 128, - "description": "Optional space-separated search words matched against title and description; at most 128 Unicode code points." + "description": "Optional search words separated by whitespace, at most 128 Unicode code points. A dashboard matches when every word appears in its title or description." }, "sort": { "type": "array", @@ -31864,7 +32876,7 @@ "type": "string", "minLength": 1, "maxLength": 128, - "description": "Space-separated search words; at least one word and at most 128 Unicode code points." + "description": "Search words separated by whitespace; at least one word and at most 128 Unicode code points. A dashboard matches when every word appears in its title or description." }, "sort": { "type": "array", @@ -31923,13 +32935,15 @@ "type": "integer", "format": "int64", "minimum": 0, - "description": "Unix timestamp in milliseconds." + "description": "Start of the window as a Unix timestamp in milliseconds. Must be 0 or greater and less than `to_ms`.", + "maximum": 9007199254740991 }, "to_ms": { "type": "integer", "format": "int64", "minimum": 1, - "description": "Unix timestamp in milliseconds." + "description": "End of the window as a Unix timestamp in milliseconds. Must be greater than `from_ms`; `instant` queries are evaluated at this time.", + "maximum": 9007199254740991 } }, "required": [ @@ -31939,15 +32953,15 @@ }, "DashboardRuntimeError": { "type": "object", - "description": "Per-variable or per-query failure. A failed arm does not fail the whole call.", + "description": "Failure of one variable or one query. A failed variable or query does not fail the whole call.", "properties": { "reason": { "type": "string", - "description": "Machine-readable failure reason. Observed values include `invalid_request`, `variable_invalid`, `panel_missing`, `field_missing`, `datasource_permission_denied`, `timeout`, `panel_deadline`, `panel_canceled`, `canceled`, `overloaded`, `source_too_large`, `edge_unavailable`, `edge_upgrade_required`, `edge_version_unknown`, `mixed_edge_versions` and `internal`." + "description": "Machine-readable failure reason. The set is open; current values:\n- `invalid_request`: the query or datasource setup is rejected (unsupported datasource type or query mode, non-empty `args` where none are allowed, a malformed argument).\n- `variable_invalid`: a variable could not be used (no selection and no default, a selection outside the candidates, an unresolved dependency, a bad substitution, or an unusable candidate list).\n- `panel_missing`: the panel is not in the dashboard (queries resolve only).\n- `datasource_permission_denied`: the datasource is missing, disabled, not accessible to the caller, or no accessible datasource matches the variable.\n- `field_missing`, `value_not_scalar`, `empty_field_name`, `duplicate_field_name`, `field_type_changed`: the result does not fit the panel's visualization, or a SQL variable query returned unusable columns.\n- `timeout`: the datasource call timed out; `panel_deadline`: the run hit the overall 35-second deadline.\n- `canceled`, `panel_canceled`: the call was cancelled.\n- `overloaded`: the datasource side is rate limiting.\n- `too_many_rows`, `result_too_large`, `source_too_large`: a row, size or candidate-count limit was exceeded.\n- `edge_unavailable`, `no_active_edge`, `edge_upgrade_required`, `edge_version_unknown`, `mixed_edge_versions`: the Edge cluster of the datasource is not connected, too old, of unknown version, or mixed.\n- `internal`: an unexpected server-side error." }, "message": { "type": "string", - "description": "Human-readable detail for the failure." + "description": "Human-readable detail for display or troubleshooting; its wording is not stable, so do not parse it." } }, "required": [ @@ -31957,18 +32971,18 @@ }, "DashboardRuntimeDatasource": { "type": "object", - "description": "The datasource a runtime query was bound to.", + "description": "The datasource a runtime variable or query was bound to.", "properties": { "id": { "type": "integer", "format": "uint64", "minimum": 1, - "description": "Datasource ID." + "description": "Datasource ID, as listed by the datasource list endpoint." }, "type": { "type": "string", "pattern": "^[a-z][a-z0-9_]{0,63}$", - "description": "Datasource type identifier." + "description": "Datasource type identifier. Resolved queries and `query` variables only use `prometheus`, `mysql` or `loki`; the datasource chosen by a `datasource` variable can be any type identifier the variable was configured with." }, "name": { "type": "string", @@ -31983,12 +32997,12 @@ }, "DashboardResolvedVariable": { "type": "object", - "description": "One resolved variable. An unreachable datasource, a bad expression or an empty result leaves `candidates` incomplete and fills `error` instead of failing the request.", + "description": "One resolved variable. A failure (no selection and no default, a selection outside the candidates, an unresolved dependency, an unreachable datasource, an unusable query result) fills `error` and leaves `selection` out instead of failing the request.", "properties": { "name": { "type": "string", "pattern": "^[A-Za-z_][A-Za-z0-9_]{0,63}$", - "description": "Variable name." + "description": "Variable name, as defined in the dashboard or draft." }, "kind": { "type": "string", @@ -32004,7 +33018,7 @@ "items": { "$ref": "#/components/schemas/DashboardCandidate" }, - "description": "Resolved candidates, at most 1000." + "description": "Selectable options, at most 1000; an empty array when there are none or resolution failed. Order: `custom` keeps the definition order, `datasource` is sorted by name then ID, `query` is sorted by value." }, "selection": { "$ref": "#/components/schemas/DashboardSelection" @@ -32039,13 +33053,13 @@ "additionalProperties": { "$ref": "#/components/schemas/DashboardSelection" }, - "description": "Selections already made, keyed by variable name, at most 20 entries. Variables omitted here fall back to their stored defaults." + "description": "Selections already made, keyed by variable name, at most 20 entries. Variables without an entry fall back to their stored defaults; a name the dashboard does not define fails the call with HTTP 400.", + "maxProperties": 20 } }, "required": [ "dashboard_id", - "time", - "variables" + "time" ] }, "DashboardVariablesResolveResponse": { @@ -32055,7 +33069,7 @@ "dashboard_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Dashboard ID." + "description": "ID of the dashboard the variables were resolved for, echoing the request." }, "revision": { "type": "integer", @@ -32092,7 +33106,7 @@ "ref_id": { "type": "string", "pattern": "^[A-Z]$", - "description": "Panel-local query reference." + "description": "Query reference within the panel: a single letter `A`–`Z`." }, "datasource": { "$ref": "#/components/schemas/DashboardRuntimeDatasource" @@ -32104,27 +33118,24 @@ "instant", "window" ], - "description": "Evaluation mode: `range` = a stepped time series; `instant` = a single point in time; `window` = raw rows inside a bounded time window." + "description": "Evaluation mode: `range` = a stepped time series; `instant` = a single point in time; `window` = rows inside a bounded time window. Prometheus and Loki queries use `range` or `instant`; MySQL queries use `window`." }, "expr": { "type": "string", - "description": "Expression with variable templates substituted." + "description": "Expression with variable templates substituted. Built-in time variables stay verbatim when the request set `preserve_builtin_variables` to `true`." }, "args": { "type": "object", "additionalProperties": { "type": "string" }, - "description": "Query arguments; empty object when none." + "description": "Query arguments; an empty object when none. Only Loki queries carry arguments: `loki.limit` (a decimal integer from 1 to 1000, the maximum number of log entries) and `loki.direction` (`latest` or `earliest`)." }, "min_step_seconds": { - "type": [ - "integer", - "null" - ], + "type": "integer", "format": "int64", "minimum": 1, - "description": "Minimum step in seconds; null when unset." + "description": "Minimum step in seconds from the panel query; omitted when unset." } }, "required": [ @@ -32137,12 +33148,12 @@ }, "DashboardResolvedPanelQueries": { "type": "object", - "description": "Per-panel resolution result. `state` is `success` when every query resolved, `partial` when some did and `error` when none did.", + "description": "Per-panel resolution result. `state` is `success` when every query resolved, `partial` when some did and `error` when none did. `error` describes only the first failure.", "properties": { "panel_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Panel ID." + "description": "ID of the panel, echoing an entry of `panel_ids`." }, "state": { "type": "string", @@ -32151,14 +33162,14 @@ "partial", "error" ], - "description": "Aggregate state of the panel's queries: `success` = every query resolved; `partial` = some resolved; `error` = none resolved." + "description": "Resolution state of the panel's queries: `success` = every query resolved; `partial` = some resolved and some failed; `error` = none resolved, including a panel that does not exist." }, "queries": { "type": "array", "items": { "$ref": "#/components/schemas/DashboardResolvedQuery" }, - "description": "Successfully resolved queries." + "description": "Queries that resolved successfully, in the panel's query order. Queries that failed are left out; empty array when none resolved." }, "error": { "$ref": "#/components/schemas/DashboardRuntimeError" @@ -32197,7 +33208,8 @@ "additionalProperties": { "$ref": "#/components/schemas/DashboardSelection" }, - "description": "Selections keyed by variable name, at most 20 entries." + "description": "Selections keyed by variable name, at most 20 entries. Variables without an entry fall back to their stored defaults; a name the dashboard does not define fails the call with HTTP 400.", + "maxProperties": 20 }, "max_data_points": { "type": [ @@ -32206,7 +33218,7 @@ ], "minimum": 2, "maximum": 5000, - "description": "Downsampling target used to compute the step and render the built-in time variables, 2–5000 points; omit or send null for the server default of 100." + "description": "Target maximum number of points per series, used to compute the step and render the built-in time variables. 2–5000; omit or send null for the default of 100." }, "preserve_builtin_variables": { "type": "boolean", @@ -32216,18 +33228,17 @@ "required": [ "dashboard_id", "panel_ids", - "time", - "variables" + "time" ] }, "DashboardQueriesResolveResponse": { "type": "object", - "description": "One entry per requested panel, in request order.", + "description": "Resolved queries of the requested panels, plus the effective variable selections they were resolved with. Nothing is executed.", "properties": { "dashboard_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Dashboard ID." + "description": "ID of the dashboard the queries were resolved against, echoing the request." }, "revision": { "type": "integer", @@ -32243,14 +33254,14 @@ "additionalProperties": { "$ref": "#/components/schemas/DashboardSelection" }, - "description": "Selections that resolved successfully." + "description": "Effective selections of the variables that resolved successfully, keyed by variable name; variables that failed to resolve are left out." }, "panels": { "type": "array", "items": { "$ref": "#/components/schemas/DashboardResolvedPanelQueries" }, - "description": "Per-panel results." + "description": "One entry per requested panel, in request order." } }, "required": [ @@ -32268,12 +33279,12 @@ "max_concurrency": { "type": "integer", "minimum": 1, - "description": "Concurrency cap applied to the panel's queries." + "description": "Maximum number of the panel's queries executed at the same time; fixed at 6." }, "execution_count": { "type": "integer", "minimum": 0, - "description": "Number of queries launched." + "description": "Number of queries that resolved successfully and were dispatched for execution; queries that failed to resolve are not counted." } }, "required": [ @@ -32283,12 +33294,12 @@ }, "DashboardPanelRunRef": { "type": "object", - "description": "Result of one query inside a panel run. The raw execution payload differs per datasource type and is passed through unmodified, so it is not schema-constrained here.", + "description": "Result of one query inside a panel run or preview. The raw execution payload differs per datasource type and is passed through unmodified, so it is not schema-constrained here.", "properties": { "ref_id": { "type": "string", "pattern": "^[A-Z]$", - "description": "Panel-local query reference." + "description": "Query reference within the panel: a single letter `A`–`Z`, as set in the panel's `queries`." }, "state": { "type": "string", @@ -32297,16 +33308,16 @@ "error", "incompatible" ], - "description": "Per-query execution state: `success` = the query executed; `error` = the query failed; `incompatible` = the datasource accepted the call but the query mode or field selection does not fit the datasource type." + "description": "Per-query state: `success` = the query ran and `execution` is present; `error` = the query could not be resolved or executed, or the run was cancelled or timed out, and `error` explains why; `incompatible` = the query ran, but its result does not fit the panel's visualization (for example a configured field is missing or not numeric), so `execution` is still present and `error` explains the mismatch." }, "child_request_id": { "type": "string", - "description": "Request ID of the underlying datasource execution; use it when tracing a single query." + "description": "Request ID of the underlying datasource execution; use it when tracing a single query. Absent when the query never reached the datasource." }, "execution": { "type": "object", "additionalProperties": true, - "description": "Datasource-specific execution payload, passed through unmodified." + "description": "Datasource-specific execution result, passed through unmodified. Present when `state` is `success` or `incompatible`; absent when `state` is `error`." }, "error": { "$ref": "#/components/schemas/DashboardRuntimeError" @@ -32319,7 +33330,7 @@ }, "DashboardPanelRunRequest": { "type": "object", - "description": "Execute one panel against the stored dashboard. Omit `revision` to run the current revision; send it to have stale responses rejected.", + "description": "Execute one panel of a stored dashboard. Omit `revision` (or send 0) to run the current revision; send it to have a stale call rejected. Text panels cannot be run.", "properties": { "dashboard_id": { "type": "string", @@ -32329,13 +33340,12 @@ "panel_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Panel to execute." + "description": "ID of the panel to execute. It must belong to the dashboard, otherwise the call returns `TargetNotFound` (HTTP 404)." }, "revision": { "type": "integer", "format": "uint64", - "minimum": 1, - "description": "Revision guard; when set it must equal the current revision." + "description": "Revision guard. When set (non-zero) it must equal the dashboard's current revision, otherwise the call fails with `DashboardRevisionConflict` (HTTP 409). Omit or send 0 to skip the check." }, "time": { "$ref": "#/components/schemas/DashboardAbsoluteTimeRange" @@ -32345,7 +33355,8 @@ "additionalProperties": { "$ref": "#/components/schemas/DashboardSelection" }, - "description": "Selections keyed by variable name, at most 20 entries." + "description": "Selections keyed by variable name, at most 20 entries. Variables without an entry fall back to their stored defaults; a name the dashboard does not define fails the call with HTTP 400.", + "maxProperties": 20 }, "max_data_points": { "type": [ @@ -32354,29 +33365,28 @@ ], "minimum": 2, "maximum": 5000, - "description": "Downsampling target, 2–5000 points; omit or send null for the server default of 100." + "description": "Target maximum number of points per series for `range` queries; the server derives the query step from it. 2–5000; omit or send null for the default of 100." } }, "required": [ "dashboard_id", "panel_id", - "time", - "variables" + "time" ] }, "DashboardPanelRunResponse": { "type": "object", - "description": "Panel execution result. `run_state` aggregates the per-query states: `success` when all succeeded, `partial` when some did, otherwise `incompatible`, `cancelled` or `error`. The total response is capped at 8 MiB.", + "description": "Panel execution result. HTTP 200 is returned even when every query failed; read `run_state` and each ref's `state` and `error`. A response larger than 8 MiB is rejected with `EntityTooLarge` (HTTP 413) instead of being truncated.", "properties": { "dashboard_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Dashboard ID." + "description": "ID of the dashboard that was run, echoing the request." }, "panel_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Panel ID." + "description": "ID of the panel that was run, echoing the request." }, "revision": { "type": "integer", @@ -32393,7 +33403,7 @@ "cancelled", "error" ], - "description": "Aggregate state of the run: `success` = all queries succeeded; `partial` = some succeeded; `incompatible` = at least one query is incompatible with its datasource; `cancelled` = the run was cancelled; `error` = all queries failed." + "description": "Aggregate state of the run: `success` = every query succeeded; `partial` = at least one query succeeded and at least one did not; `cancelled` = no query succeeded and the client cancelled the request; `incompatible` = no query succeeded and at least one query ran but returned a result that does not fit the panel's visualization; `error` = no query succeeded and none is `incompatible` (also when the panel has no queries)." }, "time": { "$ref": "#/components/schemas/DashboardAbsoluteTimeRange" @@ -32403,14 +33413,14 @@ "additionalProperties": { "$ref": "#/components/schemas/DashboardSelection" }, - "description": "Selections that resolved successfully." + "description": "Effective selections of the variables that resolved successfully, keyed by variable name; variables that failed to resolve are left out." }, "refs": { "type": "array", "items": { "$ref": "#/components/schemas/DashboardPanelRunRef" }, - "description": "One entry per query in the panel." + "description": "One entry per query of the panel, in the panel's query order. A query that failed to resolve appears with `state` `error`." }, "display": { "$ref": "#/components/schemas/DashboardVizConfig" @@ -32446,13 +33456,13 @@ "dashboard_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Required for `existing`, forbidden for `new`." + "description": "Required for `existing`, forbidden for `new`. The caller must have access to the dashboard's folder." }, "folder_id": { "type": "integer", "format": "uint64", "minimum": 1, - "description": "Required for `new`, forbidden for `existing`." + "description": "Required for `new`, forbidden for `existing`. Must be a folder the caller can access, otherwise the call returns `FolderNotFound` (HTTP 404)." } }, "required": [ @@ -32472,14 +33482,15 @@ "$ref": "#/components/schemas/DashboardVariable" }, "maxItems": 20, - "description": "Draft variables, at most 20." + "description": "Draft variables, at most 20. They are validated like a stored definition (names, dependencies, option limits) and must stay within 1 MiB." }, "selections": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/DashboardSelection" }, - "description": "Selections keyed by variable name, at most 20 entries." + "description": "Selections keyed by variable name, at most 20 entries. Variables without an entry fall back to their draft default; a name that is not in `variables` fails the call with HTTP 400.", + "maxProperties": 20 }, "time": { "$ref": "#/components/schemas/DashboardAbsoluteTimeRange" @@ -32488,7 +33499,6 @@ "required": [ "context", "variables", - "selections", "time" ] }, @@ -32501,14 +33511,14 @@ "items": { "$ref": "#/components/schemas/DashboardResolvedVariable" }, - "description": "Resolved variables." + "description": "Resolved variables, in the order of the draft `variables`." }, "selections": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/DashboardSelection" }, - "description": "Effective selections keyed by variable name." + "description": "Effective selections keyed by variable name; only variables that resolved successfully appear." } }, "required": [ @@ -32518,7 +33528,7 @@ }, "DashboardPanelPreviewRequest": { "type": "object", - "description": "Execute a draft panel inline, without saving a dashboard revision. Subject to the same 1 MiB definition-size ceiling.", + "description": "Execute a draft panel inline, without saving a dashboard revision. The draft `panel` and `variables` together must stay within 1 MiB, and the request body within 2 MiB.", "properties": { "context": { "$ref": "#/components/schemas/DashboardDraftContext" @@ -32532,14 +33542,15 @@ "$ref": "#/components/schemas/DashboardVariable" }, "maxItems": 20, - "description": "Draft variables the panel may reference." + "description": "Draft variables the panel may reference, at most 20. Required; the panel's queries can only use variables listed here." }, "selections": { "type": "object", "additionalProperties": { "$ref": "#/components/schemas/DashboardSelection" }, - "description": "Selections keyed by variable name." + "description": "Selections keyed by variable name, at most 20 entries. Variables without an entry fall back to their draft default.", + "maxProperties": 20 }, "time": { "$ref": "#/components/schemas/DashboardAbsoluteTimeRange" @@ -32551,25 +33562,24 @@ ], "minimum": 2, "maximum": 5000, - "description": "Downsampling target, 2–5000 points." + "description": "Target maximum number of points per series for `range` queries; the server derives the query step from it. 2–5000; omit or send null for the default of 100." } }, "required": [ "context", "panel", "variables", - "selections", "time" ] }, "DashboardPanelPreviewResponse": { "type": "object", - "description": "Draft panel execution result. Same shape as a stored panel run, minus the dashboard identity.", + "description": "Draft panel execution result. Same shape as a stored panel run, minus `dashboard_id` and `revision`. HTTP 200 is returned even when every query failed; a response larger than 8 MiB is rejected with `EntityTooLarge` (HTTP 413).", "properties": { "panel_id": { "type": "string", "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$", - "description": "Panel ID." + "description": "ID of the draft panel, echoing `panel.id` from the request." }, "run_state": { "type": "string", @@ -32580,7 +33590,7 @@ "cancelled", "error" ], - "description": "Aggregate state of the run: `success` = all queries succeeded; `partial` = some succeeded; `incompatible` = at least one query is incompatible with its datasource; `cancelled` = the run was cancelled; `error` = all queries failed." + "description": "Aggregate state of the run: `success` = every query succeeded; `partial` = at least one query succeeded and at least one did not; `cancelled` = no query succeeded and the client cancelled the request; `incompatible` = no query succeeded and at least one query ran but returned a result that does not fit the panel's visualization; `error` = no query succeeded and none is `incompatible` (also when the panel has no queries)." }, "time": { "$ref": "#/components/schemas/DashboardAbsoluteTimeRange" @@ -32590,14 +33600,14 @@ "additionalProperties": { "$ref": "#/components/schemas/DashboardSelection" }, - "description": "Selections that resolved successfully." + "description": "Effective selections of the variables that resolved successfully, keyed by variable name; variables that failed to resolve are left out." }, "refs": { "type": "array", "items": { "$ref": "#/components/schemas/DashboardPanelRunRef" }, - "description": "One entry per query in the panel." + "description": "One entry per query of the panel, in the panel's query order. A query that failed to resolve appears with `state` `error`." }, "display": { "$ref": "#/components/schemas/DashboardVizConfig" @@ -32618,12 +33628,12 @@ }, "FolderItem": { "type": "object", - "description": "A monitor folder (监控节点). Folders form a tree; `parent_path` is the comma-separated ancestor ID list, so the caller can rebuild the tree and search it client-side.", + "description": "A monitor folder. Folders form a tree; `parent_path` is the comma-separated ancestor ID list, so the caller can rebuild the tree and search it client-side.", "properties": { "id": { "type": "integer", "format": "uint64", - "description": "Folder ID." + "description": "Folder ID. Pass it as `id` to update, move, or delete the folder, as `parent_id` or `dest_parent_id` to nest folders under it, and as `folder_id` on alert rules and dashboards." }, "account_id": { "type": "integer", @@ -32642,7 +33652,7 @@ "team_id": { "type": "integer", "format": "uint64", - "description": "Team the folder is scoped to; 0 when account-wide." + "description": "ID of the team the folder belongs to; 0 when it has no team. Members of the team can see and modify the folder." }, "name": { "type": "string", @@ -32655,7 +33665,7 @@ "creator_id": { "type": "integer", "format": "uint64", - "description": "Member ID of the creator." + "description": "Member ID of the creator; the creator can always see and modify the folder." }, "creator_name": { "type": "string", @@ -32664,7 +33674,7 @@ "updater_id": { "type": "integer", "format": "uint64", - "description": "Member ID of the last updater." + "description": "Member ID of the last updater. Updates and moves both set it." }, "updater_name": { "type": "string", @@ -32673,12 +33683,12 @@ "created_at": { "type": "integer", "format": "int64", - "description": "Unix timestamp in seconds." + "description": "Creation time as a Unix timestamp in seconds." }, "updated_at": { "type": "integer", "format": "int64", - "description": "Unix timestamp in seconds." + "description": "Time of the last update or move as a Unix timestamp in seconds." } }, "required": [ @@ -32727,7 +33737,7 @@ }, "category": { "type": "string", - "description": "Filter by category. Accepts a comma-separated list, for example `event.alert,event.change`." + "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": [ @@ -32753,7 +33763,7 @@ "properties": { "plugin_type": { "type": "string", - "description": "Type identifier to pass as `plugin_type` when creating an integration.", + "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" }, "plugin_type_name": { @@ -32777,7 +33787,11 @@ }, "status": { "type": "string", - "description": "Platform status of the type." + "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", @@ -32847,23 +33861,23 @@ }, "category": { "type": "string", - "description": "Filter by category. Accepts a comma-separated list." + "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. Merged into `plugin_type` when both are set." + "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": "Filter by integration type. Accepts a comma-separated list." + "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": { "type": "string", - "description": "Filter by status. Accepts a comma-separated list." + "description": "Comma-separated status filter: `enabled` (accepting events) and/or `disabled` (paused)." }, "name": { "type": "string", - "description": "Filter by integration name." + "description": "Filter by integration name; matches any name that contains this text." }, "ref_ids": { "type": "array", @@ -32921,7 +33935,7 @@ "integration_id": { "type": "integer", "format": "int64", - "description": "Integration ID." + "description": "Integration ID; pass it as `integration_id` to the other `/integration/*` endpoints." }, "team_id": { "type": "integer", @@ -33073,7 +34087,7 @@ "type": "integer", "format": "int64", "minimum": 1, - "description": "Integration ID.", + "description": "ID of a public integration, returned by `POST /integration/list`. An unknown ID or a channel-owned integration returns `ResourceNotFound`.", "example": 6113996590131 } } @@ -33106,7 +34120,7 @@ "integration_id": { "type": "integer", "format": "int64", - "description": "Integration ID." + "description": "Integration ID; pass it as `integration_id` to the other `/integration/*` endpoints." }, "team_id": { "type": "integer", @@ -33318,7 +34332,7 @@ "type": "integer", "format": "int64", "minimum": 1, - "description": "Integration ID.", + "description": "ID of a public integration, returned by `POST /integration/list`. An unknown ID or a channel-owned integration returns `ResourceNotFound`.", "example": 6113996590131 }, "name": { @@ -33369,7 +34383,7 @@ "type": "integer", "format": "int64", "minimum": 1, - "description": "Integration ID.", + "description": "ID of a public integration, returned by `POST /integration/list`. An unknown ID or a channel-owned integration returns `ResourceNotFound`.", "example": 6113996590131 } } @@ -33390,26 +34404,26 @@ }, "FolderCreateRequest": { "type": "object", - "description": "Monitor folder request.", + "description": "Request to create a monitor folder.", "properties": { "name": { "type": "string", - "description": "Folder name; cannot contain a period, slash, or comma.", + "description": "Folder name; required, and must not contain a period (`.`), slash (`/`), or comma (`,`).", "minLength": 1 }, "note": { "type": "string", - "description": "Free-form note; omitted or empty clears the note on update." + "description": "Free-form note. Empty when omitted." }, "parent_id": { "type": "integer", - "description": "Parent folder ID; 0 or omitted creates a root folder.", + "description": "ID of the parent folder; 0 or omitted creates a root folder. The caller must be allowed to modify the parent.", "format": "uint64", "minimum": 0 }, "team_id": { "type": "integer", - "description": "Team ID; 0 means account-wide. Omitted on update resets to 0.", + "description": "ID of the team the folder belongs to; 0 or omitted means no team. Members of the team can see and modify the folder and everything below it.", "format": "uint64", "minimum": 0 } @@ -33420,26 +34434,26 @@ }, "FolderUpdateRequest": { "type": "object", - "description": "Monitor folder request.", + "description": "Request to update a monitor folder. Editable fields are replaced as a whole.", "properties": { "id": { "type": "integer", - "description": "Folder ID.", + "description": "ID of the folder to update, from `/monit/folder/list` or the create response.", "format": "uint64", "minimum": 1 }, "name": { "type": "string", - "description": "Folder name; cannot contain a period, slash, or comma.", + "description": "New folder name; required, and must not contain a period (`.`), slash (`/`), or comma (`,`).", "minLength": 1 }, "note": { "type": "string", - "description": "Free-form note; omitted or empty clears the note on update." + "description": "New note. Omitted or empty clears the note." }, "team_id": { "type": "integer", - "description": "Team ID; 0 means account-wide. Omitted on update resets to 0.", + "description": "New team ID; 0 or omitted removes the team assignment.", "format": "uint64", "minimum": 0 } @@ -33451,17 +34465,17 @@ }, "FolderMoveRequest": { "type": "object", - "description": "Monitor folder request.", + "description": "Request to move a monitor folder and its descendants.", "properties": { "id": { "type": "integer", - "description": "Folder ID.", + "description": "ID of the folder to move, from `/monit/folder/list`.", "format": "uint64", "minimum": 1 }, "dest_parent_id": { "type": "integer", - "description": "Destination parent folder ID; required even when 0 to move to the root.", + "description": "ID of the new parent folder; send 0 to move to the root. The field cannot be omitted. Must differ from `id` and must not be a descendant of the folder.", "format": "uint64", "minimum": 0 } @@ -33473,11 +34487,11 @@ }, "FolderDeleteRequest": { "type": "object", - "description": "Monitor folder request.", + "description": "Request to delete a monitor folder.", "properties": { "id": { "type": "integer", - "description": "Folder ID.", + "description": "ID of the folder to delete, from `/monit/folder/list`. The folder must be empty.", "format": "uint64", "minimum": 1 } @@ -33492,13 +34506,13 @@ "properties": { "folder_id": { "type": "integer", - "description": "Folder ID.", + "description": "ID of the folder this entry describes; matches `id` in `/monit/folder/list`.", "format": "uint64", "minimum": 0 }, "has_issue": { "type": "boolean", - "description": "Whether this folder or a visible descendant has active alerts or rule runtime issues." + "description": "`true` when a rule in this folder or in any descendant has an active alert or a runtime problem (`runtime_state` of `offline`, `abnormal`, `stale`, or `no_datasource`). Rules in folders the caller cannot read are not counted." } }, "required": [ @@ -33512,7 +34526,7 @@ "properties": { "items": { "type": "array", - "description": "Folder health summaries.", + "description": "One health entry per folder visible to the caller, sorted by `folder_id`.", "items": { "$ref": "#/components/schemas/FolderHealthItem" } @@ -33525,15 +34539,10 @@ }, "securitySchemes": { "AppKeyAuth": { - "description": "App key issued from the Flashduty console under Account → APP Keys. Required on every public API call. Keep it secret — it grants the same access as the owning account.", + "type": "apiKey", "in": "query", "name": "app_key", - "type": "apiKey" - }, - "AutomationTriggerBearerAuth": { - "description": "Bearer token generated for one Automation HTTP POST trigger. This is not an app_key.", - "scheme": "bearer", - "type": "http" + "description": "APP Key created in the Flashduty console under My → APP Key. Send it as the `app_key` query parameter or in the `Fd-App-Key` request header. Its effective access is the intersection of the key's permission scope and the creator's current role permissions. Keep it secret." } } }, @@ -33546,67 +34555,76 @@ "paths": { "/account/info": { "post": { + "summary": "Get account detail", "description": "Return the current account's profile and settings.", "operationId": "account-read-info", + "tags": [ + "Platform/Account" + ], + "security": [ + { + "AppKeyAuth": [] + } + ], "requestBody": { "content": { "application/json": { - "example": {}, "schema": { "type": "object" - } + }, + "example": {} } } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AccountInfo" + } + } + } + ] + }, "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { "account_id": 1001, "account_name": "acme", - "avatar": "https://cdn.flashcat.cloud/avatar/acme.png", - "country_code": "CN", - "created_at": 1716960000, "domain": "acme", - "email": "ops@acme.example", "extra_domains": [ "acme-corp" ], - "locale": "zh-CN", "phone": "138****8000", + "country_code": "CN", + "email": "ops@acme.example", + "avatar": "https://example.com/avatar/acme.png", + "locale": "zh-CN", + "time_zone": "Asia/Shanghai", + "created_at": 1716960000, "restrictions": { - "allow_subdomain": true, + "ips": [ + "203.0.113.0/24" + ], "email_domains": [ "acme.example" ], - "ips": [ - "203.0.113.0/24" - ] - }, - "time_zone": "Asia/Shanghai" - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "properties": { - "data": { - "$ref": "#/components/schemas/AccountInfo" - } - }, - "type": "object" + "allow_subdomain": true } - ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -33614,6 +34632,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -33621,82 +34642,69 @@ "$ref": "#/components/responses/ServerError" } }, - "security": [ - { - "AppKeyAuth": [] - } - ], - "summary": "Get account detail", - "tags": [ - "Platform/Account" - ], "x-mint": { - "content": "| Permission | Description |\n| --- | --- |\n| None | None — any valid app_key can call this operation. |\n\nFind this operation in the [Platform API reference](/en/api-reference/platform/account/account-read-info).", - "href": "/en/api-reference/platform/account/account-read-info", "metadata": { "sidebarTitle": "Get account detail" - } + }, + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — but see the credential requirement under Usage |\n\n## Usage\n\n- Requires the account owner's credentials (for example an app key created by the account owner); member credentials return `401 Unauthorized`. Members can use `POST /member/info` instead.\n- `restrictions` is present only when join or access restrictions have been configured; `mp_plat` and `mp_account_id` only for accounts provisioned through a cloud marketplace.", + "href": "/en/api-reference/platform/account/account-read-info" } } }, "/alert-event/list": { "post": { - "description": "Return a cursor-paginated list of raw alert events across all alerts, with filtering by integration, channel, time range, and severity.", "operationId": "alert-event-read-list", - "requestBody": { - "content": { - "application/json": { - "example": { - "end_time": 1712707200, - "limit": 20, - "severities": "Critical", - "start_time": 1712620800 - }, - "schema": { - "$ref": "#/components/schemas/AlertEventGlobalListRequest" - } - } - }, - "required": true + "summary": "List raw alert events", + "description": "Return a cursor-paginated list of raw alert events across all alerts, with filtering by integration, channel, time range, and severity.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Both `start_time` and `end_time` are required Unix epoch seconds. `start_time` must be less than `end_time`; the span must not exceed 31 days.\n- Results are filtered by the caller's channel data-access permissions. When `channel_ids` is sent and none of the listed channels is accessible to the caller, the result is empty.\n- `severities` is a comma-separated list matched against `event_severity`, e.g. `\"Critical,Warning\"`. Values are not validated, so an unknown value (or `Ok`) matches nothing.\n- Pass `search_after_ctx` from the previous response for the next page; without it, `p`/`limit` page numbers apply and `p * limit` must stay within 10,000.", + "href": "/en/api-reference/on-call/alerts/alert-event-read-list", + "metadata": { + "sidebarTitle": "List raw alert events" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "has_next_page": false, - "items": [ - { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "event_id": "663a1b2c3d4e5f6789abc001", - "event_severity": "Critical", - "event_time": 1712650000, - "title": "CPU usage > 90%" - } - ], - "total": 1 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/AlertEventGlobalListResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "total": 1, + "has_next_page": false, + "items": [ + { + "event_id": "663a1b2c3d4e5f6789abc001", + "alert_id": "663a1b2c3d4e5f6789abcdef", + "title": "CPU usage > 90%", + "event_severity": "Critical", + "event_time": 1712650000 + } + ], + "search_after_ctx": "663a1b2c3d4e5f6789abc001" + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -33704,6 +34712,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -33711,80 +34722,82 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List raw alert events", - "tags": [ - "On-call/Alerts" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) |\n\n## Usage\n\n- Both `start_time` and `end_time` are required Unix epoch seconds. `start_time` must be less than `end_time`; the span must not exceed 31 days.\n- Results are filtered by the caller's channel data-access permissions.\n- `severities` is a comma-separated string, e.g. `\"Critical,Warning\"`.", - "href": "/en/api-reference/on-call/alerts/alert-event-read-list", - "metadata": { - "sidebarTitle": "List raw alert events" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertEventGlobalListRequest" + }, + "example": { + "start_time": 1712620800, + "end_time": 1712707200, + "limit": 20, + "severities": "Critical" + } + } } } } }, "/alert/event/list": { "post": { - "description": "Return raw events for an alert with cursor or page-number pagination.", "operationId": "alert-read-event-list", - "requestBody": { - "content": { - "application/json": { - "example": { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "limit": 20 - }, - "schema": { - "$ref": "#/components/schemas/AlertEventListRequest" - } - } - }, - "required": true + "summary": "List events for an alert", + "description": "Return raw events for an alert with cursor or page-number pagination.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- Results are newest-first by default. Set `asc=true` to read events oldest-first.\n- Use `limit` with `search_after_ctx` from the previous response to fetch the next page.\n- Classic page-number pagination is also supported with `p`, but `p * limit` must stay within 10,000 records.\n- An `alert_id` not found in the account returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/alerts/alert-read-event-list", + "metadata": { + "sidebarTitle": "List events for an alert" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "has_next_page": true, - "items": [ - { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "event_id": "663a1b2c3d4e5f6789abc001", - "event_severity": "Critical", - "event_status": "Critical", - "event_time": 1712650000, - "labels": { - "host": "web-01" - }, - "title": "CPU usage > 90%" - } - ], - "search_after_ctx": "663a1b2c3d4e5f6789abc001", - "total": 57 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/AlertEventListResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "total": 57, + "has_next_page": true, + "search_after_ctx": "663a1b2c3d4e5f6789abc001", + "items": [ + { + "event_id": "663a1b2c3d4e5f6789abc001", + "alert_id": "663a1b2c3d4e5f6789abcdef", + "title": "CPU usage > 90%", + "event_severity": "Critical", + "event_status": "Critical", + "event_time": 1712650000, + "labels": { + "host": "web-01" + } + } + ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -33792,6 +34805,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -33799,77 +34815,78 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List events for an alert", - "tags": [ - "On-call/Alerts" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) |\n\n## Usage\n\n- Results are newest-first by default. Set `asc=true` to read events oldest-first.\n- Use `limit` with `search_after_ctx` from the previous response to fetch the next page.\n- Classic page-number pagination is also supported with `p`, but `p * limit` must stay within 10,000 records.\n- Each alert can accumulate a large raw event history; prefer cursor pagination for hot alerts.", - "href": "/en/api-reference/on-call/alerts/alert-read-event-list", - "metadata": { - "sidebarTitle": "List events for an alert" - } - } - } - }, - "/alert/feed": { - "post": { - "description": "Return the activity feed (comments, state changes, merges, silence events) for a single alert, with page-based pagination.", - "operationId": "alert-read-feed", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertEventListRequest" + }, "example": { "alert_id": "663a1b2c3d4e5f6789abcdef", - "asc": false, "limit": 20 - }, - "schema": { - "$ref": "#/components/schemas/AlertFeedRequest" } } - }, - "required": true + } + } + } + }, + "/alert/feed": { + "post": { + "operationId": "alert-read-feed", + "summary": "List alert activity feed", + "description": "Return the activity feed (comments, state changes, merges, silence events) for a single alert, with page-based pagination.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Use `p` (page number, starting at 1) and `limit` (max 100, default 20) for pagination.\n- Set `asc` to `true` for chronological order.\n- Use `types` to filter by specific feed types (e.g. `a_comm`, `a_merge`).\n- An `alert_id` not found in the account returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/alerts/alert-read-feed", + "metadata": { + "sidebarTitle": "List alert activity feed" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "has_next_page": false, - "items": [ - { - "created_at": 1712651000, - "creator_id": 80011, - "detail": { - "comment": "Investigating now." - }, - "ref_id": "663a1b2c3d4e5f6789abcdef", - "type": "a_comm" - } - ] - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/AlertFeedResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "has_next_page": false, + "items": [ + { + "ref_id": "663a1b2c3d4e5f6789abcdef", + "type": "a_comm", + "detail": { + "comment": "Investigating now." + }, + "account_id": 10023, + "creator_id": 80011, + "created_at": 1712651000000, + "updated_at": 1712651000000 + } + ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -33877,6 +34894,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -33884,69 +34904,71 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List alert activity feed", - "tags": [ - "On-call/Alerts" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) |\n\n## Usage\n\n- Use `p` (page number, starting at 1) and `limit` (max 100, default 20) for pagination.\n- Set `asc` to `true` for chronological order.\n- Use `types` to filter by specific feed types (e.g. `a_comm`, `a_merge`).", - "href": "/en/api-reference/on-call/alerts/alert-read-feed", - "metadata": { - "sidebarTitle": "List alert activity feed" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertFeedRequest" + }, + "example": { + "alert_id": "663a1b2c3d4e5f6789abcdef", + "limit": 20, + "asc": false + } + } } } } }, "/alert/info": { "post": { - "description": "Return the full details of a single alert by its ID, including its associated incident and event count.", "operationId": "alert-read-info", - "requestBody": { - "content": { - "application/json": { - "example": { - "alert_id": "663a1b2c3d4e5f6789abcdef" - }, - "schema": { - "$ref": "#/components/schemas/AlertInfoRequest" - } - } - }, - "required": true + "summary": "Get alert detail", + "description": "Return the full details of a single alert by its ID, including its associated incident and event count.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- `alert_id` is an ObjectID hex string returned by `POST /alert/list` or `POST /alert-event/list`.\n- An `alert_id` not found in the account returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/alerts/alert-read-info", + "metadata": { + "sidebarTitle": "Get alert detail" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "alert_severity": "Critical", - "alert_status": "Critical", - "event_cnt": 3, - "start_time": 1712650000, - "title": "CPU usage > 90%" - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/AlertItem" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "alert_id": "663a1b2c3d4e5f6789abcdef", + "title": "CPU usage > 90%", + "alert_severity": "Critical", + "alert_status": "Critical", + "start_time": 1712650000, + "event_cnt": 3 + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -33954,6 +34976,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -33961,92 +34986,90 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Get alert detail", - "tags": [ - "On-call/Alerts" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) |\n\n## Usage\n\n- `alert_id` is an ObjectID hex string returned by `POST /alert/list` or `POST /alert-event/list`.", - "href": "/en/api-reference/on-call/alerts/alert-read-info", - "metadata": { - "sidebarTitle": "Get alert detail" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertInfoRequest" + }, + "example": { + "alert_id": "663a1b2c3d4e5f6789abcdef" + } + } } } } }, "/alert/list": { "post": { - "description": "Return a cursor-paginated list of alerts matching the given filters.", "operationId": "alert-read-list", - "requestBody": { - "content": { - "application/json": { - "example": { - "end_time": 1712707200, - "is_active": true, - "limit": 20, - "start_time": 1712620800 - }, - "schema": { - "$ref": "#/components/schemas/AlertListRequest" - } - } - }, - "required": true + "summary": "List alerts", + "description": "Return a cursor-paginated list of alerts matching the given filters.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- `start_time` and `end_time` are required Unix seconds and filter on the alert's `start_time`; the span must not exceed 31 days.\n- With `by_updated_at: true`, an `updated_at` window with the same bounds is added on top of the `start_time` filter, and the span must not exceed 7 days.\n- A `start_time` earlier than the account's data retention period is moved up to the retention start; an `end_time` before that start returns `InvalidParameter`.\n- Pass `search_after_ctx` from the previous response for the next page; without it, `p`/`limit` page numbers apply and `p * limit` must stay within 10,000.\n- `total` is capped at 1,000. `has_next_page` does not depend on `total`: it is exact in both page-number and cursor mode, also past 1,000 alerts. Every non-empty page returns `search_after_ctx` for its last alert; pass it back to read past the 10,000-row page-number limit.\n- Results are filtered by the caller's channel data-access permissions.\n- Set `is_active` to `true` to retrieve only active (firing) alerts; `false` to retrieve resolved alerts.", + "href": "/en/api-reference/on-call/alerts/alert-read-list", + "metadata": { + "sidebarTitle": "List alerts" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertListResponse" + } + } + } + ] + }, "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { + "total": 1, "has_next_page": false, "items": [ { - "account_id": 10023, "alert_id": "663a1b2c3d4e5f6789abcdef", + "integration_id": 10001, + "channel_id": 20001, + "account_id": 10023, + "title": "CPU usage > 90%", "alert_severity": "Critical", "alert_status": "Critical", - "channel_id": 20001, - "channel_name": "Production", - "created_at": 1712650000, + "start_time": 1712650000, + "last_time": 1712655000, "end_time": 0, - "event_cnt": 3, - "ever_muted": false, - "integration_id": 10001, - "integration_name": "Prometheus", - "integration_type": "prometheus", "labels": { "host": "web-01" }, - "last_time": 1712655000, - "start_time": 1712650000, - "title": "CPU usage > 90%", - "updated_at": 1712655000 + "ever_muted": false, + "created_at": 1712650000, + "updated_at": 1712655000, + "integration_name": "Prometheus", + "integration_type": "prometheus", + "channel_name": "Production", + "event_cnt": 3 } ], - "total": 1 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "properties": { - "data": { - "$ref": "#/components/schemas/AlertListResponse" - } - }, - "type": "object" - } - ] + "search_after_ctx": "663a1b2c3d4e5f6789abcdef" + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -34054,6 +35077,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -34061,73 +35087,74 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List alerts", - "tags": [ - "On-call/Alerts" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) |\n\n## Usage\n\n- Both `start_time` and `end_time` are required Unix epoch seconds. Maximum span is 31 days.\n- Use `search_after_ctx` from the previous response to fetch the next page.\n- Results are filtered by the caller's channel data-access permissions.\n- Set `is_active` to `true` to retrieve only active (firing) alerts; `false` to retrieve resolved alerts.", - "href": "/en/api-reference/on-call/alerts/alert-read-list", - "metadata": { - "sidebarTitle": "List alerts" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertListRequest" + }, + "example": { + "start_time": 1712620800, + "end_time": 1712707200, + "limit": 20, + "is_active": true + } + } } } } }, "/alert/list-by-ids": { "post": { - "description": "Return the details of multiple alerts by their IDs in a single request. Note: this endpoint does not paginate — `total` and `has_next_page` are always `0`/`false` and `search_after_ctx` is never set.", "operationId": "alert-read-list-by-ids", - "requestBody": { - "content": { - "application/json": { - "example": { - "alert_ids": [ - "663a1b2c3d4e5f6789abcdef" - ] - }, - "schema": { - "$ref": "#/components/schemas/AlertListByIDsRequest" - } - } - }, - "required": true + "summary": "List alerts by IDs", + "description": "Return the details of several alerts by ID in one request, without pagination.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- A malformed ID fails the request with `InvalidParameter`; well-formed IDs not found in the account are left out of `items`.\n- The response is not paginated: `total` is always `0`, `has_next_page` is always `false`, and `search_after_ctx` is omitted.", + "href": "/en/api-reference/on-call/alerts/alert-read-list-by-ids", + "metadata": { + "sidebarTitle": "List alerts by IDs" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "has_next_page": false, - "items": [ - { - "alert_id": "663a1b2c3d4e5f6789abcdef", - "title": "CPU usage > 90%" - } - ], - "total": 0 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/AlertListResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "total": 0, + "has_next_page": false, + "items": [ + { + "alert_id": "663a1b2c3d4e5f6789abcdef", + "title": "CPU usage > 90%" + } + ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -34135,6 +35162,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -34142,65 +35172,64 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List alerts by IDs", - "tags": [ - "On-call/Alerts" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) |\n\n## Usage\n\n- All provided `alert_ids` must belong to the caller's account; any invalid ID causes the entire request to fail.", - "href": "/en/api-reference/on-call/alerts/alert-read-list-by-ids", - "metadata": { - "sidebarTitle": "List alerts by IDs" - } - } - } - }, - "/alert/merge": { - "post": { - "description": "Associate one or more alerts with an existing incident. If a source alert previously belonged to a different incident and that incident becomes empty after the merge, it will be automatically closed.", - "operationId": "alert-write-merge", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertListByIDsRequest" + }, "example": { "alert_ids": [ "663a1b2c3d4e5f6789abcdef" - ], - "incident_id": "663a000000000000deadbeef" - }, - "schema": { - "$ref": "#/components/schemas/AlertMergeRequest" + ] } } - }, - "required": true + } + } + } + }, + "/alert/merge": { + "post": { + "operationId": "alert-write-merge", + "summary": "Merge alerts into an incident", + "description": "Move one or more alerts into an existing incident and close source incidents left empty.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Every `alert_ids` entry and the `incident_id` must belong to the account; an unknown ID returns `InvalidParameter`.\n- Alerts already in the target incident are skipped. A source incident left with no alerts is closed.\n- `title` and `owner_id` update the target incident only when they differ from its current values.\n- Only one incident change runs per account at a time; a concurrent call returns `RequestTooFrequently`.", + "href": "/en/api-reference/on-call/alerts/alert-write-merge", + "metadata": { + "sidebarTitle": "Merge alerts into an incident" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/EmptyObject" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -34208,6 +35237,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -34215,47 +35247,66 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Merge alerts into an incident", - "tags": [ - "On-call/Alerts" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) |\n\n## Usage\n\n- All `alert_ids` and the `incident_id` must belong to the caller's account.\n- Optionally set `title` and `owner_id` to update the target incident at the same time.", - "href": "/en/api-reference/on-call/alerts/alert-write-merge", - "metadata": { - "sidebarTitle": "Merge alerts into an incident" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertMergeRequest" + }, + "example": { + "alert_ids": [ + "663a1b2c3d4e5f6789abcdef" + ], + "incident_id": "663a000000000000deadbeef" + } + } } } } }, "/alert/pipeline/info": { "post": { - "description": "Return the alert processing pipeline configured for a specific integration.", "operationId": "alert-read-pipeline-info", - "requestBody": { - "content": { - "application/json": { - "example": { - "integration_id": 10001 - }, - "schema": { - "$ref": "#/components/schemas/AlertPipelineInfoRequest" - } - } - }, - "required": true + "summary": "Get alert pipeline", + "description": "Return the alert processing pipeline configured for a specific integration.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- When the integration has no pipeline, the response carries only `request_id` and the `data` field is omitted.\n- `integration_id` may be any account-level or channel-owned integration of the account; an unknown ID returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/alerts/alert-read-pipeline-info", + "metadata": { + "sidebarTitle": "Get alert pipeline" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertPipelineItem" + } + } + } + ] + }, "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { - "created_at": 1710000000, - "creator_id": 80011, "integration_id": 10001, "rules": [ { + "kind": "title_reset", "if": [ { "key": "labels.env", @@ -34265,43 +35316,27 @@ ] } ], - "kind": "title_reset", "settings": { "title": "[TPL]{{.Labels.service}} / {{.Labels.check}}" } }, { - "if": null, "kind": "severity_reset", + "if": null, "settings": { "severity": "Warning" } } ], "status": "enabled", - "updated_at": 1712000000, - "updated_by": 80011 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "properties": { - "data": { - "$ref": "#/components/schemas/AlertPipelineItem" - } - }, - "type": "object" - } - ] + "creator_id": 80011, + "updated_by": 80011, + "created_at": 1710000000, + "updated_at": 1712000000 + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -34309,6 +35344,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -34316,52 +35354,65 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Get alert pipeline", - "tags": [ - "On-call/Alerts" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Integrations Read** (`on-call`) |\n\n## Usage\n\n- Returns `null` data if no pipeline has been configured for the given integration.\n- Requires the caller to have access to the integration.", - "href": "/en/api-reference/on-call/alerts/alert-read-pipeline-info", - "metadata": { - "sidebarTitle": "Get alert pipeline" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertPipelineInfoRequest" + }, + "example": { + "integration_id": 10001 + } + } } } } }, "/alert/pipeline/list": { "post": { - "description": "Return the alert processing pipelines configured for multiple integrations.", "operationId": "alert-read-pipeline-list", - "requestBody": { - "content": { - "application/json": { - "example": { - "integration_ids": [ - 10001, - 10002 - ] - }, - "schema": { - "$ref": "#/components/schemas/AlertPipelineListRequest" - } - } - }, - "required": true + "summary": "List alert pipelines", + "description": "Return the alert processing pipelines configured for multiple integrations.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Every `integration_ids` entry must be an integration of the account; one unknown ID fails the whole request with `InvalidParameter`.\n- `items` holds one entry per integration that has a pipeline; integrations without one are absent.", + "href": "/en/api-reference/on-call/alerts/alert-read-pipeline-list", + "metadata": { + "sidebarTitle": "List alert pipelines" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/AlertPipelineListResponse" + } + } + } + ] + }, "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { "items": [ { - "created_at": 1710000000, - "creator_id": 80011, "integration_id": 10001, "rules": [ { + "kind": "alert_inhibit", "if": [ { "key": "labels.cluster", @@ -34371,14 +35422,13 @@ ] } ], - "kind": "alert_inhibit", "settings": { "equals": [ - "service" + "labels.service" ], "source_filters": [ { - "key": "alert_severity", + "key": "severity", "oper": "IN", "vals": [ "Critical" @@ -34389,31 +35439,91 @@ } ], "status": "enabled", - "updated_at": 1712000000, - "updated_by": 80011 + "creator_id": 80011, + "updated_by": 80011, + "created_at": 1710000000, + "updated_at": 1712000000 } ] - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertPipelineListRequest" + }, + "example": { + "integration_ids": [ + 10001, + 10002 + ] + } + } + } + } + } + }, + "/alert/pipeline/upsert": { + "post": { + "operationId": "alert-write-pipeline-upsert", + "summary": "Create or update alert pipeline", + "description": "Set the alert processing pipeline for an integration. Replaces the existing configuration entirely.", + "tags": [ + "On-call/Alerts" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Replaces the integration's whole rule list with `rules`; an empty array removes every rule. At most 50 rules.\n- Rules run in array order on each incoming event of the integration before it becomes an alert; `alert_drop`, or an `alert_inhibit` that matches, discards the event and stops processing.\n- `integration_id` may be an account-level or a channel-owned integration; an ID not in the account returns `InvalidParameter`.\n- Write access also requires object permission: the account owner, an administrator, the integration creator, or a member of its team (for a channel-owned integration, a member of the channel's team); with no team, any caller with the API permission may write.\n- An `alert_inhibit` rule requires the Standard plan or higher; otherwise the call returns `NoLicense`.\n- On success the response carries only `request_id`; the `data` field is omitted.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", + "href": "/en/api-reference/on-call/alerts/alert-write-pipeline-upsert", + "metadata": { + "sidebarTitle": "Create or update alert pipeline" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AlertPipelineListResponse" + "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -34421,6 +35531,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -34428,30 +35541,18 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List alert pipelines", - "tags": [ - "On-call/Alerts" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Integrations Read** (`on-call`) |\n\n## Usage\n\n- All `integration_ids` must be accessible to the caller.", - "href": "/en/api-reference/on-call/alerts/alert-read-pipeline-list", - "metadata": { - "sidebarTitle": "List alert pipelines" - } - } - } - }, - "/alert/pipeline/upsert": { - "post": { - "description": "Set the alert processing pipeline for an integration. Replaces the existing configuration entirely.", - "operationId": "alert-write-pipeline-upsert", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertPipelineUpsertRequest" + }, "example": { "integration_id": 10001, "rules": [ { + "kind": "title_reset", "if": [ { "key": "labels.env", @@ -34461,53 +35562,80 @@ ] } ], - "kind": "title_reset", "settings": { "title": "[TPL]{{.Labels.service}} / {{.Labels.check}}" } }, { - "if": null, "kind": "severity_reset", + "if": null, "settings": { "severity": "Warning" } } ] - }, - "schema": { - "$ref": "#/components/schemas/AlertPipelineUpsertRequest" } } - }, - "required": true + } + } + } + }, + "/audit/operation/list": { + "post": { + "operationId": "audit-read-operation-list", + "summary": "List auditable operation types", + "description": "Return all operation names that are recorded in the audit log, for use as `operations` filter values.", + "tags": [ + "Platform/Audit logs" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Audit Read** (`organization`) |\n\n## Usage\n\n- Use the `name` values from this response as `operations` filter values in `POST /audit/search`.\n- `name_cn` is the Chinese label shown in the console, returned in Chinese regardless of the request language; `name` is the stable value to filter on.", + "href": "/en/api-reference/platform/audit-logs/audit-read-operation-list", + "metadata": { + "sidebarTitle": "List auditable operation types" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": null, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/AuditOperationListResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "name": "template:write:create", + "name_cn": "创建模板" + }, + { + "name": "template:write:delete", + "name_cn": "删除模板" + }, + { + "name": "incident:write:acknowledge", + "name_cn": "认领故障" + } + ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -34515,6 +35643,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -34522,75 +35653,82 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Create or update alert pipeline", - "tags": [ - "On-call/Alerts" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Maximum 50 rules per pipeline.\n- Each rule has a `kind` (one of `title_reset`, `description_reset`, `severity_reset`, `alert_drop`, `alert_inhibit`), an optional `if` filter, and `settings` specific to the kind.\n- The `alert_inhibit` kind requires the Standard license or higher.\n- Every call is recorded in the account audit log. Don't put secrets in request fields.", - "href": "/en/api-reference/on-call/alerts/alert-write-pipeline-upsert", - "metadata": { - "sidebarTitle": "Create or update alert pipeline" - } - } - } - }, - "/audit/operation/list": { - "post": { - "description": "Return all operation names that are recorded in the audit log, for use as `operations` filter values.", - "operationId": "audit-read-operation-list", "requestBody": { + "required": true, "content": { "application/json": { - "example": {}, "schema": { "$ref": "#/components/schemas/AuditOperationListRequest" - } + }, + "example": {} } - }, - "required": true + } + } + } + }, + "/audit/search": { + "post": { + "operationId": "audit-read-search", + "summary": "Search audit logs", + "description": "Return a cursor-paginated list of audit log entries within a time range.", + "tags": [ + "Platform/Audit logs" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Audit Read** (`organization`) |\n\n## Usage\n\n- Time range is required. Maximum span is 90 days. Both `start_time` and `end_time` are Unix epoch **seconds**.\n- Use `search_after_ctx` from the previous response to fetch the next page. The token is opaque — do not construct it manually.\n- The retention window depends on the account's license. Queries beyond the retention boundary silently return an empty result rather than an error.\n- Pass an explicit `limit` (1–99) for predictable paging; when it is omitted or 0 the server chooses the page size, which may be the whole result set. Entries are returned newest first.", + "href": "/en/api-reference/platform/audit-logs/audit-read-search", + "metadata": { + "sidebarTitle": "Search audit logs" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "items": [ - { - "name": "template:write:create", - "name_cn": "创建模板" - }, - { - "name": "template:write:delete", - "name_cn": "删除模板" - }, - { - "name": "incident:write:acknowledge", - "name_cn": "认领故障" - } - ] - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AuditOperationListResponse" + "$ref": "#/components/schemas/AuditSearchResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "total": 2, + "search_after_ctx": "", + "docs": [ + { + "created_at": 1712700123456, + "account_id": 10023, + "member_id": 80011, + "member_name": "Alice", + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "ip": "203.0.113.42", + "operation": "template:write:create", + "operation_name": "创建模板", + "body": "{\"template_name\":\"Prod default\"}", + "params": [], + "is_dangerous": false, + "is_write": true, + "principal_kind": "member", + "credential_type": "", + "credential_id": 0 + } + ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -34598,6 +35736,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -34605,90 +35746,71 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List auditable operation types", - "tags": [ - "Platform/Audit logs" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Audit Read** (`organization`) |\n\n## Usage\n\n- Use the `name` values from this response as `operations` filter values in `POST /audit/search`.\n- `name_cn` is the human-readable Chinese label shown in the console; `name` is the stable wire value to filter on.", - "href": "/en/api-reference/platform/audit-logs/audit-read-operation-list", - "metadata": { - "sidebarTitle": "List auditable operation types" - } - } - } - }, - "/audit/search": { - "post": { - "description": "Return a cursor-paginated list of audit log entries within a time range.", - "operationId": "audit-read-search", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/AuditSearchRequest" + }, "example": { + "start_time": 1712620800, "end_time": 1712707200, "limit": 20, "operations": [ "template:write:create", "template:write:delete" - ], - "start_time": 1712620800 - }, - "schema": { - "$ref": "#/components/schemas/AuditSearchRequest" + ] } } - }, - "required": true + } + } + } + }, + "/calendar/create": { + "post": { + "operationId": "calendarCreate", + "summary": "Create calendar", + "description": "Create a personal service calendar with its weekly workdays and linked holiday calendars.", + "tags": [ + "On-call/Calendars" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- An account can hold at most 5 calendars: once it has 5, a create call by any member returns `InvalidParameter`.\n- `cal_name` must be unique within the account, `timezone` must be a valid IANA name, and a nonzero `team_id` must be a team of the account; otherwise the call returns `InvalidParameter`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/calendars/calendar-create", + "metadata": { + "sidebarTitle": "Create calendar" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "docs": [ - { - "account_id": 10023, - "body": "{\"template_name\":\"Prod default\"}", - "created_at": 1712700123456, - "credential_id": 0, - "credential_type": "", - "ip": "203.0.113.42", - "is_dangerous": false, - "is_write": true, - "member_id": 80011, - "member_name": "Alice", - "operation": "template:write:create", - "operation_name": "创建模板", - "params": [], - "principal_kind": "member", - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - } - ], - "search_after_ctx": "", - "total": 2 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/AuditSearchResponse" + "$ref": "#/components/schemas/CalendarCreateResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "cal_name": "API Test Calendar" + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -34696,6 +35818,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -34703,26 +35828,13 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Search audit logs", - "tags": [ - "Platform/Audit logs" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Audit Read** (`organization`) |\n\n## Usage\n\n- Time range is required. Maximum span is 90 days. Both `start_time` and `end_time` are Unix epoch **seconds**.\n- Use `search_after_ctx` from the previous response to fetch the next page. The token is opaque — do not construct it manually.\n- The retention window depends on the account's license. Queries beyond the retention boundary silently return an empty result rather than an error.\n- `limit` accepts 0–99; omitting it (or 0) returns all matching rows in the window with no page-size cap. Rows are returned newest first.", - "href": "/en/api-reference/platform/audit-logs/audit-read-search", - "metadata": { - "sidebarTitle": "Search audit logs" - } - } - } - }, - "/calendar/create": { - "post": { - "description": "Create a personal service calendar. Each account is limited to 5 calendars unless the Flashcat-Break-Cal-Limit header is set.", - "operationId": "calendarCreate", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/CalendarCreateRequest" + }, "example": { "cal_name": "Production On-Call Calendar", "description": "Calendar for production on-call team", @@ -34734,43 +35846,53 @@ 4, 5 ] - }, - "schema": { - "$ref": "#/components/schemas/CalendarCreateRequest" } } - }, - "required": true + } + } + } + }, + "/calendar/delete": { + "post": { + "operationId": "calendarDelete", + "summary": "Delete calendar", + "description": "Delete a personal service calendar and its events when no rule references it.", + "tags": [ + "On-call/Calendars" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- If escalation rules or silence rules still use the calendar, the call returns HTTP 400 with `error.code` = `ReferenceExist` and `data.refs` listing them.\n- The calendar's own events are deleted together with it.\n- Only personal calendars can be changed, and only by the account owner, an administrator, the calendar creator, or a member of the calendar's team; other callers get `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/calendars/calendar-delete", + "metadata": { + "sidebarTitle": "Delete calendar" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "cal_name": "API Test Calendar" - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarCreateResponse" + "$ref": "#/components/schemas/CalendarEmptyObject" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -34778,6 +35900,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -34785,62 +35910,62 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Create calendar", - "tags": [ - "On-call/Calendars" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/calendars/calendar-create", - "metadata": { - "sidebarTitle": "Create calendar" - } - } - } - }, - "/calendar/delete": { - "post": { - "description": "Delete a personal service calendar. The call fails when referenced by escalation or silence rules.", - "operationId": "calendarDelete", "requestBody": { + "required": true, "content": { "application/json": { - "example": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM" - }, "schema": { "$ref": "#/components/schemas/CalendarIDRequest" + }, + "example": { + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM" } } - }, - "required": true + } + } + } + }, + "/calendar/event/delete": { + "post": { + "operationId": "calEventDelete", + "summary": "Delete calendar event", + "description": "Delete one personal-calendar event by ID, or clear the calendar's own events from a date range.", + "tags": [ + "On-call/Calendars" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- Pass either `event_id`, or both `start_at` and `end_at` (dates in `YYYY-MM-DD`, covering [`start_at`, `end_at`)); any other combination returns `InvalidParameter`.\n- Cleared days fall back to the linked holiday calendars and the weekly workdays.\n- Only personal calendars can be changed, and only by the account owner, an administrator, the calendar creator, or a member of the calendar's team; other callers get `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/calendars/cal-event-delete", + "metadata": { + "sidebarTitle": "Delete calendar event" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/CalendarEmptyObject" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -34848,6 +35973,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -34855,140 +35983,85 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Delete calendar", - "tags": [ - "On-call/Calendars" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/calendars/calendar-delete", - "metadata": { - "sidebarTitle": "Delete calendar" - } - } - } - }, - "/calendar/event/delete": { - "post": { - "description": "Delete one event of a personal calendar by event_id, or clear the calendar's own events off the days [start_at, end_at). Pass either event_id or both start_at and end_at. Cleared days fall back to the linked holiday calendars and the weekly workdays.", - "operationId": "calEventDelete", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/CalEventIDRequest" + }, "example": { "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4" - }, - "schema": { - "$ref": "#/components/schemas/CalEventIDRequest" } } - }, - "required": true + } + } + } + }, + "/calendar/event/list": { + "post": { + "operationId": "calEventList", + "summary": "List calendar events", + "description": "Return a personal calendar's events for a year, month or day, plus the resolved state of each day.", + "tags": [ + "On-call/Calendars" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- `year` defaults to the current year; without `month` the whole year is returned, and `day` requires `month`.\n- `items` merges the calendar's own events (`cale.*` IDs), one generated `non_work.YYYYMMDD` entry per non-working weekday when `workdays` is set, and the events of the linked holiday calendars; `total` counts all of them.\n- `days` gives the resolved state of every day in the scope.\n- Only personal calendars (`cal_id` starting with `cal.`) are supported; other IDs return `InvalidParameter`.", + "href": "/en/api-reference/on-call/calendars/cal-event-list", + "metadata": { + "sidebarTitle": "List calendar events" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarEmptyObject" + "$ref": "#/components/schemas/CalEventListResponse" } - }, - "type": "object" + } } ] - } - } - }, - "description": "Success" - }, - "400": { - "$ref": "#/components/responses/BadRequest" - }, - "401": { - "$ref": "#/components/responses/Unauthorized" - }, - "429": { - "$ref": "#/components/responses/TooManyRequests" - }, - "500": { - "$ref": "#/components/responses/ServerError" - } - }, - "summary": "Delete calendar event", - "tags": [ - "On-call/Calendars" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/calendars/cal-event-delete", - "metadata": { - "sidebarTitle": "Delete calendar event" - } - } - } - }, - "/calendar/event/list": { - "post": { - "description": "Return events for a personal calendar within a year/month/day scope. When month and day are both omitted the whole year is returned. The response also carries days, the resolved state of every day in the scope.", - "operationId": "calEventList", - "requestBody": { - "content": { - "application/json": { - "example": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "month": 5, - "year": 2024 - }, - "schema": { - "$ref": "#/components/schemas/CalEventListRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { + }, "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { "items": [ { "account_id": 2451002751131, - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "created_at": 1775972034, "creator_id": 2476444212131, + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4", + "summary": "Test Holiday", "description": "A test holiday event", + "start_at": "2026-05-01", "end_at": "2026-05-02", - "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4", "is_off": true, - "start_at": "2026-05-01", - "summary": "Test Holiday", + "created_at": 1775972034, "updated_at": 1775972034 }, { "account_id": 2451002751131, - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "created_at": 0, "creator_id": 2451002751131, + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "event_id": "non_work.20260502", + "summary": "non-working day (Saturday)", "description": "", + "start_at": "2026-05-02", "end_at": "2026-05-03", - "event_id": "non_work.20260502", "is_off": true, - "start_at": "2026-05-02", - "summary": "non-working day (Saturday)", + "created_at": 0, "updated_at": 0 } ], @@ -35013,27 +36086,10 @@ "is_off": false } } - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "properties": { - "data": { - "$ref": "#/components/schemas/CalEventListResponse" - } - }, - "type": "object" - } - ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -35041,6 +36097,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -35048,71 +36107,68 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List calendar events", - "tags": [ - "On-call/Calendars" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |", - "href": "/en/api-reference/on-call/calendars/cal-event-list", - "metadata": { - "sidebarTitle": "List calendar events" - } - } - } - }, - "/calendar/event/upsert": { - "post": { - "description": "Create or update an event the calendar owns (a day off or a working-day override) over the days [start_at, end_at). Omit event_id to create a new event; a given event_id must be an existing event of this calendar. The write clears the calendar's other own events off the same days: an event fully inside the range is deleted, one partly inside is shortened, and one spanning the range is split in two, so the latest write decides those days. end_at must be later than start_at.", - "operationId": "calEventUpsert", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/CalEventListRequest" + }, "example": { "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "description": "International Workers Day holiday", - "end_at": "2024-05-06", - "is_off": true, - "start_at": "2024-05-01", - "summary": "Labour Day" - }, - "schema": { - "$ref": "#/components/schemas/CalEventUpsertRequest" + "year": 2024, + "month": 5 } } - }, - "required": true + } + } + } + }, + "/calendar/event/upsert": { + "post": { + "operationId": "calEventUpsert", + "summary": "Upsert calendar event", + "description": "Create or update one of a personal calendar's own events: a day off or a working-day override.", + "tags": [ + "On-call/Calendars" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- The event covers the days [`start_at`, `end_at`), dates in `YYYY-MM-DD`; `end_at` must be later than `start_at`.\n- Omit `event_id` to create an event; a given `event_id` must be an existing event of this calendar.\n- The write clears the calendar's other own events off the same days: an event fully inside the range is deleted, one partly inside is shortened, and one spanning the range is split in two, so the latest write decides those days.\n- Only personal calendars can be changed, and only by the account owner, an administrator, the calendar creator, or a member of the calendar's team; other callers get `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/calendars/cal-event-upsert", + "metadata": { + "sidebarTitle": "Upsert calendar event" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", - "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4", - "summary": "Test Holiday" - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/CalEventUpsertResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "event_id": "cale.KyG9XWTCU5CucbwukEVBQ4", + "summary": "Test Holiday" + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -35120,6 +36176,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -35127,54 +36186,71 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Upsert calendar event", - "tags": [ - "On-call/Calendars" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/calendars/cal-event-upsert", - "metadata": { - "sidebarTitle": "Upsert calendar event" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CalEventUpsertRequest" + }, + "example": { + "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", + "summary": "Labour Day", + "start_at": "2024-05-01", + "end_at": "2024-05-06", + "is_off": true, + "description": "International Workers Day holiday" + } + } } } } }, "/calendar/info": { "post": { - "description": "Return details of a service calendar.", "operationId": "calendarInfo", - "requestBody": { - "content": { - "application/json": { - "example": { - "cal_id": "cal.eh9gvPtWeH3xXgKeVSRxRg" - }, - "schema": { - "$ref": "#/components/schemas/CalendarIDRequest" - } - } - }, - "required": true + "summary": "Get calendar info", + "description": "Return the details of one service calendar of the account by its ID.", + "tags": [ + "On-call/Calendars" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- An unknown `cal_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/calendars/calendar-info", + "metadata": { + "sidebarTitle": "Get calendar info" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/CalendarItem" + } + } + } + ] + }, "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { "account_id": 2451002751131, + "team_id": 2477033058131, "cal_id": "cal.eh9gvPtWeH3xXgKeVSRxRg", "cal_name": "Stock Exchange Calendar", - "created_at": 1702455630, - "creator_id": 2476444212131, "description": "A stock market trading calendar example", - "kind": "personal", - "status": "enabled", - "team_id": 2477033058131, "timezone": "Asia/Shanghai", - "updated_at": 1775529526, - "updated_by": 3790925372131, + "kind": "personal", "workdays": [ 0, 1, @@ -35183,28 +36259,16 @@ 4, 5, 6 - ] - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "properties": { - "data": { - "$ref": "#/components/schemas/CalendarItem" - } - }, - "type": "object" - } - ] + ], + "created_at": 1702455630, + "updated_at": 1775529526, + "creator_id": 2476444212131, + "updated_by": 3790925372131, + "status": "enabled" + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -35212,6 +36276,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -35219,56 +36286,68 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Get calendar info", - "tags": [ - "On-call/Calendars" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |", - "href": "/en/api-reference/on-call/calendars/calendar-info", - "metadata": { - "sidebarTitle": "Get calendar info" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CalendarIDRequest" + }, + "example": { + "cal_id": "cal.eh9gvPtWeH3xXgKeVSRxRg" + } + } } } } }, "/calendar/list": { "post": { - "description": "Return the list of service calendars visible to the current account.", "operationId": "calendarList", - "requestBody": { - "content": { - "application/json": { - "example": { - "kind": "personal" - }, - "schema": { - "$ref": "#/components/schemas/CalendarListRequest" - } - } - }, - "required": true + "summary": "List calendars", + "description": "Return the list of service calendars visible to the current account.", + "tags": [ + "On-call/Calendars" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Without `kind`, personal calendars are returned. `region.official.holiday` returns public holiday calendars, filtered to the caller's locale unless `no_locale` is `true`; use their `cal_id` in `extra_cal_ids`.\n- The list is not paginated; `total` equals the number of items.", + "href": "/en/api-reference/on-call/calendars/calendar-list", + "metadata": { + "sidebarTitle": "List calendars" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/CalendarListResponse" + } + } + } + ] + }, "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { "items": [ { "account_id": 2451002751131, + "team_id": 2477033058131, "cal_id": "cal.eh9gvPtWeH3xXgKeVSRxRg", "cal_name": "Stock Exchange Calendar", - "created_at": 1702455630, - "creator_id": 2476444212131, "description": "A stock market trading calendar example", - "kind": "personal", - "status": "enabled", - "team_id": 2477033058131, "timezone": "Asia/Shanghai", - "updated_at": 1775529526, - "updated_by": 3790925372131, + "kind": "personal", "workdays": [ 0, 1, @@ -35277,48 +36356,108 @@ 4, 5, 6 - ] + ], + "created_at": 1702455630, + "updated_at": 1775529526, + "creator_id": 2476444212131, + "updated_by": 3790925372131, + "status": "enabled" }, { "account_id": 2451002751131, + "team_id": 0, "cal_id": "cal.VZYkchxJhGELSF4jzkUAud", "cal_name": "HK Stock Exchange Calendar", - "created_at": 1702968470, - "creator_id": 2451002751131, "description": "Hong Kong Stock Exchange trading days calendar", + "timezone": "Asia/Shanghai", + "kind": "personal", "extra_cal_ids": [ "zh-cn.china.official" ], - "kind": "personal", - "status": "enabled", - "team_id": 0, - "timezone": "Asia/Shanghai", + "created_at": 1702968470, "updated_at": 1775188967, - "updated_by": 3790925372131 + "creator_id": 2451002751131, + "updated_by": 3790925372131, + "status": "enabled" } ], "total": 8 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CalendarListRequest" + }, + "example": { + "kind": "personal" + } + } + } + } + } + }, + "/calendar/update": { + "post": { + "operationId": "calendarUpdate", + "summary": "Update calendar", + "description": "Update a personal service calendar; only the fields you send are changed.", + "tags": [ + "On-call/Calendars" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |\n\n## Usage\n\n- Send at least one field besides `cal_id`; otherwise the call returns `InvalidParameter`.\n- `workdays` and `extra_cal_ids` replace the stored lists when sent (an empty array clears them); `team_id: 0` removes the team.\n- `cal_name` must stay unique within the account.\n- Only personal calendars can be changed, and only by the account owner, an administrator, the calendar creator, or a member of the calendar's team; other callers get `AccessDenied`.\n- On success the response carries only `request_id`; the `data` field is omitted.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/calendars/calendar-update", + "metadata": { + "sidebarTitle": "Update calendar" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarListResponse" + "$ref": "#/components/schemas/CalendarEmptyObject" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -35326,6 +36465,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -35333,26 +36475,13 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List calendars", - "tags": [ - "On-call/Calendars" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |", - "href": "/en/api-reference/on-call/calendars/calendar-list", - "metadata": { - "sidebarTitle": "List calendars" - } - } - } - }, - "/calendar/update": { - "post": { - "description": "Update a personal service calendar. Only non-null fields are updated.", - "operationId": "calendarUpdate", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/CalendarUpdateRequest" + }, "example": { "cal_id": "cal.QiNvtdKs4Wj52kZhT3LafM", "cal_name": "Production On-Call Calendar (Updated)", @@ -35364,40 +36493,79 @@ 4, 5 ] - }, - "schema": { - "$ref": "#/components/schemas/CalendarUpdateRequest" } } - }, - "required": true + } + } + } + }, + "/change/list": { + "post": { + "operationId": "change-read-list", + "summary": "List changes", + "description": "Query change records within a time window, with filtering, search, and pagination.", + "tags": [ + "On-call/Changes" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- `start_time` and `end_time` are both required: `start_time` must be less than `end_time`, and the window can span at most 31 days.\n- A change matches when its `[start_time, last_time]` range overlaps the query window.\n- Set `include_events` to `true` to attach each change's underlying events in `events`.", + "href": "/en/api-reference/on-call/changes/change-read-list", + "metadata": { + "sidebarTitle": "List changes" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/CalendarEmptyObject" + "$ref": "#/components/schemas/ListChangeResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "total": 1, + "has_next_page": false, + "items": [ + { + "change_id": "664a1b2c3d4e5f6a7b8c9d0e", + "account_id": 10001, + "channel_id": 5001, + "channel_name": "Production", + "channel_status": "enabled", + "integration_id": 362, + "integration_name": "GitHub Deploy", + "title": "Deploy api-server v2.3.1", + "description": "Rolling deploy to production cluster", + "change_key": "deploy-api-server-2311", + "change_status": "Done", + "start_time": 1716962400, + "last_time": 1716962700, + "end_time": 1716963000, + "labels": { + "service": "api-server", + "env": "prod" + }, + "link": "https://github.com/acme/api-server/actions/runs/123" + } + ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -35405,6 +36573,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -35412,97 +36583,74 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Update calendar", - "tags": [ - "On-call/Calendars" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Calendars Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/calendars/calendar-update", - "metadata": { - "sidebarTitle": "Update calendar" - } - } - } - }, - "/change/list": { - "post": { - "description": "Query change records within a time window, with filtering, search, and pagination.", - "operationId": "change-read-list", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ListChangeRequest" + }, "example": { - "asc": false, + "start_time": 1716960000, "end_time": 1717046400, - "include_events": false, + "p": 1, + "limit": 10, "integration_ids": [ 362 ], - "limit": 10, "orderby": "start_time", - "p": 1, - "start_time": 1716960000 - }, - "schema": { - "$ref": "#/components/schemas/ListChangeRequest" + "asc": false, + "include_events": false } } - }, - "required": true + } + } + } + }, + "/channel/create": { + "post": { + "operationId": "channelCreate", + "summary": "Create channel", + "description": "Create a channel, optionally with a default escalation rule and channel-exclusive integrations.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- `channel_name` must be unique within the account; a duplicate returns `InvalidParameter`.\n- `group.method` `p` requires the Standard license or higher and `i` requires the Pro license. Creating a channel beyond the plan's channel quota also returns `NoLicense`.\n- When `escalate_rule` is set, an enabled escalation rule named `Default` is created with one level that notifies `escalate_rule.target` once.\n- Each ID in `plugin_ids` creates one channel-exclusive integration of that integration type, named after the type.\n- When `is_external_report_enabled` is `true`, the response also carries `external_report_token`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-create", + "metadata": { + "sidebarTitle": "Create channel" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "has_next_page": false, - "items": [ - { - "account_id": 10001, - "change_id": "664a1b2c3d4e5f6a7b8c9d0e", - "change_key": "deploy-api-server-2311", - "change_status": "Done", - "channel_id": 5001, - "channel_name": "Production", - "channel_status": "enabled", - "description": "Rolling deploy to production cluster", - "end_time": 1716963000, - "integration_id": 362, - "integration_name": "GitHub Deploy", - "labels": { - "env": "prod", - "service": "api-server" - }, - "last_time": 1716962700, - "link": "https://github.com/acme/api-server/actions/runs/123", - "start_time": 1716962400, - "title": "Deploy api-server v2.3.1" - } - ], - "total": 1 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListChangeResponse" + "$ref": "#/components/schemas/ChannelCreateResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "channel_id": 6294542005131, + "channel_name": "Production Alerts" + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -35510,6 +36658,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -35517,74 +36668,76 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List changes", - "tags": [ - "On-call/Changes" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n", - "href": "/en/api-reference/on-call/changes/change-read-list", - "metadata": { - "sidebarTitle": "List changes" - } - } - } - }, - "/channel/create": { - "post": { - "description": "Create a new channel for incident management.", - "operationId": "channelCreate", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateChannelRequest" + }, "example": { - "auto_resolve_mode": "trigger", - "auto_resolve_timeout": 86400, + "team_id": 3521074710131, "channel_name": "Production Alerts", "description": "Handles all production environment alerts", "group": { "method": "p", + "equals": [ + [ + "labels.service" + ] + ], "time_window": 10, "window_type": "tumbling" }, - "team_id": 3521074710131 - }, - "schema": { - "$ref": "#/components/schemas/CreateChannelRequest" + "auto_resolve_timeout": 86400, + "auto_resolve_mode": "trigger" } } - }, - "required": true + } + } + } + }, + "/channel/delete": { + "post": { + "operationId": "channelDelete", + "summary": "Delete channel", + "description": "Delete a disabled channel together with its rules and channel-exclusive integrations.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` channel can be deleted; any other status returns `InvalidParameter`.\n- If a shared integration's routing rule still targets the channel (in a case or the default branch), the call returns HTTP 400 with `error.code` `ReferenceExist` and the referencing integrations in `data.refs`. Remove the channel from those routes with `POST /route/upsert` first.\n- All escalation, silence, drop, inhibit and subscribe rules of the channel and its channel-exclusive integrations are deleted. The channel itself is soft-deleted: `POST /channel/info` still returns it with `status` `deleted`.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-delete", + "metadata": { + "sidebarTitle": "Delete channel" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "channel_id": 6294542005131, - "channel_name": "API Test Channel" - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ChannelCreateResponse" + "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -35592,6 +36745,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -35599,62 +36755,62 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Create channel", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-create", - "metadata": { - "sidebarTitle": "Create channel" - } - } - } - }, - "/channel/delete": { - "post": { - "description": "Delete a channel. Only a `disabled` channel can be deleted; all of its escalation, silence, drop and inhibit rules are deleted with it. The call fails when an integration route still references the channel.", - "operationId": "channelDelete", "requestBody": { + "required": true, "content": { "application/json": { - "example": { - "channel_id": 3521074710131 - }, "schema": { "$ref": "#/components/schemas/ChannelIDRequest" + }, + "example": { + "channel_id": 3521074710131 } } - }, - "required": true + } + } + } + }, + "/channel/disable": { + "post": { + "operationId": "channelDisable", + "summary": "Disable channel", + "description": "Disable a channel; while disabled it discards all incoming alert events.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` channel can be disabled; any other status returns `InvalidParameter`.\n- Rules and integrations are kept. Alert processing may take up to about one minute to see the new status.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-disable", + "metadata": { + "sidebarTitle": "Disable channel" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -35662,6 +36818,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -35669,62 +36828,62 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Delete channel", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-delete", - "metadata": { - "sidebarTitle": "Delete channel" - } - } - } - }, - "/channel/disable": { - "post": { - "description": "Disable a channel to stop incident routing without deleting it; a disabled channel discards incoming events. Only an `enabled` channel can be disabled.", - "operationId": "channelDisable", "requestBody": { + "required": true, "content": { "application/json": { - "example": { - "channel_id": 3521074710131 - }, "schema": { "$ref": "#/components/schemas/ChannelIDRequest" + }, + "example": { + "channel_id": 3521074710131 } } - }, - "required": true + } + } + } + }, + "/channel/enable": { + "post": { + "operationId": "channelEnable", + "summary": "Enable channel", + "description": "Enable a disabled channel so it processes incoming alert events again.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` channel can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-enable", + "metadata": { + "sidebarTitle": "Enable channel" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -35732,6 +36891,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -35739,62 +36901,65 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Disable channel", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-disable", - "metadata": { - "sidebarTitle": "Disable channel" - } - } - } - }, - "/channel/enable": { - "post": { - "description": "Enable a channel to resume incident routing. Only a `disabled` channel can be enabled.", - "operationId": "channelEnable", "requestBody": { + "required": true, "content": { "application/json": { - "example": { - "channel_id": 3521074710131 - }, "schema": { "$ref": "#/components/schemas/ChannelIDRequest" + }, + "example": { + "channel_id": 3521074710131 } } - }, - "required": true + } + } + } + }, + "/channel/escalate/rule/create": { + "post": { + "operationId": "channelEscalateRuleCreate", + "summary": "Create escalation rule", + "description": "Create an escalation rule that decides who is notified about a channel's incidents, and how.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Rules are evaluated in ascending `priority`. The first enabled rule whose `time_filters` and `filters` match a new incident takes it; later rules are skipped. Omit `priority` to place the rule after all existing ones.\n- `template_id` must be an existing notification template, every member in `person_ids` must exist and every team in `team_ids` must have members; otherwise `InvalidParameter`.\n- The new rule is `enabled`.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-create", + "metadata": { + "sidebarTitle": "Create escalation rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/RuleCreateResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "rule_id": "69db2f72a0fe7db6448b1506", + "rule_name": "On-call escalation" + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -35802,6 +36967,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -35809,84 +36977,81 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Enable channel", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-enable", - "metadata": { - "sidebarTitle": "Enable channel" - } - } - } - }, - "/channel/escalate/rule/create": { - "post": { - "description": "Create an escalation rule defining who gets notified and when during an incident.", - "operationId": "channelEscalateRuleCreate", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateEscalationRuleRequest" + }, "example": { "channel_id": 3521074710131, + "rule_name": "On-call escalation", + "template_id": "6321aad26c12104586a88916", "description": "Notify primary on-call, then escalate to secondary after 30 minutes", "layers": [ { - "escalate_window": 30, - "force_escalate": false, - "max_times": 3, - "notify_step": 10, "target": { - "by": { - "follow_preference": true - }, "person_ids": [ 3790925372131 - ] - } + ], + "by": { + "follow_preference": true + } + }, + "max_times": 3, + "notify_step": 10, + "escalate_window": 30, + "force_escalate": false } - ], - "rule_name": "On-call escalation", - "template_id": "6321aad26c12104586a88916" - }, - "schema": { - "$ref": "#/components/schemas/CreateEscalationRuleRequest" + ] } } - }, - "required": true + } + } + } + }, + "/channel/escalate/rule/delete": { + "post": { + "operationId": "channelEscalateRuleDelete", + "summary": "Delete escalation rule", + "description": "Delete a disabled escalation rule so it no longer appears in the channel's rule list.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be deleted; any other status returns `InvalidParameter`.\n- The rule is soft-deleted: it disappears from the list, but `POST /channel/escalate/rule/info` still returns it with `status` `deleted`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-delete", + "metadata": { + "sidebarTitle": "Delete escalation rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "rule_id": "69db2f72a0fe7db6448b1506", - "rule_name": "Test escalation rule" - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleCreateResponse" + "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -35894,6 +37059,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -35901,63 +37069,63 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Create escalation rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-create", - "metadata": { - "sidebarTitle": "Create escalation rule" - } - } - } - }, - "/channel/escalate/rule/delete": { - "post": { - "description": "Delete an escalation rule. Only a `disabled` rule can be deleted.", - "operationId": "channelEscalateRuleDelete", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, "example": { "channel_id": 3521074710131, "rule_id": "6621b23f4a2c5e0012ab34cd" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" } } - }, - "required": true + } + } + } + }, + "/channel/escalate/rule/disable": { + "post": { + "operationId": "channelEscalateRuleDisable", + "summary": "Disable escalation rule", + "description": "Disable an escalation rule without deleting it.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` rule can be disabled; any other status returns `InvalidParameter`.\n- A disabled rule takes no new incidents, and incidents already assigned through it stop receiving its notifications and escalations.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-disable", + "metadata": { + "sidebarTitle": "Disable escalation rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -35965,6 +37133,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -35972,63 +37143,63 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Delete escalation rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-delete", - "metadata": { - "sidebarTitle": "Delete escalation rule" - } - } - } - }, - "/channel/escalate/rule/disable": { - "post": { - "description": "Disable an escalation rule without deleting it. Only an `enabled` rule can be disabled.", - "operationId": "channelEscalateRuleDisable", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, "example": { "channel_id": 3521074710131, "rule_id": "6621b23f4a2c5e0012ab34cd" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" } } - }, - "required": true + } + } + } + }, + "/channel/escalate/rule/enable": { + "post": { + "operationId": "channelEscalateRuleEnable", + "summary": "Enable escalation rule", + "description": "Enable a disabled escalation rule so it can take new incidents again.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-enable", + "metadata": { + "sidebarTitle": "Enable escalation rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -36036,6 +37207,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -36043,63 +37217,95 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Disable escalation rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-disable", - "metadata": { - "sidebarTitle": "Disable escalation rule" - } - } - } - }, - "/channel/escalate/rule/enable": { - "post": { - "description": "Enable a disabled escalation rule. Only a `disabled` rule can be enabled.", - "operationId": "channelEscalateRuleEnable", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, "example": { "channel_id": 3521074710131, "rule_id": "6621b23f4a2c5e0012ab34cd" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" } } - }, - "required": true + } + } + } + }, + "/channel/escalate/rule/info": { + "post": { + "operationId": "channelEscalateRuleInfo", + "summary": "Get escalation rule detail", + "description": "Return one escalation rule of a channel, including its levels, time windows and filters.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- A deleted rule is still returned, with `status` `deleted`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-info", + "metadata": { + "sidebarTitle": "Get escalation rule detail" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/EscalateRuleItem" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "account_id": 2451002751131, + "channel_id": 6193426913131, + "priority": 0, + "aggr_window": 0, + "rule_name": "Default", + "description": "", + "layers": [ + { + "max_times": 1, + "notify_step": 10, + "target": { + "person_ids": [ + 3790925372131 + ], + "by": { + "follow_preference": true + }, + "webhooks": null + }, + "escalate_window": 30, + "force_escalate": false + } + ], + "time_filters": [], + "filters": [], + "status": "enabled", + "template_id": "6321aad26c12104586a88916", + "rule_id": "69bd0ce95a238693176c1d66", + "updated_by": 3790925372131, + "created_at": 1773997289, + "updated_at": 1773997289 + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -36107,6 +37313,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -36114,95 +37323,99 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Enable escalation rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-enable", - "metadata": { - "sidebarTitle": "Enable escalation rule" - } - } - } - }, - "/channel/escalate/rule/info": { - "post": { - "description": "Retrieve detailed information for a specific escalation rule.", - "operationId": "channelEscalateRuleInfo", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, "example": { "channel_id": 1001, "rule_id": "6621b23f4a2c5e0012ab34d0" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" } } - }, - "required": true + } + } + } + }, + "/channel/escalate/rule/list": { + "post": { + "operationId": "channelEscalateRuleList", + "summary": "List escalation rules", + "description": "List a channel's escalation rules in the order they are evaluated.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- An unknown `channel_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-list", + "metadata": { + "sidebarTitle": "List escalation rules" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "account_id": 2451002751131, - "aggr_window": 0, - "channel_id": 6193426913131, - "created_at": 1773997289, - "description": "", - "filters": [], - "layers": [ - { - "escalate_window": 30, - "force_escalate": false, - "max_times": 1, - "notify_step": 10, - "target": { - "by": { - "follow_preference": true - }, - "person_ids": [ - 3790925372131 - ], - "webhooks": null - } - } - ], - "priority": 0, - "rule_id": "69bd0ce95a238693176c1d66", - "rule_name": "Default", - "status": "enabled", - "template_id": "6321aad26c12104586a88916", - "time_filters": [], - "updated_at": 1773997289, - "updated_by": 3790925372131 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EscalateRuleItem" + "$ref": "#/components/schemas/ListEscalationRulesResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "account_id": 2451002751131, + "channel_id": 6193426913131, + "priority": 0, + "aggr_window": 0, + "rule_name": "Default", + "description": "", + "layers": [ + { + "max_times": 1, + "notify_step": 10, + "target": { + "person_ids": [ + 3790925372131 + ], + "by": { + "follow_preference": true + }, + "webhooks": null + }, + "escalate_window": 30, + "force_escalate": false + } + ], + "time_filters": [], + "filters": [], + "status": "enabled", + "template_id": "6321aad26c12104586a88916", + "rule_id": "69bd0ce95a238693176c1d66", + "updated_by": 3790925372131, + "created_at": 1773997289, + "updated_at": 1773997289 + } + ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -36210,6 +37423,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -36217,98 +37433,62 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Get escalation rule detail", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-info", - "metadata": { - "sidebarTitle": "Get escalation rule detail" - } - } - } - }, - "/channel/escalate/rule/list": { - "post": { - "description": "List all escalation rules for a channel.", - "operationId": "channelEscalateRuleList", "requestBody": { + "required": true, "content": { "application/json": { - "example": { - "channel_id": 1001 - }, "schema": { "$ref": "#/components/schemas/ChannelScopedListRequest" + }, + "example": { + "channel_id": 1001 } } - }, - "required": true + } + } + } + }, + "/channel/escalate/rule/update": { + "post": { + "operationId": "channelEscalateRuleUpdate", + "summary": "Update escalation rule", + "description": "Replace the configuration of an existing escalation rule.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Full replacement: omitted `description`, `aggr_window`, `time_filters` and `filters` are reset to empty or `0`. Only `priority` keeps its current value when omitted.\n- Validation is the same as for create. The rule's `status` is not changed; use the enable and disable endpoints.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-escalate-rule-update", + "metadata": { + "sidebarTitle": "Update escalation rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "items": [ - { - "account_id": 2451002751131, - "aggr_window": 0, - "channel_id": 6193426913131, - "created_at": 1773997289, - "description": "", - "filters": [], - "layers": [ - { - "escalate_window": 30, - "force_escalate": false, - "max_times": 1, - "notify_step": 10, - "target": { - "by": { - "follow_preference": true - }, - "person_ids": [ - 3790925372131 - ], - "webhooks": null - } - } - ], - "priority": 0, - "rule_id": "69bd0ce95a238693176c1d66", - "rule_name": "Default", - "status": "enabled", - "template_id": "6321aad26c12104586a88916", - "time_filters": [], - "updated_at": 1773997289, - "updated_by": 3790925372131 - } - ] - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListEscalationRulesResponse" + "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -36316,6 +37496,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -36323,31 +37506,24 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List escalation rules", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-list", - "metadata": { - "sidebarTitle": "List escalation rules" - } - } - } - }, - "/channel/escalate/rule/update": { - "post": { - "description": "Update an existing escalation rule configuration.", - "operationId": "channelEscalateRuleUpdate", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateEscalationRuleRequest" + }, "example": { "channel_id": 1001, + "rule_id": "6621b23f4a2c5e0012ab34d0", + "template_id": "6621b23f4a2c5e0012ab34d1", + "rule_name": "Default escalation", "layers": [ { "target": { + "person_ids": [ + 42 + ], "by": { "critical": [ "voice" @@ -36355,50 +37531,62 @@ "warning": [ "sms" ] - }, - "person_ids": [ - 42 - ] + } } } - ], - "rule_id": "6621b23f4a2c5e0012ab34d0", - "rule_name": "Default escalation", - "template_id": "6621b23f4a2c5e0012ab34d1" - }, - "schema": { - "$ref": "#/components/schemas/UpdateEscalationRuleRequest" + ] } } - }, - "required": true + } + } + } + }, + "/channel/info": { + "post": { + "operationId": "channelInfo", + "summary": "Get channel detail", + "description": "Return one channel's full configuration with counts of its active incidents from the last 30 days.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Deleted channels are still returned, with `status` `deleted`.\n- A private channel (`is_private: true`) returns `AccessDenied` unless the caller is the account owner or an admin, its creator, or a member of its owning or managing teams.\n- `team_name`, `creator_name` and `is_starred` are not returned here; use `POST /channel/list` for them.\n- An unknown `channel_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/channel-info", + "metadata": { + "sidebarTitle": "Get channel detail" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ChannelItem" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "channel_id": 1001, + "channel_name": "Production Alerts", + "status": "enabled", + "team_id": 10 + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -36406,6 +37594,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -36413,67 +37604,70 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Update escalation rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-escalate-rule-update", - "metadata": { - "sidebarTitle": "Update escalation rule" - } - } - } - }, - "/channel/info": { - "post": { - "description": "Retrieve detailed information for a specific channel.", - "operationId": "channelInfo", "requestBody": { + "required": true, "content": { "application/json": { - "example": { - "channel_id": 1001 - }, "schema": { "$ref": "#/components/schemas/ChannelInfoRequest" + }, + "example": { + "channel_id": 1001 } } - }, - "required": true + } + } + } + }, + "/channel/infos": { + "post": { + "operationId": "channelInfos", + "summary": "Batch get channels", + "description": "Return the ID, name and status of up to 1,000 channels in one call.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- IDs that do not exist are skipped. Deleted channels are included, with `status` `deleted`.\n- Items are ordered by channel creation, not by the order of `channel_ids`.\n- Private channels are included regardless of the caller's team membership.", + "href": "/en/api-reference/on-call/channels/channel-infos", + "metadata": { + "sidebarTitle": "Batch get channels" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "channel_id": 1001, - "channel_name": "Production Alerts", - "status": "enabled", - "team_id": 10 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ChannelItem" + "$ref": "#/components/schemas/ChannelInfosResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "channel_id": 1001, + "channel_name": "Production Alerts", + "status": "enabled" + } + ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -36481,6 +37675,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -36488,73 +37685,68 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Get channel detail", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |", - "href": "/en/api-reference/on-call/channels/channel-info", - "metadata": { - "sidebarTitle": "Get channel detail" - } - } - } - }, - "/channel/infos": { - "post": { - "description": "Retrieve multiple channels by their IDs.", - "operationId": "channelInfos", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelInfosRequest" + }, "example": { "channel_ids": [ 1001, 1002 ] - }, - "schema": { - "$ref": "#/components/schemas/ChannelInfosRequest" } } - }, - "required": true + } + } + } + }, + "/channel/inhibit/rule/create": { + "post": { + "operationId": "channelInhibitRuleCreate", + "summary": "Create inhibit rule", + "description": "Create an inhibit rule that mutes alert events while a related source alert is still active.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Requires the Standard license or higher; otherwise the call returns `NoLicense`.\n- An incoming event is inhibited when it matches `target_filters` and the same channel has an active (not recovered) alert with a different `alert_key` that matches `source_filters`, started within the 10 minutes before the event, and has the same value for every key in `equals`.\n- The rule never fires when `equals` or `source_filters` is empty, or when the incoming event has no value for a label listed in `equals`.\n- Inhibit rules are checked after drop and silence rules; the first matching inhibit rule is applied.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-create", + "metadata": { + "sidebarTitle": "Create inhibit rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "items": [ - { - "channel_id": 1001, - "channel_name": "Production Alerts", - "status": "enabled" - } - ] - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ChannelInfosResponse" + "$ref": "#/components/schemas/RuleCreateResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "rule_id": "69db2f69a0fe7db6448b1504", + "rule_name": "Suppress Info when Critical fires" + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -36562,6 +37754,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -36569,35 +37764,21 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Batch get channels", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |", - "href": "/en/api-reference/on-call/channels/channel-infos", - "metadata": { - "sidebarTitle": "Batch get channels" - } - } - } - }, - "/channel/inhibit/rule/create": { - "post": { - "description": "Create an inhibit rule to suppress lower-priority alerts when higher-priority ones are firing.", - "operationId": "channelInhibitRuleCreate", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateInhibitRuleRequest" + }, "example": { "channel_id": 3521074710131, + "rule_name": "Suppress Info when Critical fires", "description": "When a Critical alert fires, suppress matching Info alerts", "equals": [ "labels.cluster", "labels.service" ], - "is_directly_discard": false, - "rule_name": "Suppress Info when Critical fires", "source_filters": [ [ { @@ -36619,44 +37800,55 @@ ] } ] - ] - }, - "schema": { - "$ref": "#/components/schemas/CreateInhibitRuleRequest" + ], + "is_directly_discard": false } } - }, - "required": true + } + } + } + }, + "/channel/inhibit/rule/delete": { + "post": { + "operationId": "channelInhibitRuleDelete", + "summary": "Delete inhibit rule", + "description": "Delete a disabled inhibit rule so it no longer appears in the channel's rule list.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be deleted; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-delete", + "metadata": { + "sidebarTitle": "Delete inhibit rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "rule_id": "69db2f69a0fe7db6448b1504", - "rule_name": "Test inhibit rule" - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleCreateResponse" + "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -36664,6 +37856,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -36671,63 +37866,63 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Create inhibit rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-create", - "metadata": { - "sidebarTitle": "Create inhibit rule" - } - } - } - }, - "/channel/inhibit/rule/delete": { - "post": { - "description": "Delete an inhibit rule. Only a `disabled` rule can be deleted.", - "operationId": "channelInhibitRuleDelete", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, "example": { "channel_id": 3521074710131, "rule_id": "6621b23f4a2c5e0012ab34cd" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" } } - }, - "required": true + } + } + } + }, + "/channel/inhibit/rule/disable": { + "post": { + "operationId": "channelInhibitRuleDisable", + "summary": "Disable inhibit rule", + "description": "Disable an inhibit rule without deleting it.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` rule can be disabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-disable", + "metadata": { + "sidebarTitle": "Disable inhibit rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] - } + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} + } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -36735,6 +37930,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -36742,63 +37940,63 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Delete inhibit rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-delete", - "metadata": { - "sidebarTitle": "Delete inhibit rule" - } - } - } - }, - "/channel/inhibit/rule/disable": { - "post": { - "description": "Disable an inhibit rule without deleting it. Only an `enabled` rule can be disabled.", - "operationId": "channelInhibitRuleDisable", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, "example": { "channel_id": 3521074710131, "rule_id": "6621b23f4a2c5e0012ab34cd" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" } } - }, - "required": true + } + } + } + }, + "/channel/inhibit/rule/enable": { + "post": { + "operationId": "channelInhibitRuleEnable", + "summary": "Enable inhibit rule", + "description": "Enable a disabled inhibit rule so it mutes matching alert events again.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Requires the Standard license or higher; otherwise the call returns `NoLicense`.\n- Only a `disabled` rule can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-enable", + "metadata": { + "sidebarTitle": "Enable inhibit rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -36806,6 +38004,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -36813,138 +38014,77 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Disable inhibit rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-disable", - "metadata": { - "sidebarTitle": "Disable inhibit rule" - } - } - } - }, - "/channel/inhibit/rule/enable": { - "post": { - "description": "Enable a disabled inhibit rule. Only a `disabled` rule can be enabled.", - "operationId": "channelInhibitRuleEnable", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, "example": { "channel_id": 3521074710131, "rule_id": "6621b23f4a2c5e0012ab34cd" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" } } - }, - "required": true + } + } + } + }, + "/channel/inhibit/rule/list": { + "post": { + "operationId": "channelInhibitRuleList", + "summary": "List inhibit rules", + "description": "List a channel's inhibit rules, oldest first.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) |\n\n## Usage\n\n- An unknown `channel_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-list", + "metadata": { + "sidebarTitle": "List inhibit rules" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ListInhibitRulesResponse" } - }, - "type": "object" + } } ] - } - } - }, - "description": "Success" - }, - "400": { - "$ref": "#/components/responses/BadRequest" - }, - "401": { - "$ref": "#/components/responses/Unauthorized" - }, - "429": { - "$ref": "#/components/responses/TooManyRequests" - }, - "500": { - "$ref": "#/components/responses/ServerError" - } - }, - "summary": "Enable inhibit rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-enable", - "metadata": { - "sidebarTitle": "Enable inhibit rule" - } - } - } - }, - "/channel/inhibit/rule/list": { - "post": { - "description": "List all inhibit rules configured for a channel.", - "operationId": "channelInhibitRuleList", - "requestBody": { - "content": { - "application/json": { - "example": { - "channel_id": 1001 - }, - "schema": { - "$ref": "#/components/schemas/ChannelScopedListRequest" - } - } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { + }, "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { "items": [ { "account_id": 2451002751131, "channel_id": 5967964835131, - "created_at": 1773979184, - "description": "", - "equals": [ - "data_source_id", - "labels._account_id" - ], - "is_directly_discard": false, - "rule_id": "69bcc630b9e63df36603e425", "rule_name": "Suppress downstream alerts", + "description": "", "source_filters": [ [ { "key": "severity", "oper": "IN", "vals": [ - "Info" + "Critical" ] } ] ], - "status": "enabled", "target_filters": [ [ { @@ -36956,31 +38096,95 @@ } ] ], - "updated_at": 1773979184, - "updated_by": 3790925372131 + "equals": [ + "labels.cluster", + "labels.service" + ], + "is_directly_discard": false, + "status": "enabled", + "rule_id": "69bcc630b9e63df36603e425", + "updated_by": 3790925372131, + "created_at": 1773979184, + "updated_at": 1773979184 } ] - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, + } + } + } + } + }, + "400": { + "$ref": "#/components/responses/BadRequest" + }, + "401": { + "$ref": "#/components/responses/Unauthorized" + }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, + "429": { + "$ref": "#/components/responses/TooManyRequests" + }, + "500": { + "$ref": "#/components/responses/ServerError" + } + }, + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelScopedListRequest" + }, + "example": { + "channel_id": 1001 + } + } + } + } + } + }, + "/channel/inhibit/rule/update": { + "post": { + "operationId": "channelInhibitRuleUpdate", + "summary": "Update inhibit rule", + "description": "Replace the configuration of an existing inhibit rule.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Full replacement: omitted `source_filters` and `target_filters` become empty, an omitted `is_directly_discard` becomes `false`, and an omitted `description` becomes empty.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-update", + "metadata": { + "sidebarTitle": "Update inhibit rule" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListInhibitRulesResponse" + "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -36988,6 +38192,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -36995,67 +38202,77 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List inhibit rules", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-list", - "metadata": { - "sidebarTitle": "List inhibit rules" - } - } - } - }, - "/channel/inhibit/rule/update": { - "post": { - "description": "Update an existing inhibit rule configuration.", - "operationId": "channelInhibitRuleUpdate", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateInhibitRuleRequest" + }, "example": { "channel_id": 1001, + "rule_id": "6621b23f4a2c5e0012ab34ce", + "rule_name": "Suppress downstream", "equals": [ "labels.cluster" - ], - "rule_id": "6621b23f4a2c5e0012ab34ce", - "rule_name": "Suppress downstream" - }, - "schema": { - "$ref": "#/components/schemas/UpdateInhibitRuleRequest" + ] } } - }, - "required": true + } + } + } + }, + "/channel/list": { + "post": { + "operationId": "channelList", + "summary": "List channels", + "description": "List the channels visible to the caller, with filters, sorting and pagination.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- Without filters, every channel in the account is returned except private channels the caller cannot access. Deleted channels are never returned.\n- Setting both `is_my_team` and `is_my_starred` to `true` returns `InvalidParameter`. `is_my_managed` takes precedence over both. With `is_my_managed` or `is_my_team`, `team_ids` is ignored.\n- With `is_brief: true`, items carry only `channel_id`, `channel_name`, `description`, `status` and `is_starred`, and all matches are returned in one page.\n- Always pass `p`. When it is omitted the first page is returned, but `has_next_page` is then `true` whenever anything matches.", + "href": "/en/api-reference/on-call/channels/channel-list", + "metadata": { + "sidebarTitle": "List channels" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ListChannelsResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "total": 42, + "has_next_page": true, + "items": [ + { + "channel_id": 1001, + "channel_name": "Production Alerts", + "status": "enabled" + } + ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -37063,6 +38280,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -37070,75 +38290,68 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Update inhibit rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-inhibit-rule-update", - "metadata": { - "sidebarTitle": "Update inhibit rule" - } - } - } - }, - "/channel/list": { - "post": { - "description": "List channels accessible to the current user with optional filters.", - "operationId": "channelList", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ListChannelsRequest" + }, "example": { - "asc": false, + "p": 1, "limit": 20, "orderby": "created_at", - "p": 1 - }, - "schema": { - "$ref": "#/components/schemas/ListChannelsRequest" + "asc": false } } - }, - "required": true + } + } + } + }, + "/channel/silence/rule/create": { + "post": { + "operationId": "channelSilenceRuleCreate", + "summary": "Create silence rule", + "description": "Create a silence rule that mutes or drops matching alert events during a time window.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Set exactly one of `time_filter` (one-off window) or `time_filters` (recurring windows), and give `filters` at least one condition; otherwise `InvalidParameter`.\n- Each incoming event is checked against drop rules first, then silence rules, then inhibit rules. The first enabled silence rule whose window covers the current time and whose `filters` match is applied.\n- With `from_incident_id`, only one enabled silence rule may exist per incident; creating a second returns `InvalidParameter`.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-silence-rule-create", + "metadata": { + "sidebarTitle": "Create silence rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "has_next_page": true, - "items": [ - { - "channel_id": 1001, - "channel_name": "Production Alerts", - "status": "enabled" - } - ], - "total": 42 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListChannelsResponse" + "$ref": "#/components/schemas/RuleCreateResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "rule_id": "69db2f66a0fe7db6448b1503", + "rule_name": "Maintenance window silence" + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -37146,6 +38359,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -37153,29 +38369,21 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List channels", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |", - "href": "/en/api-reference/on-call/channels/channel-list", - "metadata": { - "sidebarTitle": "List channels" - } - } - } - }, - "/channel/silence/rule/create": { - "post": { - "description": "Create a silence rule to suppress notifications matching specified conditions.", - "operationId": "channelSilenceRuleCreate", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateSilenceRuleRequest" + }, "example": { "channel_id": 3521074710131, + "rule_name": "Maintenance window silence", "description": "Silence all Info alerts during planned maintenance", + "time_filter": { + "start_time": 1773388800, + "end_time": 1773414000 + }, "filters": [ [ { @@ -37187,49 +38395,54 @@ } ] ], - "is_directly_discard": false, - "rule_name": "Maintenance window silence", - "time_filter": { - "end_time": 1773414000, - "start_time": 1773388800 - } - }, - "schema": { - "$ref": "#/components/schemas/CreateSilenceRuleRequest" + "is_directly_discard": false } } - }, - "required": true + } + } + } + }, + "/channel/silence/rule/delete": { + "post": { + "operationId": "channelSilenceRuleDelete", + "summary": "Delete silence rule", + "description": "Delete a disabled silence rule so it no longer appears in the channel's rule list.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be deleted; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-silence-rule-delete", + "metadata": { + "sidebarTitle": "Delete silence rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "rule_id": "69db2f66a0fe7db6448b1503", - "rule_name": "Test silence rule" - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleCreateResponse" + "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -37237,6 +38450,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -37244,63 +38460,63 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Create silence rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-silence-rule-create", - "metadata": { - "sidebarTitle": "Create silence rule" - } - } - } - }, - "/channel/silence/rule/delete": { - "post": { - "description": "Delete a silence rule. Only a `disabled` rule can be deleted.", - "operationId": "channelSilenceRuleDelete", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, "example": { "channel_id": 3521074710131, "rule_id": "6621b23f4a2c5e0012ab34cd" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" } } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, + } + } + } + }, + "/channel/silence/rule/disable": { + "post": { + "operationId": "channelSilenceRuleDisable", + "summary": "Disable silence rule", + "description": "Disable a silence rule without deleting it.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` rule can be disabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-silence-rule-disable", + "metadata": { + "sidebarTitle": "Disable silence rule" + } + }, + "responses": { + "200": { + "description": "Success", + "content": { + "application/json": { "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -37308,6 +38524,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -37315,63 +38534,63 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Delete silence rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-silence-rule-delete", - "metadata": { - "sidebarTitle": "Delete silence rule" - } - } - } - }, - "/channel/silence/rule/disable": { - "post": { - "description": "Disable a silence rule without deleting it. Only an `enabled` rule can be disabled.", - "operationId": "channelSilenceRuleDisable", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, "example": { "channel_id": 3521074710131, "rule_id": "6621b23f4a2c5e0012ab34cd" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" } } - }, - "required": true + } + } + } + }, + "/channel/silence/rule/enable": { + "post": { + "operationId": "channelSilenceRuleEnable", + "summary": "Enable silence rule", + "description": "Enable a disabled silence rule so it silences matching alert events again.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-silence-rule-enable", + "metadata": { + "sidebarTitle": "Enable silence rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -37379,6 +38598,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -37386,63 +38608,96 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Disable silence rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-silence-rule-disable", - "metadata": { - "sidebarTitle": "Disable silence rule" - } - } - } - }, - "/channel/silence/rule/enable": { - "post": { - "description": "Enable a disabled silence rule. Only a `disabled` rule can be enabled.", - "operationId": "channelSilenceRuleEnable", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, "example": { "channel_id": 3521074710131, "rule_id": "6621b23f4a2c5e0012ab34cd" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" } } - }, - "required": true + } + } + } + }, + "/channel/silence/rule/list": { + "post": { + "operationId": "channelSilenceRuleList", + "summary": "List silence rules", + "description": "List a channel's silence rules and whether each one is in effect right now.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) |\n\n## Usage\n\n- Listing also permanently removes one-off-window rules that are due for automatic cleanup (see `is_auto_delete`), so they no longer appear. Rules with recurring `time_filters` are never removed this way.\n- An unknown `channel_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/channel-silence-rule-list", + "metadata": { + "sidebarTitle": "List silence rules" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/ListSilenceRulesResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "account_id": 2451002751131, + "channel_id": 5967964835131, + "rule_name": "Silence Info alerts", + "description": "", + "from_incident_id": "000000000000000000000000", + "time_filters": [], + "time_filter": { + "start_time": 1773388800, + "end_time": 1773414000 + }, + "filters": [ + [ + { + "key": "severity", + "oper": "IN", + "vals": [ + "Info" + ] + } + ] + ], + "is_directly_discard": true, + "status": "enabled", + "rule_id": "69b3c426b4a6f5abf1f54873", + "updated_by": 3790925372131, + "created_at": 1773388838, + "updated_at": 1773388838, + "is_effective": false + } + ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -37450,6 +38705,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -37457,95 +38715,62 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Enable silence rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-silence-rule-enable", - "metadata": { - "sidebarTitle": "Enable silence rule" - } - } - } - }, - "/channel/silence/rule/list": { - "post": { - "description": "List all silence rules configured for a channel.", - "operationId": "channelSilenceRuleList", "requestBody": { + "required": true, "content": { "application/json": { - "example": { - "channel_id": 1001 - }, "schema": { "$ref": "#/components/schemas/ChannelScopedListRequest" + }, + "example": { + "channel_id": 1001 } } - }, - "required": true + } + } + } + }, + "/channel/silence/rule/update": { + "post": { + "operationId": "channelSilenceRuleUpdate", + "summary": "Update silence rule", + "description": "Replace the configuration of an existing silence rule.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- The same time window and `filters` requirements as create apply. Switching between `time_filter` and `time_filters` clears the other one.\n- `description`, `is_directly_discard` and `is_auto_delete` are always overwritten, so omitting them resets them to empty or `false`. `from_incident_id` cannot be changed.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-silence-rule-update", + "metadata": { + "sidebarTitle": "Update silence rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "items": [ - { - "account_id": 2451002751131, - "channel_id": 5967964835131, - "created_at": 1773388838, - "description": "", - "filters": [ - [ - { - "key": "severity", - "oper": "IN", - "vals": [ - "Info" - ] - } - ] - ], - "from_incident_id": "000000000000000000000000", - "is_directly_discard": true, - "is_effective": false, - "rule_id": "69b3c426b4a6f5abf1f54873", - "rule_name": "Silence Info alerts", - "status": "enabled", - "time_filter": { - "end_time": 1773414000, - "start_time": 1773388800 - }, - "time_filters": [], - "updated_at": 1773388838, - "updated_by": 3790925372131 - } - ] - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/ListSilenceRulesResponse" + "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -37553,6 +38778,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -37560,28 +38788,21 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List silence rules", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Read** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-silence-rule-list", - "metadata": { - "sidebarTitle": "List silence rules" - } - } - } - }, - "/channel/silence/rule/update": { - "post": { - "description": "Update an existing silence rule configuration.", - "operationId": "channelSilenceRuleUpdate", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateSilenceRuleRequest" + }, "example": { "channel_id": 1001, + "rule_id": "6621b23f4a2c5e0012ab34cd", + "rule_name": "Mute during maintenance", + "time_filter": { + "start_time": 1710000000, + "end_time": 1710086400 + }, "filters": [ [ { @@ -37592,47 +38813,57 @@ ] } ] - ], - "rule_id": "6621b23f4a2c5e0012ab34cd", - "rule_name": "Mute during maintenance", - "time_filter": { - "end_time": 1710086400, - "start_time": 1710000000 - } - }, - "schema": { - "$ref": "#/components/schemas/UpdateSilenceRuleRequest" + ] } } - }, - "required": true + } + } + } + }, + "/channel/unsubscribe/rule/create": { + "post": { + "operationId": "channelUnsubscribeRuleCreate", + "summary": "Create drop rule", + "description": "Create a drop rule that discards matching alert events before any alert or incident is created.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Drop rules are checked first, before silence and inhibit rules. An event matching any enabled drop rule is discarded: no alert, incident or notification is produced.\n- Without `filters`, or with an empty list, the rule matches nothing.\n- An unknown `channel_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-create", + "metadata": { + "sidebarTitle": "Create drop rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/EmptyResponse" + "$ref": "#/components/schemas/RuleCreateResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "rule_id": "69db2f6ba0fe7db6448b1505", + "rule_name": "Drop test environment alerts" + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -37640,6 +38871,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -37647,28 +38881,16 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Update silence rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-silence-rule-update", - "metadata": { - "sidebarTitle": "Update silence rule" - } - } - } - }, - "/channel/unsubscribe/rule/create": { - "post": { - "description": "Create a drop rule to filter out unwanted alerts before they become incidents.", - "operationId": "channelUnsubscribeRuleCreate", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/CreateDropRuleRequest" + }, "example": { "channel_id": 3521074710131, + "rule_name": "Drop test environment alerts", "description": "Discard all alerts from the test environment before they create incidents", "filters": [ [ @@ -37681,45 +38903,54 @@ ] } ] - ], - "rule_name": "Drop test environment alerts" - }, - "schema": { - "$ref": "#/components/schemas/CreateDropRuleRequest" + ] } } - }, - "required": true + } + } + } + }, + "/channel/unsubscribe/rule/delete": { + "post": { + "operationId": "channelUnsubscribeRuleDelete", + "summary": "Delete drop rule", + "description": "Delete a disabled drop rule so it no longer appears in the channel's rule list.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be deleted; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-delete", + "metadata": { + "sidebarTitle": "Delete drop rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "rule_id": "69db2f6ba0fe7db6448b1505", - "rule_name": "Test drop rule" - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { - "$ref": "#/components/schemas/RuleCreateResponse" + "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -37727,6 +38958,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -37734,63 +38968,63 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Create drop rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |", - "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-create", - "metadata": { - "sidebarTitle": "Create drop rule" - } - } - } - }, - "/channel/unsubscribe/rule/delete": { - "post": { - "description": "Delete a drop rule. Only a `disabled` rule can be deleted.", - "operationId": "channelUnsubscribeRuleDelete", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, "example": { "channel_id": 3521074710131, "rule_id": "6621b23f4a2c5e0012ab34cd" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" } } - }, - "required": true + } + } + } + }, + "/channel/unsubscribe/rule/disable": { + "post": { + "operationId": "channelUnsubscribeRuleDisable", + "summary": "Disable drop rule", + "description": "Disable a drop rule without deleting it.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only an `enabled` rule can be disabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-disable", + "metadata": { + "sidebarTitle": "Disable drop rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -37798,6 +39032,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -37805,134 +39042,63 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Delete drop rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |", - "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-delete", - "metadata": { - "sidebarTitle": "Delete drop rule" - } - } - } - }, - "/channel/unsubscribe/rule/disable": { - "post": { - "description": "Disable a drop rule without deleting it. Only an `enabled` rule can be disabled.", - "operationId": "channelUnsubscribeRuleDisable", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, "example": { "channel_id": 3521074710131, "rule_id": "6621b23f4a2c5e0012ab34cd" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" } } - }, - "required": true - }, - "responses": { - "200": { - "content": { - "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "properties": { - "data": { - "$ref": "#/components/schemas/EmptyResponse" - } - }, - "type": "object" - } - ] - } - } - }, - "description": "Success" - }, - "400": { - "$ref": "#/components/responses/BadRequest" - }, - "401": { - "$ref": "#/components/responses/Unauthorized" - }, - "429": { - "$ref": "#/components/responses/TooManyRequests" - }, - "500": { - "$ref": "#/components/responses/ServerError" - } - }, - "summary": "Disable drop rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |", - "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-disable", - "metadata": { - "sidebarTitle": "Disable drop rule" } } } }, "/channel/unsubscribe/rule/enable": { "post": { - "description": "Enable a disabled drop rule. Only a `disabled` rule can be enabled.", "operationId": "channelUnsubscribeRuleEnable", - "requestBody": { - "content": { - "application/json": { - "example": { - "channel_id": 3521074710131, - "rule_id": "6621b23f4a2c5e0012ab34cd" - }, - "schema": { - "$ref": "#/components/schemas/ChannelRuleIDRequest" - } - } - }, - "required": true + "summary": "Enable drop rule", + "description": "Enable a disabled drop rule so it discards matching alert events again.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Only a `disabled` rule can be enabled; any other status returns `InvalidParameter`.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-enable", + "metadata": { + "sidebarTitle": "Enable drop rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -37940,6 +39106,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -37947,47 +39116,65 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Enable drop rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |", - "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-enable", - "metadata": { - "sidebarTitle": "Enable drop rule" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelRuleIDRequest" + }, + "example": { + "channel_id": 3521074710131, + "rule_id": "6621b23f4a2c5e0012ab34cd" + } + } } } } }, "/channel/unsubscribe/rule/list": { "post": { - "description": "List drop rules for a channel.", "operationId": "channelUnsubscribeRuleList", - "requestBody": { - "content": { - "application/json": { - "example": { - "channel_id": 1001 - }, - "schema": { - "$ref": "#/components/schemas/ChannelScopedListRequest" - } - } - }, - "required": true + "summary": "List drop rules", + "description": "List a channel's drop rules, oldest first.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n\n## Usage\n\n- An unknown `channel_id` returns `InvalidParameter`.", + "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-list", + "metadata": { + "sidebarTitle": "List drop rules" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ListDropRulesResponse" + } + } + } + ] + }, "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { "items": [ { "account_id": 2451002751131, "channel_id": 5967964835131, - "created_at": 1773978928, + "rule_name": "Drop test alerts", "description": "", "filters": [ [ @@ -38000,34 +39187,17 @@ } ] ], - "rule_id": "69bcc530b9e63df36603e421", - "rule_name": "Drop test alerts", "status": "enabled", - "updated_at": 1773978928, - "updated_by": 3790925372131 + "rule_id": "69bcc530b9e63df36603e421", + "updated_by": 3790925372131, + "created_at": 1773978928, + "updated_at": 1773978928 } ] - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "properties": { - "data": { - "$ref": "#/components/schemas/ListDropRulesResponse" - } - }, - "type": "object" - } - ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -38035,6 +39205,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -38042,75 +39215,62 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List drop rules", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |", - "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-list", - "metadata": { - "sidebarTitle": "List drop rules" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ChannelScopedListRequest" + }, + "example": { + "channel_id": 1001 + } + } } } } }, "/channel/unsubscribe/rule/update": { "post": { - "description": "Update an existing drop rule configuration.", "operationId": "channelUnsubscribeRuleUpdate", - "requestBody": { - "content": { - "application/json": { - "example": { - "channel_id": 1001, - "filters": [ - [ - { - "key": "labels.env", - "oper": "IN", - "vals": [ - "test" - ] - } - ] - ], - "rule_id": "6621b23f4a2c5e0012ab34cf", - "rule_name": "Drop test alerts" - }, - "schema": { - "$ref": "#/components/schemas/UpdateDropRuleRequest" - } - } - }, - "required": true + "summary": "Update drop rule", + "description": "Replace the name, description and conditions of an existing drop rule.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Full replacement: an omitted `description` becomes empty, and an omitted `filters` clears all conditions so the rule matches nothing.\n- An unknown `channel_id` or `rule_id` returns `InvalidParameter`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-update", + "metadata": { + "sidebarTitle": "Update drop rule" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": {}, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EmptyResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": {} } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -38118,6 +39278,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -38125,66 +39288,77 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Update drop rule", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |", - "href": "/en/api-reference/on-call/channels/channel-unsubscribe-rule-update", - "metadata": { - "sidebarTitle": "Update drop rule" - } - } - } - }, - "/channel/update": { - "post": { - "description": "Update an existing channel's configuration and settings.", - "operationId": "channelUpdate", "requestBody": { + "required": true, "content": { "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateDropRuleRequest" + }, "example": { "channel_id": 1001, - "channel_name": "Production Alerts (v2)", - "description": "Updated description" - }, - "schema": { - "$ref": "#/components/schemas/UpdateChannelRequest" + "rule_id": "6621b23f4a2c5e0012ab34cf", + "rule_name": "Drop test alerts", + "filters": [ + [ + { + "key": "labels.env", + "oper": "IN", + "vals": [ + "test" + ] + } + ] + ] } } - }, - "required": true + } + } + } + }, + "/channel/update": { + "post": { + "operationId": "channelUpdate", + "summary": "Update channel", + "description": "Update a channel's settings; only the fields present in the request are changed.", + "tags": [ + "On-call/Channels" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |\n\n## Usage\n\n- Omitted or `null` fields keep their current value. `group`, `flapping` and `event_group` each replace the whole stored object.\n- Pass `managing_team_ids: []` to remove all managing teams.\n- `auto_resolve_mode` is applied only together with `auto_resolve_timeout`; when `auto_resolve_timeout` is sent without `auto_resolve_mode`, the mode resets to `trigger`.\n- Setting `is_external_report_enabled` to `true` generates a new `external_report_token` on every call and the previous token stops working; `false` clears the token.\n- A `channel_name` used by another channel returns `InvalidParameter`; `group.method` `p` or `i` without the matching license returns `NoLicense`.\n- The caller must also be able to edit the channel: the account owner or an admin, the channel creator, or a member of its managing teams (of its owning team when `managing_team_ids` is empty). Otherwise the call returns `AccessDenied`.\n- Every call is recorded in the account audit log.", + "href": "/en/api-reference/on-call/channels/channel-update", + "metadata": { + "sidebarTitle": "Update channel" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "external_report_token": "" - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/UpdateChannelResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "external_report_token": "" + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -38192,6 +39366,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -38199,66 +39376,70 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Update channel", - "tags": [ - "On-call/Channels" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | **Channels Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/channels/channel-update", - "metadata": { - "sidebarTitle": "Update channel" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UpdateChannelRequest" + }, + "example": { + "channel_id": 3521074710131, + "channel_name": "Production Alerts (v2)", + "description": "Updated description" + } + } } } } }, "/datasource/im/person/try-link": { "post": { - "description": "Try to automatically link unbound members to their IM accounts for one integration.", "operationId": "datasourceImPersonTryLink", - "requestBody": { - "content": { - "application/json": { - "example": { - "integration_id": 6113996590131 - }, - "schema": { - "$ref": "#/components/schemas/TryLinkPersonRequest" - } - } - }, - "required": true + "summary": "Attempt IM person linking", + "description": "Try to automatically link unbound members to their IM accounts for one integration.", + "tags": [ + "On-call/Integrations" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Looks up every account member not yet linked to this integration's IM app by email and phone; only Feishu, DingTalk and WeCom integrations are supported, other types return `InvalidParameter`.\n- A disabled integration returns `InvalidParameter`.\n- Returns `RequestLocked` while another linking run for the same integration is in progress, and `InvalidParameter` when the IM platform refuses the lookup (missing contact permissions or rejected credentials).\n- `new_linked_person_ids` is an empty array when nobody could be newly linked.", + "href": "/en/api-reference/on-call/integrations/datasource-im-person-try-link", + "metadata": { + "sidebarTitle": "Attempt IM person linking" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "new_linked_person_ids": [ - 5348648172131 - ] - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/TryLinkPersonResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "new_linked_person_ids": [ + 5348648172131 + ], + "unmatched_count": 2, + "no_contact_count": 1 + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -38266,6 +39447,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -38273,88 +39457,90 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Attempt IM person linking", - "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 | **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- The server uses member email and phone values to find matching users in DingTalk, Feishu, or WeCom.\n- When no member can be linked, the response either carries an empty `new_linked_person_ids` array or omits the `data` field entirely.", - "href": "/en/api-reference/on-call/integrations/datasource-im-person-try-link", - "metadata": { - "sidebarTitle": "Attempt IM person linking" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TryLinkPersonRequest" + }, + "example": { + "integration_id": 6113996590131 + } + } } } } }, "/datasource/im/war-room-enabled/list": { "post": { - "description": "List IM integrations that have the war-room feature enabled for the account.", "operationId": "im-war-room-enabled-list", - "requestBody": { - "content": { - "application/json": { - "example": {}, - "schema": { - "type": "object" - } - } - }, - "required": true + "summary": "List war-room-enabled IM integrations", + "description": "List IM integrations that have the war-room feature enabled for the account.", + "tags": [ + "On-call/IM 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 Read** (`on-call`) or **Channels Manage** (`on-call`) or **Incidents Read** (`on-call`) or **Incidents Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Returns enabled and disabled Feishu, DingTalk, WeCom, Slack, and Microsoft Teams integrations whose settings have `war_room_enabled` set to `true`; deleted integrations are excluded.\n- Secret values inside `settings` are masked as `******`.", + "href": "/en/api-reference/on-call/integrations/im-war-room-enabled-list", + "metadata": { + "sidebarTitle": "List war-room-enabled IM integrations" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { + "schema": { + "allOf": [ + { + "$ref": "#/components/schemas/SuccessEnvelope" + }, + { + "type": "object", + "properties": { + "data": { + "$ref": "#/components/schemas/ListWarRoomEnabledResponse" + } + } + } + ] + }, "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", "data": { "items": [ { + "data_source_id": 362, "account_id": 10001, + "team_id": 0, + "plugin_id": 101, + "name": "Feishu Ops", + "status": "enabled", "category": "im", - "created_at": 1716962400, - "creator_id": 20001, - "data_source_id": 362, + "plugin_type": "feishu_app", + "plugin_type_name": "Feishu", "description": "Feishu war-room integration", - "exclusive_data_source_id": 0, - "integration_id": 362, "integration_key": "ik_8f3a2b1c9d0e", - "last_time": 0, - "name": "Feishu Ops", - "no_editable": false, - "plugin_id": 101, - "plugin_type": "feishu", - "plugin_type_name": "Feishu", "ref_id": "", "settings": { "war_room_enabled": true }, - "status": "enabled", - "team_id": 0, + "no_editable": false, + "creator_id": 20001, + "updated_by": 20001, + "created_at": 1716962400, "updated_at": 1716962700, - "updated_by": 20001 + "last_time": 0, + "exclusive_data_source_id": 0, + "integration_id": 362 } ] - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, - "schema": { - "allOf": [ - { - "$ref": "#/components/schemas/SuccessEnvelope" - }, - { - "properties": { - "data": { - "$ref": "#/components/schemas/ListWarRoomEnabledResponse" - } - }, - "type": "object" - } - ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -38362,6 +39548,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -38369,80 +39558,78 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List war-room-enabled IM integrations", - "tags": [ - "On-call/IM integrations" - ], - "x-mint": { - "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **1,000 requests/minute**; **50 requests/second** per account |\n| Permissions | None — any valid `app_key` can call this operation |\n", - "href": "/en/api-reference/on-call/integrations/im-war-room-enabled-list", - "metadata": { - "sidebarTitle": "List war-room-enabled IM integrations" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object" + }, + "example": {} + } } } } }, "/enrichment/info": { "post": { - "description": "Return the enrichment rule set configured for a specific integration.", "operationId": "enrichment-read-info", - "requestBody": { - "content": { - "application/json": { - "example": { - "integration_id": 5001 - }, - "schema": { - "$ref": "#/components/schemas/EnrichmentInfoRequest" - } - } - }, - "required": true + "summary": "Get enrichment rules", + "description": "Return the enrichment rule set configured for a specific integration.", + "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 Read** (`on-call`) or **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- `integration_id` must be an existing integration of the account; otherwise `InvalidParameter`.\n- Returns `data: null` when the integration has no rule set.", + "href": "/en/api-reference/on-call/alert-enrichment/enrichment-read-info", + "metadata": { + "sidebarTitle": "Get enrichment rules" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "created_at": 1710000000, - "creator_id": 80011, - "integration_id": 5001, - "rules": [ - { - "kind": "extraction", - "settings": { - "override": true, - "pattern": "^(prod|staging|dev).*$", - "result_label": "environment", - "source_field": "labels.env" - } - } - ], - "status": "enabled", - "updated_at": 1710000000, - "updated_by": 80011 - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EnrichmentItem" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "integration_id": 5001, + "rules": [ + { + "kind": "extraction", + "settings": { + "source_field": "labels.env", + "result_label": "environment", + "pattern": "^(prod|staging|dev).*$", + "override": true + } + } + ], + "status": "enabled", + "updated_by": 80011, + "creator_id": 80011, + "created_at": 1710000000, + "updated_at": 1710000000 + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -38450,6 +39637,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -38457,77 +39647,74 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "Get enrichment rules", - "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 Read** (`on-call`) or **Channels Manage** (`on-call`) or **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Returns `null` if no enrichment rules have been configured for the integration.", - "href": "/en/api-reference/on-call/alert-enrichment/enrichment-read-info", - "metadata": { - "sidebarTitle": "Get enrichment rules" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnrichmentInfoRequest" + }, + "example": { + "integration_id": 5001 + } + } } } } }, "/enrichment/list": { "post": { - "description": "Return the enrichment rule sets for a list of integration IDs.", "operationId": "enrichment-read-list", - "requestBody": { - "content": { - "application/json": { - "example": { - "integration_ids": [ - 5001, - 5002 - ] - }, - "schema": { - "$ref": "#/components/schemas/EnrichmentListRequest" - } - } - }, - "required": true + "summary": "List enrichment rules", + "description": "Return the enrichment rule sets for a list of integration IDs.", + "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 | **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |\n\n## Usage\n\n- Every ID must be an existing integration of the account; otherwise `InvalidParameter`.\n- Integrations that have no rule set are left out of `items`.", + "href": "/en/api-reference/on-call/alert-enrichment/enrichment-read-list", + "metadata": { + "sidebarTitle": "List enrichment rules" + } }, "responses": { "200": { + "description": "Success", "content": { "application/json": { - "example": { - "data": { - "items": [ - { - "created_at": 1710000000, - "creator_id": 80011, - "integration_id": 5001, - "rules": [], - "status": "enabled", - "updated_at": 1710000000, - "updated_by": 80011 - } - ] - }, - "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4" - }, "schema": { "allOf": [ { "$ref": "#/components/schemas/SuccessEnvelope" }, { + "type": "object", "properties": { "data": { "$ref": "#/components/schemas/EnrichmentListResponse" } - }, - "type": "object" + } } ] + }, + "example": { + "request_id": "01HK8XQE3Z7JM2NTFQ5YJ8P9R4", + "data": { + "items": [ + { + "integration_id": 5001, + "rules": [], + "status": "enabled", + "updated_by": 80011, + "creator_id": 80011, + "created_at": 1710000000, + "updated_at": 1710000000 + } + ] + } } } - }, - "description": "Success" + } }, "400": { "$ref": "#/components/responses/BadRequest" @@ -38535,6 +39722,9 @@ "401": { "$ref": "#/components/responses/Unauthorized" }, + "403": { + "$ref": "#/components/responses/Forbidden" + }, "429": { "$ref": "#/components/responses/TooManyRequests" }, @@ -38542,73 +39732,68 @@ "$ref": "#/components/responses/ServerError" } }, - "summary": "List enrichment rules", - "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 | **Integrations Read** (`on-call`) or **Integrations Manage** (`on-call`) |", - "href": "/en/api-reference/on-call/alert-enrichment/enrichment-read-list", - "metadata": { - "sidebarTitle": "List enrichment rules" + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EnrichmentListRequest" + }, + "example": { + "integration_ids": [ + 5001, + 5002 + ] + } + } } } } }, "/enrichment/mapping/api/create": { "post": { - "description": "Create a new external HTTP API endpoint used to enrich alerts via HTTP lookup.", "operationId": "mapping-api-write-create", - "requestBody": { - "content": { - "application/json": { - "example": { - "api_name": "CMDB API", - "description": "Query CMDB for host metadata", - "headers": { - "X-Token": "mytoken" - }, - "insecure_skip_verify": false, - "retry_count": 1, - "timeout": 2, - "url": "https://cmdb.example.com/api/lookup" - }, - "schema": { - "$ref": "#/components/schemas/MappingAPICreateRequest" - } - } - }, - "required": true + "summary": "Create mapping API", + "description": "Register an external HTTP API that enrichment rules call to look up alert labels.", + "tags": [ + "On-call/Alert enrichment" + ], + "x-mint": { + "content": "## Restrictions\n\n| Aspect | Value |\n| ------ | ----- |\n| Rate limits | **300 requests/minute**; **20 requests/second** per account |\n| Permissions | **Mappings Manage** (`on-call`) |\n\n## Usage\n\n- An enrichment rule with `mapping_type` = `api` sends `POST ` with the configured `headers` and the JSON body `{\"result_label_keys\": [...], \"event\": {...}}` (the alert event). The API must answer HTTP 200 with `{\"result_labels\": {\"