# Rootly AI Source: https://docs.rootly.com/ai/ai An AI responder on your team: grounded in the incident's live context, and never able to do more than the person asking. ## Overview Rootly AI is an AI responder built into the places your team already works. Ask it what's happening and it answers from the incident's live context. Ask it to do something and it does it, capped at what you can do in Rootly and audited under the name of the person who asked. Everything below is opt-in and governed from [AI Settings](/ai/ai-settings). *** ## Where It Works | Surface | What you get | Learn more | | ---------- | -------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- | | **Slack** | The full agent in your incident channels: it pages responders, updates the incident, assigns roles, and drafts comms | [Rootly AI in Slack](/ai/rootly-in-slack/overview) | | **Web** | Ask-anything chat on the incident page, read-only by design | [Rootly AI in Web](/ai/ask-rootly-ai) | | **Mobile** | A live summary card, plus chat that updates the incident with confirmation | [Rootly AI on Mobile](/ai/rootly-ai-on-mobile) | *** ## What It Does | Feature | In one line | Learn more | | ------------------------ | ------------------------------------------------------------------------------------------- | --------------------------------------------------------- | | **AI Summaries** | Titles, summaries, catchups, and status write-ups, generated from the incident's own record | [AI Summaries](/ai/ai-summaries) | | **Related Incidents** | Ranked matches from your incident history, grounded in how each one was resolved | [Related Incidents](/ai/related-incidents) | | **Meeting Scribe** | Turns the bridge call into a live, speaker-labeled record on the incident | [Meeting Scribe](/ai/meeting-scribe) | | **AI in Retrospectives** | Drafts retrospective sections from incident data, sources shown and fully editable | [AI in Retrospectives](/ai/ai-in-retrospectives/overview) | *** ## Extend It | Direction | In one line | Learn more | | --------------------- | ------------------------------------------------------------------------------------------- | -------------------------------------- | | **Connectors** | Bring your data to Rootly AI: it investigates with your observability, code, and docs tools | [Connectors](/ai/connectors/overview) | | **Rootly MCP Server** | Bring Rootly to your AI: query incidents and on-call from Claude, Cursor, or any MCP client | [MCP Server](/integrations/mcp-server) | *** ## Govern It One switch opts your organization in; per-feature toggles decide where Rootly AI shows up. | Page | What it covers | Learn more | | -------------------------------------------------- | ------------------------------------------------------------------ | ------------------------------------------------------------ | | **AI Settings** | Every Rootly AI control in one place | [AI Settings](/ai/ai-settings) | | **Data Privacy for Rootly AI** | The agent's data access, retention, audit, and model details | [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) | | **Data Privacy for AI Summaries & Meeting Scribe** | Data handling for the single-turn features and the scribe pipeline | [AI Summaries & Meeting Scribe](/ai/data-privacy-for-ai) | # Building AI Templates Source: https://docs.rootly.com/ai/ai-in-retrospectives/building-ai-templates Add Rootly AI blocks to a retrospective template and preview the output against a past incident before rollout. ## AI Blocks Start in the Template The fastest way to get Rootly AI-generated retrospectives is to add AI blocks to a **template**. Every retrospective created from that template generates those sections automatically. The quickest start of all is a **[starter template](#start-from-a-starter-template)**, a ready-made, Rootly AI-powered template you can adopt in one click. You can also drop AI blocks into an individual document on the fly (see [Using AI Blocks](/ai/ai-in-retrospectives/using-ai-blocks)), but templates are where you set the standard for the whole team. For how templates work in general, including formats, Liquid, data blocks, and defaults, see [Configuring Templates](/retrospectives/configuring-templates). *** ## Start from a Starter Template Rootly ships four starter templates: | Starter template | Best for | What's inside | | :---------------------------------- | :------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | **Standard Incident Retrospective** | A thorough, all-purpose retro | Summary, Impact, Root Cause, Mitigation, and Resolution AI blocks, plus Timeline and Follow-ups data blocks | | **Quick Retro** | Low-severity incidents and fast write-ups | A Summary AI block, plus Timeline and Follow-ups data blocks | | **Customer-Facing RCA / COE** | A root-cause analysis you can share with customers | Summary, Impact, Root Cause, and Resolution AI blocks, plus corrective-action Follow-ups | | **Major Incident (SEV1) Deep-Dive** | High-severity, leadership-visible incidents | All six AI blocks, plus Timeline and Follow-ups data blocks | You can adopt a starter from two places: * On the **Retrospectives → Document Templates** page, click **Try template** on a starter to open the builder preloaded with it. Nothing is created until you save. * Already in the builder? Open the **AI Library** tab in the sidebar and click a starter to insert its content. An empty document is seeded with it; a document that already has content gets the starter appended. Each insert gets fresh blocks, so you can insert more than one without collisions. *** ## Open the Template Builder To build a template from scratch: In Rootly, go to **Retrospectives → Document Templates**. Click **New Template** for a blank document, or **Try template** on a starter to begin from a ready-made one (see above). Open the **AI Library** sidebar for starter templates and the AI Blocks palette. *** ## Add AI Blocks from the Palette To add an AI block: * **Drag** it from the palette into the position you want in the document, or * Click into the document, type `/`, and pick it from the slash menu. *** ## The Preset Blocks Rootly ships six preset AI blocks. | Block | What it drafts | | :------------------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Summary** | A concise overview of what happened and how it was resolved, written for a broad audience. | | **Impact** | Who and what was affected: customers, services, scope, and duration. | | **Root Cause** | The underlying cause and contributing factors. | | **Mitigation** | The immediate steps taken to reduce or stop the impact. | | **Resolution** | How the incident was fully resolved. | | **Curated Timeline** | A readable, narrative timeline of the key moments. This is different from the raw **Timeline** data block, which lists every event; the Curated Timeline summarizes the story. | *** ## Custom AI Blocks When none of the presets fit, add a **Custom AI block**: Add it from the palette or the slash menu. The title becomes the section heading. Describe what you want this section to contain in plain language, for example, *"Summarize the customer communications sent during the incident and whether they went out on time."* Rootly AI drafts that section from the same incident context as the presets. *** ## Steer Generation with Instructions You don't have to accept the preset prompts as-is. You can layer your own guidance on top: * **Per-block custom instructions.** Add instructions to any preset block to put your own spin on it, for example, *"Write Impact in customer-minutes-lost"* or *"Keep Root Cause to three sentences and name the failing service."* The instruction is saved on the template and applied every time that block generates. * **Template-level general instructions.** Set instructions that apply to **every** AI block in the template, like audience and house style, so all your retrospectives read consistently. *** ## Preview Against a Past Incident Before you roll a template out, preview it against a **real past incident** to see exactly what each AI block would produce with that incident's data. In the builder, choose **Preview**, select a past incident, and iterate until the output reads the way you want. *** ## Publish When the template looks right, save and publish it. To control which incidents get which template (by severity, team, or incident type), see [Configuring Templates](/retrospectives/configuring-templates). *** ## Related Pages What AI blocks are and how they draft your retrospective. Insert, generate, edit, and regenerate AI blocks inside a retrospective document. How retrospective templates work. # Rootly AI in Retrospectives Source: https://docs.rootly.com/ai/ai-in-retrospectives/overview Rootly AI drafts retrospective sections from incident data, timeline events, Slack channels, and bridge-call transcripts. ## Overview **AI blocks** solve the blank-page problem. Inside the [Rootly retrospective editor](/collaborative-retrospectives/using-the-editor), an AI block is a section, such as Summary or Root Cause, that Rootly AI drafts for you from the incident's own context. You decide which blocks belong in a retrospective by adding them to a [template](/retrospectives/configuring-templates), and every retrospective created from that template generates those sections automatically. Every AI block shows the sources it drew on and stays fully editable. *** ## How AI Blocks Work AI blocks live in the [Rootly retrospective editor](/collaborative-retrospectives/using-the-editor), right alongside your headings, text, data blocks, and Liquid variables. * **Each block has a purpose-built prompt.** You don't write it, you just add the block. * **They pull context automatically.** Every block draws on the incident's metadata, its timeline, the incident Slack channel, and bridge-call transcripts (when captured via the Rootly AI [Meeting Scribe](/ai/meeting-scribe)), with no setup required. * **They stay live in the document.** Regenerate, edit inline, convert to plain text, comment, or rate. * **Steer generation** with custom instructions on the template. *** ## Key Capabilities at a Glance | Capability | Description | Where | | :------------------------------ | :--------------------------------------------------------------------------- | :------------------------ | | Preset AI blocks | Six ready-made section types, each with an expert prompt | Template builder + editor | | Custom AI block | Write your own section with a title and a plain-language prompt | Template builder + editor | | Rootly AI-powered templates | Add AI blocks to a template so every retro generates them automatically | Template builder | | Custom instructions | Steer how each block (or the whole template) is written | Template builder | | Preview against a past incident | See exactly what a block produces before rolling out the template | Template builder | | Insert on the fly | Add an AI block to any retro document with the slash menu | Editor | | Regenerate & edit | Regenerate any block, edit it inline, convert it to plain text, or delete it | Editor | | Sources & prompt | Inspect what a block drew on and the prompt behind it | Editor | *** ## The AI Block Types Rootly ships six preset blocks, from Summary to Curated Timeline, plus a custom block for any section you define with your own prompt. See the full list in [Building AI Templates](/ai/ai-in-retrospectives/building-ai-templates#the-preset-blocks), and learn how to work with them in a document in [Using AI Blocks](/ai/ai-in-retrospectives/using-ai-blocks). *** ## How Permissions Work AI blocks respect your existing Rootly retrospective permissions. There is no separate AI permission system. * Anyone who can edit a retrospective can insert, generate, regenerate, edit, and convert AI blocks. * **Observers (read-only users) cannot modify AI blocks**. They can't regenerate, edit, convert, or delete them, just as they can't edit the rest of the document. *** ## Frequently Asked Questions Rootly AI in Retrospectives is enabled from **AI & Agents**. Ask your Rootly Admin to turn it on for your workspace. Once it's on, AI blocks appear in the template builder palette and the editor's slash menu. From the incident's metadata, its timeline, the incident Slack channel, and the bridge-call transcript (when captured via the Rootly AI Meeting Scribe). No other external sources are used. Rootly AI warns you before regenerating a block you've edited by hand, so you don't lose your changes by accident. No. Incident context is used to generate your draft and is not used to fine-tune base models. *** ## Related Pages Add AI blocks to a template and preview them against a past incident before rollout. Insert, generate, edit, and regenerate AI blocks inside a retrospective document. The editor AI blocks live in, with formatting, data blocks, Liquid, and collaboration. How retrospective templates work. # Insert and Edit AI Blocks in Retrospectives Source: https://docs.rootly.com/ai/ai-in-retrospectives/using-ai-blocks Insert Rootly AI blocks in a retrospective, watch them generate, inspect their sources, and edit, regenerate, convert, or rate the output. ## Working with AI Blocks in a Retrospective When a retrospective is created from a template that contains AI blocks, those sections generate automatically. You can also add AI blocks to any document yourself. For everything else about the editor, including formatting, data blocks, Liquid, and collaboration, see [Using the Retrospective Editor](/collaborative-retrospectives/using-the-editor). *** ## Insert a Block with the Slash Menu Put the cursor where you want the section. Type `/` to open the menu. Choose one of the presets (Summary, Impact, Root Cause, Mitigation, Resolution, Curated Timeline) or a **Custom AI block**. For a custom block, give it a title and a short prompt describing what you want. The block is inserted and begins generating from the incident's context. *** ## See How a Block Was Generated AI blocks aren't a black box. Open a block's details for a short description of what the block is for, plus: * **The sources** it drew on: incident metadata, timeline events, the incident Slack channel, and the bridge-call transcript when available. * **The system prompt** behind the block, so you know how it was instructed to write. *** ## Work with a Generated Block A generated block behaves like the rest of your document. From the block's toolbar you can: * **Edit inline.** Generated content is just text. * **Regenerate.** Ask Rootly AI to write the section again. If you've changed the block's instructions, the new draft reflects them. * **Convert to plain text.** "Freeze" the block. Its content becomes ordinary document text and is no longer a live AI block. * **Delete.** Remove the block entirely. * **Comment.** Works like anywhere else in the document. If you regenerate a block you've edited by hand, Rootly AI asks you to confirm first. *** ## Give Feedback Rate any block with 👍 / 👎. Feedback flows into Rootly's evaluation pipeline and does not directly fine-tune the model. *** ## Exporting When you publish or export a retrospective, AI block content is rendered as **static content** at the time of export. See [Exporting Retrospectives](/collaborative-retrospectives/exporting-retrospectives) for export destinations and options. *** ## Permissions AI blocks follow your retrospective permissions; see [the overview](/ai/ai-in-retrospectives/overview#how-permissions-work). *** ## Frequently Asked Questions Refresh the document. If a block fails to generate, you can regenerate it from its toolbar. If it keeps failing, the incident may have very little context for that section; try a different block or add detail to the incident. Yes. Set custom instructions on the block in the template. See [Building AI Templates](/ai/ai-in-retrospectives/building-ai-templates). *** ## Related Pages What AI blocks are and how they draft your retrospective. Add AI blocks to a template and preview them against a past incident before rollout. The editor AI blocks live in, with formatting, data blocks, Liquid, and collaboration. # AI Settings Source: https://docs.rootly.com/ai/ai-settings Govern Rootly AI from AI & Agents: the organization-wide opt-in, per-feature toggles, AI SRE access, and what each connector is allowed to read. ## Overview Every Rootly AI control lives in one place: **AI & Agents**. Decide what Rootly AI does, where it shows up, and what it can access, placing control in your team's hands. Rootly AI's three tiers of control: the global opt-in switch, fine-grained feature toggles, and connector data access *** ## Global Guardrails for Rootly AI's entire surface area. Every section below, from Features to AI SRE to Connectors, is gated by what you set here. | Setting | What it controls | | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- | | **Opt in to Rootly AI capabilities** | The organization-wide switch. Turning it off disables every Rootly AI feature at once, regardless of the individual toggles under Features. | *** ## Features Rootly AI's core capabilities are grouped by surface area, so your team decides exactly where Rootly AI shows up. ### Incidents | Toggle | What it controls | Learn more | | -------------------------- | ------------------------------------------------------------------------------------- | ------------------------------------------ | | **Incident summarization** | AI-generated summaries that bring your team up to speed on the incident. | [AI Summaries](/ai/ai-summaries) | | **Related incidents** | Ranked matches from your own incident history, grounded in how each one was resolved. | [Related Incidents](/ai/related-incidents) | ### Slack | Toggle | What it controls | Learn more | | ------------------------- | ---------------------------------------------------------- | -------------------------------------------------- | | **Rootly Agent in Slack** | The AI assistant responders talk to without leaving Slack. | [Rootly AI in Slack](/ai/rootly-in-slack/overview) | ### Retros | Toggle | What it controls | Learn more | | ------------------------ | ------------------------------------------------------------- | --------------------------------------------------------- | | **AI in Retrospectives** | AI help drafting retrospectives, right inside your templates. | [AI in Retrospectives](/ai/ai-in-retrospectives/overview) | ### Web | Toggle | What it controls | Learn more | | ----------------------- | ---------------------------------------- | ------------------------------------- | | **Rootly Agent in Web** | The ask-anything AI chat in the web app. | [Rootly AI in Web](/ai/ask-rootly-ai) | ### Mobile | Toggle | What it controls | Learn more | | -------------------------- | ------------------------------ | ---------------------------------------------- | | **Rootly Agent in Mobile** | The AI chat in the mobile app. | [Rootly AI on Mobile](/ai/rootly-ai-on-mobile) | *** ## AI SRE Your AI SRE teammate: it autonomously investigates alerts and hands responders the likely root cause with recommended next steps. Your Rootly account team enables it for your organization. *** ## Connectors You choose the data sources Rootly AI can query during investigations: observability platforms, code hosts, docs, and your own MCP servers. Configure them here, documented in full at [Connectors](/ai/connectors/overview). *** ## Related Pages What Rootly AI is and everything it can do. What Rootly AI sees, retention, and model training controls. Every data source Rootly AI can investigate with. # AI Summaries Source: https://docs.rootly.com/ai/ai-summaries Titles, summaries, catchups, and status write-ups, generated from the incident's own record so nobody has to write documentation mid-incident. ## Overview Documentation is the first casualty of a real incident. AI Summaries writes it for you, from what the incident already knows: metadata, alerts, timeline events, action items, and (when permitted) Slack messages and meeting transcripts. | Feature | What you get | Where | | -------------------- | --------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | | **Incident summary** | A single-paragraph narrative: problem, impact, cause, resolution steps, and who was involved. Regenerate as the incident evolves. | Slack (`/rootly summary`) | | **Incident catchup** | The summary, expanded and delivered privately to responders joining midstream. Only you see it. | Slack (`/rootly catchup`) | | **Generated title** | A title under 90 characters that says what actually broke, readable on any dashboard. | Slack (`/rootly update`, then **Generate with AI**) | | **Status summaries** | One or two sentences explaining each transition: mitigated, resolved, cancelled, or closed. | Web and Slack status dialogs (**Generate with AI**) | Every output is grounded in the incident record. When there isn't enough context to say something true, Rootly AI says so instead of guessing. These are single-turn generators: one click or command, one result. For a conversation you can question, refine, and act from, talk to [Rootly AI in Slack](/ai/rootly-in-slack/overview). *** ## Incident Summaries Run `/rootly summary` in the incident channel. When configured, the summary appends a structured attributes list: meeting links, severity, affected environments and services, and selected form field values. *** ## Catch Up Mid-Incident `/rootly catchup` (also `catch up`, `catch-up`, or `summarize`) returns an expanded summary as an ephemeral message. A structured catchup brief in Slack: status, impact, root cause, commander, roles, and open action items Catchup requires permission to generate summaries on the incident or permission to update it. *** ## Generated Titles Run `/rootly update` in the incident channel and click **Generate with AI**. Rootly AI reads the summary, alerts, and early timeline to produce the title. Regenerate as the picture sharpens. The Slack update-incident dialog with the Generate with AI button under the title field *** ## Status Summaries When an incident changes status, Rootly AI drafts the explanation, focused on what the transition needs: | Status | The summary explains | | ------------- | ----------------------------------- | | **Mitigated** | What was done to reduce impact | | **Resolved** | How the incident was fully resolved | | **Cancelled** | Why the incident was cancelled | | **Closed** | Why the incident was closed | In the web app, click **Generate with AI** next to the status message field when updating status. In Slack, `/rootly mitigate` or `/rootly resolve` opens the same dialog. You review and edit the draft before submitting. The Mark as Resolved dialog in Slack, with a generated resolution summary and the Generate with AI button *** ## Setup All four features are part of Rootly AI, behind the [organization-wide opt-in](/ai/ai-settings). Only Admins can change AI settings. 1. Open **AI & Agents** and turn on **Opt in to Rootly AI capabilities**. Titles and status summaries are available immediately; they have no separate toggle. 2. Under **Features**, toggle **Incident summarization** on. This enables both summaries and catchup. For the best results, set **Slack channel message visibility** to **All messages** or **All messages in Public + pinned in Private**, so summaries can draw on channel communications. In private incidents, these features read the incident's own record. Slack channel messages are included only when your message visibility setting covers private incidents. *** ## Frequently Asked Questions The incident record is too thin. Add a description, alerts, timeline events, or action items, then generate again. In private incidents, confirm your message visibility settings allow Rootly AI access. Generation only sees what the incident knows at that moment. Record the missing detail (a timeline event, a resolution note, an action item), then regenerate. If Slack messages or transcripts should be included, check your visibility settings. It did, privately. Catchup summaries are ephemeral and visible only to the person who ran the command. Confirm **Incident summarization** is toggled on under **AI & Agents**, and that you have permission to generate summaries on the incident or to update it. *** ## Related Pages The conversational agent that answers questions and takes actions. Ranked matches from your own incident history. Every Rootly AI control in one place. # Rootly AI in Web Source: https://docs.rootly.com/ai/ask-rootly-ai Ask Rootly AI about any incident from the web app: a read-only chat grounded in that incident's live timeline, roles, alerts, severity, and status. ## Overview **Rootly AI in Web** is an AI chat built into the incident page of the Rootly web app. Open it on any incident and ask questions in natural language. Answers are grounded in that incident's live context: its timeline, alerts, chat history, and bridge-call transcripts. The Rootly AI panel on an incident page, breaking down the incident's status, leading root cause theory, and response so far **Read-only by design.** The web panel answers questions and never changes your incident. Actions live in [Rootly AI in Slack](/ai/rootly-in-slack/overview) and [Rootly AI on Mobile](/ai/rootly-ai-on-mobile). *** ## Using the Panel Open **Rootly AI** on any incident page. | Question type | Example ask | | -------------------- | ------------------------------------------------------------------------------------------------ | | Get caught up | "Catch me up on this incident" | | Roles and ownership | "Who is working on what?" | | Severity reasoning | "Why is this a SEV1?" | | Response review | "What have we tried so far?" | | Open work | "What action items are still open?" | | Draft communications | "Draft a status update for stakeholders" | | Bridge call recap | "What was discussed on the bridge?" (requires a [Meeting Scribe](/ai/meeting-scribe) transcript) | | Timeline | "Summarize the last 30 minutes" or "Show the timeline in UTC" | *** ## Multiple Chats and History Keep separate conversations per incident. Start a new chat or switch to an earlier one from the panel header. Chats are **private to you**, scoped to your user and the incident. Other responders can't see your chats, and you can't see theirs. *** ## Configuration Rootly AI in Web is available to all customers. An Admin must enable it, and using the panel requires an **Incident Response seat**. 1. Open **AI & Agents** and toggle on **Opt in to Rootly AI capabilities**. 2. Under **Features**, turn on **Rootly Agent in Web**. See [AI Settings](/ai/ai-settings) for every Rootly AI control. *** ## Troubleshooting Check that **Rootly Agent in Web** is enabled under **AI & Agents** and that you have an Incident Response seat. Also confirm you have access to the incident (see [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai)). Replies stream in as they're generated. If you switch chats or close the panel mid-reply, generation finishes in the background. Reopen the chat to see the complete answer. *** ## Related Pages The same agent in your incident channels, with actions. What Rootly AI is and everything it can do. What Rootly AI sees, retention, and model training controls. # Atlassian (Jira + Confluence) Source: https://docs.rootly.com/ai/connectors/atlassian Connect Rootly AI to Atlassian — Jira issues, Confluence pages, and project context — via a single one-click authorization. ## Overview Atlassian is a one-click connector that gives Rootly AI read access to your Atlassian Cloud instance during investigations. A single OAuth flow connects **both Jira and Confluence** — Rootly AI can then look up related Jira issues to see if a bug was already reported, and search Confluence runbooks and architecture docs for how a system is supposed to work. Every query is **read-only**. Rootly AI can search and read Jira issues and Confluence pages but cannot create, comment on, or edit anything on the Atlassian side. *** ## Before You Start * **An Atlassian Cloud instance** with permission to authorize third-party OAuth apps. * **Read access** to the Jira projects and Confluence spaces you want Rootly AI to be able to see. *** ## Setup Open **Configuration → AI → Connectors** and click **Connect** on the Atlassian card. Sign in to Atlassian and authorize Rootly AI for the site you want to connect. When the flow completes, the card flips to **Connected**. *** ## What Rootly AI Can Read **Jira:** * **Issues** — search across projects by keyword, assignee, status, or label. * **Comments and history** — the discussion thread on an issue. * **Project context** — project names, keys, and issue types. **Confluence:** * **Pages** — search across spaces for runbooks, architecture docs, and past incident write-ups. * **Page content** — full body text of matched pages. * **Space context** — space names and structure so Rootly AI can distinguish "Team X's runbooks" from "Team Y's." Rootly AI reaches for Confluence when a question is about *"how is this supposed to work?"* — pairing it with a runbook-heavy Confluence and Sentry / observability data covers "what broke and how do we fix it?" investigations end-to-end. *** ## During an Incident *"There's already an open ticket for this exact error, filed last week. Here's the link."* Rootly AI searches Jira for issues that match the current exception or error signature. If someone already reported it — bug ticket, customer complaint, tracked-work item — Rootly AI surfaces the link during the investigation, so the team doesn't waste time re-triaging a known issue. On the Confluence side: *"Here's the runbook for this service."* When a responder asks how to handle a specific failure mode, Rootly AI searches Confluence for matching runbooks and cites the relevant one. *** ## Best Practices * **Authorize with an account that has broad read access.** Rootly AI can only see the Jira projects and Confluence spaces the authorizing user has access to. If large chunks of your knowledge base are restricted, Rootly AI won't be able to reason over them. * **Keep runbook titles searchable.** Confluence page titles are the primary signal Rootly AI uses to decide which page is relevant. Descriptive titles ("Payments API — on-call runbook") beat generic ones ("Runbook"). * **Link Jira issues to real components.** Rootly AI can filter by project, but component-level context helps it surface the *right* related issue, not just any related one. *** ## Troubleshooting The authorizing Atlassian user doesn't have access to those projects or spaces. Confirm the account has the right permissions, then disconnect and reconnect so the OAuth grant refreshes. Confluence search ranks by title match and recency. If a stale page has a more matching title than the current one, Rootly AI may cite it. Rename or archive outdated pages so search surfaces the right ones. If an Atlassian admin revokes the Rootly AI app from Atlassian's side, Rootly's card still shows Connected but every query fails. Reconnect from Rootly to reauthorize. *** ## Frequently Asked Questions No. A single Atlassian OAuth flow covers both. Which one actually returns data depends on the authorizing user's permissions. The one-click flow is built for Atlassian Cloud. If you're on Data Center, contact support to see whether a Custom connector via [Custom (Any OAuth MCP)](/ai/connectors/custom) makes sense for your setup. No. Connectors are read-only. To create Jira issues from an incident, use the existing [Jira integration](/integrations/jira/jira) — that's a separate configuration. Rootly does not maintain a persistent copy of Atlassian data — queries run at investigation time and the response is used in reasoning only. Query results *do* appear in the LLM traces Rootly logs for quality monitoring, as with every tool call Rootly AI makes. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for the retention boundary. *** ## Related Pages All connectors and how they fit together. The other knowledge-management connector. What Rootly AI sees, retention, and model training controls. # AWS Source: https://docs.rootly.com/ai/connectors/aws Give Rootly AI read-only access to your AWS account via an IAM Role — with fine-grained service and region scoping and optional EKS support. ## Overview Connecting AWS gives Rootly AI **read-only access** to your AWS account. Once connected, Rootly AI can look up CloudWatch metrics, EC2 instance state, RDS database status, SQS queue depth, and other AWS services during investigations — grounding its reasoning in the actual state of your infrastructure rather than best-guess inference. Access is granted through an **IAM Role** you create in your AWS account. You control which AWS services the role can read and which regions it can operate in. *** ## Before You Start You'll need: * **AWS Console access** to the account you want to connect, with permission to create IAM Roles. * **The External ID shown on the AWS connection modal in Rootly** — this is unique to your Rootly organization. Copy it when the modal opens; it goes into the trust policy on the AWS side. * **A decision on scope** — which AWS services and regions should Rootly AI be able to read? You can start narrow and expand later. All Rootly AI access to AWS is **read-only**. The IAM Role can't launch instances, modify security groups, or change any configuration — only describe existing state. *** ## Setup Provisioning Options You have three ways to create the IAM Role in AWS. Pick whichever matches how your team manages AWS infrastructure. ### Option 1 — CloudFormation (Recommended) The one-click path. Rootly generates a CloudFormation template with your External ID pre-filled — review it in the AWS Console and click **Create stack**. Open **Configuration → AI → Connectors** in Rootly and click **Connect** on the AWS card. The connection modal shows your External ID at the top — copy it now. Click **Launch CloudFormation stack** in the AWS Configuration section of the Rootly modal. A new tab opens directly to AWS CloudFormation with the template and External ID pre-populated. Review the template — it creates one IAM Role with the read-only permissions matching the services you selected. Click **Create stack** in the AWS Console. Wait for the stack status to reach `CREATE_COMPLETE` — usually 30–60 seconds. Once complete, open the stack's **Outputs** tab and copy the **RoleArn** value. Return to the Rootly connection modal and paste the Role ARN into the **IAM Role ARN** field. Click **Test Connection** to verify, then save. ### Option 2 — Terraform If your team manages AWS through Terraform, Rootly provides a Terraform module in the connection modal that creates the same IAM Role. Apply the module in your Terraform workspace, copy the resulting Role ARN into the Rootly modal, and click Test Connection. ### Option 3 — Manual Console Setup For teams that prefer clicking through the AWS Console step-by-step, or for accounts where CloudFormation isn't an option. Log in to the AWS Console for the account you want to connect. Navigate to **IAM → Roles**. Click **Create role**. Choose **Custom trust policy** as the trusted entity type. Paste the trust policy shown in the Rootly modal — it references your External ID. Click **Next** and attach permissions matching the services you selected in the Rootly modal: * **If you selected specific services** — add a custom inline policy with exactly the read access needed for those services. Rootly displays the exact policy JSON on the connection modal. * **If you selected all services** — attach the AWS managed **ReadOnlyAccess** policy for account-wide read access. Click **Next**, name the role something recognizable (for example, `RootlyAIReadOnly`), and click **Create role**. From the role detail page, copy the **Role ARN**. Paste it into the Rootly connection modal's **IAM Role ARN** field, click **Test Connection**, then save. *** ## Configuring Access Scope Rootly AI's AWS integration accepts two scoping dimensions. Both are configured on the Rootly connection modal *before* you generate the IAM policy — the policy Rootly creates matches your selections exactly. Search and select the AWS services Rootly AI should be able to describe (EC2, RDS, CloudWatch, S3, SQS, and so on). **Leave empty to allow all services** — that grants the equivalent of the AWS managed `ReadOnlyAccess` policy. Narrow is safer than broad. Start with the services your team actually operates; the connection can be updated later to add more services. Search and select AWS regions Rootly AI can query. **Leave empty to allow all regions.** When set, Rootly AI directs API calls only to those regions. For a hard enforcement at the AWS side, add a `Condition` on `aws:RequestedRegion` to the role's attached permission policy (the trust policy alone cannot bound the resulting session's regional reach). For most teams, "the services you operate" plus "the regions you deploy in" is the right starting scope. If your AWS presence is a single region running EC2, RDS, and CloudWatch, that's a three-service one-region role — much smaller scope of impact than granting `ReadOnlyAccess` account-wide. *** ## Optional: EKS Support If Rootly AI needs to query Kubernetes clusters managed by EKS (nodes, workloads, cluster events), enable the **EKS Support** section on the Rootly connection modal and follow its generated instructions. The modal produces the narrow, read-only permission set (typically `eks:DescribeCluster`, `eks:ListClusters`, `eks:DescribeNodegroup`, `eks:ListNodegroups`, and an EKS **access entry** attaching the `AmazonEKSClusterAdminPolicy`-alternative *view* policy at cluster scope) that Rootly AI actually needs. Prefer that over broad managed policies like `AmazonEKSClusterPolicy`, which grant write actions Rootly AI never uses. **EKS API access restrictions:** If your EKS cluster's API server endpoint is restricted to specific IP ranges, allow Rootly AI's outbound IPs (listed on the connection modal) so Rootly AI can reach the cluster. *** ## Verifying The Connection Click **Test Connection** in the Rootly modal after pasting the Role ARN. Rootly checks that the role can be used with the External ID you set, and reports back: * **Connection verified** — the role is set up correctly. Save the integration and Rootly AI can now query AWS. * **Assume-role failed** — the trust policy on the AWS role doesn't reference the External ID correctly. Recheck the trust policy on the AWS side. * **Permissions insufficient** — the role works but doesn't grant the reads Rootly AI needs. Recheck the permissions policy against the services you selected. ## During an Incident *"CPU is pegged on the checkout-api EC2 instance for the last 15 minutes. Here's the CloudWatch metric."* Rootly AI queries CloudWatch for the metrics correlated with the current incident's affected services — CPU, memory, request counts, error rates — and cites the specific graph in the investigation output. Responders see the underlying infrastructure state without switching to the AWS console. *** ## Adjusting Access After Setup To narrow or broaden scope after the initial connection: Configuration → AI → Connectors → click **Configure** on the AWS card. Add or remove services and regions from the multi-select pickers. Rootly displays the *updated* IAM policy JSON matching your new selection. Copy the updated policy JSON and replace the inline policy on your IAM Role in AWS. Rootly does not modify the AWS-side policy for you — the Rootly UI shows what the policy should be; you apply it on the AWS side. Save the updated configuration in Rootly. New Rootly AI queries respect the new scope on the next investigation. *** ## Best Practices * **Start with narrow service and region scope.** You can always expand. Granting broad `ReadOnlyAccess` up front makes it harder to reason about what Rootly AI has seen after the fact. * **Use a memorable role name.** `RootlyAIReadOnly` (or similar) makes the role easy to find in IAM Roles listings and easy to identify in CloudTrail logs. * **Guard the External ID.** The External ID keeps your Rootly connection separate from every other Rootly customer's. Don't paste it into public issues, screenshots, or Slack channels. * **Audit AWS-side access changes.** Any change to the IAM Role's trust policy or attached permissions should go through the same review process as any other AWS IAM change. * **Consider a dedicated AWS account for observability queries.** If you have a hub-and-spoke AWS setup with a central observability account, connect that account to Rootly AI rather than each spoke account individually. * **Reconnect if you suspect misuse.** If you rotate the External ID or suspect the role has been misused, disconnect the integration from Rootly, delete the AWS-side role, and re-run the setup. Reconnection generates a fresh External ID. *** ## Troubleshooting Two common causes: (1) the trust policy on the AWS role doesn't reference the correct External ID — check for typos or a stale External ID from a previous connection attempt; (2) the trust policy JSON in the Rootly modal wasn't pasted correctly on the AWS side. The IAM user or role you're running CloudFormation as needs permission to create IAM Roles and attach policies. Run as an admin user, or ask an AWS admin to run the stack for you and share the resulting Role ARN. AWS returns current state at the moment of the query. If it looks stale, check what the AWS Console shows for the same resource — if AWS itself shows the same value, the "staleness" is coming from AWS's own metric-emission timing (CloudWatch metrics often lag actual events by 1–5 minutes). Two likely causes: (1) the IAM Role doesn't have `AmazonEKSClusterPolicy` attached — attach it and retry; (2) the EKS cluster API endpoint is IP-restricted and Rootly AI's outbound IPs aren't allowed — add them to the endpoint's allow-list (they're shown on the Rootly modal's EKS section). Selected-services scope mismatch. Open the AWS integration's Configure screen in Rootly to see which services are currently selected. If a service you expect Rootly AI to use isn't listed, add it — but remember to also update the AWS-side IAM policy to grant read permissions for that service (Rootly shows the updated policy JSON when you change the selection). Open **Configure** on the AWS card, paste the new Role ARN, click Test Connection, and save. The Connected status alone doesn't verify current-credential health — a rotation without reconnecting leaves stale credentials in place. *** ## Frequently Asked Questions Yes. The IAM policies Rootly generates grant only `Describe*`, `Get*`, `List*`, and equivalent read-only actions. Rootly AI cannot start or stop instances, modify security groups, or change any configuration. The External ID is a per-organization identifier that keeps your Rootly connection separate from every other Rootly customer's. Your role's trust policy checks that the External ID matches your organization's specifically, so nobody else can use the same connection pattern to reach your role. Currently one AWS integration per Rootly team. If you operate multiple AWS accounts, connect the one that hosts the majority of your observability signals — typically a hub or central account. Multi-account support is on the roadmap. Investigation flows most often call **CloudWatch** (metrics and log queries), **EC2** and **RDS** (instance and database state), and **ELB / ALB** (load balancer health). Add these first if you're scoping narrowly. **CloudTrail** is also useful for "what changed in AWS recently" investigations. Yes. Every API call Rootly AI makes appears in your CloudTrail logs. You can audit exactly what Rootly AI queried and when. Use the role name (for example, `RootlyAIReadOnly`) as the CloudTrail filter to see the full history. Rootly AI's AWS calls count against your account's standard AWS API rate limits. In practice, investigation volume is low — a handful of calls per investigation — so rate limits are not a concern for typical use. (1) Click Disconnect on the AWS card in Rootly — this removes the stored Role ARN and External ID. (2) In AWS, delete the IAM Role and any CloudFormation stack that created it. *** ## Related Pages The full list of Connectors and how they fit together. What Rootly AI sees, retention, and model-training controls. AWS's own reference on how External IDs work in IAM trust policies. # Azure Monitor AI Connector Source: https://docs.rootly.com/ai/connectors/azure-monitor Give Rootly AI read-only access to Azure logs, metrics, alerts, deployments, health, and control-plane changes. ## Overview The Azure Monitor AI connector lets Rootly AI investigate Azure resources with Microsoft's public Azure Monitor, Log Analytics, Resource Manager, Resource Graph, and Resource Health APIs. Rootly calls those APIs directly; you don't need to deploy or operate an MCP server. Azure has two Rootly AI connectors. This native connector reads operational evidence directly from Azure APIs. [Azure Resource Manager (MCP)](/ai/connectors/azure-resource-manager) uses Microsoft's hosted MCP endpoint for resource inventory and deployment status. You can connect both. An Azure alert source is a third, separate inbound integration that sends alerts to Rootly for routing and paging. See [Alert Sources](/alerts/alert-sources) for the ingestion workflow. The connector is read-only. Microsoft Entra ID and Azure role-based access control (RBAC) authorize the Rootly enterprise application, while a second Rootly allowlist limits each AI investigation to the subscriptions, workspaces, resources, and capabilities selected for your Rootly team. Contact your Rootly account team to receive the Rootly enterprise application consent link and application ID. After that one-time enrollment step, a Rootly admin configures and manages the connector from **AI & Agents → Connectors**. ## Before You Start You'll need: * A Microsoft Entra administrator who can grant tenant-wide admin consent to the Rootly enterprise application. * Permission to look up the Rootly enterprise application in Microsoft Entra, or its tenant-specific service-principal object ID from your Entra administrator. * Permission to assign Azure roles at the scopes Rootly AI will investigate. * Rootly admin permission to manage AI connectors. * The tenant ID and subscription IDs for the Azure environment. * The workspace ID and full Azure Resource Manager ID for each Log Analytics workspace. * The full Azure Resource Manager ID for every resource Rootly AI may inspect. * A decision about which Azure evidence capabilities to enable. The connector supports Microsoft Azure public cloud. Azure Government, Azure China, and other sovereign cloud endpoints aren't supported. ## Connect Azure Monitor Open the consent link supplied by your Rootly account team and sign in as a Microsoft Entra administrator. Before accepting, compare the application ID on the consent details with the application ID Rootly supplied. If they don't match, stop and contact your Rootly account team. Then review the publisher and requested access before granting consent for your tenant. Consent creates a Rootly service principal in your tenant. Rootly keeps the application credential in Rootly's environment; you don't create or send Rootly a client secret. Microsoft documents the [tenant-wide admin consent flow](https://learn.microsoft.com/en-us/entra/identity/enterprise-apps/grant-admin-consent) and the [admin consent protocol](https://learn.microsoft.com/en-us/entra/identity-platform/v2-admin-consent). Use Azure Cloud Shell or an authenticated Azure CLI to collect the IDs you'll enter in the Rootly connector form: ```bash Collect Azure identifiers theme={null} AZURE_TENANT_ID='YOUR_TENANT_ID' az account list --all \ --query "[?tenantId=='${AZURE_TENANT_ID}' && state=='Enabled'].{subscriptionId:id, name:name}" \ --output table az account set --subscription YOUR_SELECTED_SUBSCRIPTION_ID az monitor log-analytics workspace show \ --resource-group YOUR_RESOURCE_GROUP \ --workspace-name YOUR_WORKSPACE \ --query '{workspaceId:customerId, resourceId:id}' \ --output json az resource show \ --resource-group YOUR_RESOURCE_GROUP \ --name YOUR_RESOURCE_NAME \ --resource-type YOUR_RESOURCE_TYPE \ --query id \ --output tsv az deployment group list \ --resource-group YOUR_RESOURCE_GROUP \ --query '[].id' \ --output tsv ``` Repeat the `az account set` and resource-discovery commands for every selected subscription in the configured tenant. Keep these IDs for the self-serve Rootly form; you don't need to send them to Rootly. Share them with your Rootly account team only if you request help validating a narrower RBAC assignment or troubleshooting setup. A workspace requires both identifiers. The workspace ID selects the Logs API endpoint; the full resource ID authorizes table and schema discovery through Azure Resource Manager. The v0 Deployments capability supports resource-group-scoped deployments. `az deployment group list` returns the required deployment IDs; subscription- and management-group-scoped deployment IDs aren't supported. Find the Rootly service principal with the application ID supplied by your Rootly account team, then assign **Monitoring Reader** at the smallest scope that covers the selected resources: ```bash Assign Monitoring Reader theme={null} ROOTLY_APP_ID='APPLICATION_ID_FROM_ROOTLY' AZURE_SUBSCRIPTION_IDS=( 'FIRST_SELECTED_SUBSCRIPTION_ID' 'SECOND_SELECTED_SUBSCRIPTION_ID' ) ROOTLY_SERVICE_PRINCIPAL_ID="$( az ad sp show --id "$ROOTLY_APP_ID" --query id --output tsv )" for AZURE_SUBSCRIPTION_ID in "${AZURE_SUBSCRIPTION_IDS[@]}"; do az role assignment create \ --assignee-object-id "$ROOTLY_SERVICE_PRINCIPAL_ID" \ --assignee-principal-type ServicePrincipal \ --role 'Monitoring Reader' \ --scope "/subscriptions/$AZURE_SUBSCRIPTION_ID" done ``` `az ad sp show` reads the tenant's service-principal directory through Microsoft Graph. If your signed-in account can't perform that lookup, ask an Entra administrator to provide the Rootly enterprise application's **Object ID**, then set `ROOTLY_SERVICE_PRINCIPAL_ID` to that value directly. The application ID and object ID are different. Subscription scope supports the complete connector, including subscription-level alerts and Resource Graph changes. For narrower resource-group or resource assignments, tell your Rootly account team which capabilities you need so the reduced scope can be tested before activation. **Monitoring Reader** grants read access without configuration changes. Don't grant **Monitoring Contributor**. Microsoft documents the permissions in [Roles, permissions, and security in Azure Monitor](https://learn.microsoft.com/en-us/azure/azure-monitor/fundamentals/roles-permissions-security). Select only the evidence sources your responders need. At least one capability must remain enabled; disabling a capability also removes its inventory from resource discovery. | Capability | Rootly AI can read | | ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Logs | Authorized Log Analytics workspaces, live table metadata and schema, bounded Kusto Query Language (KQL) results, AKS workload evidence from Container Insights, and Application Insights operation traces | | Metrics | Live metric definitions and bounded metric series for authorized resources | | Alerts | Azure Monitor alert instances plus read-only alert-rule, action-group receiver-count, and alert-processing-rule configuration | | Activity logs | Control-plane operations and callers for an authorized resource | | Resource changes | Azure Resource Graph change history for authorized resources | | Deployments | Operations and failures for explicitly allowlisted resource-group-scoped Azure Resource Manager deployment IDs | | Resource health | Current Azure Resource Health plus subscription-scoped Service Health incidents, planned maintenance, and advisories | | Diagnostic settings | Read-only routing configuration for logs and metrics | Each enabled capability needs a matching target: Logs needs at least one workspace, Alerts needs a subscription, and resource-scoped capabilities need an authorized workspace or resource. Rootly rejects configurations that would expose a tool with no usable target. Rootly AI can also correlate Activity Log and Resource Graph evidence in one exact pre-event window. It treats temporal proximity as evidence, not proof of causation. In Rootly, go to **AI & Agents → Connectors**, find **Azure Monitor (Native)**, and click **Connect**. Enter the scope you collected: * **Microsoft Entra tenant ID** — the tenant where you granted consent. * **Authorized subscription IDs** — one subscription UUID per line. * **Log Analytics workspaces** — one `workspace UUID | full workspace resource ID` pair per line. * **Authorized Azure resource IDs** — one full resource ID per line, including each resource-group-scoped deployment ID Rootly AI may inspect. * **Data the agent may read** — select only the capabilities responders need. At least one is required. Click **Connect**. Rootly verifies that its enterprise application can mint a management token for the tenant before the connector is marked **Connected**. This check confirms tenant authorization; it doesn't prove that every configured resource is readable. Azure RBAC is enforced again on each investigation request. Don't enter or send Azure credentials or client secrets. To change the allowlist later, open the connected **Azure Monitor (Native)** card and click **Configure**. Saving re-verifies tenant authorization. **Disconnect** removes the connector from the Rootly team. Ask Rootly AI a question that should produce known evidence, then compare the cited result with Azure: * *"Which service had the highest failed-request rate in the last hour?"* * *"What changed on this resource in the 15 minutes before the first failure?"* * *"Did an Azure deployment operation fail before the latency increase?"* * *"Azure logs are missing for this resource. Where are its diagnostic settings routing telemetry?"* * *"Do Azure Monitor alerts, Resource Health, logs, and metrics agree about the impact?"* * *"Why didn't this Azure alert page anyone? Check whether the rule, processing rules, and action-group delivery path are configured."* * *"Trace this Application Insights operation ID across requests, dependencies, exceptions, and traces. Which service failed?"* * *"Are this AKS workload's pods restarting, emitting warning events, or logging errors?"* * *"Could a Service Health incident or planned maintenance explain the symptoms?"* ## What Rootly AI Can Read The connector exposes these read-only operations: * List the subscriptions, resources, and Log Analytics workspaces in the Rootly allowlist. * Discover live Log Analytics tables and retrieve the exact schema for one table. * Run KQL against one authorized workspace. * Discover metric definitions and query metric series for one authorized resource. * List Azure Monitor alert instances. * Inspect alert rules, referenced action groups, receiver counts, and alert processing rules without returning receiver addresses or webhook URLs. * List Activity Log events and Resource Graph changes. * Correlate Activity Log events and resource changes before an event. * List deployment operations for an explicitly authorized deployment ID. * Read current Resource Health. * List subscription-scoped Azure Service Health events. * Read diagnostic settings. * Inspect AKS pod state, restart counts, warning events, and container logs from Container Insights telemetry. * Trace one Application Insights operation across requests, dependencies, exceptions, and traces, prioritizing failures over routine trace messages. Rootly AI discovers table columns and metric names before generating a query. This avoids relying on table shapes or metric definitions from another workspace or resource. ## Scope and Safety Limits Azure RBAC remains authoritative. Rootly adds the following limits before making a request: | Limit | Behavior | | ------------------ | ----------------------------------------------------------------------------------------------------------------------- | | Resource scope | Every subscription, workspace, resource, and deployment must be in the Rootly allowlist | | Query duration | Log, metric, activity, and change windows can't exceed 24 hours | | Log rows | A KQL result returns at most 500 rows | | Log response | A Logs API response can't exceed 1 MB | | Metadata response | An Azure management response can't exceed 5 MB | | Metrics | One request can query up to 10 metric names | | Cross-resource KQL | Cross-workspace, Resource Graph, Azure Data Explorer, cross-cluster/database, and external-data expressions are blocked | | Transport | Azure requests use bounded connection and response timeouts | Rootly mints short-lived, audience-specific application tokens for the customer tenant and keeps each token only on the in-memory client handling that Azure request path. Tokens aren't stored in the Azure connector record or a shared cache. ## Interpreting Empty Results An empty Azure response is evidence about the query, not proof that a service is healthy. * No alerts means Azure Monitor returned no matching alert instances for that filter and time range. * No Service Health events means Azure returned no matching subscription events in the selected window; it isn't proof that the platform or every dependency was healthy. * No Activity Log events means no matching control-plane events were visible in that window. * No Resource Graph changes is inconclusive because Azure may omit or delay some change details. * No diagnostic settings means that resource has no resource-level diagnostic export. Telemetry can still arrive through another path, including Application Insights. * A table definition confirms that the table exists, not that it contains recent rows. * An unknown or absent Resource Health state is inconclusive. * No AKS workload rows can mean there was no matching activity, Container Insights wasn't configured, or telemetry wasn't available. This connector doesn't query the live Kubernetes API. * No rows for an Application Insights operation ID can mean the ID or time window was wrong, sampling omitted telemetry, or the workspace didn't receive that operation. Use more than one signal when testing a hypothesis. Compare logs or metrics with alerts, health, activity, deployments, and change history where available. ## Troubleshooting Confirm that admin consent completed in the same tenant ID configured in Rootly. In **Microsoft Entra admin center → Enterprise applications**, find the Rootly application and confirm that it is enabled. Revoked consent, a disabled service principal, or a tenant ID copied from another directory prevents Rootly from saving the connector. Confirm that the role assignment targets the enterprise application's **service principal object ID**, not the application ID. Check the assignment scope and allow time for Azure RBAC propagation. Microsoft notes that new Azure Monitor API role assignments can take time to become effective. Confirm that Monitoring Reader covers the Log Analytics workspace and that Rootly has both the workspace ID and its full resource ID. Microsoft documents `Microsoft.OperationalInsights/workspaces/query/*/read` as the permission required to query a workspace. The requested ID isn't in the Rootly allowlist, or its subscription isn't configured. Copy the exact Azure Resource Manager ID returned by Azure CLI into the **Azure Monitor (Native)** connector's allowlist. Resource IDs are case-insensitive, but every path segment must be present. Narrow the time range, aggregate in KQL, or select fewer columns. Rootly rejects oversized responses and caps returned rows so an investigation can't pull an unbounded telemetry set into model context. ## Frequently Asked Questions No. This connector calls Microsoft's maintained Azure APIs directly. The separate [Azure Resource Manager (MCP)](/ai/connectors/azure-resource-manager) connector uses Microsoft's hosted endpoint. Neither connector requires you to host a server. You don't create a client secret for Rootly. Rootly operates its own Microsoft Entra application credential. The connector stores your tenant ID and explicit allowlists, then mints short-lived tokens for that tenant when Rootly AI needs Azure evidence. No. The connector exposes read-only operations, and the supported setup uses Monitoring Reader. Rootly doesn't expose deployment, configuration, alert-state, or diagnostic-setting write operations. No. Alert Sources send monitoring alerts into Rootly. The Azure Monitor AI connector lets Rootly AI retrieve Azure evidence during an investigation. Configure each surface separately. One Azure tenant can be active per Rootly team. Use separate Rootly teams when investigations require isolated Azure tenants. ## Related Pages Inventory Azure resources and inspect ARM deployment status through Microsoft's hosted MCP endpoint. Compare Rootly AI connectors and setup flows. Review connector data handling and retention. # Azure Resource Manager (MCP) Source: https://docs.rootly.com/ai/connectors/azure-resource-manager Connect Rootly AI to Microsoft's hosted Azure Resource Manager MCP endpoint for read-only resource inventory and deployment status. ## Overview The **Azure Resource Manager (MCP)** connector lets Rootly AI inventory Azure resources and inspect Azure Resource Manager deployment status. Rootly connects to Microsoft's maintained endpoint at `https://mcp.management.azure.com` and uses delegated Microsoft Entra OAuth, so you don't deploy or operate an MCP server. Azure has two Rootly AI connectors. Use this MCP connector for resource inventory and ARM deployment status. Use [Azure Monitor](/ai/connectors/azure-monitor) for logs, metrics, alert instances, activity and resource changes, Resource Health, and diagnostic settings. You can connect both. This connector is also separate from the existing Azure alert source, which sends Azure alerts into Rootly for routing and paging. See [Alert Sources](/alerts/alert-sources). ## Before You Start You'll need: * A Microsoft Entra account that can authorize Rootly and read the Azure subscriptions and resources responders need to investigate. * Azure RBAC assignments for that account at the smallest appropriate subscription, resource-group, or resource scope. * Permission to manage AI connectors in Rootly. Rootly AI inherits the authorizing user's Azure access. Connecting the MCP endpoint does not grant additional Azure permissions. If that user is deprovisioned or loses Azure RBAC, Rootly AI immediately loses the same visibility; reconnect with an appropriate account when ownership or access changes. ## Connect Azure Resource Manager (MCP) In Rootly, go to **AI & Agents → Connectors** and click **Connect** on the **Azure Resource Manager (MCP)** card. Sign in with the Microsoft Entra account Rootly AI should use and approve the requested access. Rootly uses Microsoft's fixed hosted MCP endpoint; there is no endpoint URL, tenant secret, or MCP server to configure. After authorization and Rootly's catalog probe succeed, the connector card shows **Connected**. Ask a resource question whose answer you can verify in Azure before relying on the connector during an incident. ## What Rootly AI Can Read Rootly exposes four reviewed MCP tools: | Tool | Purpose | | ----------------------- | ------------------------------------------------------------------------------- | | `generate_query` | Generate a candidate Azure Resource Graph query from a natural-language request | | `validate_query` | Check a generated query before execution | | `execute_query` | Run the reviewed query against resources visible through Azure RBAC | | `get_deployment_status` | Read the status of a known ARM deployment using exact identifiers | The hosted MCP catalog also advertises write-capable Azure tools. Rootly filters those tools out; this connector exposes only the four operations above. Treat `generate_query` as a draft, not proof that a query answers the intended question. Rootly AI validates and semantically reviews generated Resource Graph queries before execution. An empty result is inconclusive and can also mean the authorizing user lacks access to the relevant scope. ## Choosing Between the Azure AI Connectors | Question | Use | | ------------------------------------------------------------------------------------------------------------- | --------------------------------------------- | | *"Which Azure resources match this service, tag, type, or configuration?"* | Azure Resource Manager (MCP) | | *"What is the exact status of this ARM deployment?"* | Azure Resource Manager (MCP) | | *"What do the logs and metrics show around the incident?"* | [Azure Monitor](/ai/connectors/azure-monitor) | | *"What alert, activity-log event, resource change, health event, or diagnostic setting explains the impact?"* | [Azure Monitor](/ai/connectors/azure-monitor) | Connect both when responders need resource discovery and deep operational evidence in the same investigation. ## Security and Data Handling * Microsoft hosts and maintains the MCP endpoint; Rootly does not require a customer-hosted service. * Microsoft Entra OAuth identifies the authorizing user, and Azure RBAC remains authoritative. * Rootly fixes the endpoint to `https://mcp.management.azure.com`; users cannot substitute another host for this provider. * Rootly applies a read-only tool allowlist even if the upstream catalog exposes mutation tools. * Requests use a bounded 60-second timeout. Query results can appear in Rootly AI traces used for quality monitoring. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for retention and model-training controls. ## Troubleshooting Confirm that you're signing in to the intended Microsoft Entra tenant and that your organization permits the Rootly enterprise application. An Entra administrator may need to approve the application or consent policy first. Check the Azure RBAC assignments of the account that authorized Rootly. The connector can only query subscriptions and resources that account can read. Empty Resource Graph results are not proof that a resource doesn't exist. Query validation checks syntax and Azure acceptance, not whether the query captures the intended semantics. Make the resource types, subscriptions, tags, and desired fields explicit, then ask Rootly AI to review the query before execution. Provide the exact ARM deployment identifiers and confirm the authorizing account can read that deployment scope. Use the native [Azure Monitor connector](/ai/connectors/azure-monitor) when you need deployment operations correlated with logs, activity, or resource changes. ## Related Pages Query Azure operational evidence through Rootly's native read-only connector. Send Azure alerts into Rootly for routing and paging. Compare all Rootly AI connectors and setup flows. # Braintrust Source: https://docs.rootly.com/ai/connectors/braintrust Give Rootly AI read-only access to Braintrust logs, traces, and eval outputs with one-click OAuth, so incidents touching your AI features can be traced. ## Overview Braintrust is a one-click connector that gives Rootly AI read access to your Braintrust organization during investigations. If your team runs AI features in production, Braintrust holds the logs, traces, and eval results that tell you what your models are doing. When an AI-adjacent incident fires, Rootly AI can pull that context directly. Every query is **read-only**. Rootly AI can inspect logs, traces, and eval outputs but cannot modify anything on the Braintrust side. *** ## Before You Start * **A Braintrust organization** with permission to authorize third-party OAuth apps. * **Read access** to the projects, logs, and eval runs you want Rootly AI to be able to see. *** ## Setup Open **Configuration → AI → Connectors** and click **Connect** on the Braintrust card. Sign in to Braintrust and authorize Rootly AI for the organization you want to connect. When the flow completes, the card flips to **Connected**. *** ## What Rootly AI Can Read * **Logs** — production AI logs including inputs, outputs, and latency. * **Traces** — the full trace of a multi-step AI request, useful for debugging chain / agent failures. * **Evals** — recent eval run results, useful when an incident is about "did the last deploy regress model quality?" Rootly AI reaches for Braintrust when the incident is AI-adjacent — a jump in hallucinations, a latency spike in a chain, an eval regressing after a deploy. Pair with GitHub so Rootly AI can also see the code / prompt change that caused it. *** ## During an Incident *"The last eval on the checkout-agent shows a 12% hallucination increase after yesterday's prompt change."* When the incident is AI-adjacent — a jump in bad model output, a chain that's suddenly slower, an eval that regressed — Rootly AI pulls the most recent eval run, the trace of the failing request, and the metadata linking it to a specific deploy or prompt change. Responders see the AI-specific signal alongside the rest of the incident context, without having to switch to Braintrust. *** ## Best Practices * **Authorize with an account that has broad project access.** Restricting the connector to one Braintrust project starves cross-project investigations. * **Tag logs and eval runs meaningfully.** Rootly AI leans on Braintrust metadata to filter to the right subset of logs. Useful tags include environment (production vs staging), deploy version, and model. * **Pair with a code connector.** Braintrust tells Rootly AI *how* the AI is behaving; GitHub tells it *what changed*. Together they cover "did prompt engineering, code, or the model itself cause this?" *** ## Troubleshooting The authorizing Braintrust user doesn't have access to those projects. Confirm the account has read permission on every project Rootly AI should see, then disconnect and reconnect to refresh the OAuth grant. Braintrust logs are retained for a limited window depending on plan. If you're asking about older logs, they may have been purged upstream. Rootly AI can only read what Braintrust still stores. If a Braintrust admin revokes the Rootly AI OAuth grant from Braintrust's side, Rootly's card still shows Connected but every query fails. Reconnect from Rootly to reauthorize. *** ## Frequently Asked Questions No. Braintrust is only useful if your team is already running AI features in production and using Braintrust to observe them. Rootly AI works fine without it — the connector just adds AI-observability signal when relevant. No. Every connector is read-only. Rootly AI can read Braintrust data but never invoke write actions. Rootly does not maintain a persistent copy of Braintrust data — queries run at investigation time and the response is used in reasoning only. Query results *do* appear in the LLM traces Rootly logs for quality monitoring, as with every tool call Rootly AI makes. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for the retention boundary. *** ## Related Pages All connectors and how they fit together. The other observability connector — different signal shape, useful in combination. What Rootly AI sees, retention, and model training controls. # ClickHouse AI Connector Source: https://docs.rootly.com/ai/connectors/clickhouse Connect Rootly AI to a ClickHouse database for bounded, read-only investigation queries across logs, metrics, traces, and operational data. ## Overview The **ClickHouse AI connector** gives Rootly AI direct, read-only access to the ClickHouse data your responders use during investigations. Rootly AI can discover databases and tables, inspect column schemas, and run bounded SQL queries against logs, metrics, traces, or other operational data. Rootly calls ClickHouse's HTTPS interface directly. You don't need to deploy an MCP server or copy ClickHouse data into Rootly. Queries run on demand, and ClickHouse remains the source of truth. The ClickHouse account is the primary authorization boundary. Rootly adds query validation and resource limits, but it can read every database and table granted to the configured account. Create a dedicated account with access only to the data Rootly AI should investigate. *** ## Before You Start You'll need: * A public ClickHouse HTTPS endpoint that Rootly can reach. * A dedicated ClickHouse username and password. * `SELECT` access on only the databases and tables Rootly AI should query. * Permission in Rootly to manage AI connectors. For ClickHouse Cloud, copy the **HTTPS endpoint** from your service's connection details. It normally uses port `8443` and looks like `https://example.us-east-1.aws.clickhouse.cloud:8443`. Self-hosted deployments must expose a trusted HTTPS endpoint to Rootly. Plain HTTP endpoints, private network addresses, embedded credentials, URL paths, query strings, and fragments are rejected. Don't connect the `default` user or an administrative account. Application-level query checks don't replace ClickHouse access control. The configured account should be unable to insert, alter, delete, or administer data. *** ## Create a Read-Only ClickHouse Account Run the following statements as a ClickHouse administrator. Replace the database name, username, and password before running them: ```sql Create a read-only account theme={null} CREATE ROLE rootly_ai_role; GRANT SELECT ON observability.* TO rootly_ai_role; ALTER ROLE rootly_ai_role SETTINGS readonly = 1, max_execution_time = 15 MAX 15, max_rows_to_read = 100000000 MAX 100000000, max_bytes_to_read = 5000000000 MAX 5000000000, max_memory_usage = 2000000000 MAX 2000000000, max_threads = 4 MAX 4; CREATE USER rootly_readonly IDENTIFIED WITH sha256_password BY 'REPLACE_WITH_A_STRONG_PASSWORD'; GRANT rootly_ai_role TO rootly_readonly; ALTER USER rootly_readonly DEFAULT ROLE rootly_ai_role; ``` Grant individual databases rather than `*.*` when possible. Repeat the `GRANT SELECT` statement for each database Rootly AI needs. The role mirrors Rootly's per-request read, time, memory, and thread limits. The `readonly = 1` setting blocks data-definition and data-modification queries at the ClickHouse layer. Rootly also sends `readonly=1` with every request and rejects mutations, administration statements, settings changes, multiple statements, output formats, and external-network table functions before sending a query. ClickHouse Cloud also lets you create users and assign roles from its SQL console. Keep the same least-privilege shape: a dedicated identity, `SELECT` on selected databases, and no administrative grants. ### Verify the account Test the endpoint and credentials before connecting them to Rootly: ```bash Verify with curl theme={null} curl --fail-with-body \ --user 'rootly_readonly' \ --data-binary 'SELECT 1' \ 'https://YOUR_CLICKHOUSE_HOST:8443/?readonly=1' ``` `curl` prompts for the password without placing it in shell history or the process arguments. The command should return `1`. Then verify that the account can read an intended table and can't create one; enter the password at each prompt: ```bash Verify read-only access theme={null} curl --fail-with-body \ --user 'rootly_readonly' \ --data-binary 'SELECT 1 FROM YOUR_DATABASE.YOUR_TABLE LIMIT 1' \ 'https://YOUR_CLICKHOUSE_HOST:8443/?readonly=1' curl --fail-with-body \ --user 'rootly_readonly' \ --data-binary "SELECT name FROM system.tables WHERE database = 'YOUR_DATABASE' LIMIT 1" \ 'https://YOUR_CLICKHOUSE_HOST:8443/?readonly=1' curl --fail-with-body \ --user 'rootly_readonly' \ --data-binary 'CREATE TABLE YOUR_DATABASE.rootly_permission_test (id UInt8) ENGINE = Memory' \ 'https://YOUR_CLICKHOUSE_HOST:8443/?readonly=1' ``` Both `SELECT` statements should succeed. The `CREATE TABLE` statement should fail with a read-only error. *** ## Connect ClickHouse Go to **AI & Agents → Connectors**, find **ClickHouse**, and click **Connect**. Enter the public HTTPS origin, including its port when required. Use only the origin, such as `https://example.clickhouse.cloud:8443`; don't include a database path or query parameters. Enter the database Rootly AI should use for unqualified table names. Leave this field blank to use the ClickHouse account's default database. Enter the dedicated read-only username and password, then click **Connect**. Rootly runs `SELECT 1` with the connector's read-only settings. The card shows **Connected** only after ClickHouse authenticates the account and completes the query. A label that identifies this connection in investigation citations, such as `Production Observability`. The public HTTPS origin for ClickHouse. Include a non-default port, but don't include credentials, a path, query parameters, or a fragment. The optional default database for queries. Database discovery still shows every database visible to the configured account. The dedicated ClickHouse account with narrowly scoped `SELECT` grants. The password for the dedicated account. Rootly encrypts it at rest and doesn't show it again. *** ## What Rootly AI Can Query The connector exposes four read-only tools: | Operation | What it does | | -------------- | -------------------------------------------------------------------------------------------------------- | | List databases | Lists databases visible to the configured ClickHouse account. | | List tables | Lists tables in one database with engine, row-count, and byte-size metadata when ClickHouse provides it. | | Describe table | Lists a table's columns, types, defaults, expressions, and comments. | | Query | Runs one `SELECT`, `WITH`, or `EXPLAIN` statement and returns a bounded JSON result. | Rootly AI discovers the database, table, and column names before composing SQL. Ask questions that identify a useful time window and service, environment, or trace identifier. For example: * *"Which services produced the most error spans in the 15 minutes before this incident?"* * *"Compare checkout latency by deployment version for the last hour."* * *"Find traces containing this request ID and summarize the failing dependency."* * *"Did log volume or error rate change after the deployment at 14:05 UTC?"* ClickHouse SQL remains authoritative for query semantics. Rootly AI can query standard tables, views, and the `system` catalog when the account has access. *** ## Query and Resource Limits Every query is subject to application and ClickHouse request limits: | Limit | Behavior | | --------------- | --------------------------------------------------------------------------------------- | | Statement type | One `SELECT`, `WITH`, or `EXPLAIN` statement | | Returned rows | 200 rows by default; 1,000 rows maximum | | Response size | 1 MB maximum | | Execution time | 15 seconds in ClickHouse; 20-second HTTP timeout | | Rows read | 100 million maximum | | Bytes read | 5 GB maximum | | Memory | 2 GB maximum | | Threads | 4 maximum | | Result overflow | ClickHouse stops the result at the configured boundary and Rootly marks it as truncated | Rootly rejects data-definition language (DDL), mutations, administrative commands, `SET` and `SETTINGS` changes, multiple statements, custom `FORMAT` clauses, and external-network table functions such as `url`, `s3`, `http`, `remote`, `mysql`, and `postgresql`. These limits protect investigation context and shared ClickHouse capacity. They aren't a substitute for ClickHouse quotas or workload controls. Use `MAX` or `CONST` [settings-profile constraints](https://clickhouse.com/docs/reference/statements/create/settings-profile) when a server-side cap must remain authoritative; ClickHouse rejects a request that exceeds the constraint. Use [quotas](https://clickhouse.com/docs/concepts/features/configuration/server-config/quotas) to bound cumulative use across queries. Test the Rootly connection after tightening either control. Aggregate and filter before returning raw rows. Narrow time windows, select only useful columns, and group by service or error attribute so the result stays below the row and response limits. *** ## Data Handling and Permissions * **On-demand queries.** Rootly AI queries ClickHouse only when an investigation or direct question needs the data. The connector doesn't run a background ingestion job. * **ClickHouse permissions apply.** Rootly can only read objects granted to the configured account. * **Defense in depth.** Rootly validates query shape and sends read-only, execution, result, memory, and thread settings with every request. * **Encrypted credentials.** Rootly encrypts the username and password at rest and excludes them from audit-version payloads. * **Credential cleanup.** Disconnecting the AI connector scrubs the stored username and password before soft-deleting the connection. * **AI traces may contain results.** Connector responses can appear in Rootly AI's model and observability traces. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for retention details. One active ClickHouse connection can be configured per Rootly team. Use a ClickHouse view or a dedicated database when responders need a curated schema rather than broad table access. *** ## Managing the Connection Open the ClickHouse card to update or disconnect it. When editing the connection, leave both credential fields blank to keep the current username and password. If you enter replacement credentials, Rootly verifies them before saving the change. Disconnecting removes the stored credentials and prevents future queries. It doesn't change the ClickHouse account or delete ClickHouse data. Revoke or delete the ClickHouse account separately if it is no longer needed. If your firewall restricts inbound traffic, add [Rootly's published IP ranges](/integrations/ip-whitelist) before connecting ClickHouse. *** ## Troubleshooting Confirm that the value is a public HTTPS origin and that DNS and the certificate are valid. Include port `8443` for ClickHouse Cloud when it appears in the connection details. Rootly rejects HTTP, private and loopback destinations, embedded credentials, URL paths, query parameters, and fragments. If you restrict inbound traffic, add Rootly's published IP ranges. Repeat the `curl` check in [Verify the account](#verify-the-account) with the same HTTPS origin, username, and password. Confirm that the account uses password authentication and hasn't been disabled or rotated. When updating Rootly after a rotation, enter both the username and password. `SELECT 1` confirms connectivity and authentication but doesn't prove the account can read your data. Grant `SELECT` on the intended database and its tables. The discovery tools also read `system.databases`, `system.tables`, and `system.columns`; confirm that your ClickHouse policy permits those catalog queries. Use one `SELECT`, `WITH`, or `EXPLAIN` statement without a trailing semicolon or `FORMAT` clause. Remove settings changes, mutations, DDL, administration commands, and external-network table functions. Rootly rejects these query shapes even if the ClickHouse account could run them. Filter to a shorter incident window, select fewer columns, aggregate before sorting, or use a lower-cardinality grouping. Rootly limits execution time, rows, bytes, memory, threads, and response size. A truncated result is partial evidence, not a complete count. Confirm that the expected exporter is writing to the database and table granted to the Rootly account. Check the event timestamp column and query the same time range directly in ClickHouse. Empty results can mean the wrong database, table, time zone, or filter; they don't prove that the service is healthy. *** ## Frequently Asked Questions No. Rootly calls ClickHouse's HTTPS query interface directly and provides its own bounded AI tools for database discovery, schema inspection, and read-only SQL. No. Rootly exposes only read operations, rejects mutations and administrative statements, and sends `readonly=1` with each request. Keep the dedicated ClickHouse account read-only as the authoritative server-side control. The connector requires a public HTTPS endpoint. Place a trusted HTTPS proxy or load balancer in front of the cluster, restrict it to Rootly's published IP ranges, and keep ClickHouse authentication enabled. One active ClickHouse connection can be configured per Rootly team. To expose data from several clusters, consolidate the required investigation data behind one approved ClickHouse endpoint or use separate Rootly teams. *** ## Related Pages Compare Rootly AI connectors and setup flows. Review connector data handling, traces, and retention. Configure users, roles, and grants in ClickHouse. # Cloudflare Source: https://docs.rootly.com/ai/connectors/cloudflare Connect Rootly AI to Cloudflare — DNS, Workers, Zero Trust, audit logs, Radar, CASB, Logpush, and more — via a single one-click authorization. ## Overview Cloudflare is a one-click connector that gives Rootly AI read access to your Cloudflare account across **fourteen surfaces** — from core Cloudflare (DNS, Workers, Zero Trust) through Cloudflare's observability and security products. Sign in once through Cloudflare's authorization screen and every enabled surface is available to Rootly AI during investigations. Because it's one-click, there are no configuration forms to fill in — Rootly AI queries whatever the authorizing Cloudflare user has permission to see. You do not need to enable every surface. Cloudflare gates each product behind its own permissions — Rootly AI will only be able to read from surfaces the connecting user (and your Cloudflare plan) actually has access to. *** ## Before You Start * **A Cloudflare account** with permission to authorize third-party OAuth apps. * **Roles on the surfaces you want available.** The connecting Cloudflare user's account roles determine what Rootly AI can see — for example, without CASB permissions the Cloudflare CASB surface won't return data even though the connector is technically enabled. *** ## Setup Open **Configuration → AI → Connectors** and click **Connect** on the Cloudflare card. Sign in to Cloudflare and authorize Rootly AI. When the flow completes, the card flips to **Connected** and Rootly AI can query every surface your Cloudflare account exposes. *** ## Surfaces Rootly AI Can Read Cloudflare exposes fourteen distinct surfaces through this connector. Each one gives Rootly AI a different kind of context during an investigation. ### Infrastructure | Surface | What Rootly AI reads | | --------------------- | ------------------------------------------------ | | **Cloudflare** (core) | DNS records, Workers, Zero Trust posture | | **Workers Bindings** | Storage bindings, AI bindings, compute resources | | **Workers Builds** | Build history, insights, deploy management | | **Containers** | Sandboxes, dev environments, isolation posture | | **Browser** | Rendering, screenshots, browser automation state | ### Observability & security | Surface | What Rootly AI reads | | --------------------------------- | ------------------------------------------------------ | | **Cloudflare Observability** | Logs, analytics, debugging traces | | **DNS Analytics** | DNS query volume, performance, troubleshooting signals | | **Audit Logs** | Change tracking, admin activity, compliance reports | | **Radar** | Traffic insights, trends, URL scans | | **CASB** | SaaS security posture, misconfigurations, compliance | | **Logpush** | Log pipeline job health and summaries | | **AI Gateway** | AI ops analytics, gateway metrics | | **Digital Experience Monitoring** | DEX scores, user experience monitoring | | **GraphQL Analytics** | GraphQL queries and analytics | You don't need to memorize the list — Rootly AI picks the right surface based on the question. Asking *"why is our DNS slow?"* pulls from DNS Analytics + Radar automatically. ## During an Incident *"An audit log shows a config change during the incident window."* Rootly AI queries Cloudflare's audit log for changes during the incident window — DNS record edits, Zero Trust policy modifications, Workers deploys — and surfaces them in the investigation output. When the incident correlates with a Cloudflare config change, responders see the exact change, who made it, and when, without leaving Rootly. *** ## Best Practices * **Authorize with an account that already has broad Cloudflare permissions.** Rootly AI can only see what the connecting user can see. A restricted user makes the connector superficially "Connected" but starves the underlying queries. * **Use it alongside a code and observability connector.** Cloudflare tells you what's happening at the edge; pairing it with GitHub (for recent deploys) and Datadog / Sentry (for the origin) makes for much stronger investigations. * **Prefer Radar for organization-wide traffic questions.** For customer-specific traffic, Cloudflare Observability and DNS Analytics give better fidelity. * **Rotate the connection if a Cloudflare admin's permissions change.** Disconnect and reconnect with the new user's account so Rootly AI sees the updated scope. *** ## Troubleshooting Cloudflare gates each surface behind its own product permission (CASB, Zero Trust, Radar Business, etc.). If the connecting user's Cloudflare account doesn't have access to a surface — either by role or by plan tier — Rootly AI can't read from it either. Grant the user access on the Cloudflare side, then disconnect and reconnect so the OAuth grant refreshes. Confirm the connecting user has access to the zone in question. Multi-zone Cloudflare accounts route by permission, so a user restricted to one zone will only surface data from that zone. If a Cloudflare admin revokes the OAuth grant from Cloudflare's side, Rootly AI's card still shows Connected but every query fails. Reconnect from Rootly to re-authorize. *** ## Frequently Asked Questions No. A single Cloudflare OAuth authorization covers all fourteen surfaces. Which surfaces actually return data depends on the connecting user's Cloudflare permissions and your plan. Rootly does not maintain a persistent copy of Cloudflare data — queries run at investigation time and the response is used in reasoning only. Query results *do* appear in the LLM traces Rootly logs for quality monitoring, as with every tool call Rootly AI makes. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for the retention boundary. Yes — indirectly, through the connecting user's Cloudflare roles. Rootly AI cannot read a surface that the authorizing user doesn't have access to in Cloudflare. Not directly today. The current fourteen surfaces cover DNS, Workers, Zero Trust, and Cloudflare's observability + security products. Ask support if Pages coverage is on your roadmap. *** ## Related Pages All connectors and how they fit together. The other infrastructure connector. What Rootly AI sees, retention, and model training controls. # Custom (Any OAuth MCP) Source: https://docs.rootly.com/ai/connectors/custom Bring your own OAuth-based MCP server as a Rootly AI connector, with an allowlist of tools it can call during investigations. ## Overview The **Custom** connector lets you point Rootly AI at any OAuth-based MCP server that isn't in the built-in catalog. This covers internal tools your team hosts, third-party services that expose MCP endpoints, and vendor integrations Rootly hasn't shipped native support for yet. Once connected, you can ask Rootly AI about whatever the server exposes: A responder asking Rootly AI in Slack who owns checkout-api; the reply lists owner team, on-call handle, criticality tier, repo, dashboard, and dependencies from the custom internal KB You provide the endpoint and the OAuth details. Rootly AI authorizes against your server, then calls tools you've explicitly allowlisted during investigations. Unlike built-in connectors, the Custom connector does **not** filter write-capable tools server-side. Rootly AI can call any tool you allowlist, including tools that mutate state on your MCP server. Allowlist read-only tools unless you specifically want Rootly AI to be able to invoke a write. *** ## Before You Start Rootly AI doesn't use pre-shared credentials for custom MCP servers. It registers itself as an OAuth client against your server at connect time, then authorizes through the standard OAuth flow. Rootly treats a custom server exactly like one of its built-in connectors: the same MCP protocol version (**2025-06-18**) and the same OAuth implementation, with no fallbacks or leniency for user-supplied URLs. In practice that means your server has to implement the MCP authorization spec as written: metadata discovery, Dynamic Client Registration, PKCE, and resource indicators. A running MCP server reachable at a public HTTPS URL with a valid TLS certificate. Private and reserved IP ranges, `localhost`, and self-signed certificates are rejected. Every discovery, registration, and token request also has a **15-second timeout**; slow well-known endpoints fail the connection. This is where discovery starts, and everything else hangs off it. Rootly needs the `authorization_servers` array to know which authorization server to talk to. Serve it either way: * `GET /.well-known/oauth-protected-resource/` returning `200` with JSON. The path is **suffixed with your MCP server's path**: for `https://mcp.your-company.com/mcp`, Rootly requests `https://mcp.your-company.com/.well-known/oauth-protected-resource/mcp`, not the bare well-known path. * Or return `401` from the MCP endpoint itself with a `WWW-Authenticate` header carrying `resource_metadata="https://…"`. Rootly fetches `/.well-known/oauth-authorization-server` on the issuer from `authorization_servers[0]` (path-suffixed the same way when the issuer has a path) and requires a `200`. The document must advertise: * `authorization_endpoint` * `token_endpoint` * `registration_endpoint` There are **no default endpoint paths**. Rootly does not guess `/authorize`, `/token`, or `/register`. If an endpoint isn't in this document, the connection fails. Rootly `POST`s to your advertised `registration_endpoint` with `token_endpoint_auth_method: "none"`, `grant_types: ["authorization_code", "refresh_token"]`, `response_types: ["code"]`, `client_name: "Rootly"`, and Rootly's single callback URL as `redirect_uris`. Your server must respond **`201 Created`** with a `client_id`; a `200` with a valid body still fails. Rootly registers as a public client and does not expect a client secret. At the token endpoint it sends `client_id` **in the request body**, not via HTTP Basic auth. An authorization server that only accepts Basic auth will reject the token exchange. (If your registration response does return a `client_secret`, Rootly stores it and switches to Basic auth automatically.) Rootly always sends `code_challenge_method=S256`. Your authorization server must support S256 code challenges; `plain` is never offered. Rootly sends a `resource` parameter on the authorization request, the token exchange, **and** every refresh. The value is the `resource` field from your protected resource metadata, or the canonical origin + path of your MCP URL. Your authorization server must accept the parameter and issue a token valid for that resource rather than erroring on it. Your token endpoint must return a `refresh_token` alongside the access token, and the `refresh_token` grant must work on its own. Without it the connection works initially and then stops once the first access token expires. Rootly does **not** send a `scope` parameter for custom connections. Your authorization server has to grant a sensible default scope rather than rejecting the request for a missing `scope`. After authorization, Rootly `POST`s JSON-RPC to your MCP URL with `Authorization: Bearer`, `Accept: application/json, text/event-stream`, and `MCP-Protocol-Version: 2025-06-18`, echoing `Mcp-Session-Id` back if you set it. Your server must handle `initialize`, `notifications/initialized`, `tools/list` (cursor pagination supported, up to 1,000 tools), and `tools/call`. Replies may be JSON or SSE. The subset of your server's tools you're comfortable letting Rootly AI call. You control this explicitly after authorization. Most MCP server frameworks ship DCR, PKCE, and the well-known metadata endpoints already wired up. If you built your server on one of those, this is usually already satisfied. Confirm it before you assume it's missing. *** ## Setup Go to **Configuration → AI → Connectors** and click **Connect** on the **Custom MCP** card. The **Connect a custom MCP server** dialog opens. The Custom MCP card on the Connectors page, showing the Connect button A label that tells this server apart from your other custom connections. Rootly also uses it when citing the connector in investigations (for example, *"queried the internal-ops MCP"*), so pick something responders will recognize. A public HTTPS endpoint Rootly can reach, for example `https://mcp.your-company.com/mcp`. Private and internal-only addresses are blocked. Shown on this connection's tile: a short note on what it gives Rootly AI access to. Useful once you have several custom connections. The Connect a custom MCP server dialog with a connection name, MCP server URL, and description filled in Rootly registers itself as a client against your server, then redirects to your MCP server's OAuth flow. Sign in and grant access. If registration fails, you'll see the error at this point rather than after authorization. See [Troubleshooting](#troubleshooting) for the common causes. After authorization, Rootly discovers the tools your server exposes and opens the **Choose tools** screen for that connection. Check only the tools investigations may call, then click **Save tools**. Unchecked tools are never exposed to Rootly AI. The Choose tools screen listing the server's discovered tools with checkboxes, each showing its name and description Once tools are saved, the card shows **Connected**. Rootly AI can now reach for this server during investigations. The connection's card on the Connectors page showing a Connected badge with Configure and Disconnect actions **Public HTTPS only.** Rootly can't reach an MCP server on a private network or via `localhost`. If your MCP is behind a VPN, expose it through a reverse proxy with a valid TLS certificate before connecting. *** ## During an Incident When you connect a Custom MCP endpoint, Rootly AI calls the tools you allowlist during investigations and when responders ask it questions. Teams commonly expose internal deploy trackers, feature-flag services, service catalogs, or bespoke telemetry. The examples below come from the same internal knowledge base connection as the overview. The question every responder asks first, answered from your own deploy and feature-flag history: Rootly AI in Slack answering "has anything changed on checkout-api?" from a custom internal KB: a deploy 19 minutes earlier and a feature-flag flip, including the rollback command Internal data also carries context no vendor tool has, and Rootly AI reasons over it. Here, customer SLA data becomes business impact and suggested next steps: Rootly AI listing the customer accounts that depend on the affected service with ARR and SLA per account, then assessing SLA risk and suggesting next steps ### Write Tools Built-in connectors are strictly read-only. The Custom connector is the one place Rootly AI can act on your systems, and only through a write-capable tool you have deliberately allowlisted. Here, a responder asks Rootly AI to record the incident's findings, and the note lands in the knowledge base for whoever hits this failure mode next: A responder asking Rootly AI to add a note to checkout-api recording the incident; Rootly AI confirms the note was saved to the custom KB and will appear in future service lookups Newly discovered tools stay unchecked until you enable them, so a write tool is always a deliberate choice. Read the warning at the top of this page before allowlisting one. *** ## Managing the Connection Open the connection's **Configure** screen to: * **Change which tools are exposed.** Reopen **Choose tools**, adjust the checkboxes, and click **Save tools**. Unchecking a tool takes effect on the next investigation. * **Update the endpoint URL.** If you move your MCP server, point Rootly at the new host. Rootly re-authorizes on save. * **Rotate credentials.** Disconnect and reconnect to trigger a fresh OAuth flow. Old tokens are revoked. Your server's tool catalog isn't frozen at connect time. Each time you open **Choose tools**, Rootly re-discovers what the server exposes. Ship a new tool and it appears in the list, unchecked, ready to enable when you are: The Choose tools screen after the server shipped a new add_service_note tool, discovered automatically and unchecked by default *** ## Best Practices * **Start with a minimal allowlist.** Only allowlist the tools you're sure Rootly AI should call. It's easier to add later than to explain a surprise tool call. * **Give the connection a descriptive name.** *"Internal ops MCP"* or *"Finance data MCP"* is more useful than *"Custom MCP"* when Rootly AI cites it in an investigation summary. Use the optional description to record what it exposes. * **Rotate on personnel changes.** The OAuth grant is tied to whoever authorized it. When that person leaves, disconnect and reconnect from someone else's account so the connection doesn't die silently. * **Prefer named connectors over Custom when a native one exists.** If Rootly ships a first-class connector for what you're doing, use it. First-class connectors get better UI, tighter tool sets, and validated setup. *** ## Troubleshooting The URL must be a public HTTPS endpoint with a valid TLS certificate. Private IPs, `localhost`, and self-signed certificates are rejected. Deploy behind a public gateway with a real cert. The full message reads: *"Rootly couldn't complete the OAuth handshake with that server. It must support OAuth discovery and dynamic client registration. Check the URL and try again."* Rootly discovers your endpoints and registers itself as a client *before* the authorization redirect, so this surfaces at connect time rather than after sign-in. Work through these in order; discovery fails first, so start at the top: * **Protected resource metadata is missing.** Discovery begins here and everything else depends on it. Confirm `GET https://your-host/.well-known/oauth-protected-resource/` returns `200` with an `authorization_servers` array. Note the path suffix: the bare well-known path isn't checked. Alternatively, return `401` from the MCP endpoint with `WWW-Authenticate: Bearer resource_metadata="https://…"`. * **Authorization server metadata is missing or incomplete.** `/.well-known/oauth-authorization-server` on the issuer must return `200` and advertise `authorization_endpoint`, `token_endpoint`, and `registration_endpoint`. Rootly has **no fallback paths**. Serving DCR at `/register` without advertising it in this document still fails. If the issuer has no path, check for a 404 caused by a trailing slash on the well-known URL. * **The registration endpoint doesn't return `201 Created`.** A `200` with a valid body still fails; Rootly requires `201`. Check what your server returns for a `POST` to its registration path. * **Your server requires a client secret.** Rootly registers as a public client with `token_endpoint_auth_method` set to `none`. Authorization servers that reject public-client registration can't complete this step. * **Your server rejects the requested grants.** Rootly asks for `authorization_code` and `refresh_token` with the `code` response type. If your server doesn't allow that combination for dynamically registered clients, registration fails. * **Something in the chain is slow.** Each discovery, registration, and token request times out after 15 seconds. Registration and discovery worked, so the failure is in the token exchange. The usual causes: * **No S256 PKCE support.** Rootly always sends `code_challenge_method=S256`. * **The `resource` parameter is rejected.** Rootly sends it on the authorization request, the token exchange, and every refresh. Your authorization server must accept it, not error on an unrecognized parameter. * **The token endpoint requires HTTP Basic auth.** As a public client, Rootly sends `client_id` in the request body. * **A `scope` parameter is required.** Rootly doesn't send one for custom connections. Your server needs a usable default scope. Almost always missing refresh tokens. Rootly requests the `refresh_token` grant at registration; if your server registers the client but never issues refresh tokens, the connection works until the first access token expires and then every query fails. Confirm your token endpoint returns a `refresh_token` alongside the access token, then disconnect and reconnect. Your MCP server has to expose a tool discovery endpoint that Rootly can call after OAuth completes. If your server doesn't return a tool list, the **Choose tools** screen comes up empty and there's nothing to select. Confirm the discovery response with an independent MCP client, then reconnect. Rootly AI only reaches for a tool when the current question actually needs it. If the tool isn't showing up, it usually means the question didn't warrant that lookup, not that the connector is broken. Try a prompt that explicitly targets the tool's data. If someone revokes the OAuth grant on the MCP server side, Rootly's card still shows Connected but every query fails. Reconnect to trigger a fresh OAuth flow. *** ## Frequently Asked Questions Built-in connectors ship with dedicated setup UI, tested tool sets, and per-provider troubleshooting. The Custom connector is the escape hatch: point it at any OAuth-based MCP endpoint and provide your own allowlist. Use built-ins when they exist; use Custom when they don't. Yes. Each connection is independent, with its own connection name, URL, and set of chosen tools. Common for teams that expose one MCP per internal system. Not today. The Custom connector requires OAuth 2.0 with Dynamic Client Registration on the MCP server. If your MCP only exposes API-key auth, wrap it in an OAuth-capable gateway or contact support to request first-class API-key support. Because there's no admin step where you hand Rootly a client ID and secret. Rootly creates its own OAuth client on your server at the moment you connect, which is what makes the flow self-serve: you paste a URL and authorize, rather than pre-provisioning credentials on both sides. It also means each connection gets its own client rather than sharing one across every Rootly customer. Not currently. Registration happens automatically at connect time and there's no field for supplying an existing client ID or secret. If your authorization server can't allow dynamic registration, the workaround is an OAuth-capable gateway in front of your MCP server that does permit it. Rootly AI can only call tools you allowlist, but *what those tools do* is defined by your MCP server, not by Rootly. Rootly doesn't inspect a tool's semantics or filter out write-capable tools automatically. **Only allowlist tools you're comfortable Rootly AI invoking**, and prefer read-only operations for anything you don't want Rootly AI to be able to mutate. Built-in connectors ship with a curated read-only tool set; the Custom connector puts that responsibility on you. *** ## Related Pages All connectors and how they fit together. What Rootly AI sees, retention, and model training controls. Another endpoint-based connector and a good reference for public-HTTPS requirements. # Dash0 AI Connector Source: https://docs.rootly.com/ai/connectors/dash0 Connect Rootly AI to Dash0 — traces, logs, metrics, services, dashboards, and alerts — with a region selection and one OAuth authorization. ## Overview The **Dash0** connector lets Rootly AI query your Dash0 environment during incident investigations. Dash0 is an OpenTelemetry-native observability platform, so this connector gives Rootly AI access to your traces, logs, metrics, service catalog, dashboards, and alerting — all through a single integration. Setup is a region selection followed by an OAuth authorization. There is no API key to create or paste. Rootly AI's access is **read-only**. It authorizes with a read scope and can query your Dash0 data but never create, modify, or delete dashboards, alerts, or check rules. *** ## Before You Start An account with access to the datasets you want Rootly AI to query. Rootly AI inherits the read access of whoever authorizes the connection. Dash0 runs in multiple regions and your data lives in exactly one. You'll pick this during setup, and picking the wrong one means Rootly AI authorizes against an instance that doesn't hold your data. Connecting a data source requires the permission to manage AI connectors on your Rootly account. If the **Connect** button is unavailable, ask a Rootly admin. If you're not sure which region you're on, go to **Settings → Endpoints** in the Dash0 UI — the API URL shown there (e.g., `api.us-west-2.aws.dash0.com`) contains the region. Alternatively, check the region selector in the Dash0 app. *** ## Connecting Go to **Configuration → AI → Connectors** and click **Connect** on the **Dash0** card. The **Connect Dash0** dialog opens. Select the region your Dash0 environment runs in: * **US West 2** — `api.us-west-2.aws.dash0.com` (AWS Oregon) * **EU West 1** — `api.eu-west-1.aws.dash0.com` (AWS Ireland) * **EU Central 1** — `api.eu-central-1.aws.dash0.com` (AWS Frankfurt) * **Europe West 4** — `api.europe-west4.gcp.dash0.com` (GCP Netherlands) Selecting the wrong region sends Rootly's queries to an instance that doesn't contain your data. Click **Connect Dash0**. Rootly redirects to Dash0's OAuth authorization flow — sign in if needed, review the requested access, and approve. Dash0 sends you back to Rootly, and the card flips to **Connected**. *** ## What Rootly AI Can Read Once connected, Rootly AI can query Dash0 for: * **Traces** — inspect distributed traces across your OpenTelemetry-instrumented services. * **Logs** — search and filter across your ingested log streams. * **Metrics** — query metrics via PromQL, including Dash0's synthetic metrics (`dash0.spans`, `dash0.logs`). * **Service catalog** — list all services with health indicators (request rates, error percentages, latency P95), resource types, and inter-service dependencies. * **Dashboards** — look up dashboard configurations to correlate what humans typically monitor with what's happening in the incident. * **Check rules & failed checks** — list alerting rules and active/historical check failures. * **Kubernetes** — query pod status and metadata for K8s-instrumented workloads. * **Synthetic checks** — check the status and results of synthetic monitors. Access is scoped by the permissions on the authorizing Dash0 account. *** ## During an Incident *"Error rate on the checkout service jumped to 4.2% at 2:14pm. The service graph shows it depends on payment-api, which started returning 503s two minutes earlier."* Rootly AI queries Dash0 for the service catalog, traces, logs, and metrics correlated with the current incident. When error rates spike, latency degrades, or dependencies start failing, Rootly AI surfaces the exact service, dependency chain, and correlated signals — no manual dashboard-hunting required. Because Dash0 is OpenTelemetry-native, the service catalog includes automatically discovered inter-service dependencies derived from your trace data. Rootly AI uses these dependencies for blast-radius analysis — understanding which upstream and downstream services are affected by an incident. *** ## Best Practices * **Authorize with a service account, not a personal one.** If a personal Dash0 account leaves the organization, the integration silently breaks the next time it's queried. A service account with stable membership avoids that. * **Verify region selection before authorizing.** Wrong-region is the #1 setup failure. Double-check the region against your actual Dash0 URL before hitting Connect. * **Ensure your services emit OpenTelemetry traces.** Dash0's service catalog and dependency map are built from trace data. Services that only emit metrics or logs will appear in the catalog but won't have dependency information. * **Test with `/rootly test`.** After connecting, declare a test incident and confirm Rootly AI can pull Dash0 signals during the investigation. *** ## Troubleshooting Common causes: (1) the authorizing user doesn't have permission to grant third-party access in Dash0 — check with a Dash0 admin; (2) your organization has restricted third-party grants at the workspace level. You authorized against a Dash0 region that doesn't contain your data. Disconnect the integration, reconnect against the correct region, and re-authorize. There's no way to migrate a wrong-region connection; you have to disconnect and start over. Dependencies are inferred from OpenTelemetry trace data. If your services only emit metrics or logs (no traces), Dash0 can't observe inter-service calls. Ensure your services are instrumented with an OpenTelemetry SDK or auto-instrumentation agent that emits spans. Two common causes: 1. **Authorizer permissions** — Rootly AI inherits the access of whoever authorized the connection. If the authorizing Dash0 account can only see certain datasets or services, Rootly AI has the same limitation. Re-authorize with a broader account to fix. 2. **Missing telemetry** — Rootly AI auto-discovers all datasets and ingests from each. If a service isn't appearing in any dataset, verify it's instrumented and sending data to Dash0. *** ## Frequently Asked Questions No. The connector uses OAuth 2.0 — you authorize through Dash0's consent screen, and Rootly AI receives a scoped access token. No API key to create or paste. One Dash0 connector per Rootly team currently. If you operate across multiple regions, connect the one that hosts most of your observability signal. Rootly AI queries Dash0 fresh on each investigation call and does not maintain a persistent copy of your Dash0 data. However, query results do appear in the LLM traces Rootly logs for quality monitoring — the same as every other tool call. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for retention details. Dash0 supports all four OTel signals: traces, metrics, logs, and profiles. Rootly AI can query traces, metrics, and logs through the connector. The connector gives Rootly AI read access to your Dash0 data through Dash0's MCP tools. Agent0 (Dash0's own AI assistant) is a separate feature — the two don't interact. *** ## Related Pages The full list of Connectors and how they fit together. Another OTel-native observability connector — similar setup flow. What Rootly AI sees, retention, and model-training controls. # Datadog MCP Connector Source: https://docs.rootly.com/ai/connectors/datadog Connect Rootly AI to Datadog through read-only OAuth, with API and application keys available as a fallback. The **Datadog MCP** connector lets Rootly AI query operational data during investigations. It can inspect services, logs, metrics, monitors, application performance monitoring (APM) spans and traces, and Real User Monitoring (RUM) events through Datadog's hosted Model Context Protocol (MCP) server. OAuth 2.0 is the recommended authentication method. Rootly also supports Datadog API and application keys for organizations that can't use OAuth. Rootly requests read permissions only and exposes a reviewed investigation tool set. It doesn't request Datadog's `mcp_write` permission or expose Datadog tools that create or modify resources. This connector is independent of the Datadog [Alert Source](/alerts/alerts). The Alert Source sends Datadog alerts into Rootly. The Datadog MCP connector lets Rootly AI query Datadog on demand. You can configure both for the same Rootly team. ## Before You Start You need: * A Datadog account with access to the data Rootly AI should query. * Permission in Rootly to manage AI connectors. * A supported Datadog site: US1, US3, US5, EU1, AP1, or AP2. Datadog's hosted MCP server isn't available for GovCloud. * The Datadog role permissions listed below. ### Required: Allow Rootly's OAuth Callback Complete this prerequisite before starting OAuth. Otherwise, Datadog rejects the authorization request or can't return the user to Rootly. A Datadog administrator must allowlist Rootly's callback URL before anyone connects with OAuth. In Datadog, open **Organization Settings → Organization Preferences → MCP OAuth Redirect URLs** and add: ```text theme={null} https://rootly.com/account/ai-sre/remote_mcp_sources/callback ``` If Rootly support gave you a different Rootly environment, replace `https://rootly.com` with that environment's base URL. Keep the `/account/ai-sre/remote_mcp_sources/callback` path unchanged. ## Required Permissions The Datadog user authorizing OAuth needs these permissions through their role. Rootly requests the matching OAuth scopes. | Capability | Datadog permission or OAuth scope | | ------------------------------ | ---------------------------------------- | | MCP data access | `mcp_read` | | Metrics | `metrics_read`, `timeseries_query` | | Monitors | `monitors_read` | | APM traces and service catalog | `apm_read`, `apm_service_catalog_read` | | Logs | `logs_read_data`, `logs_read_index_data` | | RUM applications | `rum_apps_read` | | Database Monitoring | `dbm_read` | Datadog applies the authorizing user's role permissions in addition to the OAuth scopes. Rootly AI can't retrieve data the user can't access. `dbm_parameterized_queries_read` is a valid Datadog role and application-key permission, but Datadog's MCP OAuth client doesn't authorize that scope. OAuth can investigate Database Monitoring metrics and spans with `dbm_read`; use API and application keys when an investigation needs parameterized query-pattern access. Rootly doesn't request `mcp_write`. A custom Datadog role only needs **MCP Read** and the resource-level read permissions for the data Rootly should access. ### Additional Permissions for API and Application Keys The key-based fallback validates the application key's scopes before saving the connection. The application key and the user or service account that owns it need every permission below: This broader list intentionally preserves the existing key-based connector's legacy read surface for backward compatibility. Use OAuth when you want the smallest permission set supported by the Datadog MCP connector. * `user_app_keys` * `mcp_read` * `apm_read` * `apm_service_catalog_read` * `containers_read` * `logs_read_data` * `logs_read_index_data` * `monitors_read` * `apm_api_catalog_read` * `apm_pipelines_read` * `apm_remote_configuration_read` * `apm_retention_filter_read` * `apm_service_ingest_read` * `continuous_profiler_pgo_read` * `continuous_profiler_read` * `debugger_read` * `dashboards_read` * `dbm_parameterized_queries_read` * `dbm_read` * `error_tracking_read` * `events_read` * `logs_read_archives` * `logs_read_config` * `logs_read_workspaces` * `metrics_read` * `timeseries_query` * `notebooks_read` * `on_call_read` * `rum_apps_read` * `cd_visibility_read` * `ci_visibility_read` * `synthetics_default_settings_read` * `synthetics_global_variable_read` * `synthetics_private_location_read` * `synthetics_read` * `teams_read` The API key identifies the Datadog organization and doesn't carry permissions. The `user_app_keys` permission lets Rootly inspect the submitted application key's scopes during setup. *** ## Connect Datadog with OAuth Before continuing, confirm that a Datadog administrator completed [Required: Allow Rootly's OAuth Callback](#required-allow-rootlys-oauth-callback). In Rootly, go to **AI & Agents → Connectors**, find **Datadog MCP**, and click **Connect**. Select the site that hosts your Datadog organization: | Site | API host | Stable MCP endpoint | | ---- | ----------------------- | -------------------------------------- | | US1 | `api.datadoghq.com` | `https://mcp.datadoghq.com/v1/mcp` | | US3 | `api.us3.datadoghq.com` | `https://mcp.us3.datadoghq.com/v1/mcp` | | US5 | `api.us5.datadoghq.com` | `https://mcp.us5.datadoghq.com/v1/mcp` | | EU1 | `api.datadoghq.eu` | `https://mcp.datadoghq.eu/v1/mcp` | | AP1 | `api.ap1.datadoghq.com` | `https://mcp.ap1.datadoghq.com/v1/mcp` | | AP2 | `api.ap2.datadoghq.com` | `https://mcp.ap2.datadoghq.com/v1/mcp` | Choose the site that matches your Datadog login URL. Each site has its own MCP and OAuth endpoints. Click **Connect with OAuth**. You don't need to create or share an API key, application key, client ID, or client secret. Sign in to Datadog. If your account belongs to more than one organization, select the organization Rootly AI should query. Review the requested read permissions and authorize Rootly. Datadog returns you to Rootly after approval. Return to **AI & Agents → Connectors**. The Datadog MCP card shows **Connected** after Rootly validates the OAuth grant and Datadog tool catalog. Rootly uses OAuth 2.0 with Dynamic Client Registration and Proof Key for Code Exchange (PKCE). Access and refresh credentials are encrypted at rest. If a Datadog connection already exists, Rootly keeps it active during a new OAuth attempt. Rootly replaces the existing connection only after authorization and validation succeed. ## Connect with API and Application Keys Use this fallback when your organization can't complete the OAuth flow. Create a Datadog API key and a scoped application key owned by a dedicated service account. Grant the application key and its owner every permission under [Additional Permissions for API and Application Keys](#additional-permissions-for-api-and-application-keys). In Rootly, open **AI & Agents → Connectors**, find **Datadog MCP**, and click **Connect**. Choose the correct Datadog site, then expand **Use API and application keys instead**. Enter the API key and application key, then click **Connect with keys**. Rootly validates the credentials and application key permissions before saving the connection. Rootly encrypts the API and application keys at rest. *** ## What Rootly AI Can Read Rootly connects to Datadog's `core` MCP toolset and exposes reviewed, read-only investigation tools. | Category | What Rootly AI can inspect | | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Services and environments | Service catalog entries and observed environment values used to scope later queries. | | Logs | Bounded log searches, individual log details, counts, grouped signatures, and incident-to-baseline comparisons. | | Metrics | Metric discovery, metadata and tags, timeseries values, contributor breakdowns, and matched-window comparisons. | | APM | Bounded span searches and aggregations, slow-operation comparisons, and trace details. | | Monitors | Monitor definitions and states filtered by query, tags, or environment. | | RUM | Aggregated browser and mobile events for user-impact analysis. | | Database signals | Blocking-condition, workload, and substrate comparisons when Datadog reports the required metrics and spans. Parameterized query-pattern access requires API and application keys. | Rootly filters Datadog's upstream catalog before every call. A new tool added by Datadog doesn't become available automatically, and tools that write Datadog data remain blocked. ## Questions To Ask Include a service, environment, and bounded time range when possible. These prompts work in Rootly AI SRE and the Slack agent: * "Which services emitted new error log signatures in `prod` during the last 30 minutes compared with the preceding 30 minutes?" * "Break down `checkout-api` p95 latency by resource for the incident window. Which endpoint regressed most against baseline?" * "Find error spans for `payment-api` between 14:00 and 14:20 UTC, then expand the slowest trace and identify the failing dependency." * "Did the checkout error-rate monitor alert because of one environment, region, or host? Show the metric contributors." * "Compare blocked database sessions during the incident with the same window yesterday. Which wait type or query pattern changed?" * "How many RUM checkout errors occurred in the incident window, grouped by browser and country?" * "List the exact Datadog service and environment names before querying logs for the authentication failure." If a broad question returns irrelevant results, add the exact service, environment, signal type, and UTC time range. *** ## Data Handling and Permissions * **On-demand queries.** Rootly AI calls Datadog when an investigation or direct question needs current data. * **Datadog permissions apply.** Results are limited by the OAuth user's role or the application key owner's access. * **Read-only boundary.** Rootly requests read scopes and enforces a reviewed tool set before every call. * **Encrypted credentials.** Rootly encrypts OAuth credentials and API or application keys at rest. * **AI traces may contain results.** Datadog responses can appear in Rootly AI model and observability traces. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for retention details. * **Datadog rate limits apply.** Investigation queries count against your Datadog organization's API limits. ## Manage the Connection Open **AI & Agents → Connectors** and find the Datadog MCP card. * Click **Configure** to authorize a different Datadog organization, choose another site, or switch authentication methods. Rootly keeps the current connection active until the replacement is authorized and validated. * Click **Disconnect** to remove the connection and stop future Datadog queries. Disconnecting doesn't change or delete data in Datadog. *** ## Troubleshooting Ask a Datadog administrator to add Rootly's exact callback URL under **Organization Settings → Organization Preferences → MCP OAuth Redirect URLs**. The scheme, host, path, and trailing slash must match. For Rootly's production environment, use `https://rootly.com/account/ai-sre/remote_mcp_sources/callback` without a trailing slash. Confirm the callback URL is allowlisted in that Datadog organization, then restart the connection from Rootly. If you belong to several organizations, make sure you select the organization where an administrator added the callback URL. Rootly validates the OAuth grant and required Datadog tools before replacing the current connection. Confirm the authorizing user has `mcp_read` and the resource-level permissions listed on this page, then connect again. A failed replacement leaves the previous working connection unchanged. Confirm the OAuth user or application key owner has `mcp_read` plus the read permission for that resource. For example, monitor queries need `mcp_read` and `monitors_read`; log queries need `mcp_read`, `logs_read_data`, and `logs_read_index_data`. Grant `user_app_keys` to both the scoped application key and its owner, then connect again. Rootly rejects a key-based connection when it can't verify the application key's scopes. Confirm you selected the Datadog site that contains the data. US1, US3, US5, EU1, AP1, and AP2 use different regional MCP endpoints. Click **Configure** on the connected Datadog MCP card and reconnect to change sites. Rootly AI can only see data available to the OAuth user or application key owner. Check that identity's Datadog role, then retry with the exact service and environment names and a bounded time range. *** ## Frequently Asked Questions No. The Alert Source ingests Datadog monitor alerts into Rootly. The Datadog MCP connector lets Rootly AI query Datadog during investigations. Most teams use both. No. Rootly registers an OAuth client and stores the resulting credentials. API and application keys are an independent fallback. No. Rootly doesn't request `mcp_write`, and its reviewed Datadog tool set excludes resource creation, updates, and deletion. A Rootly team supports one active Datadog connection. Click **Configure** on the connected Datadog MCP card to authorize a replacement. Rootly keeps the current connection active until the replacement succeeds. Rootly supports US1, US3, US5, EU1, AP1, and AP2. Datadog doesn't provide its hosted MCP server for GovCloud. Rootly queries Datadog on demand. Short-lived references may be cached within an investigation so Rootly AI can expand a selected log or trace safely. *** ## Related Pages Browse every data source Rootly AI can use during an investigation. Configure Datadog monitor alerts to create Rootly alerts. Review encryption, retention, trace handling, and model controls. Review Datadog's MCP authentication, permissions, sites, and toolsets. # Dynatrace AI Connector Source: https://docs.rootly.com/ai/connectors/dynatrace Connect Rootly AI to Dynatrace's hosted MCP server with an environment name and Platform token for read-only incident investigation. ## Overview The **Dynatrace** AI connector lets Rootly AI query your Dynatrace environment during incident investigations. Rootly AI can run DQL, inspect problems and vulnerabilities, find entities, review Kubernetes events, and use Dynatrace Intelligence analysis tools without leaving the investigation. Rootly connects to Dynatrace's hosted MCP server for your environment. Setup requires your Dynatrace environment name and a Platform token; Dynatrace does not support the public OAuth and Dynamic Client Registration flow used by one-click AI connectors. Rootly AI exposes a curated read-only Dynatrace tool set. Tools that create notebooks or events, send email or Slack messages, or perform other write operations are filtered out. *** ## Before You Start The identifier before `.apps.dynatrace.com` in your Dynatrace URL. For `https://abc12345.apps.dynatrace.com`, enter `abc12345`. A Platform token for a user with access to the Dynatrace data Rootly AI should query. The user and token both need `mcp-gateway:servers:invoke` and `mcp-gateway:servers:read`, plus the permissions required by each Dynatrace MCP tool you want Rootly AI to use. Connecting a data source requires permission to manage AI connectors on your Rootly account. If **Connect** is unavailable, ask a Rootly admin. Treat the Platform token as a secret. Rootly stores it encrypted and never displays it again after setup. Create a dedicated token with only the Dynatrace permissions needed for investigation. ### Recommended Platform token scopes To enable every Dynatrace tool that Rootly currently allows, grant the full permission set that Dynatrace recommends for access to all MCP tools: | Capability | Scopes | | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | MCP gateway | `mcp-gateway:servers:invoke`, `mcp-gateway:servers:read` | | Dynatrace Intelligence | `ai:operator:execute`, `davis-copilot:conversations:execute`, `davis-copilot:nl2dql:execute`, `davis-copilot:document-search:execute`, `davis-copilot:dql2nl:execute` | | Davis analyzers | `davis:analyzers:read`, `davis:analyzers:execute` | | Documents | `document:documents:read` | | Grail data | `storage:bizevents:read`, `storage:buckets:read`, `storage:system:read`, `storage:spans:read`, `storage:entities:read`, `storage:user.events:read`, `storage:user.sessions:read`, `storage:user.replays:read`, `storage:smartscape:read`, `storage:events:read`, `storage:metrics:read`, `storage:logs:read`, `storage:files:read`, `storage:security.events:read` | Both the Platform token and its Dynatrace user must have these permissions. Their effective access is the intersection of the two. Dynatrace publishes the complete scope set for all MCP tools rather than a guaranteed minimum for each individual tool. If you reduce the token further, test every Rootly capability you expect to use. DQL can query different Grail data types, so the scopes needed by `execute-dql` depend on the query. The following mapping explains how Rootly's curated tools use those capability groups: | Rootly tool | Relevant capability or data scopes | | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- | | `ask-dynatrace-docs` | `ai:operator:execute`, `davis-copilot:conversations:execute`, and `davis-copilot:document-search:execute` | | `create-dql` | `ai:operator:execute` and `davis-copilot:nl2dql:execute` | | `explain-dql` | `ai:operator:execute` and `davis-copilot:dql2nl:execute` | | `execute-dql` | The `storage:*:read` scopes for every Grail data type addressed by the query | | `find-documents`, `find-troubleshooting-guides` | `document:documents:read` and `davis-copilot:document-search:execute` | | `get-entity-id`, `get-entity-name` | `storage:entities:read`; related lookups can also use `storage:smartscape:read` and `storage:system:read` | | `query-problems`, `get-problem-by-id`, `get-events-for-kubernetes-cluster` | `storage:events:read`, `storage:entities:read`, `storage:smartscape:read`, and `storage:system:read` | | `get-dynatrace-compliance-findings`, `get-dynatrace-vulnerabilities`, `get-security-event-details`, `get-security-events-summary` | `storage:security.events:read` and `storage:entities:read` | | `log-pattern-extractor` | `davis:analyzers:read`, `davis:analyzers:execute`, and `storage:logs:read` | | `adaptive-anomaly-detector`, `seasonal-baseline-anomaly-detector`, `static-threshold-analyzer`, `timeseries-forecast`, `timeseries-novelty-detection` | `davis:analyzers:read`, `davis:analyzers:execute`, `storage:metrics:read`, and any additional storage scope needed by the input DQL | See [Dynatrace MCP server permissions](https://docs.dynatrace.com/docs/dynatrace-intelligence/dynatrace-mcp#get-mcp-related-permissions) for Dynatrace's current source-of-truth permission list. *** ## Connecting In Dynatrace, create a [Platform token](https://docs.dynatrace.com/docs/manage/identity-access-management/access-tokens-and-oauth-clients/platform-tokens#my-platform-tokens) for the user and permissions Rootly AI should inherit. For the complete Rootly tool set, grant all scopes in [Recommended Platform token scopes](#recommended-platform-token-scopes). You can use a narrower token, but unavailable scopes disable the corresponding tools or data types. Choose an expiration date that follows your organization's token policy, and plan to replace the token through the Dynatrace connector before it expires. In Rootly, go to **AI & Agents → Connectors** and click **Connect** on the **Dynatrace** card. Enter your Dynatrace environment name without the protocol or `.apps.dynatrace.com` suffix. Paste the Platform token, then click **Connect Dynatrace**. Rootly builds the fixed Dynatrace MCP endpoint for your environment and probes it before saving the connection. An invalid environment name or token leaves any existing working connection unchanged. After the probe succeeds, the Dynatrace card shows **Connected**. Rootly AI can now query the allowed Dynatrace tools during investigations. *** ## What Rootly AI Can Read The curated Dynatrace MCP tool set covers: * **DQL** — generate, execute, and explain Dynatrace Query Language queries. * **Problems and security** — query problems, compliance findings, vulnerabilities, and security-event details and summaries. * **Entities** — resolve entity IDs and names. * **Kubernetes** — inspect Kubernetes events available in Dynatrace. * **Dynatrace Intelligence** — extract log patterns and run anomaly detection, static and seasonal threshold analysis, forecasting, and novelty detection. * **Documentation** — search Dynatrace documentation, troubleshooting guides, and documents available to the token. Rootly AI can only retrieve data that both the token and its Dynatrace user can access. Missing permissions usually appear as an authorization error or an empty result for the affected signal. When AI service-context ingestion is enabled for your Rootly account, Rootly also runs read-only DQL aggregations over recent spans and stores the resulting service identities and dependency relationships. Rootly does not persist the underlying spans or raw DQL result set as a copy of your Dynatrace telemetry. *** ## During an Incident *"Checkout errors began at 14:12. Dynatrace shows a new spike in `payment-api` failures, and the affected Kubernetes workload restarted three times in the same window."* Rootly AI can correlate Dynatrace problems, logs, spans, metrics, entities, and Kubernetes events with the Rootly incident timeline. It uses those results to identify affected services, likely causes, and the scope of impact. *** ## Best Practices * **Use a dedicated Platform token.** A separate token makes rotation and revocation independent from personal MCP clients. * **Grant only required permissions.** Start with the MCP gateway permissions and the read scopes for the signals your responders use. * **Use a stable service user.** The token inherits its user's permissions. Removing the user or its access can break future queries. * **Rotate through the Dynatrace card.** Submit the replacement token from the connector setup flow. Rootly keeps the existing connection if the new token fails its probe. * **Test a representative query.** After connecting, ask Rootly AI to inspect a known Dynatrace problem or a recent log window. *** ## Troubleshooting Enter only the environment identifier. If your Dynatrace URL is `https://abc12345.apps.dynatrace.com`, enter `abc12345`. Don't paste the full URL or another Dynatrace hostname. Confirm that the token is active and belongs to the same Dynatrace environment. Verify that both the token and its user have `mcp-gateway:servers:invoke` and `mcp-gateway:servers:read`. Check the signal-specific permissions on both the Platform token and its user. For example, log queries require `storage:logs:read`. Dynatrace applies the intersection of token and user permissions. Open the Dynatrace card and connect again with the replacement token. Rootly validates the new token before replacing the saved connection. *** ## Frequently Asked Questions Dynatrace's hosted MCP server does not support public OAuth clients or Dynamic Client Registration. Rootly uses the bearer-token method recommended by Dynatrace for this connection type. No. Rootly applies an allowlist of read and analysis tools. The `create-dql` tool generates query text; it does not create Dynatrace data. Write-capable tools, including event creation and outbound notifications, are excluded even when the Platform token has broader permissions. One Dynatrace AI connector can be active per Rootly team. Connect the environment that contains the observability data used by that team. No. The alert source sends Dynatrace alerts into Rootly. The AI connector lets Rootly AI read Dynatrace context during an investigation. Configure each surface separately. *** ## Related Pages Compare all Rootly AI connectors and setup flows. Configure Dynatrace as an alert source for Rootly. Review connector data handling, retention, and model-training controls. # GitHub AI Connector Source: https://docs.rootly.com/ai/connectors/github Give Rootly AI read-only access to GitHub commits, pull requests, deploys, and file ownership, so investigations can tie an incident to a recent change. ## Overview GitHub is a one-click connector that gives Rootly AI read access to your organization's repositories during investigations. When an incident correlates with a recent deploy or a suspicious code change, Rootly AI can pull the deploy log, the exact commit diff, and the CODEOWNERS entry for the affected files automatically — no responder has to switch tabs. Every query is **read-only**. Rootly AI can inspect commits, PRs, deploys, and file ownership but cannot push code, comment on PRs, or modify anything on the GitHub side. *** ## Before You Start * **A GitHub organization** you have permission to install third-party GitHub Apps on. * **Permission to install the Rootly AI GitHub App** for that organization — GitHub org **Owners** can install directly; other roles need install rights granted by an Owner. *** ## Setup Open **Configuration → AI → Connectors** and click **Connect** on the GitHub card. Sign in to GitHub and install the **Rootly AI GitHub App** for the organization you want to connect — choose **All repositories** for broad coverage, or **Only select repositories** to scope Rootly AI to a specific set. When the install completes, the card flips to **Connected**. *** ## What Rootly AI Can Read * **Deploys** — recent deploy events on connected repositories, including deploy time and target environment. * **Code diffs** — the exact commits that landed in a given time window, per file. * **File ownership** — CODEOWNERS entries so Rootly AI can suggest who owns the code area that broke. * **Pull requests** — recent merged PRs, their descriptions, and their authors. Rootly AI reaches for GitHub when a question is about *"what changed?"* — pairing it with an observability connector (Sentry, Datadog) gives the strongest "what caused this?" signal. *** ## During an Incident *"This error started 8 minutes after a deploy. Here's the diff that likely caused it."* Rootly AI correlates a spike in errors against your recent GitHub deploys, then pulls the exact commit range that landed. During the investigation output, responders see the failing exception paired with the specific line-by-line change that introduced it — and the CODEOWNERS entry for the affected file, so they know who to page. *** ## Best Practices * **Install with broad repo access.** Rootly AI can only see repositories the GitHub App installation covers. Selecting a narrow set of repositories on install means Rootly AI can't find the deploy that caused an incident in an unselected repo — choose **All repositories** unless you have a specific reason to restrict. * **Keep CODEOWNERS current.** Rootly AI leans on CODEOWNERS to suggest owners for affected files. A stale CODEOWNERS file leads to stale owner suggestions. * **Pair with a CI/CD connector.** GitHub tells Rootly AI what changed; a CI connector (Semaphore, or your team's own via [Custom](/ai/connectors/custom)) tells it whether the deploy pipeline succeeded. *** ## Troubleshooting The Rootly AI GitHub App installation doesn't cover those repos. On the GitHub side, open **Settings → GitHub Apps → Rootly AI → Configure**, then either switch to **All repositories** or add the missing repos to the selected list. Rootly AI will pick up the new scope on the next investigation — no reconnect needed. CODEOWNERS may be out of date, or the file isn't covered by any CODEOWNERS pattern. Update the file in your repository; Rootly AI will pick up the new owners on the next investigation. If a GitHub admin uninstalls the Rootly AI GitHub App from the organization, Rootly's card still shows Connected but every query fails. Reconnect from Rootly to reinstall the app. *** ## Frequently Asked Questions No. Every connector is read-only. Rootly AI can read GitHub data but never invoke write actions. Coverage depends on how your GitHub Enterprise instance is reachable. Contact support if you're on a self-hosted GitHub Enterprise Server and want to confirm compatibility. Rootly does not maintain a persistent copy of GitHub data — queries run at investigation time and the response is used in reasoning only. Query results *do* appear in the LLM traces Rootly logs for quality monitoring, as with every tool call Rootly AI makes. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for the retention boundary. *** ## Related Pages All connectors and how they fit together. Pair GitHub with Sentry for the strongest "what caused this?" signal. What Rootly AI sees, retention, and model training controls. # GitLab Source: https://docs.rootly.com/ai/connectors/gitlab Connect Rootly AI to GitLab — merge requests, pipelines, commits, and code diffs during incident investigations. ## Overview Connecting **GitLab** lets Rootly AI look at what shipped before an incident started. When an alert fires shortly after a deploy, Rootly AI can pull the merge requests that landed, the pipelines that ran, and the diffs they contained — without a responder switching to GitLab and piecing the timeline together by hand. Every query is **read-only**. Rootly AI can read merge requests, pipelines, and code but cannot create branches, comment, merge, or trigger pipelines. *** ## Before You Start GitLab serves its MCP endpoint through the **GitLab Duo Agent Platform**, so several things must be in place before Rootly AI can read anything. If any of the Duo or group requirements below are missing, OAuth can still succeed while GitLab queries return nothing. * **A top-level group.** Duo Agent Platform is configured per group. A personal namespace will not work. * **GitLab Duo Agent Platform turned on** for that group, under **Settings → GitLab Duo → Configuration**. * **GitLab Duo Core turned on** — *"Allow users without a GitLab Duo Pro or Enterprise seat to access GitLab Duo Agent Platform features."* * **Experiment and beta features turned on**, under **Feature preview** on the same page. The MCP server is an experimental feature and stays hidden without this. * **At least one project in the group.** MCP will not serve tools against an empty group. * **Permission to authorize third-party applications** on your GitLab account. Works with **GitLab.com and self-managed instances running GitLab 19.2 or later**. A self-managed instance must be reachable by Rootly at a public HTTPS URL. Private and internal-only addresses are blocked. *** ## Setup Go to **AI & Agents → Connectors** and click **Connect** on the **GitLab** card. The instance URL is pre-filled with `https://gitlab.com`. If you self-host, replace it with your instance's base URL — for example `https://gitlab.your-company.com`. For self-managed GitLab, you can leave **OAuth client ID** blank to use dynamic client registration or enter an instance-owned public OAuth application's ID. An explicit client ID is required when your instance disables dynamic registration. To use an explicit client ID, create an instance-owned public OAuth application with the `mcp` scope and this redirect URI: ```text theme={null} https://rootly.com/account/ai/agent/data/remote_mcp_sources/callback ``` Enter its Application ID in **OAuth client ID**. If Rootly support gave you a different Rootly environment, use that environment's base URL with the same `/account/ai/agent/data/remote_mcp_sources/callback` path. You are redirected to GitLab's authorization screen. Sign in if prompted and approve the request. GitLab returns you to Rootly after OAuth succeeds, and the card shows **Connected**. This confirms authorization only; run a GitLab query to verify that the MCP prerequisites above are enabled and projects are available. Rootly AI sees the projects your GitLab account can see. To narrow what it can read, connect with an account whose project access is already scoped appropriately. *** ## What Rootly AI Can Read * **Merge requests** — open and merged MRs, their commits, diffs, pipelines, and discussion notes. * **Pipelines and jobs** — pipeline runs and status, job results, and per-job outcomes for builds around the incident window. * **Code** — individual commits, file contents at a revision, and the repository file tree across connected projects. * **Ownership** — project members and their roles, for *"who owns this?"* * **Work tracking** — issues, work items, labels, and their notes. * **Wikis and search** — project wiki pages and cross-project search. Write tools are excluded from the connection entirely. Rootly AI cannot create issues or merge requests, comment, push branches, or start and cancel pipelines. GitLab is at its most useful for *"what changed right before this broke?"* Pair it with an observability connector: the observability tool shows the symptom, GitLab shows the change that likely caused it. *** ## Best Practices * **Connect with an account scoped to the right projects.** Rootly AI inherits the authorizing account's visibility, so an account with access to every project gives the AI access to every project. * **Use a durable, scoped identity.** Where your GitLab plan supports one, authorize with a service or bot account that has only the project access Rootly AI needs. Otherwise, choose an account with stable group membership so the connector does not stop working when a person changes roles or leaves. * **Keep the authorizing account's access current.** If the account loses access to a project, Rootly AI loses it too — usually surfacing as "no recent merge requests found" rather than an error. * **Pair with your CI connector.** GitLab pipelines cover GitLab CI; if you also run builds elsewhere, connect that tool too so the deploy picture is complete. *** ## Troubleshooting A popup blocker is the usual cause. Allow popups for your Rootly domain and click **Connect** again. Confirm you are signed in to the selected GitLab instance with an account permitted to authorize third-party applications. Some GitLab groups restrict this — a group owner may need to allow it. Almost always a missing prerequisite rather than a broken connection. GitLab returns **404** — not a permission or billing error — when the MCP server is not available to your account, so Rootly shows the card as Connected while nothing works. Re-check every item under **Before You Start**, in particular that experiment and beta features are on and that the group contains at least one project. This can occur when a self-managed instance uses OAuth dynamic client registration. GitLab creates a public client when you connect and may describe it as an *"unverified dynamic application."* GitLab.com uses Rootly's pre-registered public client and should not show this warning. To avoid the warning or when dynamic registration is disabled, configure an instance-owned public OAuth application and enter its Application ID when connecting. Rootly AI only sees what the authorizing account sees. Confirm that account has at least Reporter access to the projects in question, then disconnect and reconnect the card. Supported. Enter your instance's base URL when connecting and Rootly derives the MCP endpoint from it. Your instance must be reachable from Rootly over HTTPS, and the same Duo Agent Platform prerequisites apply on your instance as on GitLab.com. # Google Cloud Source: https://docs.rootly.com/ai/connectors/google-cloud Connect Rootly AI to selected Google Cloud projects for read-only investigations across logs, metrics, alerts, Cloud Run, GKE, and Compute Engine. ## Overview Connecting Google Cloud gives Rootly AI **read-only access** to operational data in the projects you select. During an investigation, Rootly AI can correlate Cloud Logging entries, Cloud Monitoring metrics and alerts, Cloud Run services, Google Kubernetes Engine (GKE) workloads, and Compute Engine instances. The connection uses Google OAuth and Google's managed Model Context Protocol (MCP) servers. Rootly does not ask you to create or paste a service-account key. Authorizing Google establishes which projects the Google identity is allowed to see. The project multi-select in Rootly is a separate boundary: Rootly AI only queries—and, when AI facts ingestion is enabled, ingests facts from—the projects you explicitly select. This AI connector is separate from the [Google Cloud Monitoring alert source](/integrations/google-cloud-monitoring). The alert source sends monitoring events into Rootly; this connector lets Rootly AI read selected Google Cloud projects during investigations. Configure both when you need both behaviors. *** ## Before You Start You'll need: * **A Google account** with read access to the projects you want Rootly AI to investigate. * **MCP Tool User (`roles/mcp.toolUser`)** on each selected project. Google requires this role to call managed MCP tools. * **Google Cloud IAM permissions** for the data you expect Rootly AI to read. OAuth does not grant access that the Google account does not already have. * **At least one active Google Cloud project** selected during setup. For broad investigation coverage, the authorizing identity typically needs read access to Cloud Resource Manager, Cloud Logging, Cloud Monitoring, Cloud Run, GKE, and Compute Engine. Your organization can grant a narrower set if Rootly AI only needs some of those products. See [Google Cloud MCP access control](https://docs.cloud.google.com/mcp/access-control) for Google's current role requirements. Prefer a dedicated Google Workspace user with only the required viewer permissions. A personal account can break the connection when that person leaves the organization or loses project access. *** ## Connecting Open **AI & Agents → Connectors**, find **Google Cloud**, and click **Connect**. Sign in to Google, review the requested read access, and approve the connection. Google returns you to Rootly after authorization. Search the project multi-select and choose up to 50 Google Cloud projects Rootly AI should use. The list contains active projects visible to the Google identity, including each project's display name and project ID. If a visible project is not in the list, enter its exact project ID for Rootly to verify. Save the selection. Rootly verifies the connection. When AI facts ingestion is enabled for your account, Rootly also begins ingesting project facts for the selected projects. Select one or more projects. This selection provides the project scope for investigation tools and bounds optional background fact ingestion when that feature is enabled. OAuth authorization and project selection are independent. Adding another visible project later does not require another OAuth flow. Rootly displays up to 500 discovered projects; for larger organizations, use **Add projects by exact ID** to verify and select projects outside that displayed set. Rootly never treats "all projects visible to this Google account" as permission to crawl them all. Newly created projects and projects granted to the identity later remain unselected until an administrator adds them in Rootly. *** ## What Rootly AI Can Read For the selected projects, Rootly AI can use: * **Cloud Resource Manager** — discover project IDs, names, numbers, folders, and organizations. * **Cloud Logging** — list log names and query entries with filters and time windows. * **Cloud Monitoring** — query time series, metric descriptors, alert policies, and active alerts. * **Cloud Run** — list services and inspect service configuration and status. * **Google Kubernetes Engine** — list clusters, inspect Kubernetes resources, review rollout status and events, and read workload logs. * **Compute Engine** — list instances and inspect basic instance state. All calls use an allowlist of reviewed, read-only tools. Rootly AI cannot create, update, restart, scale, or delete Google Cloud resources. ### Project And Workload Ingestion When AI facts ingestion is enabled, Rootly records selected projects, their organization or folder hierarchy, and Cloud Run services as infrastructure facts. These facts help it resolve human names such as `payments-prod` or `checkout` to the correct Google Cloud resource during an investigation. GKE resources, Compute Engine instances, logs, metrics, and alerts remain on-demand; Rootly does not persist those raw inventories or telemetry as facts. AI facts ingestion availability depends on your Rootly account rollout. If you need to confirm whether it is enabled for your account, contact Rootly Support. Live investigation tools remain available for the selected projects even when background fact ingestion is not enabled. Workload ingestion is bounded by the saved project selection. Removing a project purges the facts authored for that project, stops future ingestion, and prevents it from being used as an investigation-tool scope. It does not revoke the Google identity's IAM access; revoke or narrow that access in Google Cloud when you need an enforcement boundary outside Rootly. *** ## During an Incident You can ask natural questions such as: * *"Why did checkout errors spike in `store-prod` during the last 20 minutes? Correlate logs and request metrics."* * *"Are any Cloud Monitoring alerts firing for the payment service, and what changed in its error logs?"* * *"Is the Cloud Run checkout service healthy in `us-central1`?"* * *"Did the GKE deployment finish rolling out, and are its pods restarting?"* * *"Which Compute Engine instances in this project are stopped or unhealthy?"* If a project name is ambiguous, Rootly AI uses discovered project facts to resolve it or asks you to choose among the selected projects. *** ## Adjusting Project Scope Go to **AI & Agents → Connectors** and click **Configure** on the Google Cloud card. Add or remove projects in the multi-select. Rootly only shows active projects currently visible to the connected Google identity. Save the selection. Added projects become available for investigations and, when AI facts ingestion is enabled, background refreshes. Removed projects are excluded from future queries and refreshes. If Google definitively reports that a selected project is no longer visible, Rootly blocks live calls to that project and purges the facts it authored for that project. If other selected projects remain visible, the connection stays available. If none remain visible, the connector requires reconfiguration. Transient discovery failures do not replace the last successful fact snapshot with an empty inventory. *** ## Best Practices * **Select only operational projects Rootly AI needs.** Do not select sandbox, personal, or unrelated projects merely because the identity can see them. * **Use least-privilege viewer roles.** Grant read access only to the Google Cloud products needed for investigations. * **Use a stable identity.** A dedicated Google Workspace user avoids coupling the OAuth connection to an employee lifecycle. * **Separate environments deliberately.** Select production and staging only when responders need both, and use clear project display names so questions resolve predictably. * **Review project scope after organization changes.** Migrations between folders or organizations can change inherited IAM access. * **Audit access in Google Cloud.** Google Cloud audit logs remain the authoritative record of API calls and IAM changes. *** ## Troubleshooting Rootly displays at most 500 projects. First enter the exact project ID in **Add projects by exact ID**; Rootly verifies it before saving. If verification fails, confirm the project is active, appears for the same identity in Google Cloud Console, and grants the identity Resource Manager visibility and `roles/mcp.toolUser`. OAuth completed, but Rootly could not discover all required managed MCP tools or make a read call. Check that the required Google Cloud APIs are available to the identity, then reconnect. Organization policies that block OAuth applications can also prevent verification. Google Cloud IAM is product-specific. The identity may be able to discover the project but lack viewer access to Logging, Monitoring, Cloud Run, GKE, or Compute Engine. Test the same resource with that identity in Google Cloud Console and add only the missing viewer permissions. Open **Configure**. Rootly identifies previously selected projects that are no longer visible so you can save a repaired scope. If access was removed accidentally, restore IAM permissions first and reopen the connector. Rootly does not use the loss of access as a signal to crawl a different project. Reconnect Google Cloud and select the projects again. Password changes normally do not revoke OAuth by themselves, but account suspension, administrator revocation, or removal of IAM access does. *** ## Frequently Asked Questions Yes. One OAuth connection can authorize access to multiple projects. Rootly's multi-select stores the subset that Rootly AI may use during investigations and, when enabled, background fact ingestion. No. Project selection only narrows Rootly's behavior. Google Cloud IAM controls what the connected identity can access, and Rootly cannot expand that access. No. Even if the Google identity can see a newly created project, a Rootly administrator must explicitly add it to the connector's project selection. Not currently. The connector uses Google user OAuth and does not accept uploaded service-account JSON keys. Use a dedicated Google Workspace user with least-privilege access when you need an identity that is independent of an individual responder. Yes. Rootly exposes only reviewed read tools from Google's managed MCP servers. It does not expose mutation tools or use the connection to alter resources. Disconnect the Google Cloud card in Rootly to remove the stored OAuth credentials, stop ingestion, and delete the Google Cloud facts authored by this connector, including selected project, hierarchy, and Cloud Run service facts. Historical investigation context remains unchanged. For defense in depth, also revoke Rootly's OAuth access from the Google account or your Google Workspace administrator controls. *** ## Related Pages The full list of connectors and how they fit together. What Rootly AI sees, retention, and model-training controls. Send Google Cloud Monitoring alerts into Rootly for routing and response. Google's reference for managed MCP products and tools. # Grafana Cloud Source: https://docs.rootly.com/ai/connectors/grafana-cloud Connect Rootly AI to your Grafana Cloud stack — metrics, logs, dashboards, and alerts — with a single-field setup. ## Overview Connecting **Grafana Cloud** lets Rootly AI query your Grafana Cloud stack during investigations — pulling metrics, logs, profiles, dashboards, and alerts. You provide your stack URL, authorize Rootly AI in Grafana's consent screen, and the integration is live. If you self-host Grafana instead of using Grafana Cloud, use the [Grafana Managed integration](/ai/connectors/grafana-managed). This page is only for the managed Grafana Cloud offering. *** ## Before You Start You'll need: * **A Grafana Cloud account** with permission to authorize third-party apps against your stack. * **Your Grafana Cloud stack URL** — the base URL of your stack (for example, `https://your-stack.grafana.net`). Find it by logging in to Grafana Cloud and copying the URL of the main dashboard. That's it. No API keys, no service accounts, no self-hosted infrastructure. *** ## Connecting Open **Configuration → AI → Connectors** and click **Connect** on the Grafana Cloud card. Your stack's base URL. Must be a Grafana Cloud-hosted URL (`*.grafana.net`). ```text theme={null} https://your-stack.grafana.net ``` Click **Save**. Rootly redirects to Grafana's authorization page — sign in to Grafana Cloud (if not already signed in), review the requested access, and click **Authorize Rootly AI**. Grafana sends you back to Rootly, and the card flips to **Connected**. *** ## What Rootly AI Can Read Once connected, Rootly AI can query your Grafana Cloud stack for: * **Metrics** from any Prometheus-compatible data source connected to Grafana Cloud (including Grafana Cloud's own Prometheus). * **Logs** from Loki data sources. * **Traces** from Tempo data sources. * **Dashboard configurations** — Rootly AI can look up which dashboards exist and read their panel queries. * **Alerts and alert rules** — including firing state, alert history, and rule definitions. * **Profiles** from Pyroscope data sources (if attached to your stack). Rootly AI can only see data your authorizing Grafana Cloud user has access to. If you have Team-scoped folders in Grafana, Rootly AI's read access matches your team membership. ## During an Incident *"The checkout-api 5xx rate jumped from 0.2% to 4%. Here's the Prometheus query and dashboard."* Rootly AI queries your Grafana Cloud stack — metrics from Prometheus-compatible sources, logs from Loki, traces from Tempo — and cites the specific query, panel, or dashboard in the investigation output. Responders see the exact signal Grafana was showing at the moment the incident started. *** ## Best Practices * **Authorize with a service-oriented account, not a personal one.** If a personal Grafana account leaves your organization, the integration breaks silently. A shared service-oriented account (or an admin account with stable membership) survives staff turnover. * **Review the requested access before authorizing.** Grafana's consent screen shows exactly what Rootly AI is asking for. If any request looks broader than needed, don't authorize — reach out to Rootly support first. * **Reconnect after Grafana stack migrations.** If you migrate to a new Grafana Cloud stack, the old integration still references the old stack. Disconnect and reconnect against the new stack URL. * **Test with `/rootly test`.** Declare a test incident after connecting and confirm Rootly AI can pull Grafana signals during the investigation. *** ## Troubleshooting Two common causes: (1) your Grafana Cloud account doesn't have permission to authorize third-party apps — check with a Grafana admin; (2) the stack URL you entered doesn't match a valid Grafana Cloud stack — verify it ends in `.grafana.net` and that you can log in to it directly in a browser. The authorization is valid but your Grafana user's role doesn't include read access to whatever Rootly AI is querying. Grafana Cloud enforces role-based access per data source — check your role in Grafana's team/permissions settings. Data-source-level access. Even with the right Grafana role, some data sources (especially Team-scoped folders) require explicit permissions. Verify by logging in to Grafana as the same user and running the query directly — if you see the same empty results, the data-source access is the issue. Grafana Cloud plans include different data-source quotas and integration access. If you downgraded a plan and Rootly AI's integration is now off your plan, queries return errors. Check your plan's inclusions in Grafana Cloud settings. *** ## Frequently Asked Questions No. Grafana Cloud is fully managed — you don't run anything. Only the Grafana Managed integration requires you to deploy any additional piece yourself. One Grafana Cloud stack per Rootly team currently. If you operate multiple stacks, connect the one that hosts most of your observability signals. Multi-stack support is on the roadmap. The authorization refreshes automatically as long as the underlying Grafana Cloud user account remains active and you haven't revoked Rootly AI from the Grafana side. If either happens, the integration fails on the next query and needs re-authorization. Yes. Rootly AI's queries count as normal Grafana API calls against your plan's quotas. Investigation-driven volume is low in practice — a few queries per investigation. Yes. Grafana Cloud's audit logs record all API activity, including calls made by third-party apps. Filter by Rootly AI to see the full history. *** ## Related Pages The full list of Connectors and how they fit together. The self-hosted-Grafana counterpart. Grafana Labs' own documentation for Grafana Cloud. # Grafana Managed Source: https://docs.rootly.com/ai/connectors/grafana-managed Connect Rootly AI to your self-hosted Grafana so it can query metrics, logs, dashboards, and alerts during investigations. ## Overview Connecting **Grafana Managed** lets Rootly AI query your self-hosted Grafana instance during investigations — pulling metrics, logs, profiles, dashboards, and alerts. Every query uses a Grafana **service-account token** you provide, so Rootly AI can only see what that service account can see. If your team is on **Grafana Cloud** (the managed offering), use the [Grafana Cloud integration](/ai/connectors/grafana-cloud) instead — it's a simpler setup with no self-hosted server to manage. *** ## Before You Start You'll need three things ready before opening the connection modal: * **A running `mcp-grafana` server** with a **public HTTPS URL** that Rootly can reach. Private-network-only addresses (VPN-only, VPC-internal, `localhost`, RFC1918 IPs) are not accepted. * **Your Grafana instance URL** — the base URL of your self-hosted Grafana (for example, `https://grafana.your-company.com`). * **A Grafana service-account token** with read access to whatever data you want Rootly AI to query — metrics, logs, dashboards, alerts. Generate it from Grafana → Administration → Service accounts. Public HTTPS endpoints only. Private-IP addresses (10.x, 172.16–31.x, 192.168.x), `localhost`, `.internal` domains, and other non-routable addresses are refused at save time. If you need Rootly-only access, allow-list Rootly AI's outbound IPs at your load balancer instead of using a private address. *** ## Connecting In Rootly Open **Configuration → AI → Connectors** and click **Connect** on the Grafana Managed card. The public HTTPS endpoint of your `mcp-grafana` deployment. ```text theme={null} https://mcp-grafana.your-company.com/mcp ``` Must be a valid, publicly reachable HTTPS URL. Your Grafana's base URL — the address you'd type in a browser to open Grafana. ```text theme={null} https://grafana.your-company.com ``` A Grafana service-account token with read access to the data Rootly AI will query — metrics, logs, dashboards, alerts. Create it from **Grafana → Administration → Service accounts → Add service account → Add service account token**. Click **Save**. Rootly runs a quick check to confirm the connection works. If everything's set up correctly the card flips to **Connected** and Rootly AI can start querying Grafana. Common save-time errors: * **"Rootly couldn't reach that mcp-grafana URL. It must be a public HTTPS endpoint — private or internal-only addresses are blocked."** — the URL is a private IP, `localhost`, or an internal-only domain. Expose `mcp-grafana` on a public HTTPS endpoint and retry. * **"Rootly reached the server but the connection failed."** — the URL is reachable but something else is wrong. Check that `mcp-grafana` is running, that the Grafana instance URL is correct, and that the service-account token has adequate permissions. *** ## During an Incident *"The checkout-api 5xx rate jumped from 0.2% to 4%. Here's the Prometheus query and dashboard."* Rootly AI queries your self-managed Grafana — metrics, logs, dashboards, alerts — and cites the specific query or panel in the investigation output. Responders see the exact signal Grafana was showing at the moment the incident started, without leaving Rootly. *** ## Best Practices * **Use a dedicated service-account token, not a personal API key.** Service accounts are stable across staff turnover and have their own audit trail in Grafana. Name the service account something obvious like `rootly-ai` so it's easy to identify in Grafana's audit log. * **Scope the service-account token to the minimum roles Rootly AI needs.** Read access to metrics, logs, and dashboards is usually enough. If Rootly AI doesn't need to see alert configurations, don't grant the alerts role. * **Rotate the service-account token on a cadence.** Rotate on the same schedule as your other API tokens (quarterly is common). After rotating, paste the new token into Rootly's Configure screen — the connection is re-verified on save. * **Test with `/rootly test`.** After connecting, declare a test incident and see whether Rootly AI can pull Grafana data during the investigation. If it can't, catch it in test before a real incident. * **Consider Grafana Cloud if you're on the managed offering.** Grafana Cloud's integration doesn't require you to run and maintain the extra piece yourself. Only stick with the self-hosted Grafana Managed connector if you specifically need to run Grafana yourself. *** ## Troubleshooting The URL isn't a valid public HTTPS endpoint. Common causes: * Private IP (`10.x`, `172.16-31.x`, `192.168.x`) — not accepted. * `localhost` or `127.0.0.1` — not accepted. * Internal-only domain that doesn't resolve from Rootly's network. * Self-signed TLS certificate. Deploy behind a public HTTPS endpoint with a valid TLS certificate, then retry. If your compliance model requires network-layer restriction, allow-list Rootly's outbound IPs instead of blocking the endpoint entirely. Reachability is fine, but something else in the connection didn't succeed. Check in this order: 1. Is `mcp-grafana` actually running behind the URL? 2. Is the Grafana instance URL correct and reachable from `mcp-grafana`? 3. Does the service-account token have adequate Grafana permissions? (Test the token directly against Grafana's API.) The service-account token is authenticating but doesn't have permission to see the data being queried. Broaden the service account's roles in Grafana (or its data-source-level permissions) and retry. Something changed on the Grafana side after the initial save. Common causes: the service-account token was revoked or rotated, `mcp-grafana` was redeployed with a different config, the Grafana instance URL changed. Open the Configure screen and re-save. Rootly AI queries whatever dashboards the service-account token can see. If you have multiple Grafana instances or environments, verify that the instance URL you connected is the one you want Rootly AI to reference (for example, production Grafana, not a staging clone). *** ## Frequently Asked Questions **Grafana Cloud** connects to Grafana Labs' managed offering. One field to configure — a stack URL — and Grafana handles the rest. **Grafana Managed** connects to your self-hosted Grafana. Three fields to configure and you're responsible for running the `mcp-grafana` server that Rootly points at. Pick Grafana Cloud if you're on the managed offering; Grafana Managed if you self-host. Yes — you can point multiple Rootly teams at the same `mcp-grafana` deployment. Each team's service-account token controls what that team's Rootly AI can see. No. Every Rootly AI query reads from Grafana fresh. Grafana's own caching (dashboard query results, alert state) still applies on the Grafana side. Rootly's cloud infrastructure needs a route to reach the server. A VPN-only or private-network-only address isn't reachable from Rootly. If you need to keep the endpoint off the open internet, the standard pattern is a public HTTPS endpoint with IP allow-listing at the load balancer — allow Rootly's outbound IP ranges and deny everything else. Contact support for the current IP allow-list. Rootly AI's Grafana call fails and it moves on with whatever context it already has. The investigation isn't blocked — you just lose Grafana signal for that specific investigation. Once Grafana is back, the next investigation will query it normally. *** ## Related Pages The full list of Connectors and how they fit together. The managed-Grafana counterpart — no self-hosted server required. Grafana Labs' own reference for service accounts, roles, and mcp-grafana deployment. # Honeycomb AI Connector Source: https://docs.rootly.com/ai/connectors/honeycomb Connect Rootly AI to Honeycomb — traces, metrics, logs, BubbleUp investigations, Triggers, and SLOs — with a region selection and one OAuth authorization. ## Overview The **Honeycomb** connector lets Rootly AI query your Honeycomb environments during an investigation. Honeycomb is where high-cardinality trace data lives, so this is the connector that answers *"which specific requests are failing, and what do they have in common?"* — the question raw dashboards usually can't. Setup is a region selection followed by an OAuth authorization. There is no API key to create or paste. Rootly AI's access is **read-only**. It authorizes with a read scope and can query your Honeycomb data but never create, modify, or delete Triggers, SLOs, or environments. *** ## Before You Start An account with access to the environments you want Rootly AI to query. Rootly AI inherits the read access of whoever authorizes the connection. Honeycomb runs separate US and EU instances and your data lives in exactly one. You'll pick this during setup, and picking the wrong one means Rootly AI authorizes against an instance that doesn't hold your environments. Connecting a data source requires the permission to manage AI connectors on your Rootly account. If the **Connect** button is unavailable, ask a Rootly admin. If you're not sure which region you're on, check the URL you use to sign in to Honeycomb. EU accounts sign in on a `eu1` host; US accounts don't. *** ## Connecting Go to **Configuration → AI → Connectors** and click **Connect** on the **Honeycomb** card. The **Connect Honeycomb** dialog opens. Pick **US** for environments hosted in the US region, or **EU** for environments hosted in the EU region. This is required — the dialog won't submit without a selection. Rootly redirects you to Honeycomb's authorization screen. Sign in if prompted and grant access. Rootly requests a read-only scope. Back on the Connectors page, the Honeycomb card shows **Connected** with **Configure** and **Disconnect** actions. Rootly AI can now query Honeycomb during investigations. *** ## What Rootly AI Can Read | Signal | What it answers during an investigation | | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------- | | **Traces** | Which requests are slow or failing, and where in the call path the time or error originates | | **Metrics** | Rate, error, and duration trends across the window around the incident | | **Logs** | Individual events with their full attribute set, not just aggregate counts | | **BubbleUp** | What the failing requests have in common that the healthy ones don't — the specific customer, region, build, or endpoint driving the anomaly | | **Triggers** | Which Honeycomb Triggers fired, and when, relative to the incident timeline | | **SLOs** | Current SLO compliance and remaining error budget for the affected service | Rootly AI can read across the full range of Honeycomb queries rather than a fixed subset, and reaches for whichever read the current question needs. *** ## During an Incident *"Checkout latency is concentrated in one trace pattern. BubbleUp shows 94% of the slow requests share build `a3f21c` and the `eu-west-1` region — the other regions on the previous build look normal."* Honeycomb earns its place in an investigation when the question is *which* requests are affected rather than *how many*. Error-rate dashboards tell you something is wrong; trace data plus BubbleUp tells you the failures all share one deploy, one region, or one customer tier — which is usually the fastest path to a cause. *** ## Best Practices * **Connect Honeycomb alongside a deploy source.** Honeycomb tells you the failing requests share a build; [GitHub](/ai/connectors/github) tells you what was in that build. The pair answers "what changed" far faster than either alone. * **Authorize with an account that can see every relevant environment.** Rootly AI inherits the authorizing user's read access. Authorize from an account scoped to one team's environment and investigations will silently miss the rest. * **Keep your Triggers meaningful.** Rootly AI reads which Triggers fired and treats that as signal. Noisy Triggers that fire constantly reduce how much that signal is worth. * **Reconnect after an account change.** The authorization is tied to the user who granted it. When that person leaves or their Honeycomb access is reduced, reconnect from another account rather than leaving a connection that quietly returns less data. *** ## Troubleshooting The region field is required and the dialog rejects a submission without it. Select **US** or **EU** and submit again. Almost always the wrong region. A US-region authorization against an EU account connects cleanly — the OAuth flow succeeds — but Rootly AI is then querying an instance that holds none of your environments. Disconnect, reconnect, and pick the other region. Check the host you use to sign in to Honeycomb if you're unsure. Rootly AI inherits the read access of the account that authorized the connection. If that account can only see a subset of your Honeycomb environments, so can Rootly AI. Reconnect from an account with broader read access. Usually a popup blocker or an existing Honeycomb session in a different account. Allow popups for Rootly, or sign out of Honeycomb in that browser and retry so you can authorize with the intended account. If someone revoked Rootly's authorization on the Honeycomb side, the card can still read **Connected** while every query fails. Disconnect and reconnect to establish a fresh authorization. *** ## Frequently Asked Questions No. Setup is a region selection plus an OAuth authorization — there's no key to create, paste, or rotate. No. The connector authorizes with a read-only scope. Rootly AI can query traces, metrics, logs, Triggers, and SLOs, but cannot create or modify Triggers, SLOs, or any other Honeycomb object. One Honeycomb connection is active per team. If your data spans both regions, connect the one your incident-relevant environments live in and contact support about the other. They answer different questions. Datadog and Grafana are strongest on aggregate metrics and dashboards — *how bad is it, and since when*. Honeycomb is strongest on high-cardinality trace data — *which requests specifically, and what do they share*. Teams that run both connect both. Rootly doesn't keep a persistent copy of your Honeycomb data — queries run at investigation time and the response is used in reasoning only. Query results *do* appear in the LLM traces Rootly logs for quality monitoring, as with every tool call Rootly AI makes. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for the retention boundary. *** ## Related Pages All connectors and how they fit together. Pair with Honeycomb to tie a failing trace pattern back to the deploy that caused it. What Rootly AI sees, retention, and model training controls. # LaunchDarkly Source: https://docs.rootly.com/ai/connectors/launchdarkly Give Rootly AI read-only access to LaunchDarkly flags, targeting rules, and audit logs with one-click OAuth, to rule a recent flag change in or out fast. ## Overview LaunchDarkly is a one-click **OAuth** connector that gives Rootly AI read access to the LaunchDarkly projects your account can see. When an incident correlates with a recent flag change (which they very often do), Rootly AI can pull the flag's current targeting, its recent audit history, and the exact change that landed just before the incident started — all automatically. Every query is **read-only**. Rootly AI can inspect flags, targeting rules, and audit logs but cannot toggle flags, change targeting, or modify anything on the LaunchDarkly side. *** ## Before You Start * **A LaunchDarkly account** with permission to authorize third-party integrations for your organization. * **Read access** on the LaunchDarkly projects and environments you want Rootly AI to be able to see — Rootly AI inherits the authorizing user's read scope. *** ## Setup Open **Configuration → AI → Connectors** and click **Connect** on the LaunchDarkly card. Sign in to LaunchDarkly and authorize Rootly AI. The connection covers every project and environment the authorizing LaunchDarkly user can read — there's no per-project scope inside the OAuth flow. When authorization completes, the card flips to **Connected**. *** ## What Rootly AI Can Read * **Flags** — flag names, descriptions, and current state across environments. * **Targeting** — the current targeting rules per flag per environment. * **Audit logs** — the history of flag changes, including who changed what and when. * **Environments** — the list of environments in the project (production, staging, etc.). Rootly AI reaches for LaunchDarkly hard on the *"what changed in the last hour?"* question. Feature-flag flips are a top cause of incidents, and having the flip history in the investigation output means responders can rule it in or out immediately. *** ## During an Incident *"A feature flag flipped 3 minutes before the spike. Here's the change."* Rootly AI correlates the incident's start time against LaunchDarkly's audit log. When a flag flip lands in the window right before the incident, Rootly AI surfaces the flag name, the exact change (targeting rule diff, rollout percentage, environment), and who flipped it. Feature-flag flips are a top cause of incidents; catching them in the first minute of the investigation cuts triage time meaningfully. *** ## Best Practices * **Include a description on every flag.** Rootly AI cites flags by name and description; a well-described flag makes the investigation output actually useful. * **Use meaningful audit log messages when flipping flags.** LaunchDarkly's audit log captures the comment attached to a change — a good comment ("emergency disable — payment failures on checkout") means Rootly AI can explain *why* the flip happened, not just that it happened. * **Pair with a code connector.** LaunchDarkly tells Rootly AI which flags changed; GitHub tells it whether the flag references correspond to code that shipped. Together they're the strongest "was this deploy vs a flag flip?" signal. *** ## Troubleshooting The authorizing LaunchDarkly user doesn't have read access to those projects — Rootly AI inherits that user's LaunchDarkly permissions. Either grant the user read access on the missing projects, or reconnect from a LaunchDarkly account that already has broader coverage. Either the flag is in an environment or project the connector can't read, or its name has changed recently and the previous name is being cached in the investigation prompt. Confirm the flag key in LaunchDarkly matches what you're asking about. If a LaunchDarkly admin revokes the Rootly AI OAuth grant from LaunchDarkly's side, Rootly's card still shows Connected but every query fails. Reconnect from Rootly to reauthorize. *** ## Frequently Asked Questions No. Connectors are read-only. Rootly AI can inspect flag state and history but cannot invoke write actions. Coverage depends on how your LaunchDarkly instance is reachable. Contact support to confirm compatibility with Federal or dedicated deployments. Rootly does not maintain a persistent copy of LaunchDarkly data — queries run at investigation time and the response is used in reasoning only. Query results *do* appear in the LLM traces Rootly logs for quality monitoring, as with every tool call Rootly AI makes. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for the retention boundary. *** ## Related Pages All connectors and how they fit together. Pair LaunchDarkly with GitHub to answer "was this a flag flip vs a deploy?" What Rootly AI sees, retention, and model training controls. # Linear AI Connector Source: https://docs.rootly.com/ai/connectors/linear Give Rootly AI read-only access to Linear issues, projects, and roadmaps with one-click OAuth, so investigations can correlate incidents with recent work. ## Overview Linear is a one-click connector that gives Rootly AI read access to your Linear workspace during investigations. When an incident correlates with recent engineering work, Rootly AI can pull related issues, project context, and roadmap items automatically — useful for surfacing "was this already flagged?" or "who owns this area?" Every query is **read-only**. Rootly AI can search and read issues, projects, and roadmaps but cannot create, comment on, or edit anything on the Linear side. *** ## Before You Start * **A Linear workspace** with permission to authorize third-party OAuth apps. * **Read access** to the teams and projects you want Rootly AI to be able to see. *** ## Setup Open **Configuration → AI → Connectors** and click **Connect** on the Linear card. Sign in to Linear and authorize Rootly AI for the workspace you want to connect. When the flow completes, the card flips to **Connected**. *** ## What Rootly AI Can Read * **Issues** — active and completed issues, filterable by team, project, assignee, or label. * **Projects** — project titles, descriptions, status, and the issues within them. * **Roadmaps** — the higher-level roadmap items that group projects together. * **Comments and history** — the discussion thread on an issue. Rootly AI reaches for Linear when a question is about *"who owns this?"* or *"was this already flagged?"* — pair it with an observability connector (Sentry, Datadog) to link the incident's symptom to the tracked work. *** ## During an Incident *"There's an active project tracking the migration involved here. Current status and owner attached."* Rootly AI searches Linear for related issues and roadmap items when the incident touches ongoing work. If a migration, refactor, or planned change is already tracked, responders see the project link, current status, and owner in the investigation output — useful for figuring out whether the current incident is a symptom of known in-progress work. *** ## Best Practices * **Authorize at the workspace level.** Restricting the connector to one team means Rootly AI can't see cross-team incidents, which is exactly the case where knowing about related work matters most. * **Keep issue titles descriptive.** Linear's search ranks by title. Clear titles help Rootly AI surface the right related issue, not just any related one. * **Pick one work tracker per team.** Rootly AI supports both Linear and Atlassian (Jira). Connecting both when your team only uses one adds a source that never fires and clutters investigation output. *** ## Troubleshooting The authorizing Linear user doesn't have access to those teams. Confirm the account has the right team memberships, then disconnect and reconnect to refresh the OAuth grant. Linear search returns both open and closed issues. If a closed issue is being cited over the current work, ensure the current issue has stronger title/label signal or update the closed one so it stops being the top match. If a Linear admin revokes the Rootly AI OAuth grant from Linear's side, Rootly's card still shows Connected but every query fails. Reconnect from Rootly to reauthorize. *** ## Frequently Asked Questions Whichever your team actually uses. Rootly AI can query both, but connecting both when only one is used in practice adds a source that never returns useful signal. No. Connectors are read-only. To create Linear issues from an incident, use the existing [Linear integration](/integrations/linear/linear) — that's a separate configuration. Rootly does not maintain a persistent copy of Linear data — queries run at investigation time and the response is used in reasoning only. Query results *do* appear in the LLM traces Rootly logs for quality monitoring, as with every tool call Rootly AI makes. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for the retention boundary. *** ## Related Pages All connectors and how they fit together. The alternative work-tracking connector — covers Jira and Confluence. What Rootly AI sees, retention, and model training controls. # Metabase AI Connector Source: https://docs.rootly.com/ai/connectors/metabase Connect Rootly AI to Metabase so investigations can search your semantic layer and run current, permission-scoped analytics queries. ## Overview The **Metabase** connector gives Rootly AI read-only, on-demand access to the analytics context your responders already use. During an investigation, Rootly AI can search Metabase tables and metrics, inspect metadata, construct a structured query, and run it against your connected data sources. That makes business and operational questions available alongside incident context. For example, Rootly AI can answer *"How many customers are affected in this region?"* or *"Did checkout volume change when the errors began?"* using current Metabase results. Rootly does not ingest Metabase dashboards, questions, metadata, or query results into its persistent AI facts graph. The connector queries Metabase only when an investigation needs the context, so Metabase remains the source of truth and results do not become stale copies. Access is scoped to the Metabase user who authorizes the connection. Rootly AI can only discover and query content that person can access in Metabase. *** ## Before You Start You need: * A public Metabase instance reachable over HTTPS. * An administrator to enable **AI features** and the **MCP server** under **Admin → AI → MCP** in Metabase. * A Metabase user who can authorize the connection and has access to the databases, tables, metrics, and collections Rootly AI should query. * Permission in Rootly to manage AI connectors. Metabase serves its MCP endpoint at `/api/metabase-mcp`. You can enter either your instance URL, such as `https://metabase.example.com`, or the complete endpoint, such as `https://metabase.example.com/api/metabase-mcp`. Rootly normalizes both forms to the complete endpoint. Rootly requests these Metabase OAuth scopes: * `agent:query` * `agent:query:construct` * `agent:query:execute` * `agent:resource:read` * `agent:search` These scopes support only the reviewed metadata and structured-query tools listed below. Rootly does not request Metabase content-management or raw-SQL access. Use a narrowly scoped Metabase account. The OAuth grant carries that user's Metabase permissions, so connecting with a broadly privileged administrator exposes correspondingly broad analytics context to Rootly AI. If a self-hosted instance must be restricted at the network layer, expose it through a public HTTPS load balancer, allow-list Rootly AI's outbound IP ranges, and deny other traffic. Contact Rootly support for the current outbound IP allow-list. *** ## Setup Go to **Configuration → AI → Connectors** and click **Connect** on the **Metabase** card. Enter the public HTTPS URL for your Metabase instance or its complete `/api/metabase-mcp` endpoint, then continue. Rootly discovers Metabase's OAuth endpoints, registers as a client, and redirects you to a Metabase consent page. Sign in as the user whose permissions Rootly AI should use, review the requested access, and click **Authorize**. After Metabase redirects back, Rootly validates the token by discovering the approved tool catalog. The card shows **Connected** only after that validation succeeds. Rootly uses OAuth 2.0 with Dynamic Client Registration and PKCE. You do not need to create or paste an API key, client ID, or client secret. *** ## What Rootly AI Can Query Rootly exposes five read-only Metabase tools: | Tool | What it does | | ----------------- | --------------------------------------------------------------------------------------------------------------------------------- | | `search` | Finds tables and metrics with keyword or natural-language search. | | `read_resource` | Reads metadata for resources such as databases, schemas, tables, fields, metrics, models, questions, dashboards, and collections. | | `construct_query` | Builds a structured query against a table or metric and returns an opaque query handle. | | `execute_query` | Runs a previously constructed query and returns its results and column metadata. | | `query` | Runs a structured query or continues through a paginated result set. | Rootly does **not** expose Metabase's content-creation, update, deletion, raw SQL, or interactive visualization tools. The connector cannot create questions or dashboards, update Metabase content, or invoke `execute_sql`. Metabase metadata makes the connector more useful. Clear table and field names, descriptions, semantic types, verified models, and curated metrics help Rootly AI select the right source and construct better queries. *** ## Data Handling and Permissions * **On-demand only.** Rootly AI calls Metabase during an investigation or direct question; it does not run a background ingestion job. * **No persistent Metabase facts.** Rootly does not copy dashboards, questions, metadata, or query results into the AI facts graph. * **Metabase permissions apply.** Search, resource reads, and query execution run as the user who approved the OAuth grant. * **Read-only tool allowlist.** Rootly exposes only the five reviewed tools above, even if Metabase advertises additional tools later. * **Encrypted credentials.** OAuth credentials are encrypted at rest and scrubbed when the connection is disconnected or replaced. * **AI traces may contain results.** Connector responses can appear in Rootly AI's model and observability traces. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for retention details. *** ## Managing the Connection Open the Metabase card to reconnect or disconnect it. A Rootly team has one active Metabase connection. When you reconnect with a different URL or Metabase user, Rootly validates the new OAuth grant and tool catalog before replacing the working connection. If validation fails, the existing connection remains available. Disconnecting removes the stored OAuth credentials and prevents future Metabase queries. It does not change or delete anything in Metabase. *** ## Troubleshooting Confirm the URL is public HTTPS and that it resolves to your Metabase instance. Private addresses, `localhost`, embedded credentials, query strings, fragments, and unrelated URL paths are rejected. In Metabase, verify that **AI features** and **Admin → AI → MCP → Enable MCP server** are both enabled. Rootly validates the connection by listing Metabase's MCP tools after the redirect. Confirm that `/api/metabase-mcp` is reachable from the public internet and that your Metabase Site URL matches the public address. A reverse proxy that blocks the MCP endpoint or OAuth metadata endpoints can also cause validation to fail. The authorizing user's Metabase permissions control what Rootly can see. Sign in to Metabase as that user and confirm the resource is visible. If a different account should supply the connection, reconnect and authorize as that account. The OAuth grant may have been revoked or the user's Metabase access may have changed. Review **Admin → AI → MCP → Authorizations** in Metabase, then reconnect the Rootly connector to issue a fresh grant. Rootly AI calls connectors only when the current question needs them. Try asking a question that explicitly names the relevant Metabase metric, table, dashboard, or business measure. Also confirm that the authorizing user can access it. *** ## Related Pages Browse all Rootly AI connectors and how investigations use them. Review encryption, retention, trace handling, and model controls. Configure and audit the MCP server in Metabase. # New Relic AI Connector Source: https://docs.rootly.com/ai/connectors/new-relic Connect Rootly AI to New Relic — entities, NRQL queries, alerts, incidents, logs, and golden metrics — with OAuth or a user API key. ## Overview Connecting **New Relic** lets Rootly AI analyze New Relic data during investigations. Once connected, Rootly AI can look up entities, run NRQL queries, inspect alerts and incidents, tail logs, and read golden signals. OAuth is the recommended authentication method. A New Relic user API key (starts with `NRAK`) is available as a fallback. *** ## Before You Start You'll need: * **A New Relic user account** with access to every account and entity Rootly AI should investigate. * **An Organization Manager** who can review Feature Control Manager settings. * **New Relic MCP Server** activated in Feature Control Manager. * **Local Clients** activated for OAuth connections. * **API keys** activated only if you use the API-key fallback. * **Your account's region** — US, Europe, or Japan. * **For the API-key fallback:** a New Relic user API key created from **API Keys → Create a key → User**. The key starts with `NRAK`. To open Feature Control Manager, select your user name in the lower-left corner of New Relic, then select **Plan Management → Feature Control**. See New Relic's [Feature control manager documentation](https://docs.newrelic.com/docs/accounts/accounts-billing/new-relic-one-user-management/feature-control-manager/) for access requirements and activation steps. Rootly uses New Relic's hosted MCP server and exposes a curated read-only tool set. OAuth does not require you to create or paste an API key. If you use the fallback, Rootly requires a **user** API key, not an ingest key or a license key. *** ## Connecting Open **Configuration → AI → Connectors** and click **Connect** on the New Relic card. Match your New Relic account's hosting region: * **US / North America** — for accounts on `one.newrelic.com`. * **Europe** — for accounts on `one.eu.newrelic.com`. * **Japan** — for accounts on `one.jp.newrelic.com`. New Relic's [data center guide](https://docs.newrelic.com/docs/accounts/accounts-billing/account-setup/choose-your-data-center/) lists the same login hosts and regional availability. Selecting the wrong region will cause the connection to fail even with valid authorization. Click **Connect with OAuth**. Rootly opens a popup for New Relic authorization. Sign in if prompted and approve Rootly. Keep the Rootly page open while authorization completes. If no popup opens, allow popups for your Rootly domain and try again. Expand **Use a user API key instead**, paste a New Relic user key that starts with `NRAK`, and click **Connect with API key**. ```text theme={null} NRAK-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX ``` Create it from **API Keys → Create a key → User type** in your New Relic account. Rootly exchanges the OAuth grant or validates the API key, confirms the hosted MCP server exposes the required read tools, and then marks the card **Connected**. A failed reconnect leaves the previous working connection unchanged. Rootly only replaces an existing New Relic connection after the new authorization and MCP tool probe both succeed. *** ## What Rootly AI Can Read Once connected, Rootly AI can query New Relic for: * **Entities** — services, hosts, applications, and other New Relic entity types in your account. * **NRQL queries** — Rootly AI can compose and run NRQL against your data (metrics, events, logs, spans). * **Alerts and alert policies** — including current firing state and recent alert history. * **Incidents** in New Relic — Rootly AI can correlate its own incident context with any incidents you have open in New Relic. * **Logs** — search and inspect log lines matching a query. * **Golden signals and performance metrics** — throughput, latency, error rate, saturation across your instrumented services. Access is scoped to the New Relic user who authorizes OAuth or owns the fallback API key. If that user has restricted account access, Rootly AI inherits those restrictions. ## During an Incident *"New Relic flagged a golden-metric SLO breach at 2:12pm. Here's the slowest trace in the window."* Rootly AI pulls New Relic's entity data, NRQL query results, and alert history correlated with the incident. When a golden metric breaches or an alert fires in the incident's window, Rootly AI surfaces the exact query and trace in the investigation output. *** ## Best Practices * **Prefer OAuth.** It avoids distributing a long-lived New Relic user key and supports token refresh through New Relic's authorization flow. * **If you use the fallback, use a dedicated user API key for Rootly AI.** Don't reuse a personal key that's already in use elsewhere — it makes rotation, audit, and revocation harder. Name it something obvious like `rootly-ai` so it's easy to find in New Relic's API keys settings. * **Consider a service user for the API key.** If your New Relic account supports service users, create one specifically for Rootly AI and issue the API key from that user. This decouples Rootly AI's access from any individual staff member's account. * **Rotate fallback API keys on a cadence.** New Relic user API keys are long-lived by default. Rotate quarterly (or align with your team's existing rotation cadence). After rotating, open the New Relic card, expand **Use a user API key instead**, paste the replacement key, and click **Connect with API key**. OAuth connections use New Relic's token refresh flow instead of manual key rotation. * **Match the region carefully.** US, Europe, and Japan use separate hosted MCP endpoints. Authorization for one region will not connect to another. * **Test with `/rootly test`.** After connecting, declare a test incident and verify Rootly AI can query New Relic during the investigation. *** ## Troubleshooting Allow popups for your Rootly domain, then click **Connect with OAuth** again. Rootly keeps one popup active at a time; clicking again while it is open focuses the existing authorization window. Ask a New Relic Organization Manager to confirm **New Relic MCP Server** and **Local Clients** are active in Feature Control Manager. Then reconnect and authorize Rootly again. A canceled authorization does not replace your existing connection. The API key field is empty or the key you pasted doesn't start with `NRAK`. Only user API keys (prefix `NRAK`) are accepted — ingest keys (`NRII`) and license keys (`NRAL`) don't work. Create a new key of the User type from your New Relic account and retry. The region wasn't set. Check the host you use to open New Relic—`one.newrelic.com` for US, `one.eu.newrelic.com` for Europe, or `one.jp.newrelic.com` for Japan—and select the matching option. Rootly AI can only see what the New Relic user who authorized OAuth or owns the fallback API key can access. If that user has restricted account visibility (common in large organizations with sub-accounts), Rootly AI inherits those restrictions. Grant broader access on the New Relic side, reconnect OAuth as a user with the required access, or create the fallback API key from that user. Rootly AI composes NRQL based on the investigation context; occasionally the composed query has syntax issues or references data your account doesn't have. Check the specific error in the AI output — New Relic usually returns a helpful message. If the same query works when you run it manually in New Relic's query builder, contact support. The stored key is stale. Open the New Relic card, reconnect with OAuth, or paste the replacement user key and click **Connect with API key**. Open the New Relic card, choose the correct region, and reconnect with OAuth or re-enter the API key. Rootly preserves the working connection until the replacement succeeds. *** ## Frequently Asked Questions One New Relic integration per Rootly team currently. If your New Relic setup uses sub-accounts, connect from a user with cross-account access rather than connecting each sub-account separately. Multi-account support is on the roadmap. New Relic operates separate hosted MCP endpoints for US, Europe, and Japan. Pick the region that hosts your account; the endpoints do not share account data. No. Every query reads from New Relic fresh. NRQL results, entity lookups, alert state — all read at query time. Yes. New Relic's audit logging records the authorized user's or API key's activity. Filter by the identity used for the Rootly connection. Yes. Rootly AI's calls count as normal API activity against your New Relic account's plan quotas. Investigation-driven volume is typically low. *** ## Related Pages The full list of Connectors and how they fit together. What Rootly AI sees, retention, and model-training controls. New Relic's own documentation for API key management and account access. # Notion AI Connector Source: https://docs.rootly.com/ai/connectors/notion Connect Rootly AI to Notion with a single one-click authorization so investigations can search your docs, runbooks, and databases for relevant context. ## Overview Notion is a one-click connector that gives Rootly AI read access to your Notion workspace during investigations. When responders need a runbook, an architecture doc, or a past incident write-up, Rootly AI can pull the relevant page directly instead of asking someone to link it. Every query is **read-only**. Rootly AI can search and read Notion pages and databases but cannot create, comment on, or edit anything on the Notion side. *** ## Before You Start * **A Notion workspace** with permission to authorize third-party integrations. * **Read access** to the pages and databases you want Rootly AI to be able to see. Notion permissions are per-page/database, so the connector inherits whatever the authorizing user can see. *** ## Setup Open **Configuration → AI → Connectors** and click **Connect** on the Notion card. Sign in to Notion and grant Rootly AI access to the workspace and specific pages/databases you want it to be able to read. When the flow completes, the card flips to **Connected**. Notion's OAuth flow asks you to explicitly grant access to each page or database. If Rootly AI can't find a runbook you expected, the most common cause is that the runbook's parent page wasn't granted access during setup. *** ## What Rootly AI Can Read * **Pages** — full body text of pages you granted access to. * **Databases** — table rows, filter values, and page content within a database. * **Runbooks** — any page structured as a runbook, including the checklist blocks Notion supports. * **Search** — text search across granted content. Rootly AI reaches for Notion when a question is about *"how do we handle this?"* — think runbooks, incident playbooks, past retrospective write-ups. Pair with an observability connector so *"how do we handle this?"* has real data behind it. *** ## During an Incident *"Here's the runbook for this service, and the last retro that mentioned this failure mode."* When a responder needs to know how to handle an incident, Rootly AI searches Notion for the affected service's runbook and cites it in the investigation output. It also pulls past retrospectives that mentioned similar failure modes, so recurring issues carry their institutional memory forward instead of being solved from scratch every time. *** ## Best Practices * **Grant access at a top-level workspace or team page.** Notion access is per-page/database, so a broad grant at the top of a runbooks section is much more useful than clicking through and granting individual pages one at a time. * **Keep runbook titles descriptive.** Notion search ranks by title match. Descriptive titles ("Payments API on-call runbook — SEV1 response") beat generic ones ("Runbook"). * **Prune stale pages.** If Rootly AI cites an old runbook that's been superseded, archive the old version in Notion so search stops surfacing it. *** ## Troubleshooting Most likely cause: the page (or its parent) wasn't granted access during OAuth setup. Notion permissions are explicit — every page Rootly AI can read must have been shared with the integration. Reconnect and grant access to the parent workspace/team page. Notion search ranks by title match and recency. A stale page with a strong title match can outrank the current one. Rename or archive outdated pages so search surfaces the right ones. If a Notion workspace admin revokes the Rootly AI integration from Notion's side, Rootly's card still shows Connected but every query fails. Reconnect from Rootly to reauthorize. *** ## Frequently Asked Questions You can grant access at any level of the Notion hierarchy — granting a top-level workspace or team page cascades to its children. Grant broadly at the level where your runbooks live rather than page-by-page. No. Connectors are read-only. Rootly AI can read Notion data but never invoke write actions. Rootly does not maintain a persistent copy of Notion data — queries run at investigation time and the response is used in reasoning only. Query results *do* appear in the LLM traces Rootly logs for quality monitoring, as with every tool call Rootly AI makes. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for the retention boundary. *** ## Related Pages All connectors and how they fit together. The other knowledge-management connector — covers Confluence as well as Jira. What Rootly AI sees, retention, and model training controls. # Connectors Source: https://docs.rootly.com/ai/connectors/overview Connect your observability, code, docs, and cloud tools as data sources that Rootly AI can query during incident investigations. ## Overview Rootly AI is only as good as the context it can reach. **Connectors** link the SaaS tools your team already uses — observability platforms, code hosts, documentation systems, work trackers, feature-flag services, and cloud infrastructure — so Rootly AI can pull real context from them while investigating an incident, summarizing a timeline, or answering an operational question. When an investigation runs, Rootly AI looks up just the context it needs from each connected tool and reasons over the results alongside the incident record. Every connection is **read-only** — Rootly AI can query these tools but never modify them. *** ## How Rootly AI Uses Connectors Each connected tool gives Rootly AI a different kind of signal. | Category | What Rootly AI gets | | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Observability** — Sentry, Datadog, Dash0, Dynatrace, Grafana Cloud, Grafana Managed, New Relic, Honeycomb, Braintrust, ClickHouse, PostHog, several Cloudflare surfaces | Errors, stack traces, metrics, logs, traces, dashboards, alerts. Answers *"what is broken and how bad is it?"* | | **Code & CI/CD** — GitHub, GitLab, Semaphore | Recent deploys, code diffs, file ownership, pipeline health. Answers *"what changed right before this broke?"* | | **Infrastructure** — AWS, Azure Resource Manager (MCP), Azure Monitor, Google Cloud, Cloudflare | Cloud inventory, metrics, logs, resource health, deployments, Google Cloud workloads, DNS, Workers, and Zero Trust posture. Answers *"what's the current state of the underlying infrastructure?"* | | **Feature flags** — LaunchDarkly, PostHog | Flag targeting, recent flag changes, audit history. Answers *"did a flag flip cause this?"* | | **Work tracking** — Atlassian (Jira), Linear | Related issues, project context, ownership. Answers *"who owns this and what work is already in-flight?"* | | **Knowledge & analytics** — Notion, Atlassian (Confluence), Metabase, PostHog | Runbooks, architecture docs, past decisions, semantic-layer metadata, and current analytics. Answers *"how are we supposed to fix this, and what is the business impact?"* | | **Custom MCP** — Any OAuth MCP server | Your own MCP endpoint plus an allowlist of tools. Covers anything not in the built-in catalog. Requires OAuth 2.0 and Dynamic Client Registration on your server. | **Connectors vs. other integration surfaces** * **[Alert Sources](/alerts/alerts)** — when your monitoring fires, an incident lands in Rootly. Data flows monitoring → Rootly. * **Regular Integrations** — Rootly posts to Slack, creates Jira tickets, pages on-call. Data flows Rootly → tool. * **Connectors** — Rootly AI looks up context in your tools while investigating. For supported connectors, optional scheduled ingestion also derives facts such as service identities, dependency relationships, and selected cloud project or workload identities. Data flows tool → Rootly AI. A single vendor can appear in more than one surface. Datadog, for example, can be an Alert Source (ingesting Datadog alerts as Rootly alerts) *and* a Connector (letting Rootly AI read Datadog logs during investigation). The two configurations are separate. *** ## Rootly AI in Action What Rootly AI actually surfaces during an incident once you've connected each provider: | Connector | What responders see | | --------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | | **[GitHub](/ai/connectors/github)** | *"This error started 8 minutes after a deploy. Here's the diff that likely caused it."* | | **[GitLab](/ai/connectors/gitlab)** | *"The failing pipeline started after this merge request landed. Here's the diff and the failed job."* | | **[Datadog MCP](/ai/connectors/datadog)** | *"Latency spiked at 2:14pm on the checkout service. Here's the correlated metric."* | | **[Sentry](/ai/connectors/sentry)** | *"This is the exact stack trace, and it's hit 1,400 users so far."* | | **[Atlassian (Jira)](/ai/connectors/atlassian)** | *"There's already an open ticket for this exact error, filed last week. Here's the link."* | | **[LaunchDarkly](/ai/connectors/launchdarkly)** | *"A feature flag flipped 3 minutes before the spike. Here's the change."* | | **[Cloudflare](/ai/connectors/cloudflare)** | *"An audit log shows a config change during the incident window."* | | **[Notion](/ai/connectors/notion)** | *"Here's the runbook for this service, and the last retro that mentioned this failure mode."* | | **[Linear](/ai/connectors/linear)** | *"There's an active project tracking the migration involved here. Current status and owner attached."* | | **[AWS](/ai/connectors/aws)** | *"CPU is pegged on the checkout-api EC2 instance for the last 15 minutes. Here's the CloudWatch metric."* | | **[Google Cloud](/ai/connectors/google-cloud)** | *"The Cloud Run checkout service began logging 5xx errors after its latest revision, and request latency is rising."* | | **[Azure Resource Manager (MCP)](/ai/connectors/azure-resource-manager)** | *"Find the Azure resources for checkout and show the exact status of its latest ARM deployment."* | | **[Azure Monitor](/ai/connectors/azure-monitor)** | *"Failed requests started after this Azure deployment. Activity Log and Resource Graph show the same pre-event change."* | | **[Grafana Cloud](/ai/connectors/grafana-cloud)** / **[Grafana Managed](/ai/connectors/grafana-managed)** | *"The checkout-api 5xx rate jumped from 0.2% to 4%. Here's the Prometheus query and dashboard."* | | **[New Relic](/ai/connectors/new-relic)** | *"New Relic flagged a golden-metric SLO breach at 2:12pm. Here's the slowest trace in the window."* | | **[Dash0](/ai/connectors/dash0)** | *"The checkout service error rate jumped to 4.2%. The service graph shows it depends on payment-api, which started 503-ing two minutes earlier."* | | **[Dynatrace](/ai/connectors/dynatrace)** | *"Dynatrace shows payment-api failures and three Kubernetes restarts in the same incident window."* | | **[Honeycomb](/ai/connectors/honeycomb)** | *"94% of the slow checkout requests share build `a3f21c` and the `eu-west-1` region. Other regions on the previous build look normal."* | | **[Semaphore](/ai/connectors/semaphore)** | *"The last CI pipeline for checkout-api failed on the smoke test. Here's the job log."* | | **[Braintrust](/ai/connectors/braintrust)** | *"The last eval on the checkout-agent shows a 12% hallucination increase after yesterday's prompt change."* | | **[Metabase](/ai/connectors/metabase)** | *"Checkout failures affected 83 enterprise accounts in the EU region. Here's the current Metabase result."* | | **[ClickHouse](/ai/connectors/clickhouse)** | *"Error spans increased after the 14:05 deploy and point to the payment-api dependency. Here's the bounded ClickHouse result."* | | **[PostHog](/ai/connectors/posthog)** | *"A checkout flag changed before conversion dropped, and PostHog shows a new payment error pattern in the same window."* | | **[Custom MCP](/ai/connectors/custom)** | *"Your internal deploy MCP shows a deploy fired 4 minutes before the incident. Here's what shipped."* | Each row is one connector doing its job. The real lift shows up when multiple connectors run together on the same investigation — GitHub *and* Sentry *and* LaunchDarkly answering "was this a deploy, a bad exception, or a flag flip?" in one investigation output. *** ## Provider Directory Configure connectors in **AI & Agents → Connectors**. Providers connect through one-click authorization or a provider-specific configuration form. The native Azure Monitor connector also requires a one-time Microsoft Entra application enrollment from your Rootly account team before a Rootly admin completes the form. ### One-Click Providers Click **Connect** on the provider card, sign in on the vendor's authorization screen, and you're done. No fields to fill in. | Provider | Category | What Rootly AI gets | | ------------------------------------------------------------------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------- | | **[Sentry](/ai/connectors/sentry)** | Observability | Errors, stack traces, user impact | | **[GitHub](/ai/connectors/github)** | Code | Deploys, code diffs, ownership | | **[Atlassian](/ai/connectors/atlassian)** (Jira + Confluence) | Work tracking + Knowledge | Jira issues, Confluence pages, project context | | **[Notion](/ai/connectors/notion)** | Knowledge | Docs, runbooks, databases | | **[Linear](/ai/connectors/linear)** | Work tracking | Issues, projects, roadmaps | | **[LaunchDarkly](/ai/connectors/launchdarkly)** | Feature flags | Flags, targeting, audit logs | | **[Braintrust](/ai/connectors/braintrust)** | Observability | AI observability, logs, evals | | **[Cloudflare](/ai/connectors/cloudflare)** | Infrastructure + Observability | DNS, Workers, Zero Trust, audit logs, Radar, CASB, Logpush, and more — fourteen Cloudflare surfaces total | | **[Azure Resource Manager (MCP)](/ai/connectors/azure-resource-manager)** | Infrastructure | Azure resource inventory and ARM deployment status through Microsoft's hosted MCP endpoint | | **[PostHog](/ai/connectors/posthog)** | Observability + Feature flags | Errors, logs, product analytics, flags, and dashboards | The authorization flow requires you to be signed in to the vendor's platform with an account that has permission to grant third-party access. If the Connect button doesn't open the vendor's authorization screen, see Troubleshooting below. ### Setup-Required Providers These providers require provider-specific setup before Rootly AI can query them. Each has its own configuration form and dedicated setup guide. Azure Monitor additionally requires the one-time Entra enrollment described in its guide. Read-only cloud infrastructure via an IAM Role. CloudFormation, Terraform, or manual setup — plus optional EKS support. Read-only logs, metrics, alerts, Cloud Run, GKE, and Compute Engine across an explicit project selection. Read-only access to logs, metrics, alerts, deployments, resource health, and control-plane changes with explicit tenant, resource, and capability allowlists. Services, logs, metrics, monitors, APM traces, RUM events, and database signals. Metrics, logs, dashboards, and alerts from your Grafana Cloud stack. The same signals from a self-managed Grafana instance. Entities, NRQL, alerts, and golden metrics across US, EU, and Japan. Connect with OAuth or a user API key. Traces, logs, metrics, service catalog, dashboards, and alerts. OTel-native — pick a region and authorize. DQL, problems, entities, Kubernetes events, Davis analysis, and documents through Dynatrace MCP. Traces, metrics, logs, BubbleUp, Triggers, and SLOs. Pick US or EU, then authorize — no API key. Merge requests, pipelines, code, and project ownership. Confirm your GitLab instance, then authorize. Pipelines, job logs, and CI/CD workflow context. Semantic-layer context and current analytics through Metabase's read-only MCP tools. Direct, bounded SQL across ClickHouse logs, metrics, traces, and operational data. Bring your own OAuth-based MCP endpoint. Add an allowlist of tools Rootly AI can call. *** ## The Provider Card Every connector renders as a card with a status badge and a primary action. The provider can be connected. Click **Connect** to start the setup flow. Rootly AI can query this provider. The card shows **Configure** and **Disconnect** buttons — use Configure to update credentials or scoping, Disconnect to revoke the connection. Rootly is working on this provider but it isn't connectable yet. The Connect button is disabled. Your Rootly account doesn't have permission to manage this source. Ask an admin to enable the connection, or ask them to grant you the required permissions. *** ## Data Handling Rootly AI normally queries connectors on demand during an investigation. Rootly does not maintain a persistent copy of the connector's underlying raw data, such as logs, traces, documents, or code diffs. For supported connectors, optional fact ingestion also runs scheduled read-only queries. Observability connectors can store derived service identities and dependency relationships; Google Cloud can store selected project, hierarchy, and Cloud Run service facts. Rootly does not store the underlying telemetry or raw query result set as part of these facts. Query results *do* appear in the LLM traces Rootly logs to its evaluation and observability platform — as with every other tool call Rootly AI makes — so a connector response can be retained in trace form for quality monitoring. See **[Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai)** for the retention boundary and what's included. Credentials for setup-required connectors (API keys, IAM Role ARNs, service-account tokens) are stored encrypted and used only to query that connector on your behalf. The native Azure Monitor connector stores no customer credential: Rootly stores the tenant and explicit allowlists and uses its own Entra application credential to mint short-lived tokens. *** ## Best Practices * **Start with the observability and code connectors.** These are the two categories that consistently show up in "what caused this?" investigations. Sentry + GitHub covers most product-tier incidents; adding Datadog or Grafana on top covers infrastructure. Everything else layers value on top. * **Connect the work-tracking connector your team actually uses.** Atlassian (Jira) or Linear — pick one. Connecting both when you only use Linear adds a source that never fires and clutters the picker. * **Don't over-scope AWS.** Rootly AI works fine with narrowly scoped IAM permissions. Start with the AWS services you actually operate and expand later if Rootly AI's output is missing signal. * **Keep Azure Monitor RBAC and its Rootly allowlist aligned.** Grant the Rootly enterprise application only the Azure scopes responders need, then configure the same subscriptions, workspaces, resources, and capabilities on the **Azure Monitor (Native)** card. * **Grafana Cloud and Grafana Managed are mutually exclusive in practice.** Connect Grafana Cloud if your team is on the managed offering. Connect Grafana Managed if you self-host. * **Reconnect after major credential rotations.** If you rotate the API key or IAM Role that Rootly AI uses, the connector status shows Connected but queries fail. Reconnect from the Configure button to re-authenticate. * **Restrict who can manage connectors.** Connectors pull real customer data into investigation context. Limit the "manage connectors" permission to users who understand what each connector exposes. *** ## Troubleshooting A browser popup blocker is the most common cause. Confirm you're not blocking popups from `rootly.com`, then try again. If the screen still doesn't appear, check whether your account on the vendor's platform has permission to authorize third-party apps — some organizations restrict this to admins only. Credentials rotated on the vendor side without the connector being reconnected. Open the connector's Configure screen and re-authenticate. Any specific failure reason will be surfaced when you save. The catalog is the current supported set. If a provider is marked Coming Soon, it's on the roadmap. For anything else, use the **Custom MCP** connector, which lets you point Rootly AI at any OAuth-based MCP endpoint. If neither option works, request the provider through support. Your Rootly account role doesn't include permission to manage connectors. Ask an admin to grant you the permission, or to run the setup on your behalf. Rootly AI only reaches for connectors that carry relevant signal for the current investigation. If it isn't citing your connected Notion, that usually means the question didn't warrant a Notion lookup — not that the connector is broken. Confirm the connector is Connected, then try a prompt that explicitly targets its data (for example, *"What does our runbook say about this?"* for Notion). *** ## Frequently Asked Questions All three are ways Rootly connects to third-party tools, but they serve different purposes. **Alert Sources** bring events *into* Rootly (a Datadog monitor firing creates a Rootly alert). **Regular Integrations** let Rootly *push* actions into third-party tools (creating a Jira ticket when an incident is declared, posting to Slack when severity changes). **Connectors** let Rootly AI *read from* third-party tools while investigating. A single vendor can be all three simultaneously — the configurations are independent. Yes. Alert Sources and regular Integrations don't grant Rootly AI access to that vendor's data. If you want Rootly AI to read Datadog logs during investigations, connect Datadog as a Connector too — separate from any Datadog Alert Source you already have. Rootly does not keep a persistent copy of the underlying raw connector data. Query responses can appear in retained LLM traces. With optional fact ingestion enabled, supported observability connectors can store derived service identities and dependency relationships, while Google Cloud can store selected project, hierarchy, and Cloud Run service facts. Rootly does not store the underlying telemetry or raw query result set as part of these facts. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for full detail. Use the **[Custom MCP](/ai/connectors/custom)** connector. It lets you point Rootly AI at any OAuth-based MCP endpoint and choose which of its tools investigations may call. Good for internal MCP servers or third-party tools not yet in the built-in catalog. Your server needs to support **OAuth 2.0** and **Dynamic Client Registration** — Rootly registers its own client at connect time rather than using credentials you pre-provision. See [Custom MCP → Before You Start](/ai/connectors/custom#before-you-start) for the full requirements. Yes. Disconnecting removes the credentials Rootly uses to query the vendor and marks the card Available again. Historical investigations that referenced that connector keep their context, but Rootly AI cannot query the source in future investigations. For connectors that authored derived facts—including supported observability connectors and Google Cloud—disconnecting also deletes those facts; other Rootly data is unchanged. *** ## Related Pages Parent page for the whole Rootly AI suite. What Rootly AI sees, retention, and model training controls. The other integration surface — monitoring tools that ingest events into Rootly as alerts. # PostHog AI Connector Source: https://docs.rootly.com/ai/connectors/posthog Connect Rootly AI to PostHog for read-only error, log, feature-flag, dashboard, and product analytics context. The **PostHog** AI connector gives Rootly AI permission-scoped access to current product and operational signals during an investigation. Rootly AI can inspect errors, logs, feature-flag activity, dashboards, saved insights, and product analytics without changing your PostHog project. Rootly fixes the connection to PostHog's read-only mode and a reviewed tool set. Rootly excludes project switching, arbitrary SQL, data creation, updates, and deletion. ## Before You Start You need: * A PostHog account with access to the project Rootly AI should query. * Permission in PostHog to approve the requested OAuth access. * Permission in Rootly to manage AI connectors. Choose the PostHog project that contains the errors, logs, feature flags, and analytics used during incident response. One Rootly team can have one active PostHog connection, and each connection operates in one active PostHog organization and project. Select a specific project during authorization. Organization-wide approval does not make Rootly query every project at once, and Rootly does not expose PostHog's organization or project switching tools. To use a different project, disconnect PostHog and connect it again with that project selected. Rootly requests these OAuth scopes: | Capability | OAuth scopes | | ------------------------------------ | --------------------------------------------------------------------- | | Identity and active context | `openid`, `profile`, `email`, `user:read`, `project:read` | | Product analytics and saved insights | `query:read`, `insight:read`, `action:read` | | Errors and logs | `error_tracking:read`, `logs:read` | | Feature flags and changes | `feature_flag:read`, `activity_log:read` | | Dashboards and data schema | `dashboard:read`, `event_definition:read`, `property_definition:read` | PostHog applies the authorizing user's permissions in addition to these scopes. Rootly AI cannot retrieve a project, dashboard, flag, or event that the user cannot access. *** ## Connect PostHog Authorize the PostHog project Rootly AI should use. In Rootly, go to **AI & Agents → Connectors** and find the **PostHog** card. Click **Connect**. Rootly opens PostHog's authorization flow. You do not need to create an API key, client ID, or client secret. Sign in to the correct PostHog account, select the organization and project Rootly AI should query, and review the requested read scopes. Select a project rather than organization-wide access. Rootly's read-only tool set operates against the connection's active project and cannot switch projects later. Approve the request in PostHog. PostHog routes the connection to the account's US or EU data region automatically. Return to **AI & Agents → Connectors**. The PostHog card shows **Connected** after Rootly validates the OAuth grant and approved tool catalog. Rootly uses OAuth 2.0 with Dynamic Client Registration and Proof Key for Code Exchange (PKCE). The access and refresh credentials are encrypted at rest. *** ## What Rootly AI Can Read Rootly exposes reviewed PostHog tools across six investigation categories. | Category | Available tools | What Rootly AI can inspect | | ------------------ | -------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | Project and schema | `project-get`, `read-data-schema` | Active project metadata, events, actions, properties, and property values. | | Error tracking | `query-error-tracking-issues-list`, `query-error-tracking-issue`, `query-error-tracking-issue-events` | Error groups, issue details, affected events, and occurrence context. | | Logs | `query-logs`, `logs-count`, `logs-count-ranges`, `logs-patterns`, `logs-patterns-diff`, `logs-services-create` | Bounded log searches, counts, time ranges, recurring patterns, pattern changes, and top services. | | Product analytics | `insight-get`, `insights-list`, `query-trends`, `query-funnel`, `query-retention` | Saved insights, event trends, conversion funnels, and retention behavior. | | Feature flags | `feature-flag-get-all`, `feature-flag-get-definition-by-key`, `feature-flags-activity-retrieve` | Flag definitions and activity history for change correlation. | | Dashboards | `dashboard-get`, `dashboards-get-all`, `dashboard-insights-run` | Dashboard metadata and current results from its insights. | The `logs-services-create` name comes from PostHog's API. In this connection it calculates and returns a read-only top-services aggregation; it does not create a PostHog resource. Rootly sends both a fixed `readonly=true` restriction and the exact tool list to PostHog. Rootly also enforces the same allowlist before every call. Tools added by PostHog later do not become available automatically. *** ## Questions To Ask Name the PostHog signal and a bounded time range when possible. These prompts work in Rootly AI SRE and the Slack agent: * "What are the top unresolved PostHog errors affecting checkout in the last 24 hours? Include occurrence and affected-user counts." * "Show the dominant error and fatal log patterns for `payment-api` since the incident began." * "Compare this week's checkout failure log patterns with the previous week. What changed?" * "Did any feature flag change in the 30 minutes before conversion dropped?" * "Compare the signup funnel for the last seven days with the prior seven days. Which step regressed?" * "Run the current insights on the payments dashboard and summarize the signals relevant to this incident." * "Which events and properties are available for investigating failed subscription renewals?" If a broad question returns irrelevant results, add the service, event, flag, dashboard, issue, and time window. For example, change *"What broke?"* to *"Find new fatal log patterns for `checkout-api` between 14:00 and 15:00 UTC and compare them with the preceding hour."* *** ## Data Handling and Permissions * **On-demand queries.** Rootly AI calls PostHog when an investigation or direct question needs the data. The connection does not run a background ingestion job. * **One active project.** Each Rootly team has one PostHog connection with one active organization and project. * **PostHog permissions apply.** Results are limited by the authorizing user's access and the approved OAuth scopes. * **Read-only allowlist.** Rootly exposes only the tools listed on this page and blocks every write-capable tool or tool that Rootly has not reviewed. * **No arbitrary SQL.** Rootly excludes PostHog's SQL execution tools. Analytics use structured trends, funnel, retention, insight, and dashboard operations. * **Encrypted credentials.** Rootly encrypts OAuth credentials at rest and removes them when you disconnect the AI connector. * **AI traces may contain results.** PostHog responses can appear in Rootly AI model and observability traces. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for retention details. PostHog's hosted MCP server proxies requests to the account's US or EU region and does not store the analytics results. PostHog API rate limits still apply to MCP calls. *** ## Manage the Connection Open **AI & Agents → Connectors** and find the PostHog card. * Click **Disconnect** to remove the stored OAuth credentials and stop future PostHog queries. * Click **Connect** after disconnecting to authorize a different account, organization, or project. Disconnecting does not change or delete data in PostHog. *** ## Troubleshooting Confirm that your browser allows redirects from Rootly and that you can reach `mcp.posthog.com`. Sign in to PostHog in the same browser, then click **Connect** again. Rootly validates the OAuth grant by listing PostHog's approved tools. Disconnect any failed connection, confirm your PostHog access is active, and connect again. If the problem continues, contact Rootly support with the time of the failed attempt. A connection uses the active project selected during authorization. Disconnect PostHog, click **Connect**, and select the intended project. Rootly does not expose PostHog's project-switching tool. Sign in to PostHog as the authorizing user and confirm the item exists in the connected project and is visible to that user. Then retry with its exact name or key and a bounded time range. The OAuth grant may have been revoked, the user's project access may have changed, or the refresh credential may have expired. Disconnect the AI connector and authorize it again. Add the signal type, service or event name, and time range. Ask separate questions for errors, logs, flags, and product analytics when the investigation spans several PostHog products. *** ## Frequently Asked Questions No. Rootly forces PostHog's read-only mode, requests read scopes, filters the hosted catalog to the reviewed tools listed on this page, and enforces that allowlist before each call. One MCP connection has one active organization and project. Rootly excludes the switching tools, so selecting the intended project keeps every investigation in a predictable context. Organization-wide approval does not query all projects together. A Rootly team supports one active PostHog connection. To use another project, disconnect the current connection and authorize the replacement project. No. Rootly uses PostHog's OAuth flow and stores the resulting credentials encrypted. Do not paste a personal API key into Rootly. PostHog routes the hosted MCP connection to the US or EU region associated with the account you authorize. *** ## Related Pages Browse every data source Rootly AI can use during an investigation. Review encryption, retention, trace handling, and model controls. Review PostHog's hosted MCP server and authentication behavior. Browse PostHog's complete upstream tool catalog. # Semaphore Source: https://docs.rootly.com/ai/connectors/semaphore Connect Rootly AI to Semaphore CI/CD — pipelines, job logs, and workflow context during incident investigations. ## Overview Connecting **Semaphore** lets Rootly AI query your CI/CD pipeline history during investigations. When an incident correlates with a recent deploy or a suspicious pipeline change, Rootly AI can pull the pipeline, job logs, and workflow context automatically — no need for a responder to jump between Semaphore and Rootly manually. Every query is **read-only**. Rootly AI can inspect pipelines and jobs but cannot trigger, cancel, or modify them. *** ## Before You Start * **A Semaphore account** with permission to create API tokens. * **A Semaphore API token** with read access to the pipelines and projects you want Rootly AI to see. * **Your Semaphore organization URL** (for example, `https://your-org.semaphoreci.com`). *** ## Setup Go to **Configuration → AI → Connectors** and click **Connect** on the **Semaphore** card. Paste your Semaphore organization URL — the base URL you sign in to (for example, `https://your-org.semaphoreci.com`). Generate a Semaphore API token from your account settings and paste it into Rootly. Only tokens with read access to pipelines are needed. Rootly runs a quick check to confirm it can reach Semaphore. If the check passes the card flips to **Connected**. *** ## What Rootly AI Can Read * **Pipelines** — pipeline runs, status, timing, associated commits and branches. * **Jobs** — job status, exit codes, timing per step. * **Job logs** — log output for individual jobs, useful when a build failure precedes an incident. * **Workflows** — workflow structure and the projects they belong to. Rootly AI reaches for CI/CD data when a question is about *"what changed?"* or *"did the deploy fail?"* If your incident isn't deploy-related, the Semaphore connector may not come up in the investigation — that's expected. ## During an Incident *"The last CI pipeline for checkout-api failed on the smoke test. Here's the job log."* Rootly AI queries Semaphore for the pipeline history on the incident's affected services. When a recent pipeline failed or a specific job (test, build, deploy) went red just before the incident, Rootly AI surfaces the pipeline link and the failing job's log directly in the investigation output. *** ## Best Practices * **Scope the token to read-only.** Rootly AI never needs to write to Semaphore. Use the narrowest-permission token that covers the pipelines you care about. * **Rotate the token on a cadence.** Rotate on the same schedule as your other CI credentials (quarterly is common). After rotating, paste the new token into Rootly's Configure screen. * **Pair with GitHub.** Semaphore tells you the pipeline result; GitHub tells you what changed in the code. The two together give Rootly AI the strongest "what caused this?" signal. *** ## Troubleshooting The API token is invalid, expired, or lacks permission. Regenerate it in Semaphore, confirm it can read pipelines using the Semaphore API directly, then paste the new token into Rootly. The token's scope is too narrow. Confirm it can read the projects containing the pipelines you're asking about. Semaphore tokens can be restricted to specific projects or organizations. Semaphore retains job logs for a limited window; older logs may have been purged upstream. Rootly AI can only read what Semaphore still stores. *** ## Frequently Asked Questions No. Every connector is read-only. Rootly AI can read pipeline data but never invoke pipeline actions. Yes — through the Semaphore API token's own scope. Create a token that only grants access to the projects you want Rootly AI to be able to reach. No. Rootly AI queries Semaphore at investigation time; nothing is persistently cached. *** ## Related Pages All connectors and how they fit together. Pair Semaphore with GitHub for the strongest "what changed?" signal. What Rootly AI sees, retention, and model training controls. # Sentry AI Connector Source: https://docs.rootly.com/ai/connectors/sentry Connect Rootly AI to Sentry — errors, stack traces, and user-impact context — via a single one-click authorization. ## Overview Sentry is a one-click connector that gives Rootly AI read access to your Sentry organization during investigations. When an incident is tied to a spike in a specific exception, Rootly AI can pull the error signature, the stack trace at the point of failure, and how many users are affected — automatically, without a responder digging through Sentry. Every query is **read-only**. Rootly AI can inspect issues, events, and user impact but cannot resolve, assign, or modify anything on the Sentry side. *** ## Before You Start * **A Sentry organization** with permission to authorize third-party OAuth apps. * **Permission to install** the Rootly AI Sentry integration for that organization. *** ## Setup Open **Configuration → AI → Connectors** and click **Connect** on the Sentry card. Sign in to Sentry and authorize Rootly AI for the organization you want to connect. When the flow completes, the card flips to **Connected**. *** ## What Rootly AI Can Read * **Errors** — active issues in the connected organization, grouped by exception signature. * **Stack traces** — the frames captured at the point of failure, with file, line, and function context. * **User impact** — how many users are affected and how frequently. * **Recent events** — events fired against a given issue in a recent time window. Rootly AI leans on Sentry heavily during "what's actually broken?" investigations. Pairing it with GitHub (for the recent code change) and an infrastructure connector like AWS or Cloudflare (for the underlying state) covers most product-tier incidents. *** ## During an Incident *"This is the exact stack trace, and it's hit 1,400 users so far."* Rootly AI pulls the current top exception on the affected service, along with the frame-by-frame stack trace at the point of failure and the user-impact count. Responders don't have to open Sentry — the stack lands in the investigation output alongside the incident summary. *** ## Best Practices * **Authorize at the organization level, not per-project.** Restricting the connector to one Sentry project starves investigations that span multiple services. * **Keep Sentry project ownership assignments up to date.** Rootly AI can surface who owns an affected project — a stale ownership map leads to stale owner suggestions. * **Pair with a code connector.** Sentry tells you *what* is failing; a code connector (GitHub) tells you *what changed just before*. Together they answer most "what caused this?" questions in one investigation. *** ## Troubleshooting The authorizing Sentry user or installation doesn't have access to those projects. Confirm the installation covers every project Rootly AI should read, then disconnect and reconnect to refresh the OAuth grant. Sentry sometimes surfaces recurring issues that share a stack signature. If the wrong issue is being cited, look at the event timestamps in Sentry directly — the connector reads what Sentry serves, so a stale grouping on the Sentry side propagates. If a Sentry admin revokes the Rootly AI installation from Sentry's side, Rootly's card still shows Connected but every query fails. Reconnect from Rootly to reinstall. *** ## Frequently Asked Questions No. Every connector is read-only. Rootly AI can read Sentry data but never invoke write actions. Coverage depends on how your Sentry Self-Hosted instance is reachable. If it's public HTTPS with OAuth exposed, contact support to confirm compatibility. Rootly does not maintain a persistent copy of Sentry data — queries run at investigation time and the response is used in reasoning only. Query results *do* appear in the LLM traces Rootly logs for quality monitoring, as with every tool call Rootly AI makes. See [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) for the retention boundary. *** ## Related Pages All connectors and how they fit together. Pair Sentry with GitHub for the strongest "what caused this?" signal. What Rootly AI sees, retention, and model training controls. # Data Privacy for AI Summaries & Web Copilot Source: https://docs.rootly.com/ai/data-privacy-for-ai Data privacy for Rootly's classic AI features—generated titles, summaries, catchup, AI Editor, and Web Copilot—covering OpenAI handling and opt-out. This page covers Rootly's classic AI features—generated titles, incident summaries, catchup, the AI Editor, and Web Copilot which use OpenAI models. The conversational **Rootly AI** agent uses a different model stack and data path; see [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai). Rootly is dedicated to maintaining the highest standards of privacy and security. [Read more about Rootly's data philosophy](https://rootly.com/blog/building-a-privacy-first-ai-for-incident-management). ## How Your Data Is Handled * Rootly AI, driven by OpenAI, incorporates multiple safeguards to ensure the security of your data, providing you with peace of mind. * Data sent to OpenAI is solely used to provide Rootly AI services and is neither stored nor used for training purposes by OpenAI. * Rootly automatically redacts the following PII before sending any data to OpenAI: * email, addresses, phone numbers, credit card numbers, social security numbers (SSNs) and passwords in URLs * For these features, private incident data is **never** sent to OpenAI. * Rootly AI never uses your data (even if anonymously) to improve results for other customers; it stays within the walls of your organization and is only used there. * You may opt-out at any time via the [AI configuration page](https://rootly.com/account/ai/configurations). No future changes to how your data is used will be made without your explicit approval. * Optionally, organizations may [integrate their OpenAI account](https://rootly.com/account/integrations/open_ai_accounts/new) to take advantage of any organization specific data retention policies. ## Data Included in AI Processing **Data from the incident that will be considered includes:** * Built-in and custom fields * Human-created timeline events * Completed action items * Timestamps * Alert source * Mitigated and resolved messages * Slack messages from the incident channel (depending upon [Slack channel message visibility](https://rootly.com/account/ai/configurations)) ## Data Excluded From AI Processing **Data that is not considered includes:** * Incident feedback * Automated timeline events relating to action items, workflow runs and playbooks * Any data from private incidents Note: To enable higher quality output, updated [Slack scopes](/integrations/slack/slack#refresh-connection) are required. *** ## Related Pages The companion privacy page — data access, retention, audit, and model details for the Rootly AI agent. Titles, summaries, catchups, and status write-ups — the feature set this privacy page covers. The umbrella page for every Rootly AI capability, including the conversational agent and Web Copilot. # Data Privacy for Rootly AI Source: https://docs.rootly.com/ai/data-privacy-for-rootly-ai How Rootly AI—the AI agent in Slack, web, and mobile—handles data access, encryption, RBAC, audit logs, retention, BYOK, and PII redaction. This page covers **Rootly AI**, the AI agent available in Slack, the web app, and the mobile app. Rootly's other AI features—generated titles, incident summaries, catchup, the AI Editor, and Web Copilot—use a different model stack and data path; see [Data Privacy for AI Summaries & Web Copilot](/ai/data-privacy-for-ai). ## Data Access & Scope ### What Data Does Rootly AI Access? Rootly AI reads the incident and conversation context for the request in front of it, plus relevant data from configured connectors. It does not crawl broader Rootly data or message history. Depending on the surface, that context includes: * **In Slack:** app mentions in channels where it's been added, messages in incident channels (where Rootly creates an assistant thread automatically when it's mentioned), DMs sent directly to the bot, the recent context of the active thread, and an active incident bridge transcript if one is attached via the Meeting Scribe. * **In the web and mobile apps:** the incident you're viewing and your conversation with it—its timeline, severity, status, roles, alerts, and (subject to your privacy settings) related Slack discussion. * **From connectors:** data fetched on demand for the investigation. With optional scheduled fact ingestion enabled, supported observability connectors can also contribute derived service identities and dependency relationships, while Google Cloud can contribute selected project, hierarchy, and Cloud Run service facts. In Slack, Rootly AI does **not** crawl historical Slack messages, browse channels it hasn't been invited to, or call Slack's `conversations.history` API. It sees only the message in front of it plus the immediate conversational context. ### Does It Read History Retroactively? No. Rootly AI only acts on the context available from the moment you invoke it—the active Slack thread, or the incident you have open in the web or mobile app. There is no backfill of historical Slack data. ### Can We Limit Rootly AI to Specific Channels? In Slack, per-channel scopes (for example, restricting `@Rootly` to `#incidents-*` channels) are not currently configurable. Admins can enable or disable Rootly AI for their team through a workspace-level toggle in Web via **AI & Agents → Configuration**. ### Are DMs Covered? Yes. In Slack, when Rootly AI is enabled, users can DM the bot directly. DMs are read-only by design—write operations like paging or creating action items are filtered out at that surface and only work inside incident channels. DMs honor the same Rootly access controls as everywhere else: a user can only retrieve incident data they're already entitled to see in the Rootly web app. ### What About Private Channels? In Slack, Rootly AI processes events from any channel it's been invited to, public or private. There is no separate data path for private-channel content. If your security model requires private-channel data to flow through different infrastructure, please flag to your CSM. *** ## Data Privacy ### Is Our Data Used to Train AI Models? Customer data is processed in-context for each request and is not used to fine-tune base models. Rootly AI uses Claude Sonnet 4.6 from Anthropic as the default with OpenAI's GPT-5 as a fallback. Both are accessed through a managed gateway. ### Where Is Data Processed? Data flows through Rootly's own infrastructure and LLM gateway and provider infrastructure. All traffic is routed through the Rootly-managed gateway. ### What Data Is Stored, and Where? Four places store data during normal operation: 1. **Conversation history:** persisted to Rootly's database so multi-turn conversations work. See retention below. 2. **Model traces:** every LLM call is logged to Rootly's evaluation and observability platform for quality monitoring and debugging. 3. **Provider request logs:** Anthropic and OpenAI handle request data per their standard data-use policies. 4. **Derived connector facts:** with optional fact ingestion enabled, Rootly stores derived connector facts in its database. Supported observability connectors can contribute service identities and dependency relationships; Google Cloud can contribute selected project, hierarchy, and Cloud Run service facts. Rootly does not store the underlying telemetry or raw query result set as part of this graph. Disconnecting a connector immediately deletes the derived facts it authored. Disabling fact ingestion stops future ingestion and scheduled refreshes but does not delete existing facts; disconnect the connector to remove them. All PII is automatically scrubbed from outgoing prompts, and all LLM inference for Rootly AI runs in US-based infrastructure. Rootly does not currently offer region routing for teams. If this is a requirement, please contact your CSM. ### How Long Is Conversation Data Retained? Rootly AI keeps a short-term session record for multi-turn follow-ups; that record is hard-deleted 90 days after the last activity. In Slack, Rootly AI's replies and users' prompts also live as regular Slack channel messages—Rootly stores those alongside every other message from channels where the Slack integration is active, **with no automatic expiry today.** Meeting Scribe transcripts (when bridge recording is on) are likewise currently retained without automatic expiry. ### Can We Configure Our Own Retention Window? Per-tenant retention configuration is not currently available. The 90-day default applies to all tenants. ### Are Queries Logged for Support and Debugging? Yes. Tool-call telemetry (which tools Rootly AI invoked, durations, outcomes) is logged to Rootly's observability platform for support and quality monitoring. Tool arguments are scrubbed of PII before logging. Full LLM traces (prompts, completions) are logged to Rootly's evaluation platform. A per-customer opt-out of debug logging is not currently available. *** ## Encryption, Keys & BYOK ### Does BYOK (Bring Your Own Key) Apply? BYOK support is on the roadmap. All Rootly AI traffic currently uses the Rootly-managed gateway and credentials. *** ## Cost & Usage ### Are There Token Caps? Yes. Each tenant has a configurable, per-minute token budget enforced server-side. The default sits in the 250,000 tokens-per-minute range. This is a generous cap to prevent abuse. When a tenant exceeds its budget, Rootly AI returns a rate-limit message and the request stops. *** ## Access Control & Permissions ### Does Rootly AI Respect Our Existing Rootly Roles and Permissions? Yes. Rootly AI cannot perform any action the requesting user couldn't perform themselves in the Rootly web app. Access checks happen at three layers: * Tool-class permissions (the user's role must allow the category of action) * Per-field permissions (sensitive fields like incident summary require specific abilities) * Runtime data scoping (read queries are scoped to records the user can see) Custom roles, per-severity restrictions, per-status restrictions, and incident-level permission sets are all honoured. ### Who Can Configure Rootly AI? Rootly administrators can enable or disable Rootly AI per workspace in the Web app via **AI & Agents → Configuration**. In Slack, workspace admins control whether the Rootly app is installed at all, but enablement is managed in Rootly. *** ## Audit & Compliance ### Are AI Actions Logged in the Audit Trail? Yes. Any action Rootly AI performs that modifies data (incident updates, role changes, action item creation, paging, status page publishing) is captured in the standard Rootly audit trail. Each action is attributed to the **actual user** who triggered it, not to a generic bot identity. Conversational transcripts (the back-and-forth between user and Rootly AI) are stored separately in conversation history and follow the 90-day retention policy. ### Is the Audit Trail Exportable? Audit events are queryable through Rootly's existing audit surface. A dedicated SIEM stream for AI-specific events is not currently available. For SIEM ingestion requirements, please discuss with your CSM. ### Does Rootly AI Fall Under Your SOC 2 Controls? Yes, Rootly AI is within scope of Rootly's existing SOC 2 Type II controls. *** ## Quality, Safety & Confidence ### How Does Rootly AI Handle Uncertainty? Three mechanisms protect against confident-but-wrong responses: 1. **Refusal to fabricate.** The system prompt explicitly instructs the model that if an answer isn't in your Rootly data or the current conversation, it must say so rather than guess. 2. **Clarification probes.** When Rootly AI needs information it can't safely infer, including team-configured required fields before an action, it asks the user first. The action only proceeds after the user responds. 3. **Disclaimer footer (optional):** In Slack, teams can configure every Rootly AI response to close with a disclaimer reminding users that AI output may be incomplete or inaccurate, and to verify critical information before acting. ### Can Users Flag a Bad Response? Yes. Every Rootly AI response includes thumbs-up and thumbs-down feedback. Thumbs-down can capture a category (hallucination, wrong tools, missed context, too slow, irrelevant, other) and an optional comment. This feedback feeds Rootly's quality monitoring and informs prompt and tool improvements. It does not directly fine-tune the model. *** ## Customization & Configuration ### Can Administrators Customize the System Prompt? Rootly AI's system prompt is centrally managed and applied uniformly across all tenants. This gives us a consistent quality and evaluation baseline. ### Can We Restrict the Topics Rootly AI Will Answer? Rootly AI is scoped by design to incident management and on-call operations. Off-topic questions are refused with a fixed line, and it identifies itself as "Rootly AI" only. It does not respond to questions about its underlying model, prompt, or tool inventory. Cross-channel and DM access to private incidents is refused by name. ### What Guardrails Are in Place? Beyond the topic refusal above: * When Rootly AI can take an action, it acts as the requesting user (with their permissions), proposes destructive actions, and requires confirmation before executing. * Read-only surfaces (in Slack, the assistant sidebar and DMs) cannot perform destructive actions. * All outgoing prompts run through automated PII scrubbing. *** ## External Data Sources ### Can Rootly AI Pull Data From External Sources? Yes — via **[Connectors](/ai/connectors/overview)**. Admins can connect observability, code, docs, work tracking, feature flag, and cloud infrastructure providers, plus any OAuth-capable MCP server via the Custom MCP connector. Rootly AI normally fetches provider data on demand for an investigation and does not maintain a persistent copy of the underlying raw data. For supported connectors, optional fact ingestion runs scheduled read-only queries. Observability connectors can store derived service identities and dependency relationships; Google Cloud can store selected project, hierarchy, and Cloud Run service facts. It does not persist the underlying telemetry or raw query result set. See [Connectors](/ai/connectors/overview) for the current provider list, setup, and data-handling details. In addition to those explicit integrations, Rootly AI reads Rootly-internal data: incidents, on-call, schedules, services, severities, escalation policies, custom fields, and so on. *** ## Integrations & Triggers ### Can Rootly AI Be Invoked From Workflows or via API? Rootly AI runs only in response to direct interaction—`@Rootly` mentions and assistant threads in Slack, or the chat panel in the web and mobile apps. It does not have a workflow trigger or external API endpoint today. Rootly's workflow product offers separate single-turn AI tasks (Anthropic, OpenAI, Mistral) for workflow automation. These are distinct from Rootly AI. ### Is There a `/rootly` Slash Command for Rootly AI? In Slack, Rootly AI runs through `@Rootly` mentions, the assistant sidebar, DMs, and interactive card responses. Earlier `/rootly` slash commands exist for the single-turn AI features but are not entry points to Rootly AI. *** ## Reliability & Failover ### What Happens if the LLM Provider Is Unavailable? Rootly offers two layers of resilience: 1. **Cross-vendor failover.** Each model tier in the configuration has a primary and a fallback on a different provider. Retryable errors (rate limits, overloaded responses, 5xx) automatically retry against the fallback. 2. **Graceful failure.** If multiple providers fail or another error occurs, Rootly AI replies with a "Something went wrong, please try again" message and stops. Failed requests do not automatically retry, and users must invoke Rootly AI again to complete their original request. ### Is There Rate Limiting per Workspace or per User? Per-team token-per-minute budgets are enforced (see Cost & Usage). A per-user rate limit on top of that is not currently implemented. *** ## Related Pages The companion privacy page — data handling for the classic AI summary and Web Copilot features. Where the Rootly AI agent is opted into and configured per surface. The agent surface most workspaces enable first — actions the agent can take on your behalf. # Rootly AI Meeting Scribe Source: https://docs.rootly.com/ai/meeting-scribe The scribe joins your incident bridges, transcribes them live with speaker labels, and turns the call into a record your whole team can use. ## Overview The bridge call is where incidents actually get solved, and the first place that context is lost. Meeting Scribe joins the bridge automatically and preserves the call as a live, searchable, speaker-labeled record attached to the incident. Late responders catch up from the live transcript instead of interrupting the call. Transcripts flow straight into [AI Summaries](/ai/ai-summaries) and [retrospectives](/ai/ai-in-retrospectives/overview). Supported platforms: **Zoom, Google Meet, Microsoft Teams, Webex, and GoToMeeting**. *** ## What You Get During the call, the scribe joins as **Rootly Scribe** in the participant list, announces itself, then provides: * **Live transcription**, streamed back to Rootly in real time with speaker identification * **Audio recording**, and video where the platform supports it * **Slack notifications** in the incident channel when recording starts and when the transcript is ready * **Live context for catchup**, so `/rootly catchup` already knows what the bridge discussed After the call, the incident's **Scribe** tab holds the full speaker-labeled transcript, a Rootly AI meeting summary of the key points and decisions, and the optional video recording. Every transcript is PII-redacted before storage across 36 categories, from credentials to personal identifiers. See [Data Privacy for AI Summaries & Meeting Scribe](/ai/data-privacy-for-ai) for the full list. The incident Scribe tab with the Rootly AI meeting summary and the speaker-labeled transcript *** ## Setup Meeting Scribe rides on your existing meeting-platform integration: connect the platform, then enable the scribe toggle. **Prefer the Rootly-generated meeting URL.** When an incident starts, Rootly creates the meeting room and pins the link in the incident's Slack channel; the scribe is created automatically for that meeting. You can also [attach a different meeting URL](/incidents/managing-incidents/updating-incident-integration-links) to the incident and the scribe will target it, but the Rootly-generated link works with zero extra steps. Follow [Zoom → Installation](/integrations/zoom/zoom#installation) to connect your Zoom account via OAuth. Go to **Integrations → Zoom**, then toggle on **Meeting transcript and summary**. In the same settings pane, enable **Auto-join bot**. The scribe then joins without waiting for a host to admit it, so it never sits in a waiting room while the call starts without it. Zoom-specific issues live at [Zoom Meeting Scribe Troubleshooting](/integrations/zoom/zoom#troubleshooting-meeting-scribe). Follow [Google Meet → Installation](/integrations/google-meet/google-meet#installation). For production use, connect via a **Google Cloud Service Account** rather than personal OAuth: service accounts survive staff turnover and give the integration a stable identity. Go to **Integrations → Google Meet**, then toggle on **Meeting transcript and summary**. **Host management** in Google Workspace's Meet safety settings can hold the scribe in the waiting room. See [Google Workspace Meet safety settings block admission](/integrations/google-meet/google-meet#google-workspace-meet-safety-settings-block-admission) for the fix hierarchy. Connect the platform, then enable **Meeting transcript and summary** under **Integrations → Microsoft Teams**. Video meetings need the **separate** [Microsoft Teams Meeting integration](/integrations/microsoft-teams#microsoft-teams-meeting), a distinct OAuth connection with its own permissions, not the main [Microsoft Teams](/integrations/microsoft-teams) integration. Connect [Webex](/integrations/webex/webex), then enable **Meeting transcript and summary** under **Integrations → Webex**. Connect [GoToMeeting](/integrations/go-to-meeting), then enable **Meeting transcript and summary** under **Integrations → GoToMeeting**. *** ## Limits and Scribe Behavior | Behavior | Detail | | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Bot display name** | The scribe appears as **Rootly Scribe** in the Zoom, Google Meet, and Microsoft Teams participant list. A bot already sitting in a live call keeps its previous name until the next session, and past recordings are not relabeled. | | **Waiting-room timeout** | Unadmitted for 10 minutes, the scribe leaves. Reinvite it from the **Scribe** tab or with `@Rootly`. Zoom's **Auto-join bot** avoids admission entirely. | | **Nobody-joined timeout** | If no participants show up within 5 minutes of the scribe joining, it leaves. Reinvite once responders are on the call. | | **Recording sessions** | Each join or rejoin creates a new session, up to 10 per platform per incident. | | **Retries** | If the meeting hasn't started, the scribe retries for a short window. After leaving for any other reason it does not auto-rejoin; reinvite from the **Scribe** tab or with `@Rootly`. | | **Monthly usage cap** | Each team has a monthly recording cap across all platforms. Once exceeded, the scribe skips new meetings until the cap resets or an admin raises it. | | **Google Meet credentials** | Personal OAuth is tied to one user's account and breaks when that user leaves or the token expires. Use a service account for production. | | **Meeting URL** | The scribe joins the URL attached to the incident. URLs not attached to any incident are not picked up. | *** ## Recording Sessions Sessions appear chronologically in the **Scribe** tab, each with its own transcript, summary, and optional video. * **Pause and resume** mid-call without ending the session. Resuming picks up in the same session. * **Reinvite** the scribe if it leaves or is removed, either from the **Scribe** tab or by mentioning `@Rootly` in the incident channel and asking it to re-add the meeting scribe. Reinviting starts a new session and preserves everything already captured. The `@Rootly` route needs [Rootly AI in Slack](/ai/rootly-in-slack/overview) enabled for your workspace, and it runs in the incident channel only. It is capped at your own Rootly permissions like every other Rootly AI action. Rootly AI confirms the platform and the new session number in its reply, so you can see the rejoin landed and how much of that platform's 10-session limit for this incident has been used. A responder asks @Rootly to hop back into the bridge, and Rootly AI replies that the meeting bot was re-added to the Google Meet call as session 6 and is joining shortly *** ## Multilingual Support The scribe transcribes 20+ languages, auto-detecting the language spoken and producing the transcript in it. Your Rootly account team enables it for your workspace. *** ## Privacy and Security **The short version:** | Guarantee | Detail | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------ | | **Redacted before storage** | Every transcript passes PII redaction across 36 categories before it is stored. | | **Scoped access** | Meeting data is visible only within the associated incident and team, with audit logging on deletions. | | **No retention at AssemblyAI or OpenAI** | Neither keeps data after processing. Recall.ai media retention is managed separately by Rootly. | | **You control deletion** | Recordings and transcripts can be deleted from the **Scribe** tab at any time. | The full dossier, covering subprocessors, the data flow, every redaction category, and retention per storage location, lives at [Data Privacy for AI Summaries & Meeting Scribe](/ai/data-privacy-for-ai). *** ## Troubleshooting For platform-specific issues, start with the dedicated pages: Auto-join, waiting rooms, host controls, and Zoom-specific failure modes. Service account setup, admin console settings, and admission failures. Check in order: the meeting URL is attached to the incident (the pinned Rootly-generated link works out of the box; a manually added URL must be [attached to the incident](/incidents/managing-incidents/updating-incident-integration-links)); **Meeting transcript and summary** is toggled on under **Integrations → \[platform]**; and the scribe is being admitted. Zoom without Auto-join needs a human to admit it, and Google Meet Host management can hold it in the waiting room even with a service account. One of the two timeouts fired. Either no one admitted the scribe within 10 minutes, or it got in and no responders joined within 5. Reinvite from the **Scribe** tab or by asking `@Rootly` in the incident channel, and enable Zoom Auto-join to prevent the first case. Post-meeting processing takes a few minutes. Check the **Scribe** tab and refresh. Past 10 minutes with nothing, confirm the scribe actually recorded: there should be a *Recording started* event in the incident timeline. The incident is probably carrying a personal meeting room or a manually generated link. The scribe is scoped to the meeting attached to the incident. Start a fresh meeting from the incident's Slack channel and reinvite the scribe. Your team exceeded its monthly recording cap. Ask your Rootly admin to review usage or raise the limit. *** ## Related Pages Subprocessors, redaction categories, and retention. Where transcripts turn into summaries and catchups. Bridge transcripts as retrospective source material. # Related Incidents Source: https://docs.rootly.com/ai/related-incidents Rootly AI ranks past incidents that match the one you are running, grounded in your team's own history, and surfaces them in the Slack incident channel. ## Overview Rootly AI matches your incident against everything your team already solved. Related Incidents in Slack: a proactive summary card in the incident channel, and the full list of matches with per-incident feedback buttons when a responder asks Matches surface right in the incident channel and on demand, whenever a responder asks. ### Acting on a Match Every match card carries the same set of actions: | Button | What it does | | ------------------- | ---------------------------------------------------------------------------------------------------------------------- | | **Mark as related** | Trains the model that this was a good match, so future recommendations within your team's incident set get better. | | **Not related** | Trains the model that this was not a good match, so future recommendations within your team's incident set get better. | | **Channel** | Opens the Slack incident channel for the related incident. | | **View in Web** | Opens the related incident's details page in Rootly on the web. | Feedback only shapes recommendations for your own team — it never trains models for other customers (see [Privacy](#privacy)). *** ## Grounded Answers Ask `what fixed it?` and get an answer you can act on mid-incident: * **On the record.** The documented resolution is relayed. * **Nothing recorded.** Rootly AI says so and offers the retrospective or timeline. Anything beyond your records is labeled inference ("the pattern suggests"), not fact. *** ## Selective by Design * Reads each incident like a responder would: title, summary, severity, services, and more. * Keeps only genuine, concrete relationships. Similar wording alone doesn't qualify. Matching stays live: a new near-duplicate can hit rank #1 within minutes. ### What Qualifies as a Match | Rule | Detail | | ----------------------- | ---------------------------------------------------- | | **Your org only** | Drawn exclusively from your team's incident history. | | **Confirmed incidents** | Excludes cancelled incidents. | | **Recent history** | Looks back 180 days by default. | | **Public incidents** | Only what the whole channel can see. | On first enable, your history processes gradually in the background. New incidents become matchable within minutes. ### Get Better Matches * **Write specific titles and summaries.** Matching reads what you write. * **Fill in the fields.** Every attribute is signal. * **Record how incidents end.** Resolution notes and [retrospectives](/ai/ai-in-retrospectives/overview) answer "what fixed it?" * **Rate the responses.** **Mark as related** / **Not related** tunes suggestions to the way your team works. *** ## Privacy **Enforced in the product, not by prompt instructions:** | Guarantee | Detail | | ---------------------------------- | -------------------------------------------------------------------- | | **Filtered before the AI writes** | The AI never references, or even alludes to, inaccessible incidents. | | **Private incidents stay private** | Excluded from channels, for any asker or setting. | | **Your history only** | Matches come only from your own incidents. | | **No cross-customer training** | Your data never trains models for other customers. | | **Permissions govern the subject** | Refuses questions about incidents you can't read. | For retention and model detail, see [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai). *** ## Setup Related Incidents is part of Rootly AI, behind the [organization-wide opt-in](/ai/ai-settings), and delivered by [Rootly Agent in Slack](/ai/rootly-in-slack/overview). 1. Open **AI & Agents**. 2. Under **Features**, toggle **Related incidents** on. *** ## Frequently Asked Questions Nothing cleared the relevance bar. If just enabled, your history may still be processing. Confirm **Related incidents** and **Rootly Agent in Slack** are both on. Most misses are eligibility: check [What Qualifies as a Match](#what-qualifies-as-a-match). Weak metadata can also keep a real match below the bar. *** ## Related Pages Everything the agent can do in your incident channels. What Rootly AI is and everything it can do. Data handling and model training controls for Rootly AI. # Rootly AI on Mobile Source: https://docs.rootly.com/ai/rootly-ai-on-mobile Get an Incident Summary card and the Rootly AI chat on your phone while on-call, with the same privacy controls as the web and Slack experiences. ## Overview On any incident you have access to, the mobile app gives you an **Incident Summary** card and the conversational **Rootly AI** agent. Rootly AI on mobile uses the same capabilities and privacy controls as the web and Slack experiences. See [Rootly AI](/ai/ai) for the overview, plus [Data Privacy for AI Summaries](/ai/data-privacy-for-ai) (Incident Summary card) and [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai) (conversational agent). *** ## Enabling Rootly AI on Mobile Admins turn Rootly AI on for mobile from **AI & Agents** in the web app. Each mobile surface has its own toggle. | Toggle | What it controls | | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | | **Opt in to Rootly AI capabilities** | The global gate. Must be on before any Rootly AI feature, on any surface, is available to your team. | | **Incident summarization** | The **Incident Summary** card on an incident's Details tab in mobile. Shares one toggle with the Slack summary features. | | **Rootly Agent in Mobile** | The **Rootly AI chat panel** behind the Ask Rootly launcher on mobile. Enabled separately from **Rootly Agent in Web**. | Only Admins can change these settings. Incident access follows your existing Rootly permissions. *** ## Incident Summary On an incident's **Details** tab, Rootly AI shows a **Summary** card with a short, plain-language overview of what happened and where things stand. Regenerate it at any time to reflect the latest state. Rootly AI incident summary card in the Rootly mobile app Tap the card, or the **Ask Rootly** launcher, to open the full summary in the Rootly AI panel. It breaks the incident down into key points such as the impact, the root cause, the current status, and what's left to do, with suggested questions to dig deeper. Expanded Rootly AI incident summary in the Rootly mobile app *** ## Rootly AI Chat The **Rootly AI** panel is an AI agent for the incident you're viewing. It answers questions in natural language, grounded in that incident's live context: its timeline, severity, status, roles, alerts, and related Slack discussion. Tap **Ask Rootly** to open the chat. Four suggested prompts get you started: * **Catch me up** * **What's the customer impact** * **Who is working on what?** * **Show open action items** Rootly AI answering a question in the Rootly mobile app Your conversation is saved per incident and picks up where you left off. Rootly AI on mobile can **update the incident** on your behalf: status and severity changes, plus incident field updates. It shows you the change and asks for confirmation before anything runs, and it can only do what you can do in Rootly, nothing more. Paging responders and publishing status page updates stay in [Rootly AI in Slack](/ai/rootly-in-slack/overview). *** ## Related Pages Install the mobile app and configure notifications and critical alerts on iOS and Android. Every Rootly AI surface and how they all fit together. How Rootly AI handles data access, encryption, RBAC, audit logs, retention, and PII redaction. The same AI agent in your incident Slack channels. # Getting Started Source: https://docs.rootly.com/ai/rootly-in-slack/getting-started Turn on Rootly AI in Slack with one toggle and a Slack reconnect, then run your first interaction. Covers prerequisites, scopes, and the admin steps. ## Prerequisites * The Slack integration is installed and connected to your Rootly workspace. * You are a Rootly Admin. Once Rootly AI in Slack is on, anyone with an [Incident Response role](/ai/rootly-in-slack/overview#who-can-use-rootly-ai-in-slack) can use it. *** ## Turn On Rootly AI in Slack Setup is one toggle in Rootly plus a Slack reconnect. Reconnecting reinstalls the app with the scopes Rootly AI needs; your existing channels and workflows are unaffected. In Rootly, open **AI & Agents**. Confirm **Opt in to Rootly AI capabilities** is on under **Global**, then toggle **Rootly Agent in Slack** on under **Features**. Go to **Configuration → Integrations → Slack** and click **Refresh Connection** in the banner at the top of the page. A Slack workspace admin clicks **Allow** to re-grant the scopes Rootly AI needs. There is no need to disconnect first. Refreshing reinstalls the app with its current scopes and leaves your workspace selection, channels, Smart Defaults, and workflows intact. See [Refresh and Reconnect](/integrations/slack/slack#refresh-connection) for the full walkthrough. *** ## Your First Interaction Rootly AI is automatically present in incident channels created by Rootly. In any channel it's a member of, type `@Rootly` and ask a question. The Rootly agent's kickoff message in a new incident channel: title, commander, description, and a prompt to mention @Rootly for help Rootly AI receives your request and responds in the same thread. You can also talk to Rootly AI privately. Open Rootly from Slack's **Add agent** menu, or DM the Rootly app directly. Both surfaces answer questions only. ### Try These First * "Catch me up" * "Who's on call?" * "Escalate to SEV1" * "What are the open action items?" For the full guide to each surface, see [Using Rootly AI in Slack](/ai/rootly-in-slack/using-rootly-in-slack). For the full prompt catalog, see [What to Use Rootly AI For](/ai/rootly-in-slack/what-to-use-rootly-for). *** ## Related Pages What Rootly AI in Slack is and everything it can do. Where to invoke Rootly AI, how clarification cards work, and how actions run. The full catalog of prompts, grouped by use case. Common symptoms and how to resolve them. # Rootly AI in Slack Source: https://docs.rootly.com/ai/rootly-in-slack/overview Rootly AI in Slack answers incident questions and acts from your channel: update severity, page teams, draft comms, all within your permissions. ## Overview Ask Rootly AI to: * "This is now a SEV1. Update the incident severity." * "Draft comms to our high-value customers, letting them know the impact of the incident on their product experience." * "Page the security team, and convert this to a private incident." * "Catch me up. What's still open, and who owns it?" Rootly AI in Slack brings the parts of Rootly you reach for during an incident into the channel where your team already operates. Rootly AI in Slack answering "has anything changed on checkout-api?" with a deploy and a feature-flag change pulled from a connected source, including the rollback command Answers like this one draw on your own tools through [Connectors](/ai/connectors/overview): plug in your observability, code, and docs sources and Rootly AI investigates with them. Setup takes one toggle and a Slack reconnect. See [Getting Started](/ai/rootly-in-slack/getting-started). *** ## How Rootly AI in Slack Works Rootly AI reads from your Rootly data and the channel conversation, including bridge call transcripts when available, to answer questions and take actions on your behalf. Type `@Rootly` and ask. It uses the incident's live context to decide how to respond, and replies in-thread so the channel sees any action taken. Rootly AI also answers in the Slack assistant pane and in DMs; those two surfaces are for questions only. See [Using Rootly AI in Slack](/ai/rootly-in-slack/using-rootly-in-slack) for the full guide. Model details, including failover behavior, are documented in [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai). *** ## Key Capabilities at a Glance | Capability | What it does | Example ask | | :---------------------------------------------- | :------------------------------------------------------------------ | :---------------------------------------------------------------- | | Catch me up | Structured brief of the incident's state, key events, and open work | "@Rootly what's going on right now?" | | Who's on call | Current and historical on-call lookups | "@Rootly who's on call for the Security team?" | | Page responders | Pages a team, user, or escalation policy via Rootly On-Call | "@Rootly page the Search Experience team." | | Update an incident | Changes severity, status, roles, and fields, confirming what it did | "@Rootly bump the severity to SEV2." | | [Find related incidents](/ai/related-incidents) | Ranked matches from your own incident history | "@Rootly are there any related incidents involving this service?" | | Draft customer updates | Slack-ready or status-page-ready update copy from current state | "@Rootly write a draft update for leadership and our partners." | This table is a sample. The full prompt catalog lives in [What to Use Rootly AI For](/ai/rootly-in-slack/what-to-use-rootly-for). *** ## Who Can Use Rootly AI in Slack Rootly AI in Slack requires an **Incident Response role**. Without one, Rootly AI asks you to contact your admin, and requests to page or check who is on call are refused. *** ## How Permissions Work Rootly AI uses each user's existing Rootly permissions. If a user can't see a private incident in the web app, Rootly AI won't surface it for them in Slack. If a role doesn't allow paging, Rootly AI declines to page when that user asks. Permissions are managed in **Configuration → Roles & Permissions**. There is no separate AI permission system. *** ## Frequently Asked Questions Rootly AI has to be invited to a channel before it sees anything there or takes action. User permissions still apply on top. No. Paging happens through Rootly On-Call only. If you have a third-party paging integration configured elsewhere in Rootly, Rootly AI will not fall back to it. *** ## Related Pages Turn on Rootly AI in Slack and walk through your first interaction. Where to invoke Rootly AI, how clarification cards work, and how actions run. The full catalog of prompts, grouped by use case. Common symptoms and how to resolve them. # Troubleshooting Source: https://docs.rootly.com/ai/rootly-in-slack/troubleshooting Fix Rootly AI in Slack when it stays silent, refuses a request, or misreads an incident, including the scope limits behind each deliberate refusal. Most issues resolve with one of the fixes below. If yours doesn't, contact your Rootly account team. ## Quick Fixes | What you're seeing | The fix | | :------------------------------------------------------------------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `"AI agent is not enabled for this team."` | An admin opens **AI & Agents**, turns on **Opt in to Rootly AI capabilities** and **Rootly Agent in Slack**, then clicks [**Refresh Connection**](/integrations/slack/slack#refresh-connection) on the Slack integration page. | | Rootly AI answers, but a Slack action fails on permissions | The install predates the scopes the action needs. Click [**Refresh Connection**](/integrations/slack/slack#refresh-connection). No disconnect required. | | Rootly AI asks you to contact your admin, or refuses to page or look up on-call | You need an Incident Response role. An admin assigns one in **Configuration → Roles & Permissions**. | | No reply at all | Check the Rootly and Slack status pages, then re-ask. | | "It doesn't have access to that" | Your permissions are the ceiling: if you can't see it in the Rootly web app, Rootly AI can't show it to you. Private incidents are only accessible from inside their own channel. | | An action didn't happen | Read the thread. Rootly AI explains why in plain English; permission blocks and per-status or per-severity restrictions are the usual cause. | | A clarification card expired | Cards last 60 minutes. Re-ask the question for a fresh card. | | `"I reached the maximum number of steps for this request."` | The ask was too broad. Try `tell me about this incident` instead of `audit all our open incidents`. | | A generic error | Wait a moment and re-ask. If it keeps failing, tell your Rootly admin or account team. | | Requests pausing after heavy use | The per-team token budget resets within 60 seconds. If you hit it often, ask your account team about higher limits. | | It picked the wrong record between two similar names | Answer from the clarification card's options instead of retyping the name, and prefer exact, unique names. | | A wrong or off answer | Click 👎 and pick a category. Feedback informs prompt and tool improvements; it does not directly retrain the model. | *** ## If It Refuses a Request Refusals are usually deliberate scope, not failures: Rootly AI doesn't touch production runtimes, page through third-party vendors, write code, or change platform configuration. The full list lives at [What Rootly AI Can't Do](/ai/rootly-in-slack/what-to-use-rootly-for). *** ## Good to Know * Times render in your **team's time zone**. Ask for UTC, your own time zone, or any IANA zone and Rootly AI converts. * **Rootly AI in Web is read-only by design**; write actions live in Slack and mobile. * **Rootly AI on Mobile** takes incident updates such as status and severity, confirming with you before anything runs. Paging and status page publishing stay in Slack. * **If your role recently changed**, sign out of Slack and back in so Rootly AI picks up your current identity. * **Tenant isolation is enforced by design.** Rootly AI never surfaces incidents from teams you don't belong to. *** ## Related Pages What Rootly AI in Slack is and everything it can do. Turn on Rootly AI in Slack and walk through your first interaction. The full catalog of prompts, grouped by use case. What Rootly AI sees, retention, and model training controls. # Using Rootly AI in Slack Source: https://docs.rootly.com/ai/rootly-in-slack/using-rootly-in-slack Where to invoke Rootly AI in Slack, what to expect while it works, and how clarifications and write actions run. ## Where to Interact with Rootly AI Rootly AI is added automatically to incident channels created through Rootly. Get started by declaring an incident with `/rootly new`, then mention `@Rootly` in the channel or thread and ask "catch me up" or "page the database on-call team". Rootly AI always replies in-thread. The channel is one of three surfaces: | Where | Can it act? | Best for | | :----------------------- | :----------------------- | :----------------------------------------------------------------------------------------------------------------- | | **Incident channel** | Yes, the full action set | Running the incident: updates, paging, roles, and comms where the whole team sees them | | **Slack assistant pane** | Questions only | Catching up on the incident in view without distracting the responding team | | **Direct message** | Questions only | On-call lookups, incidents you're not actively in, personal questions like "What action items are assigned to me?" | Every surface requires an [Incident Response role](/ai/rootly-in-slack/overview#who-can-use-rootly-ai-in-slack), and access is governed by your Rootly permissions: you only see incidents and data you're entitled to. Ask questions in the incident channel when the context might be relevant to other teammates, so they can also benefit from the reply. *** ## Interacting with Rootly AI While Rootly AI works, a status indicator shows what it's doing, for example "Checking who's on call". Replies include the answer and a confirmation of any action taken. ### Giving Feedback Rate replies with 👍 / 👎. Feedback flows into Rootly's evaluation pipeline and does not directly fine-tune the model. *** ## Providing Clarifications If something is ambiguous or required data is missing, Rootly AI asks rather than guesses. | Situation | Example | | :------------------------- | :------------------------------------------------------------------------------------------------------------------- | | **Ambiguous person** | "Page David." → *"Which David did you want to page?"* with options to select the right one | | **Ambiguous severity** | "Escalate this." → *"What severity should I set?"* with buttons for the team's configured severities | | **Missing required field** | Moving to a status that requires a cause or environment → *"What environment is affected?"* with fields for the data | Rootly AI asking "Which Andre would you like to page?" with a button for each matching user and an expiry notice ### Using Clarification Cards Based on how much input Rootly AI needs, you'll be able to reply via: | Options | How you answer | | :----------------------------------- | :-------------------------------------------------------- | | Up to 5 | Buttons, with the first highlighted as the primary choice | | 5 to 25 | A single-select dropdown | | More than 25, or no fixed answer set | Free text, replied in the thread | Cards expire after **60 minutes**. Re-ask your question to get a fresh card. *** ## Taking Action with Rootly AI Ask for an action and Rootly AI runs it, confirming what it did in its reply. When an action is destructive, or Rootly AI wants your sign-off first, it posts the change as a card with a **Confirm** button and runs only after you approve. | You say | Rootly AI replies | | :---------------------- | :-------------------------------------------------- | | "I'll take commander." | *"You're now the commander."* | | "Escalate to SEV1." | *"Set severity to SEV1."* | | "Page the SRE on-call." | *"Paged the SRE team via their escalation policy."* | Rootly AI proposing an Update incident roles action after being asked "can you make me commander?", with a Confirm button before anything runs If anything fails, Rootly AI tells you why in the same thread. Every action is capped at **your permissions** and attributed to you in the audit trail. Rootly AI cannot perform any action you couldn't perform yourself in the Rootly web app. *** ## Worked Example: Paging an On-Call Team This shows the clarification flow in action: * Type `@Rootly page the team` in the incident channel. * Rootly AI searches your Rootly catalog for the team to page. * If multiple teams match, Rootly AI posts a clarification card: `"Which team do you want to page?"` with a dropdown. You pick one and click **Confirm**. A clarification card asking "Which team do you want to page?" with a dropdown listing the workspace's teams * Rootly AI pages via Rootly On-Call to the team's current on-call, using their configured notification preferences. Rootly AI replies: `"Page request submitted to Rootly On-Call for the Rootly team."` The audit trail attributes the page to you, not to Rootly AI. * **If you don't have permission to page in Rootly, Rootly AI tells you so and stops.** *** ## Related Pages What Rootly AI in Slack is and everything it can do. Turn on Rootly AI in Slack and walk through your first interaction. The full catalog of prompts, grouped by use case. Common symptoms and how to resolve them. # What to Use Rootly AI For Source: https://docs.rootly.com/ai/rootly-in-slack/what-to-use-rootly-for Example prompts for Rootly AI in Slack, from getting oriented and checking who is on call to multi-step requests, plus what it deliberately will not do. ## Overview Rootly AI in Slack answers questions grounded in your Rootly data and takes actions on your behalf, confirming destructive actions before they fire. Everything below requires an [Incident Response role](/ai/rootly-in-slack/overview#who-can-use-rootly-ai-in-slack). *** ## Everyday Questions ### Getting Oriented | **You ask** | **What Rootly AI does** | | :------------------------------------------------ | :-------------------------------------------------------------------------------------- | | "Catch me up" | Gives you a brief of the problem, status, theory, open action items, and who's involved | | "What's happened in the last hour?" | An activity digest of timeline events and channel discussion | | "Who's the commander?" | Names the current commander and other assigned roles | | "What services are impacted?" | Lists affected services, environments, and functionalities | | "Are any action items still open?" | Lists open action items with assignees and due dates | | "ELI5" or "Catch me up as a non-technical member" | Adapts tone and technical depth for different audiences | ### Look Up People, Teams, On-Call | **You ask** | **What Rootly AI does** | | :----------------------------------------------- | :---------------------------------------------------------------- | | "Who's on call for payments?" | Current on-call for the named team, escalation policy, or service | | "Who was on call when this started?" | Historical on-call for the incident's start time | | "What's the escalation chain for the SRE team?" | Full escalation policy with each step | | "Are there coverage gaps in the SRE rotation?" | Schedule and shadow analysis surfacing gaps | | "Find Sam in the team" | Searches for "Sam" across name, preferred name, and email | | "Who's pageable on the payments team right now?" | Filters team members by pageable status | ### Page, Escalate, Run the Incident Write actions are capped at your existing Rootly permissions. | **You ask** | **What Rootly AI does** | | :----------------------------------------- | :------------------------------------------------------------------------------ | | "Page the payments on-call" | Looks up the team, finds the current on-call, pages them through Rootly On-Call | | "Page Sam" | Resolves the user, confirms, pages | | "Page the SRE escalation policy" | Triggers the named escalation policy | | "Make me commander" | Self-assigns the commander role | | "Mark this SEV1" | Updates severity, confirms in reply | | "Mark this mitigated" | Moves the incident to the mitigated state with required-field check | | "Resolve this" | Resolves the incident | | "Set the impacted service to checkout-api" | Updates the impacted service list using discovery, no hallucinated names | | "Make this incident private" | Changes visibility | | "Request coverage for my shift on Friday" | Files an on-call coverage request | ### Action Items, Retros, Comms | **You ask** | **What Rootly AI does** | | :------------------------------------------------------------------ | :------------------------------------------------------------------------------ | | "Create an action item: investigate the cache miss; assign to Andy" | Parses intent, resolves the assignee, creates the item | | "Reassign the cache item to Rigel and add 4 more reviewers" | Updates assignee and adds reviewers in one go | | "Mark the rollback item done" | Closes the action item | | "Delete that duplicate action item" | Removes the item after confirmation | | "Draft a customer update" | Composes a Slack-ready or status-page-ready update from current state | | "Post a status page update saying we're investigating" | Drafts and (after confirmation) publishes a status page update | | "Add a timeline event for the rollback at 3:42 PM" | Creates a custom timeline event; backdating supported | | "Generate the retro summary" | Drafts a starter retrospective the team can add to their Retrospective document | Rootly AI drafting a status page update in Slack: title, post copy, and a suggested status with the reasoning behind it ### Search and Lookups | **You ask** | **What Rootly AI does** | | :---------------------------------------------------------- | :---------------------------------------------------------------------------------------------- | | "Show me open SEV1s" | Filters by status and severity | | "How many incidents touched checkout-service this quarter?" | Searches by service and date range, counts results | | "What's our average time-to-mitigate for SEV1s this year?" | Searches incidents and reasons over the result set | | "What custom fields are on this incident?" | Lists configured custom fields and their values | | "What status can I move this to from here?" | Lists valid next statuses given the incident's current state, team config, and sub-status rules | | "List my teams" | Returns teams the requesting user belongs to | | "What's 3:47 PM UTC in my time zone?" | Converts using your configured zone or a named IANA zone | *** ## More Complex Requests Rootly AI in Slack can also run several operations at once to answer your question, and it reasons over the results to handle requests that don't map to one specific ask. ### Critical Timeline Analysis Ask Rootly AI *"What's missing from this timeline? Be critical."* Rootly AI reads the timeline, channel discussion, roles, and standard process expectations, then identifies gaps a senior responder would catch in a retro. Things like: no commander formally assigned, no root cause documented, the incident was resolved before the fix was merged, no status page update. ### Severity Second Opinion Ask *"was SEV3 the right call?"* Rootly AI looks at the affected services, duration, the responder pattern, and customer-impact signals in the channel, then gives a nuanced opinion, pushing back when the evidence supports it. ### Extended Retrospective Conversations Rootly AI supports back-and-forth conversations during a retrospective. Ask "what could have gone better?" → "how did comms look?" → "who should have taken what role?" → "similar past incidents?" → "was the severity call right?" → "how could we have resolved faster?" Rootly AI maintains context across the thread. ### Adaptive Technical Depth Rootly AI adapts to the asker. *"Catch me up"* produces a structured exec brief. *"Catch me up, I'm a Staff Engineer"* produces a technical response naming the failing code path, the relevant error codes, and the race condition. Same incident, different audience. ### Multi-Step Actions Rootly AI can chain multiple write actions in a single conversation. For example: "page the on-call for payments, then mark this SEV1, and create an action item to investigate." Each destructive step confirms separately. The final reply summarizes everything Rootly AI did. *** ## What Rootly AI Can't Do * **Writes only happen inside incident channels.** The Slack side pane and DMs are read-only by design. * **Paging is through Rootly On-Call only.** Even if PagerDuty, Opsgenie, or JSM Ops are connected elsewhere in Rootly, Rootly AI will not page through them. * **No production runtime actions.** Rootly AI won't run kubectl, roll back a deploy, restart a pod, or flip a feature flag. It can create an action item and page someone who will. * **No code generation or PR creation.** Rootly AI doesn't write code. * **Reactive by design.** Rootly AI responds when asked; it doesn't interject in your channels uninvited. * **It won't invent data.** If the answer isn't in your Rootly data, the channel discussion, or a connected external source, Rootly AI says so rather than guessing. *** ## Related Pages What Rootly AI in Slack is and everything it can do. Turn on Rootly AI in Slack and walk through your first interaction. Where to invoke Rootly AI, how clarification cards work, and how actions run. Common symptoms and how to resolve them. # Alert Deduplication Source: https://docs.rootly.com/alerts/alert-deduplication Collapse repeat events from the same monitor into a single open Rootly alert using a stable identifier, so responders aren't paged twice. ## Overview Monitoring systems often keep sending events while a condition remains unhealthy — the same Datadog monitor or CloudWatch alarm can fire every minute until you mitigate. Without intervention, that's one new Rootly alert per event and one page per alert. **Alert Deduplication** collapses those repeat events onto a single open alert, so the responder sees the count climbing instead of getting paged again. Rootly provides **two layers** of deduplication: 1. **Configurable per–Alert Source dedupe** — by stable unique identifier (the primary mechanism) 2. **Payload-based duplicate suppression** — exact-body matching as a backstop Together they keep the alert list clean while preserving a full history of how often a condition has fired. Trying to decide between Alert Deduplication and [Alert Grouping](/alerts/alert-grouping)? Use the picker on the [Alerts](/alerts/alerts#reducing-alert-noise) page — same monitor re-firing → Deduplication; multiple different monitors lighting up at once → Grouping; both → enable both. *** ## Combining Alerts by Unique Identifier At the **Alert Source** level, you can tell Rootly to **combine duplicate alerts into one alert** using a stable identifier extracted from the payload or alert fields. To configure: Open an **Alert Source** in Rootly Web and go to the **Events** tab. Toggle on **Combine duplicate alerts into one alert**. Choose where the identifier comes from: * **Payload** — use a JSONPath into the raw payload (recommended for most cases) * **Alert field** — use a specific alert attribute Provide the **deduplication key path** (for example, a JSONPath value). Optionally apply a **regular expression** to normalize the value before matching. If deduplication is enabled, Rootly requires a valid **unique identifier**; the UI will block saves until you configure one. In the Alert Source UI, you can preview sample alerts.\ Clicking a **purple pill** in the payload viewer copies its JSONPath — use this directly as your deduplication key path. ### What Happens When a Duplicate Arrives When a new alert arrives and its deduplication key **matches an existing open alert**, Rootly: * **Does not create a new alert** * Adds a **duplicate/ignored request event** to the original alert * Increments the alert's **requests count** * Updates `last_request_at` This behavior shows up in the UI as: * A **badge** like `×3` next to the alert * A tooltip indicating how many matching requests have been received and when the last one arrived ### Choosing a Stable Deduplication Key The whole mechanism depends on the key being stable across repeat events. Aim for fields the sending tool guarantees are constant for the same underlying condition: * **Monitor IDs** (Datadog `alert_id`, CloudWatch alarm ARN, PagerDuty incident key) * **Ticket or issue IDs** (Jira issue key, Zendesk ticket ID, Sentry issue ID) * **External identifier fields** mapped through your alert source configuration Avoid: * Free-form message text (likely to vary between events) * Timestamps (always vary) * Aggregated counts or percentages embedded in the payload If you're not sure what's stable, start with a narrow key (a specific JSONPath) and watch the requests count. If repeat events are properly stacking, the count climbs on the original alert instead of new alerts appearing. *** ## Payload-Based Duplicate Suppression In addition to key-based dedupe, Rootly can also suppress **exact payload duplicates** at the team level. This is a backstop for cases where the sending tool retries the same webhook request — for example, when its webhook delivery is configured for at-least-once semantics and Rootly receives the same body twice in quick succession. When enabled, if Rootly sees another alert with the exact same **request body** as a previous "ignored" event for that alert: * The request is **counted** against the same alert * Rootly records an internal event (`ignored_alert_request`) * **No new alert is created** Duplicate alerts are **not silently discarded**.\ They are tracked as additional requests on the original alert and reflected in the alert's counter and timeline events. *** ## Best Practices * **Choose a stable deduplication key.** Use identifiers like monitor IDs, incident keys, or ticket IDs — avoid full message text or highly variable fields. * **Start narrow, then broaden if needed.** Begin with conservative dedup rules and relax them as you gain confidence, to avoid accidentally merging unrelated alerts. * **Watch the requests count.** A high `×N` count on an alert is a strong signal of ongoing or flapping conditions and can inform severity and prioritization. * **Confirm the key normalizes correctly.** If your sending tool occasionally varies the key (different casing, extra whitespace), use the optional regex to normalize before matching. * **Pair with Alert Grouping when you have both noise patterns.** If different monitors on the same service all fire at once *and* each one keeps re-firing, enable both Deduplication and [Alert Grouping](/alerts/alert-grouping). Deduplication runs at the source level before alert creation; Grouping runs on whatever survives. *** ## Troubleshooting Confirm that **Combine duplicate alerts into one alert** is enabled on the Alert Source and that the **deduplication key path** points to a stable, consistent value across repeat events. Inspect a sample payload in the source preview and copy the JSONPath directly from the purple pill to avoid typos. If the sending tool varies the key between events (different casing, extra whitespace), add a regex to normalize before matching. Deduplication requires a valid unique identifier. If the **Combine duplicate alerts** toggle is on but the key path is empty or invalid, Rootly blocks the save. Either provide a key path or toggle deduplication off. Either turn off **Combine duplicate alerts into one alert** on the Alert Source entirely, or change the deduplication key to a field that varies per event (a timestamp, event ID, or unique sequence number). Be aware that disabling deduplication means every repeat event creates a new alert and may re-page. Open both alerts and compare the field your deduplication key path points at. Common culprits: the sending tool sends a slightly different value (different casing, trailing whitespace, embedded timestamps), or the key path is too narrow and resolves to slightly different JSON locations in the two payloads. Use a regex to normalize, or pick a coarser stable identifier. *** ## Related Pages The complementary tool — collapse different-monitor alerts on the same underlying incident into a single leader-driven group. Route alerts to services, teams, and escalation policies based on payload fields and labels. The umbrella page covering alert ingestion, sources, manual paging, and the noise-reduction picker. # Alert Fields Source: https://docs.rootly.com/alerts/alert-fields Use Alert Fields to extract, normalize, and store structured alert data for routing, enrichment, automation, and triage across Rootly. Alert Fields allow you to extract key information from incoming alert payloads and store it in a normalized format that can be used consistently across Rootly. This removes the need to understand every alert provider’s unique payload structure—Rootly handles that translation automatically. Alert Fields are populated automatically on alert creation or update, depending on the mappings you configure on each Alert Source. *** ## Overview Different observability tools send alerts in very different formats. Alert Fields standardize this by letting you: * Normalize metadata such as environment, severity, region, service, or product area * Route alerts consistently, regardless of which tool sent them * Enrich alerts with structured information to help responders triage faster * Build metrics and dashboards using clean, uniform data * Simplify workflows across multi-tool monitoring environments Alert Fields become part of the alert record itself and are accessible everywhere Rootly evaluates conditions, displays alert information, or triggers automation. *** ## How Alert Fields Work When an alert is ingested: 1. Rootly reads the raw payload from the alert source. 2. Each configured mapping is evaluated using Liquid. 3. The results are stored as `alert_field_values`. 4. The normalized fields are then available throughout the platform. Rootly automatically seeds built-in fields when creating a new Alert Source so you can map values immediately. For tools without a dedicated Rootly integration, field mappings work the same way through the [Generic Webhook Alert Source](/integrations/generic-webhook-alert-source/generic-webhook-alert-source) — define the Liquid mapping per field, and any JSON payload becomes a normalized alert. *** ## Examples ### Route Alerts by Impacted Product Area Map a `product_area` field using Liquid, then build routes that send alerts to the correct on-call team. ### Enrich Alert Details for Responders Extract severity, region, deployment ID, customer tier, or any custom metadata. ### Build Better Metrics and Dashboards Use normalized field values to track trends without parsing different payload structures. ### Simplify Multi-Tool Environments Create one `severity` field and map Datadog, PagerDuty, Opsgenie, and Sentry severities into it consistently. *** ## Configuring Alert Fields To configure Alert Fields: Navigate to the Alert Source and select the **Fields** tab to view all fields currently mapped. Click **Add Field** to select an existing field or create a new one.\ New fields immediately become available across all alert sources. Specify a Liquid expression that extracts a value from the alert payload.\ Reference recent alerts using the preview on the right. Click any purple pill in the payload viewer to copy its Liquid expression. All future alerts from this source will populate the field using your mapping. If the title or description fields are left blank, Rootly automatically assigns reasonable defaults (for example, using the subject line for email alert sources). *** ## Using Alert Fields in Alert Routes Alert Fields can be referenced directly in Alert Route conditions.\ This allows your routing logic to be built once and work across all sources, as long as each source maps its payload fields correctly. Examples: * Route all `severity = critical` alerts to the primary on-call * Route `region = EU` alerts to the EMEA team * Route alerts associated with a specific service or component * Route customer-impacting alerts differently from internal signals Learn more on the **[Alert Routes](/alerts/alert-routing)** page. *** ## Using Alert Fields for Auto-Resolution Rules (Email Sources) Email alert sources support auto-resolution rules based on Alert Fields. To set this up: Open the email alert source you want to configure. Define auto-resolution conditions. Reference Alert Fields in those conditions (for example, subject text, severity, environment). When a new email alert arrives, Rootly evaluates your conditions and automatically resolves the alert if they match. *** ## Accessing Alert Fields as a Responder Responders can view alert field values in: * **Web:** Alert details panel * **Slack:** Alert details and context blocks * **Mobile:** Alert details in the Rootly mobile app This gives responders immediate access to normalized metadata without reviewing raw JSON payloads. *** ## Best Practices * **Normalize fields across all alert sources.** Use shared fields (severity, environment, service, region, etc.) to keep routing behavior consistent across monitoring tools. * **Use the preview data for accurate Liquid expressions.** Test Liquid mappings with real alerts to avoid mismatches or null values. * **Centralize routing logic using Alert Fields.** Map differences at the Alert Source layer rather than building multiple routing rules for each provider. * **Keep field values clean and human-readable.** Adopt consistent formatting across sources (for example, PRODUCTION, STAGING, DEV). * **Reference fields in workflows and automation.** Alert Fields make workflow triggers more reliable and much easier to maintain. *** ## Troubleshooting * Ensure the field is mapped on the correct Alert Source. * Confirm your Liquid expression returns a value. * Check that the alert payload changed (fields update when payload changes). * Verify your team has Alert Fields enabled. * Confirm the payload path is accurate. * Use purple-pill copy from the alert payload preview. * Add default guards in Liquid where necessary. * Not all providers send uniform payloads. * Some alerts may lack the field entirely. * The mapping may require a conditional or fallback. * Verify the field is correctly populated before routing. * Compare formatting (case sensitivity, whitespace, arrays). * Ensure the route condition exactly matches the field value. *** ## Summary Alert Fields give your organization a unified layer of structured alert data across multiple tools. They power consistent routing, faster triage, stronger automation, and cleaner reporting—making them one of the most important parts of a scalable alerting setup in Rootly. Let them do the heavy lifting so your responders don’t have to. *** ## Related Pages The umbrella page covering programmatic alert ingestion, sources, and noise reduction. Route rules use Alert Fields as their most stable condition source. Use Alert Fields for dynamic urgency assignment that survives payload changes. # Alert Grouping Source: https://docs.rootly.com/alerts/alert-grouping Reduce alert noise by automatically grouping related alerts into a single, leader-driven alert based on time windows, fields, and matching attributes. ## Overview Alert Grouping reduces noise and alert fatigue by consolidating related alerts into a **single leader alert** with associated **member alerts**.\ Responders are paged for the leader, while subsequent matching alerts join its group silently. This helps you: * Avoid duplicate pages from multiple monitors on the same issue * Keep alert timelines focused on one “source of truth” * Improve prioritization and reduce cognitive load for on-call responders **Grouping vs. Deduplication.** Both features reduce noise, but they're built for different problems. Use **Alert Grouping** when *different* monitors all fire on the same underlying incident (latency + error rate + DB health). Use [Alert Deduplication](/alerts/alert-deduplication) when *the same* monitor keeps re-firing while the issue is unresolved. See [Deduplication vs. Alert Grouping](/alerts/alerts#deduplication-vs-alert-grouping) for the full side-by-side comparison. **Non-paging alerts** (alerts that do not route to any team, service, or escalation policy) are not grouped. Only alerts that participate in routing and paging can form or join groups. *** ## How Alert Grouping Works Each **Alert Group** defines *which alerts belong together* through three settings: What the alert was routed to — team, service, or escalation policy. Alerts routed elsewhere are never candidates for this group. How long alerts are considered part of the same episode. The window is rolling and anchored to the last alert added. Which alert attributes or payload fields must match for the alerts to be treated as the same episode. When an alert arrives: 1. Rootly finds any **active group** whose rules and time window match. 2. If a match is found: * The existing alert becomes (or remains) the **group leader** * The new alert is added as a **member**, and **does not re-page** 3. If no group matches: * A **new leader alert** and group are created (and the responder is paged according to routing rules) *** ## Group Leaders vs. Members Within a group: * The **leader alert**: * Is the alert that originally caused the page * Acts as the **source of truth** for the group * Drives status and noise updates (for example, acknowledged, resolved) * **Member alerts**: * Join silently (no additional pages) * Inherit status changes from the leader * Appear on the group timeline for context You can view an alert’s group on the **Alert details page** under the **Alert Group** tab. *** ## When to Enable Alert Grouping Alert Grouping is especially useful when: * A single service has **many monitors** (error rate, latency, CPU, DB health, etc.) * A failure in one component triggers multiple alarms across: * APM, logging, metrics, and infrastructure tools * You want to treat a burst of related alerts as **one incident episode** rather than many independent pages Example: > “Service A has 5 monitors. When it goes down, all 5 fire at once. With grouping, responders get **one page** and then see all related alerts attached to that leader.” *** ## Creating an Alert Group To create a new Alert Group in the web app: * Go to **Alerts → Grouping** * Click **+ New Alert Group** * Enter a **Name** (required) and a **Description** (optional) Destinations define **which routed alerts** are candidates for this group. Under **Destinations**, choose one of: * **All services, teams, and escalation policies** * **All services** * **All teams** * **All escalation policies** * **Select routes** – only alerts routed to specific: * Services * Teams * Escalation policies To group only alerts routed to specific targets: * Choose **Select routes** * Pick the services, teams, or escalation policies you want to include Destination scoping ensures you don’t accidentally group unrelated alerts\ (for example, SRE and Security alerts) into the same cluster. Next, decide how strictly routing must match inside a group. Alerts must be routed to the **exact same** service, team, or escalation policy. Example: alerts routed to Service A group only with other Service A alerts. Alerts routed to **any** of the selected targets are allowed in the same group. Example: all alerts routed to any SRE team are grouped together. The **Time Window** defines how long alerts should be considered part of the same group. * Specify the window in **minutes** * Rootly supports values between: * **5 minutes (minimum)** * **7 days (maximum)** The time window is **rolling** and is anchored to the **last alert** added to the group. With a **10-minute** window, the group remains open as long as new alerts keep arriving within 10 minutes of the last one.\ Once 10 minutes pass with no new alerts, a **new group** will be created next time a matching alert arrives. Content Matching defines **what must be similar** between grouped alerts. Each field below is a group-on option: Matches the alert's `summary`. Matches the alert's `description`. Matches the urgency value assigned to the alert — whichever urgency levels your team has configured. The alert's `external_url` — for example, a link back to Datadog or PagerDuty. Any field within the incoming alert payload, addressed with a JSONPath expression. A normalized field you've configured on the Alert Source. Operators include: * `is one of` / `is not one of` * `contains` / `does not contain` * `starts with` / `ends with` * `matches regex` * `is empty` To group by a payload field, choose **Payload** and provide a **JSONPath**\ (for example `$.alert.feature`). For convenience, Rootly provides quick toggles such as **Group by Title** and **Group by Urgency**, which automatically create the appropriate underlying conditions. *** ## Working with Alert Groups Once your Alert Groups are configured and active: * The **first alert** that matches a group becomes the **leader** and triggers paging * Subsequent alerts that match: * Are added as **members** * **Do not** re-page responders * Update the group’s timeline with additional context When you change the leader’s status: * All member alerts’ statuses are updated to match (for example, resolving the leader resolves its members) * Noise controls on the leader (for example, marking as noise) propagate to members as they join You can inspect group membership by: * Opening an alert in the web UI * Navigating to the **Alert Group** tab *** ## Example: Grouping Multiple Monitors for One Service Suppose you have the following monitors for `checkout-service`: * Error rate > threshold * P95 latency > threshold * CPU saturation * Database connection errors If the database experiences a serious issue, **all four monitors** might fire. Without grouping: * The on-call may receive 4 pages * Each alert appears as independent noise With alert grouping: * Destination condition: **Select routes → Service: checkout-service** * Route logic: **Groups should only contain alerts for the same route** * Time window: **10 minutes** * Content matching: **Group by Service + Urgency** (or only by destination) Result: * First alert pages and becomes the **leader** * Remaining alerts join silently as **members** * The responder sees one alert with a rich history of related signals *** ## Best Practices * **Start narrow** * Group by **route + short time window** first; broaden later if needed * **Use content carefully** * Combining **Title + Urgency + Payload** can create very precise groupings * Avoid overly broad conditions that might lump unrelated incidents together * **Align with incident semantics** * Think of an Alert Group as “all signals about the same episode,” not “all alerts about the same service forever” * **Regularly review grouped alerts** * Use the Alert Group tab and alert timelines to validate whether groupings still make sense as your monitoring evolves *** ## Troubleshooting * Verify the **Destination** condition includes those routes * Check whether the **route logic** is set to “same route” vs “any selected route” * Confirm the **Time Window** hasn’t expired between alerts * Make sure content matching conditions (Title, Urgency, Payload, etc.) actually match * Narrow the **Destination** scope (for example, from “all teams” to “specific teams/services”) * Switch from “any selected route” to “same route” * Add or tighten **Content Matching** conditions (for example, require matching Title and Urgency) * Reduce the **Time Window** duration * The previous group’s time window may have expired * Conditions may have changed (for example, different title or urgency) * Destination may differ (for example, different service or team) * This is expected: only alerts that **route to a team, service, or escalation policy** can group * Convert important non-paging alerts into routed alerts via **Alert Routes** if you want them to participate in grouping *** ## Related Pages The umbrella page covering programmatic alert ingestion, sources, and noise reduction. Combine repeat firings of the same monitor before they turn into duplicate pages. How alerts reach destinations — grouping happens after routing, on the same routed alerts. # Alert Routing Source: https://docs.rootly.com/alerts/alert-routing Use Alert Routes to determine which teams, services, and escalation policies receive incoming alerts from your monitoring tools based on conditions you define. ## Overview Alert Routing ensures that alerts from your monitoring and observability systems reach the correct responders quickly and reliably. Rootly provides a unified routing layer that works across all alert sources, enabling consistent on-call workflows. Rootly supports two routing pathways: 1. **Routing inside your monitoring tool** (Datadog, PagerDuty, Opsgenie, etc.) 2. **Routing inside Rootly** using centralized **Alert Routes** This guide focuses on routing **inside Rootly**. *** ## What Is an Alert Route? An **Alert Route** defines *when*, *how*, and *to whom* Rootly should send alerts. It supports evaluation against: * Alert Sources * Alert Fields (normalized metadata) * Raw payload values (JSONPath) * Teams, services, and escalation policies **Tip:** Alert Routes work best when combined with **Alert Fields**, which let you write stable routing logic even when payload schemas vary across providers. *** ## Creating an Alert Route Navigate to **Alerts → Routes** and click **New Route**, then configure the following: Give the route a descriptive title that clarifies its purpose. Select one or more alert sources the route should evaluate. Sources can be added or removed at any time. A route can only evaluate sources that already exist, so connect the tool first — see [Alert Sources](/alerts/alert-sources) for how to connect one and what to configure on it, or the [integrations catalog](/integrations/overview) for per-vendor setup. The owning team controls who can edit the route. **Permissions:** * Team Admins may only create routes **for their own team**. * Teams can only route alerts **from alert sources they own**. After creating a route, you can begin adding Routing Rules. *** ## Configuring Routing Rules Routing Rules determine *which alerts should page responders* and *where they should go*. Click **Add routing rule** to create one. *** ## Routing Rule Conditions Conditions define when a rule should trigger. ### Select a Field You may reference: * **Alert Fields** (recommended) * **Payload values via JSONPath** Alert Fields ensure your routing logic remains stable even if payload structures change. ### Choose an Operator Supported operators include: * *is one of* * *contains* * *starts with* * *matches regex* * *is empty* * and more Use **regex** when values vary across alert providers and need flexible matching. ### Add Additional Conditions Use **AND/OR** groups to define complex routing logic. ### Live Preview Rootly shows matching historical alerts to validate your logic. *** ## Routing Rule Destinations Each rule must specify **who receives the alert**. Rules can target any of three destination types, and a single rule may include multiple destinations — all are paged when it fires. Pages the team's configured escalation policy. Recommended for easier reporting and maintenance. Pages the service's configured escalation policy. Recommended alongside teams. Page a policy directly. Works, but is harder to report on than routing through a team or service. Routing to a team or service automatically triggers its configured escalation policy. For easier reporting and maintenance, Rootly recommends routing to **teams** or **services**, not directly to escalation policies. Rules may include **multiple destinations**, all of which will be paged when the rule fires. *** ## Completing the Alert Route A route may contain any number of rules.
Rootly evaluates rules **top-to-bottom**, so ordering matters. Use the rule menu (**… → Reorder rule**) to adjust order. *** ## How Rootly Routes Alerts Rootly evaluates alerts in two sequential stages. ### Stage 1 — Payload-Based Routing If the alert payload contains a **target ID** (team or service), Rootly immediately routes the alert there without evaluating Alert Routes. ### Stage 2 — Evaluate Alert Routes If the alert does not specify a target: ### Evaluate Routes Rootly evaluates **every Alert Route associated with the alert’s source**. ### Evaluate Rules Within each route, rules are evaluated **from top to bottom**. * The first matching rule triggers paging * Rootly stops evaluating additional rules in that route * Other routes referencing the same source will still run If no rules match, the alert becomes a **Non-Paging Alert**. Review these in the Alerts dashboard by filtering **Status → Non-Paging**. Order rules **most specific → least specific** to avoid unintended matches. *** ## Alert Timeline Every routed alert includes a timeline event documenting: * Which **Alert Route** was applied * Which **Routing Rule** matched * Which **destinations** were paged This ensures responders understand *why* they were paged. *** ## Best Practices * Prefer **Alert Fields** over JSONPath for stability. * Start with broad routing categories and refine with specific rules. * Keep rule names action-oriented and descriptive. * Regularly check **Non-Paging Alerts** for routing gaps. * Route to **teams/services**, not escalation policies, for better ownership. * Combine routes thoughtfully when different teams own different tools. *** ## Troubleshooting * Ensure the alert source is included in at least one route. * Verify that at least one rule matches the alert. * Confirm the alert payload does not contain a `target_id`, which overrides routing. * Check the rule order; a broader rule may be matching first. * Validate operators and values used in conditions. * Ensure Alert Field mappings are extracting values correctly. * All routes referencing the alert source are evaluated. * Remove unnecessary alert sources from routes. * Tighten condition logic. * Review the alert payload preview (purple pill tokens). * Confirm your JSONPath reflects the actual alert structure. * Use Alert Fields whenever possible. *** ## Related Pages The umbrella page covering programmatic alert ingestion, sources, and noise reduction. Connect monitoring tools — sources are what Alert Routes evaluate. Recommended condition source for stable routing logic across payload changes. # Alert Sources Source: https://docs.rootly.com/alerts/alert-sources An alert source is how a monitoring tool gets signals into Rootly. Connect one before configuring routing, deduplication, or grouping. An **alert source** is the connection that carries signals from a monitoring, observability, or ticketing tool into Rootly. Nothing else in the Alerts section works until at least one exists: routing rules evaluate alerts *from* a source, deduplication is configured *on* a source, and grouping operates on alerts that a source produced. Connecting a source is the first step. Everything else tunes what happens afterwards. Each source is a distinct connection with its own credentials, deduplication settings, and rate limit. Connecting the same vendor twice — for example one Datadog source per environment — is a valid and common setup. *** ## How an Alert Enters Rootly Understanding the order matters, because most alerting problems are really a problem at one specific stage: Your monitoring tool detects something and sends a payload to Rootly, either through a dedicated integration or a webhook URL. The alert source parses the payload, maps it to [alert fields](/alerts/alert-fields), and works out whether this is a new alert or another event for one that already exists. If the payload matches an open alert on the same source, it is recorded against that alert instead of creating a second one. See [Alert Deduplication](/alerts/alert-deduplication). If the payload already names a target — a team or service ID — Rootly pages that target directly, without evaluating routes. Otherwise [alert routes](/alerts/alert-routing) evaluate the alert and send it to an escalation policy, a team, or a channel — or deliberately nowhere. [Alert grouping](/alerts/alert-grouping) can hold related alerts under one page, and the escalation policy takes over from there. Deduplication is configured on the source and runs before routing, so a deduplicated event never reaches a routing rule. That ordering is why noise is best fixed at the source rather than downstream. *** ## Choosing How to Connect a Tool | Approach | Use when | Setup | | ------------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | | **Dedicated integration** | Rootly has a built-in integration for your tool. Always prefer this — payloads are parsed into alert fields for you. | [Integrations](/integrations/overview) | | **Generic webhook** | Your tool can send an HTTP webhook but has no dedicated integration. You map payload fields yourself. | [Generic Webhook Alert Source](/integrations/generic-webhook-alert-source/generic-webhook-alert-source) | | **Email** | The tool can only send email. Rootly gives the source its own inbound address. | Configured on the source | | **API** | You are generating alerts from your own code or a script. | [API reference](/api-reference/overview) | [Manual paging](/alerts/manual-paging) is not an alert source. A responder paging a teammate ad hoc creates a manual alert with no source behind it — the two paths are separate, which is why manual pages appear even in an organization with no sources connected. If a dedicated integration exists, use it even if you already have a webhook working. Dedicated integrations map vendor payloads into alert fields, which is what makes routing conditions and deduplication keys straightforward instead of hand-built JSON paths. *** ## Supported Sources Rootly ingests alerts from most monitoring and ticketing tools. Each links to its own setup guide: **Alerting and paging platforms** — [PagerDuty](/integrations/pagerduty/pagerduty), [Opsgenie](/integrations/opsgenie), [Splunk On-Call (VictorOps)](/integrations/victor-ops), [PagerTree](/integrations/pager-tree) **Observability and monitoring** — [Datadog](/integrations/datadog/datadog), [Grafana](/integrations/grafana/grafana), [New Relic](/integrations/new-relic), [Prometheus Alertmanager](/integrations/alertmanager), [Honeycomb](/integrations/honeycomb), [Dynatrace](/integrations/dynatrace), [Sentry](/integrations/sentry/sentry), [Rollbar](/integrations/rollbar), [Checkly](/integrations/checkly), [Chronosphere](/integrations/chronosphere), [Nobl9](/integrations/nobl9), [Splunk](/integrations/splunk) **Cloud platforms** — [AWS CloudWatch](/integrations/aws-cloudwatch), [AWS SNS](/integrations/aws-sns), [Google Cloud Monitoring](/integrations/google-cloud-monitoring) Azure Monitor alert sources are available in Rootly even though a public setup guide isn't listed above. To enable one, go to **Alerts → Sources**, click **New alert source**, and select **Azure**. This alert source sends alerts into Rootly for routing and paging. Rootly also has two separately configured AI connectors: [Azure Resource Manager MCP](/ai/connectors/azure-resource-manager) for resource inventory and deployment status, and [Azure Monitor](/ai/connectors/azure-monitor) for operational evidence. Enabling any one does not enable the others. [AWS EventBridge](/integrations/aws-eventbridge) is not an alert source — that integration sends events from Rootly to AWS. To bring EventBridge events *into* Rootly, route them to an SNS topic subscribed to the AWS SNS source, or use the AWS CloudWatch source for CloudWatch alarms. **Ticketing and work tracking** — [Jira](/integrations/jira/jira), [ServiceNow](/integrations/service-now), [Zendesk](/integrations/zendesk) **Anything else** — [Generic Webhook Alert Source](/integrations/generic-webhook-alert-source/generic-webhook-alert-source) This list is not exhaustive, and a tool being absent does not mean it cannot be a source. Anything that can send an HTTP request or an email can become one. Browse the full [integrations catalog](/integrations/overview) for everything Rootly connects to. *** ## What You Configure on a Source Beyond credentials, three settings determine how well a source behaves. Getting these right at setup prevents most alerting complaints later. What makes two events "the same alert". Point this at a value the tool sends consistently for the same underlying problem — a monitor ID, a fingerprint, an aggregation key — and repeat events attach to the open alert instead of creating new ones. A key that includes a timestamp, a run ID, or anything else that changes per event silently disables deduplication: every event looks new. Optionally, a regular expression can normalize the value before it is compared. See [Alert Deduplication](/alerts/alert-deduplication). How Rootly knows the tool considers the problem over, so the alert can resolve without a human closing it. A rule matches on payload values or alert fields, and can require all conditions or any of them. Auto-resolution needs a reliable way to tie the resolving event back to the original alert — usually the same identifier used for deduplication. Which parts of the payload become searchable, routable alert data — service, environment, severity, region, runbook link. Routing and grouping can also read raw payload values by JSONPath, but a mapped field is stable where a JSONPath breaks the moment the vendor reshapes its payload. See [Alert Fields](/alerts/alert-fields). *** ## Ownership and Limits Each source belongs to a team, and that ownership carries into routing: a team can only build alert routes for sources it owns. Team admins can create routes for their own team only. Applied per source and API key by default, and configurable per team. A source that bursts past it has events rejected rather than queued, so raise the limit for sources you know are spiky. A single source can be evaluated by many routes, each with its own conditions. In practice, far fewer and better-scoped routes are easier to reason about than many overlapping ones. *** ## Verifying a New Source Do this before relying on the source in an escalation policy: Use the tool's own test-alert function rather than crafting a payload by hand — you want to see exactly what it sends in production. Check that it was created, and that the title and fields are populated rather than empty or raw JSON. The second event should attach to the first rather than create a duplicate. If it creates a second alert, the deduplication key is not stable. If auto-resolution is configured, the Rootly alert should resolve on its own. Once ingestion behaves, add the source to an [alert route](/alerts/alert-routing) so it starts paging. Connect and verify a source before adding it to a route that pages a human. A misconfigured deduplication key on a noisy monitor can generate a page per event, which is the fastest way to lose your team's trust in alerting. *** ## Best Practices * **One source per tool per environment.** Separate production from staging so routing conditions stay simple and a staging misfire cannot page production on-call. * **Fix noise at the source.** Deduplication runs before routing, so a stable key removes duplicates before any rule sees them. * **Map fields you intend to route on, early.** Rules can fall back to raw JSONPath, but those break when a vendor reshapes its payload — and adding a field later means revisiting the rules that should have used it. * **Name sources for what they carry**, not for the tool alone. "Datadog — production APM" beats "Datadog 2". * **Give spiky sources headroom.** Raise the rate limit for sources with known bursts rather than discovering the ceiling during an incident. *** ## Troubleshooting Work outward from Rootly: 1. **Did the tool actually send?** Check its own delivery or webhook log first. 2. **Is the endpoint or credential right?** A rotated API key is the most common cause of a source that used to work. 3. **Is the source rate limited?** Bursts past 50 alerts per minute per source are rejected rather than queued. 4. **Is anything blocking the request?** If your egress is restricted, confirm Rootly's [IP ranges](/integrations/ip-whitelist) are allowed. The deduplication key is not stable across events. Inspect a raw payload and pick a value that is identical for repeat events — a monitor ID or fingerprint — rather than one containing a timestamp or event ID. See [Alert Deduplication](/alerts/alert-deduplication). Either no auto-resolution rule is configured, or the resolving event cannot be matched to the original alert. Confirm the rule's identifier is the same value used to deduplicate, and that the tool actually sends a resolution event. Ingestion and paging are separate. Unless the payload names a target directly, an alert reaches someone only through a route — and a source with no matching route creates alerts that page nobody, which is sometimes intentional. Confirm a route includes this source, that its conditions match, and that a paging destination is set. See [Alert Routing](/alerts/alert-routing). The payload is not being mapped. Dedicated integrations map known vendor payloads automatically; a generic webhook needs the JSON paths configured by hand. See [Alert Fields](/alerts/alert-fields). *** ## Related Pages The umbrella page covering ingestion, deduplication, grouping, and routing. Route the alerts your sources produce to the right teams, services, and escalation policies. Configure per-source field mappings that normalize payload data across every tool you connect. *** ## Frequently Asked Questions Yes, and it is often the right setup. A source per environment or per team keeps routing conditions simple and stops a staging alert from reaching production on-call. Unless their payload names a target directly, they are created and visible in Rootly but page nobody. This is a legitimate configuration for signals you want recorded and searchable without waking anyone. Existing alerts remain part of the record. Deleting a source stops future ingestion; it does not erase history. Almost certainly. If it can send an HTTP request, use the [Generic Webhook Alert Source](/integrations/generic-webhook-alert-source/generic-webhook-alert-source); if it can only send email, a source can be given its own inbound address. Deduplication, because the noise comes from one monitor repeating. Grouping is for one real problem lighting up several unrelated monitors. [Alerts](/alerts/alerts) compares the two directly. # Alert Statuses Source: https://docs.rootly.com/alerts/alert-statuses Understand how alerts progress through their lifecycle in Rootly, including triggered, acknowledged, and resolved states with valid transitions. ## Overview Every alert in Rootly progresses through a well-defined **finite state machine (FSM)** that dictates how it escalates, notifies responders, synchronizes with alert groups, and ultimately resolves.\ Understanding these states ensures predictable behavior across Routing, On-Call Escalation Policies, Alert Grouping, and integrations like Slack. Rootly alerts can be in one of four statuses: * **open** * **triggered** * **acknowledged** * **resolved** These values are stored on the alert’s canonical `status` enum. All transitions, notification triggers, and timeline events are governed by Rootly’s internal state machine. ```mermaid theme={null} stateDiagram-v2 [*] --> open open --> triggered open --> resolved triggered --> triggered: retrigger triggered --> acknowledged triggered --> resolved triggered --> open: paging skipped acknowledged --> triggered: retrigger acknowledged --> resolved acknowledged --> open: paging skipped resolved --> triggered: retrigger resolved --> open: paging skipped ``` *** ## Status Definitions ### **open** The alert is not actively paging a responder. This can be its initial state before a notification target is assigned, or the result of a paging attempt that could not notify any target. Typical reasons for an `open` alert: * The alert was ingested but did not match a Routing Rule * The alert is a *non-paging alert* * It was created manually without a destination * A paging attempt could not notify any target This status allows two transitions: * `open → triggered` (once a notification target is assigned via routing or manual paging) * `open → resolved` An alert immediately transitions from **open → triggered** when Routing assigns a team, service, user, or escalation policy. When a paging attempt cannot notify any target—for example, because the selected escalation policy has no pageable targets—Rootly transitions a non-open alert back to `open` and records a `status_update/open` timeline event. ### **triggered** The alert is **actively paging responders**. This is the state where on-call users are notified based on escalation logic. A triggered alert: * Sends notifications (SMS, push, phone call, Slack) * Can be acknowledged by responders * Can be resolved manually or via automation Allowed transitions: * `triggered → acknowledged` * `triggered → resolved` * `triggered → triggered` (retrigger—for example, ack timeout, forced escalation, manual actions) * `triggered → open` (paging could not notify any target) All transitions into `triggered` create a `status_update` timeline event. ### **acknowledged** A responder confirmed that they have seen the alert and are working on it. Escalation pauses unless a timeout or retrigger occurs. Allowed transitions: * `acknowledged → resolved` * `acknowledged → triggered` (ack timeout or manual retrigger) * `acknowledged → open` (paging could not notify any target) If an acknowledged alert hits **acknowledgement timeout**, Rootly automatically **re-triggers** it and resumes escalation. ### **resolved** A closed state indicating no further action is currently required. Notifications cease and Rootly records `ended_at`; the alert can still be reopened through the transitions below. However, Rootly allows: * `resolved → triggered` (re-open regression, manual retrigger, new escalation) * `resolved → open` (paging could not notify any target) This ensures alerts can be reopened without creating duplicates. Resolved alerts remain visible and analyzable in your alert history, even after re-triggering. *** ## Summary Table of Allowed Transitions | From ↓ | To: open | To: triggered | To: acknowledged | To: resolved | | ---------------- | ------------------ | ------------- | ---------------- | ------------ | | **open** | — | ✅ | — | ✅ | | **triggered** | ✅ (paging skipped) | ✅ (retrigger) | ✅ | ✅ | | **acknowledged** | ✅ (paging skipped) | ✅ (retrigger) | — | ✅ | | **resolved** | ✅ (paging skipped) | ✅ (retrigger) | — | — | Retriggering is a first-class action in Rootly. A retrigger transitions an alert **back to `triggered`**, restarts escalation, and produces appropriate timeline events. *** ## How Rootly Records Status Changes Every transition writes a `status_update` event into the alert timeline. A status event captures four fields: The status the alert transitioned into. The status the alert transitioned out of. Who performed the action — a responder, an automation, or a system event. Additional context such as the escalation step, ack timeout, grouping rule, or routing origin that produced the transition. These timeline entries power audit trails, analytics, and seamless Slack updates. *** ## Interaction With Alert Grouping When an alert is part of an **Alert Group**, status synchronization is automatic: ### Leader Alert Behavior * The **group leader** is the first alert in the group (the one that paged). * Any change to the leader’s status cascades to all members. * Member alerts update timestamps, noise indicators, and events to match the leader. ### Member Alert Behavior * Members never independently influence group state. * Status changes come exclusively from the group leader. * Retriggering the leader retriggers all members. This ensures responders never lose the true “source of paging,” even when many alerts represent the same event. *** ## Visual Indicators Across Rootly Rootly uses consistent color/status styling across the Web UI, Slack, and Mobile: * 🟥 **Open / Triggered** — Requires action * 🟧 **Acknowledged** — Someone is actively working the alert * 🟩 **Resolved** — Incident has concluded These indicators appear in: * Alert lists * Slack alert threads * Alert details * Incident sidebars when alerts link to incidents *** ## Timestamp Behavior Each alert automatically manages two lifecycle timestamps: When the alert began. Taken from the source event when provided; otherwise set when the alert is created. Set when the alert transitions into `resolved`. Cleared whenever the alert leaves `resolved` — including transitions back to `triggered` or `open`. These timestamps power duration metrics — mean time to acknowledge (MTTA), mean time to resolve (MTTR), paging duration, and escalation analytics. *** ## Troubleshooting * It may not match any routing rules * The alert source may not be associated with an Alert Route * No notification target was assigned * The selected escalation policy may have no pageable targets, or every target may have been skipped * The alert may be a non-paging alert * Ensure its status is **triggered**, not **open** * Validate the routing rule actually assigned a team or escalation policy * Confirm notification channels are enabled * Check for quiet-only escalation paths * Review acknowledgement timeout settings * Check whether escalation policies intentionally retrigger * Ensure grouping leader logic isn’t retriggering members This is expected if: * A user manually retriggered * The system detected a regression * A new routing condition matched and assigned a destination *** ## Summary Alert Statuses are the backbone of Rootly’s alerting engine. They define: * How and when responders are notified * How escalation policies activate * How grouping behaves * How alerts appear in dashboards and Slack * How timeline events reflect real-world activity By enforcing strict, predictable transitions—and exposing complete audit trails—Rootly ensures smooth, reliable alerting workflows from ingestion → paging → acknowledgement → resolution → retriggering if needed. *** ## Related Pages Ingestion, deduplication, grouping, and routing — how status transitions fit into the broader alert lifecycle. How Rootly picks a team, service, and escalation policy when an alert enters the open status. Normalized data used to condition status-driven workflows and reporting. # Alert Urgency Source: https://docs.rootly.com/alerts/alert-urgency Learn how Alert Urgencies determine alert priority across Alert Sources, Heartbeats, Live Call Routing, and Escalation Policies for paging rules. ## Overview Alert Urgency controls **how quickly responders must act** when an alert is triggered.\ It’s the core signal Rootly uses to decide: * How aggressively to page on-call responders * Whether notifications should be **audible** (wake people up) or **quiet** * Which escalation paths apply during or outside of **working hours** Configured well, urgency ensures true incidents get immediate attention, while low-impact noise stays non-disruptive. *** ## Understanding Alert Urgency Rootly ships with three urgency levels by default: * **High** * **Medium** * **Low** You can: * Add new urgencies * Rename existing ones * Reorder them to change their relative priority Rootly automatically interprets order as: * **Top** → high urgency * **Middle** → medium urgency * **Bottom** → low urgency Urgency influences: * Escalation behavior (which paths run, what channels are used) * Whether notifications bypass **Do Not Disturb** * Dynamic Escalation Paths (for example, only wake people up on High) * Heartbeat severity * Live Call Routing behavior * Analytics on alert volume & response behavior The **team’s top urgency** becomes the default urgency for **new Alert Sources**.\ This is usually “High”, but it’s fully controlled by how you order your urgencies. *** ## How Rootly Determines Urgency When an alert is created, Rootly applies urgency in this order: 1. **Urgency Rules on the Alert Source** * If any rule matches, its urgency wins. 2. **Default Urgency on the Alert Source** * If no rule matches, Rootly uses the source’s default urgency. 3. **Team Default Urgency** * If the source has no default, Rootly falls back to your **team’s top urgency**. The **Alert** model also enforces a fallback: if no urgency is set by the source or rules, it assigns the team’s default urgency automatically. *** ## Configuring Alert Urgency Definitions Alert Urgency definitions live under the **Alerts → Urgency** tab and are shared across: * Alert Sources * Heartbeats * Live Call Routing * Escalation Policies - Go to **Alerts → Urgency** - Click **+ New Alert Urgency** or select an existing one to edit - Provide a **Name** and a **Description** (for example, “Critical – Wake up on-call immediately”) - Drag and drop urgencies to reorder them Reordering urgencies automatically updates their internal “high / medium / low” semantics and color coding. Heartbeats generate alerts when a periodic signal is missing. Assign an urgency so these alerts escalate correctly. * Go to **On-Call → Heartbeats** * Edit an existing heartbeat or click **+ New Heartbeat** * Set the **Alert Urgency** for that heartbeat Use **High** urgency for critical production heartbeats, and lower urgencies for less critical environments (for example, staging). Live Call Routing creates alerts when someone dials your on-call phone number. * Go to **On-Call → Live Call Routing** * Edit a **Routing Number** or create a new one * In **Routing Rules**, set the **Alert Urgency** An Alert Urgency is **required** for Live Call Routing **unless** you’re using a **Calling Tree**.\ With a Calling Tree, urgency is set per mapping instead. Alert Sources control how urgency is derived from incoming payloads. * Go to **Alerts → Alert Sources** * Click the pencil icon next to a source * Open the **Configure** or **Urgency** section * Click **+ Add Condition** Each rule takes four inputs: What to evaluate. Alert Field is recommended for long-term stability — payloads change when vendors reshape their schemas; normalized alert fields don't. How the value should be compared. The comparison value the operator evaluates against. Which urgency to set when the rule matches. Rootly ships with High, Medium, and Low; teams that have renamed or added urgencies will see their own values here. New Alert Sources inherit your **team’s top urgency** as their default.\ Urgency rules override this default when they match. A common pattern: * **High** urgency → always audible, 24/7 * **Medium** urgency → audible only during working hours * **Low** urgency → quiet notifications or no after-hours paging To configure this: * Go to **On-Call → Escalation Policies** * Edit the relevant policy * Configure **Working Hours** * Under **Dynamic Escalation Paths**, click **+ New Path** * Set conditions such as: * `Alert Urgency includes High` * `Within working hours is false` * Choose **Audible** or **Quiet** notification behavior * Configure targets (teams or users) for that path Dynamic Escalation Paths can match **one or many** urgencies, enabling nuanced routing such as “High or Medium after hours, Low during working hours only”. Each responder controls *how* urgency translates to alerts on their devices. * Go to **Account Settings → Notifications → On-Call Notifications** * Configure notification rules for **Audible** and **Quiet** alerts Override device Do Not Disturb and attempt higher-impact channels (for example, Rootly app push + phone call). Respect Do Not Disturb; better suited for non-urgent noise. Rootly recommends setting **at least two** channels for Audible alerts\ (for example, Push + SMS, or Push + Phone). *** ## Using Alert Fields for Dynamic Urgency Assignment [Alert Fields](/alerts/alert-fields) normalize data across different alert payloads (for example, severity, environment, customer tier).\ Urgency rules can use these fields instead of brittle JSONPaths. ### Example Patterns * If `Alert Field: Severity is Critical` → set urgency to **High** * If `Alert Field: Environment is staging` → set urgency to **Low** * If `Alert Field: Customer Tier contains "Enterprise"` → set urgency to **High** ### How to Configure Open your **Alert Source** and go to the **Urgency** or **Configure** tab. Click **+ Add Condition**. Choose **Alert Field** as the kind, then pick the desired field (only fields configured on this source will appear). Select an operator (`is`, `is_not`, `contains`, `does_not_contain`) and provide the comparison value. Choose which **Alert Urgency** to assign when the rule matches. When alerts arrive, Rootly evaluates field-based urgency rules first.\ This keeps your urgency logic stable even if the underlying payload schema changes. *** ## Where You’ll See Alert Urgency Once configured, urgency surfaces throughout Rootly: * **Alerts list & details** – visually highlighted urgency labels * **Heartbeats** – each heartbeat alert inherits its configured urgency * **Live Call Routing** – phone-originated alerts carry urgency into escalation * **Escalation Policies** – Dynamic paths filtered by urgency * **Notifications** – audible vs. quiet delivery based on urgency + path * **Analytics** – filter and analyze alert volume by urgency level *** ## Best Practices * **Drive behavior, not just labels** * Name urgencies by the action they imply (for example, “Critical – Page Immediately”) * **Use Alert Fields where possible** * Avoid tightly coupling urgency rules to a specific tool’s payload schema * **Keep the number of urgencies small** * Three to five well-defined levels are easier to reason about than many granular ones * **Align urgency with business impact** * “High” should always mean “wake someone up”, not “interesting metric blip” * **Regularly review usage** * Use analytics and retrospectives to adjust urgencies if too many alerts are High or too many critical issues are Low *** ## Troubleshooting * Confirm you added rules on the **correct Alert Source** * Check whether the rule is using **Payload (JSONPath)** or **Alert Field** * Ensure the operator is one of: `is`, `is_not`, `contains`, `does_not_contain` * Verify the payload or field value actually matches the condition * Remember: if no rules match, the **source default** or **team default** will be used * The Alert Source may not have urgency rules configured * The Source default may be set to a single urgency for all alerts * The team’s top urgency will apply if no other urgency is set * Check whether multiple sources are pointing to the same urgency configuration * Urgency is required on Live Call Routing **unless** a **Calling Tree** is configured * If using a Calling Tree, confirm mappings are set there instead * Confirm the **Alert Urgency** condition matches exactly (for example, High vs. HIGH) * Double-check **Working Hours** definitions * Ensure your personal **On-Call Notification** settings allow Audible or Quiet alerts for that path * Verify that multiple paths aren’t overlapping in unexpected ways *** ## Related Pages Where urgency drives Dynamic Escalation Paths — the audible / quiet split lives here. Use Alert Fields to assign urgency dynamically instead of writing brittle JSONPaths. Where urgency rules are configured per source and where the default urgency is set. # Alerts Source: https://docs.rootly.com/alerts/alerts How Rootly ingests, deduplicates, groups, routes, and pages on alerts from your monitoring tools — with entry points to every stage of the alert lifecycle. ## Overview An **alert** is Rootly's record of "something needs attention." Alerts arrive **programmatically** from monitoring tools like Datadog, PagerDuty, or Sentry, or **manually** from a responder paging a teammate in Web, Slack, or mobile. Once an alert exists, Rootly deduplicates repeats, groups related alerts together, routes each one to the right team, and pages the on-call responder — every stage is configurable. Structured attributes extracted from every incoming payload. Send each alert to the right team, service, or escalation policy. Set how forcefully an alert pages — high, low, or custom. Collapse repeat firings of the same monitor into one alert. Bundle related alerts from different monitors into one page. Open, triggered, acknowledged, resolved — and what drives each. Ad-hoc pages from Web, Slack, or mobile. Alert when a system stops checking in. Route inbound phone calls to on-call. *** ## Alert Lifecycle A **programmatic** alert — one that arrives from a monitoring tool through an Alert Source — moves through seven stages: 1. **Ingestion** — a monitoring tool posts to an Alert Source webhook. 2. **Deduplication** — if the same condition is already firing on an open alert, the request increments the existing alert's counter instead of creating a new one. See **[Alert Deduplication](/alerts/alert-deduplication)**. 3. **Grouping** — if several *different* monitors are firing on the same underlying incident, they bundle under one leader alert. See **[Alert Grouping](/alerts/alert-grouping)**. 4. **Routing** — Rootly assigns the alert to a team, one or more services, and an escalation policy. See **[Alert Routing](/alerts/alert-routing)**. 5. **Paging** — the escalation policy fires and notifies the on-call responder via mobile push, SMS, phone call, or Slack. 6. **Linkage** — the alert can attach to an incident (automatically via [alert workflows](/workflows/alert-workflows), or manually from the incident view). 7. **Resolution** — the alert closes when the underlying condition clears, either from the monitoring tool's resolution signal or by manual close in Rootly. See **[Alert Statuses](/alerts/alert-statuses)**. Every stage above is a distinct configuration surface in Rootly. This page is the map — each stage links to its own guide. **Manual pages take a shorter path.** When a responder pages someone directly from Web / Slack / mobile, Rootly creates the alert with the escalation target the responder picked and pages it immediately. Manual pages skip stages 1–4 — there is no Alert Source, no source-level deduplication, no grouping, and no Alert Route evaluation. See [Manual Paging](/alerts/manual-paging) for the full flow. *** ## Programmatic vs. Manual Alerts | | **Programmatic** | **Manual** | | ------------------ | --------------------------------------------------------------------- | ----------------------------------------------------- | | **Who creates it** | A monitoring or ticketing tool | A responder | | **How it arrives** | Alert Source webhook | Web, Slack, or mobile | | **Typical use** | Datadog monitor fires, PagerDuty incident opens, Zendesk ticket lands | Loop in an SME, escalate to another team, page ad-hoc | | **Learn more** | [Supported Alert Sources](#supported-alert-sources) | [Manual Paging](/alerts/manual-paging) | Manual pages page the escalation target the responder picked, so paging, on-call rotation, and acknowledgement work the same way once the escalation policy fires. What differs is *before* the escalation policy: manual pages skip Alert Source dedup, Alert Grouping, and Alert Routes — the responder is choosing the target directly instead of letting a route decide. *** ## Supported Alert Sources Rootly integrates with many alerting and ticketing tools. Some of the most common: | Integration | Trigger | | ------------------------------------------------------ | ----------------------------------------------- | | [PagerDuty](/integrations/pagerduty/pagerduty) | When a PagerDuty incident is created | | [Opsgenie](/integrations/opsgenie) | When an Opsgenie incident is created | | [Splunk On-Call](/integrations/victor-ops) (VictorOps) | When a VictorOps incident is created | | [Datadog](/integrations/datadog/datadog) | When a Datadog alert is triggered | | [Zendesk](/integrations/zendesk) | When a Zendesk ticket is created (customizable) | | [Nobl9](/integrations/nobl9) | When an SLO is not satisfied | | [Sentry](/integrations/sentry/sentry) | When a Sentry alert is triggered | Additional alert sources include **Asana, ClickUp, Rollbar, Jira, Honeycomb, ServiceNow, Linear, Grafana, Alertmanager, Google Cloud, CloudWatch, Azure, Splunk, Chronosphere, New Relic, GitLab**, and more — usually via a dedicated integration or generic webhooks. If your provider isn't listed, ingest alerts through **[Generic Webhook Alert Sources](/integrations/generic-webhook-alert-source/generic-webhook-alert-source)**. Alert ingestion is rate limited to **50 alerts per minute per source/API key** by default. The limit is configurable per team, and higher limits are available for Enterprise customers on request. *** ## Reducing Alert Noise Rootly ships two complementary noise-reduction tools: **Deduplication** and **Alert Grouping**. They solve different problems and can be enabled together. ### Deduplication vs. Alert Grouping | | **Deduplication** | **Alert Grouping** | | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | | **The problem it solves** | The same monitor keeps firing while the underlying condition is still bad | Multiple *different* monitors fire on the same underlying incident (latency + error rate + DB health all trip at once) | | **What it matches on** | A stable unique identifier on the payload (JSONPath or alert field) | Destinations (team / service / escalation policy) + a time window + content-match rules | | **Scope** | Source-level (per Alert Source, keyed dedupe) or team-level (exact-payload suppression) | Cross-source — a group rule can span monitors from different sources. **Only routed/paging alerts can join a group** | | **What happens to the new event** | No new alert is created; the existing alert's request count increments and a duplicate event appears on its timeline | A new alert is created and joins the existing alert's group as a *member*; the original alert is the *leader* | | **Paging behavior** | The original page already went out. Repeat events on an unresolved alert do not re-page in the deduped case — exact re-page behavior depends on the source and the alert's state | The leader pages once. Members join silently. No additional pages while the group's time window is open, regardless of how many member alerts arrive | | **When the consolidation window ends** | When the existing alert is resolved (the next event with the same key starts a new alert) | When the group's time window expires, OR when the leader alert is resolved | | **Best for** | *"The same alarm keeps re-firing every minute while the issue is open"* | *"Five monitors lit up on the same outage — page me once, attach the others as context"* | **Plain-English rule:** If your concern is *one noisy monitor*, use Deduplication. If your concern is *one incident lighting up multiple unrelated monitors*, use Alert Grouping. If your concern is *"stop paging me again while I'm working on it"* and you want the most deterministic behavior, **Alert Grouping is usually the better fit** — it guarantees silent membership for the duration of the time window, whereas deduplication's re-page behavior can vary by source. You can enable both. Dedup runs first (at the source level, before the alert is created), so a deduped event never reaches grouping. Grouping then handles the surviving alerts. *** ## Linking Alerts to Incidents Alerts become most useful when tied to incidents. In Rootly, alerts attach to incidents via: * **Integration mappings and workflows** — e.g., "When a PagerDuty incident is created, attach the alert to the corresponding Rootly incident." * **Automation logic** — based on service, environment, or alert attributes. * **Manual linking** — from the incident or alert views. Once linked, responders can jump from the incident to the underlying alert(s), see how many times each alert fired (via the request count), and use alert details to drive mitigation and follow-up tasks. *** ## Best Practices * **Choose a stable deduplication key.** Use identifiers like monitor IDs, incident keys, or ticket IDs — avoid full message text or highly variable fields. * **Start narrow, then broaden.** Begin with conservative dedup rules and relax them as you gain confidence, to avoid accidentally merging unrelated alerts. * **Link alerts to incidents early.** Use workflows to auto-attach alerts to incidents as soon as they're ingested. * **Watch the request count.** A high `×N` count on an alert is a strong signal of ongoing or flapping conditions and can inform severity and prioritization. * **Tune rate limits for noisy environments.** If you know a source can spike, increase the per-source rate limit for that team. * **Own each Slack channel once.** Multiple broadcasts, escalation-policy steps, and workflows can all target the same channel — pick one owner per channel to avoid duplicate posts. *** ## Troubleshooting Confirm that **Combine duplicate alerts into one alert** is enabled on the Alert Source and that the **deduplication key path** points to a stable, consistent value. If the key changes between alerts, Rootly treats them as separate alerts. Often this means deduplication is working as designed. Multiple provider alerts may be mapped to a single Rootly alert, with extra occurrences recorded as **ignored/duplicate requests** on the original alert. Make sure: * Deduplication is configured correctly, **or** payload-based suppression is enabled. * Incoming payloads actually match the configured dedup key or body. If the identifier or body differs, Rootly will create separate alerts instead of incrementing the existing one. Rootly enforces a per-team, per-source/API key rate limit (default **50 alerts/minute**). For high-throughput environments, increase the **alerts rate limit per minute** in team settings or contact support for higher Enterprise limits. Two separate notification paths are almost always targeting that channel. Rootly can post an alert to a channel through five independent mechanisms, and each one posts its own message: * **[Escalation policy](/on-call/escalation-policies) steps** — a level can notify a Slack channel directly. * **Team Alert Broadcast** — a [team](/managing-teams/configuring-teams) can broadcast every alert routed to it into a channel. * **Service Alert Broadcast** — each service can broadcast alerts on that service into a channel of its own. * **Default alerts channel** — the [Slack integration](/integrations/slack/slack) can post every new alert to one workspace-wide channel. * **[Alert workflows](/workflows/alert-workflows)** — can send Slack messages to any channel. Check each one against the alert's team, services, and escalation policy. Service broadcasts are the most commonly missed — each service is configured separately, and several services can broadcast into the same shared channel. Once you find the second path, pick one mechanism as the owner of that channel and remove the channel from the others. Check: * The integration is installed and authenticated. * The mapping points to the right team or alert source. * The webhook or outbound configuration is using the correct URL. * The payload contains all required fields for that integration. Also review integration error logs in Rootly for more details. *** ## Frequently Asked Questions No. Alerts and incidents are separate concepts — an alert says *"something needs attention,"* an incident is the coordinated response. Use [alert workflows](/workflows/alert-workflows) to automatically create or attach to an incident when an alert meets specific criteria, and let low-signal alerts stay as alerts. Not necessarily — they solve different problems and are independently useful. If your pain is *one noisy monitor re-firing*, dedup alone is enough. If your pain is *five monitors lighting up on the same outage*, grouping alone is enough. Most large tenants run both. See the comparison table above. An **Integration** is the broader connection to a third-party tool (Datadog, PagerDuty, Sentry) — it can push data both ways. An **Alert Source** is the specific webhook or ingestion channel used to *bring alerts into Rootly*. One integration usually creates one alert source, but you can configure multiple alert sources per integration if you want separate routing rules per environment or team. Not directly. Once an alert resolves, a new incoming event that matches the same dedup key starts a **new** alert — the resolved one remains a historical record. If a monitoring tool re-fires immediately after resolution, that's typically a signal the underlying condition wasn't actually cleared. From the paged responder's perspective, it's identical — same escalation policy behavior, same acknowledgement flow, same routing. The difference is purely at ingestion: manual pages originate from a responder in Web, Slack, or mobile instead of a monitoring tool webhook. See **[Manual Paging](/alerts/manual-paging)**. *** ## Related Pages The coordinated response — where alerts are triaged and worked on. The paging rules alerts fire against. Automate what happens to an alert once it lands. # Manual Paging Source: https://docs.rootly.com/alerts/manual-paging Manually page users, teams, services, or escalation policies from Rootly Web, Slack, or mobile for ad-hoc escalations and bringing in subject matter experts. ## Overview While most alerts in Rootly arrive programmatically from monitoring tools, responders often need to page someone on the fly — escalating to another team, looping in a subject matter expert, or starting a page for an issue a monitor hasn't caught. **Manual paging** lets users trigger the same escalation policies and paging behavior as a programmatic alert, from Rootly Web, Slack, or the mobile app. Manual alerts can target any of five destination types: Page a specific person directly. Kick off the team's escalation policy. Kick off the service's escalation policy. Kick off the functionality's escalation policy. Page a policy directly. When you page a team or service, Rootly runs the same escalation policy as if a programmatic alert had targeted it — the behavior is identical to automated paging. *** ## Customizing Paging Targets Rootly lets users page across all five target types by default, but seeing every option in an urgent moment can lead to decision paralysis. If your responders only ever page teams (or only ever page services), narrow the picker to the targets they actually use. To configure: Navigate to the **Alerts** page in Rootly Web. Click **Settings** in the top-right corner. Open the **Manual Paging Options** tab. Toggle on or off the target types you want available to your users. At least one paging option must remain enabled. The targets you leave on are the only targets your users will see when escalating from Rootly Web or Slack. *** ## Paging in Slack Rootly exposes two Slack paging commands — pick the one that matches what you're doing: * **`/rootly page`** — page a Rootly On-Call target (schedule, team, service, functionality, escalation policy, or user). Works in any channel shared with the Rootly bot. * **`/rootly escalate`** — escalate an incident to an external paging provider (PagerDuty, Opsgenie, VictorOps). Only available inside an incident channel. See the full [Slack commands reference](/integrations/slack/slack#slash-commands) for every command's signature and behavior. You can `@`-mention users after the command to prefill target users — for example, `/rootly page @alice @bob`. Manual paging form in Slack If your team has disabled the Rootly on-call slash commands (via **Team Settings → Custom Slack paging workflow**), `/rootly page` won't be available. Ask an admin to re-enable the commands if you need them. *** ## Paging in Web You can start a manual page from Rootly Web in three places: * **Left-hand navigation** — click **Start Paging** at any time. * **Alerts page** — click **Start Paging** in the top-right corner. * **Incident page** — click **Escalate** to page someone into the current incident. Fill out the form with context for the person you're paging, then click **Start Paging** to send the page. *** ## Paging in Mobile The Rootly [mobile app](/on-call/mobile-app) supports manual paging with the same target types available in Web. From the app, tap the paging action, pick the target type, fill out the form, and send the page — the flow mirrors what you see in Web so you don't have to learn a second mental model when you're paging from your phone. Mobile paging is especially useful during weekend or off-hours coverage when you may not have Rootly Web open, and when you need to escalate quickly without opening a laptop. *** ## Default Alert Message If your team frequently pages with similar context, configure a default title and description template so users don't have to type the same boilerplate every time. Liquid templating lets you populate fields dynamically. To configure: Open the **Alerts** page in Rootly Web. Click **Settings** in the top-right corner. Toggle on **Default alert message**. Author the title and description, using Liquid expressions where dynamic values are needed. Users can still edit the populated text before sending the page. *** ## Best Practices * **Give the person you're paging as much context as possible.** A clear title and description shortens time-to-acknowledgement and helps responders prioritize. Use a default alert message template to enforce a minimum bar. * **Narrow the paging picker to what your responders actually use.** If teams never page individual users directly, turn that target type off — every option you remove is one less decision in a high-stress moment. * **Invoke the paging command from inside an incident channel when you're extending an existing incident.** In an incident channel, the dialog attaches the resulting page to the current incident automatically. Outside a channel, the page is unattached — use this for ad-hoc paging that isn't tied to an existing incident. * **Reach for manual paging when programmatic monitoring missed something.** If a customer-reported issue isn't covered by an existing monitor, manual paging is the fast path to get someone on it. *** ## Troubleshooting The **Manual Paging Options** tab on the Alerts settings page controls which target types are visible to your users. If users, teams, services, functionalities, or escalation policies are missing from the form, ask an admin to re-enable that target type. At least one target type is always enabled. Confirm the Rootly bot is installed in the channel where you're running the command. Also check whether an admin has disabled the on-call slash commands under **Team Settings → Custom Slack paging workflow** (the setting disables `/rootly page`, `/rootly escalate`, `/rootly oncall`, `/rootly alerts`, and `/rootly override` as a set). Check the escalation policy attached to the target you paged. If the policy has no on-call user for the current time window, no one will receive a notification. Open the target's escalation policy and verify that the schedules and steps point at users who are currently on-call. Make sure **Default alert message** is toggled on under Alerts → Settings. If your template uses Liquid expressions that reference fields unavailable at paging time, those variables resolve to blank. Test the template by manually paging a test target and inspecting the populated form. *** ## Frequently Asked Questions Yes. When you page a team, service, functionality, or escalation policy, Rootly runs the attached escalation policy — which routes through the on-call schedule for that target. Paging a specific user bypasses the schedule and contacts that user directly. Yes. See the [Paging in Mobile](#paging-in-mobile) section above — the mobile app supports the same target types and form as Web. Install and configure the [Rootly mobile app](/on-call/mobile-app) if you haven't already. Yes. Every manual page creates an alert in Rootly with the title, description, and target you specified, so the page is tracked alongside programmatic alerts. `/rootly new` opens a new incident. Manual paging triggers a page (and the corresponding escalation policy) without necessarily declaring an incident, though you can attach the resulting alert to an existing incident or create one from it. *** ## Related Pages The umbrella page covering programmatic alert ingestion, sources, and noise reduction. How Rootly decides who to page and when, based on schedules and steps. Control which alerts page on-call immediately and which can wait. # [DEPRECATED] Creates a custom field option Source: https://docs.rootly.com/api-reference/[deprecated]-customfieldoptions/[deprecated]-creates-a-custom-field-option https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/custom_fields/{custom_field_id}/options [DEPRECATED] Use form field endpoints instead. Creates a new custom field option from provided data # [DEPRECATED] Delete a custom field option Source: https://docs.rootly.com/api-reference/[deprecated]-customfieldoptions/[deprecated]-delete-a-custom-field-option https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/custom_field_options/{id} [DEPRECATED] Use form field endpoints instead. Delete a specific Custom Field Option by id # [DEPRECATED] List custom field options Source: https://docs.rootly.com/api-reference/[deprecated]-customfieldoptions/[deprecated]-list-custom-field-options https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/custom_fields/{custom_field_id}/options [DEPRECATED] Use form field endpoints instead. List custom field options # [DEPRECATED] Retrieves a custom field option Source: https://docs.rootly.com/api-reference/[deprecated]-customfieldoptions/[deprecated]-retrieves-a-custom-field-option https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/custom_field_options/{id} [DEPRECATED] Use form field endpoints instead. Retrieves a specific custom field option by id # [DEPRECATED] Update a custom field option Source: https://docs.rootly.com/api-reference/[deprecated]-customfieldoptions/[deprecated]-update-a-custom-field-option https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/custom_field_options/{id} [DEPRECATED] Use form field endpoints instead. Update a specific custom field option by id # [DEPRECATED] Creates a Custom Field Source: https://docs.rootly.com/api-reference/[deprecated]-customfields/[deprecated]-creates-a-custom-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/custom_fields [DEPRECATED] Use form field endpoints instead. Creates a new custom field from provided data # [DEPRECATED] Delete a Custom Field Source: https://docs.rootly.com/api-reference/[deprecated]-customfields/[deprecated]-delete-a-custom-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/custom_fields/{id} [DEPRECATED] Use form field endpoints instead. Delete a specific custom field by id # [DEPRECATED] List Custom Fields Source: https://docs.rootly.com/api-reference/[deprecated]-customfields/[deprecated]-list-custom-fields https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/custom_fields [DEPRECATED] Use form field endpoints instead. List Custom fields # [DEPRECATED] Retrieves a Custom Field Source: https://docs.rootly.com/api-reference/[deprecated]-customfields/[deprecated]-retrieves-a-custom-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/custom_fields/{id} Retrieves a specific custom_field by id # [DEPRECATED] Update a Custom Field Source: https://docs.rootly.com/api-reference/[deprecated]-customfields/[deprecated]-update-a-custom-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/custom_fields/{id} [DEPRECATED] Use form field endpoints instead. Update a specific custom field by id # [DEPRECATED] Creates an incident custom field selection Source: https://docs.rootly.com/api-reference/[deprecated]-incidentcustomfieldselections/[deprecated]-creates-an-incident-custom-field-selection https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents/{incident_id}/custom_field_selections [DEPRECATED] Use form field endpoints instead. Creates a new incident custom field selection from provided data # [DEPRECATED] Delete an incident custom field selection Source: https://docs.rootly.com/api-reference/[deprecated]-incidentcustomfieldselections/[deprecated]-delete-an-incident-custom-field-selection https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incident_custom_field_selections/{id} [DEPRECATED] Use form field endpoints instead. Delete a specific incident custom field selection by id # [DEPRECATED] List incident custom field selections Source: https://docs.rootly.com/api-reference/[deprecated]-incidentcustomfieldselections/[deprecated]-list-incident-custom-field-selections https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incidents/{incident_id}/custom_field_selections [DEPRECATED] Use form field endpoints instead. List incident custom field selections # [DEPRECATED] Retrieves an incident custom field selection Source: https://docs.rootly.com/api-reference/[deprecated]-incidentcustomfieldselections/[deprecated]-retrieves-an-incident-custom-field-selection https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_custom_field_selections/{id} [DEPRECATED] Use form field endpoints instead. Retrieves a specific incident custom field selection by id # [DEPRECATED] Update an incident custom field selection Source: https://docs.rootly.com/api-reference/[deprecated]-incidentcustomfieldselections/[deprecated]-update-an-incident-custom-field-selection https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incident_custom_field_selections/{id} [DEPRECATED] Use form field endpoints instead. Update a specific incident custom field selection by id # [DEPRECATED] Creates a workflow custom field selection Source: https://docs.rootly.com/api-reference/[deprecated]-workflowcustomfieldselections/[deprecated]-creates-a-workflow-custom-field-selection https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/workflows/{workflow_id}/custom_field_selections [DEPRECATED] Use form field endpoints instead. Creates a new workflow custom field selection from provided data # [DEPRECATED] Delete a workflow custom field selection Source: https://docs.rootly.com/api-reference/[deprecated]-workflowcustomfieldselections/[deprecated]-delete-a-workflow-custom-field-selection https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/workflow_custom_field_selections/{id} [DEPRECATED] Use form field endpoints instead. Delete a specific workflow custom field selection by id # [DEPRECATED] List workflow custom field selections Source: https://docs.rootly.com/api-reference/[deprecated]-workflowcustomfieldselections/[deprecated]-list-workflow-custom-field-selections https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflows/{workflow_id}/custom_field_selections [DEPRECATED] Use form field endpoints instead. List workflow custom field selections # [DEPRECATED] Retrieves a workflow custom field selection Source: https://docs.rootly.com/api-reference/[deprecated]-workflowcustomfieldselections/[deprecated]-retrieves-a-workflow-custom-field-selection https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflow_custom_field_selections/{id} [DEPRECATED] Use form field endpoints instead. Retrieves a specific workflow custom field selection by id # [DEPRECATED] Update a workflow custom field selection Source: https://docs.rootly.com/api-reference/[deprecated]-workflowcustomfieldselections/[deprecated]-update-a-workflow-custom-field-selection https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/workflow_custom_field_selections/{id} [DEPRECATED] Use form field endpoints instead. Update a specific workflow custom field selection by id # Delete AI chat session Source: https://docs.rootly.com/api-reference/ai-chat/delete-ai-chat-session https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/ai/chat/sessions/{id} Permanently deletes an AI chat session and all its messages. Requires `ai.chat:write` OAuth scope or an API key. # List AI chat session messages Source: https://docs.rootly.com/api-reference/ai-chat/list-ai-chat-session-messages https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/ai/chat/sessions/{session_id}/messages Returns the user and assistant message history for a session, paginated and chronologically ordered. Internal tool messages are filtered out. Requires `ai.chat:read` OAuth scope or an API key. # Send AI chat message Source: https://docs.rootly.com/api-reference/ai-chat/send-ai-chat-message https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/ai/chat Send a message to the AI assistant and receive a synchronous reply. Optionally bind the conversation to an incident or alert for context-aware responses. Requires `ai.chat:write` OAuth scope or an API key. # Stream AI chat response (SSE) Source: https://docs.rootly.com/api-reference/ai-chat/stream-ai-chat-response-sse https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/ai/chat/stream Send a message and receive the AI response as a Server-Sent Events stream. Optionally bind to an incident or alert for context. Events: `session_id` (initial), `text` (content chunks), `task_update` (tool progress), `error`, `done` (terminal with status). Requires `ai.chat:write` OAuth scope or an API key. # Create alert event Source: https://docs.rootly.com/api-reference/alertevents/create-alert-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alerts/{alert_id}/events Creates a new alert event # Delete alert event Source: https://docs.rootly.com/api-reference/alertevents/delete-alert-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/alert_events/{id} Deletes a specific alert event. Only alert events with kind 'note' (user-created notes) can be deleted. System-generated events are immutable to maintain audit trail integrity. # List alert events Source: https://docs.rootly.com/api-reference/alertevents/list-alert-events https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alerts/{alert_id}/events List alert_events # List alert events across alerts Source: https://docs.rootly.com/api-reference/alertevents/list-alert-events-across-alerts https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_events Returns a flat list of alert events across all alerts the requester can access. Designed for periodic polling: use `page[after]` with the `next_cursor` returned in the previous response to stream forward. # Retrieve alert event Source: https://docs.rootly.com/api-reference/alertevents/retrieve-alert-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_events/{id} Retrieves a specific alert_event by id # Update alert event Source: https://docs.rootly.com/api-reference/alertevents/update-alert-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json patch /v1/alert_events/{id} Updates a specific alert event. Only alert events with kind 'note' (user-created notes) can be updated. System-generated events are immutable to maintain audit trail integrity. # Creates an alert field Source: https://docs.rootly.com/api-reference/alertfields/creates-an-alert-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alert_fields Creates a new alert field from provided data # Delete an alert field Source: https://docs.rootly.com/api-reference/alertfields/delete-an-alert-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/alert_fields/{id} Delete a specific alert field by id # List alert fields Source: https://docs.rootly.com/api-reference/alertfields/list-alert-fields https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_fields List alert fields # Retrieves an alert field Source: https://docs.rootly.com/api-reference/alertfields/retrieves-an-alert-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_fields/{id} Retrieves a specific alert field by id # Update an alert field Source: https://docs.rootly.com/api-reference/alertfields/update-an-alert-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/alert_fields/{id} Update a specific alert field by id # Creates an alert group Source: https://docs.rootly.com/api-reference/alertgroups/creates-an-alert-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alert_groups Creates a new alert group. **Note**: For enhanced functionality and future compatibility, consider using the advanced alert grouping with `conditions` field instead of the legacy `group_by_alert_title`, `group_by_alert_urgency`, and `attributes` fields. # Delete an alert group Source: https://docs.rootly.com/api-reference/alertgroups/delete-an-alert-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/alert_groups/{id} Delete a specific alert group by id # List alert groups Source: https://docs.rootly.com/api-reference/alertgroups/list-alert-groups https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_groups List alert groups # Retrieves an alert group Source: https://docs.rootly.com/api-reference/alertgroups/retrieves-an-alert-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_groups/{id} Retrieves a specific alert group by id # Update an alert group Source: https://docs.rootly.com/api-reference/alertgroups/update-an-alert-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json patch /v1/alert_groups/{id} Update a specific alert group by id. **Note**: For enhanced functionality and future compatibility, consider using the advanced alert grouping with `conditions` field instead of the legacy `group_by_alert_title`, `group_by_alert_urgency`, and `attributes` fields. # Creates an alert re-trigger rule Source: https://docs.rootly.com/api-reference/alertretriggerrules/creates-an-alert-re-trigger-rule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alert_retrigger_rules # Deletes an alert re-trigger rule Source: https://docs.rootly.com/api-reference/alertretriggerrules/deletes-an-alert-re-trigger-rule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/alert_retrigger_rules/{id} # List alert re-trigger rules Source: https://docs.rootly.com/api-reference/alertretriggerrules/list-alert-re-trigger-rules https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_retrigger_rules # Retrieves an alert re-trigger rule Source: https://docs.rootly.com/api-reference/alertretriggerrules/retrieves-an-alert-re-trigger-rule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_retrigger_rules/{id} # Updates an alert re-trigger rule Source: https://docs.rootly.com/api-reference/alertretriggerrules/updates-an-alert-re-trigger-rule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/alert_retrigger_rules/{id} # Creates an alert route Source: https://docs.rootly.com/api-reference/alertroutes/creates-an-alert-route https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alert_routes Creates a new alert route from provided data. **Note: This endpoint requires access to Advanced Alert Routing. If you're unsure whether you have access to this feature, please contact Rootly customer support.** ## Asynchronous Rule Creation For organizations with large numbers of routing rules, Rootly supports asynchronous rule processing to improve performance. When enabled, rule creation happens in the background. Asynchronous processing is also applied automatically, whether or not it is enabled for your organization, when a request carries a rule graph too large to save within the request timeout. Size is measured in total dependent records — rules plus their condition groups, conditions and destinations — and for an update it includes the rules already on the route, not just those in the payload. **Important**: Whenever rules are processed asynchronously, the rules list in the API response will not be up-to-date immediately after creation. You should refetch the alert route, or poll the async rule creation status endpoint with the `request_id` you supplied, to confirm the rules have landed. If you experience slow operations when managing alert routes with many rules, contact Rootly customer support to enable asynchronous rule processing for your organization. # Delete an alert route Source: https://docs.rootly.com/api-reference/alertroutes/delete-an-alert-route https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/alert_routes/{id} Delete a specific alert route by id. **Note: This endpoint requires access to Advanced Alert Routing. If you're unsure whether you have access to this feature, please contact Rootly customer support.** # Get an alert route Source: https://docs.rootly.com/api-reference/alertroutes/get-an-alert-route https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_routes/{id} Get a specific alert route by id. **Note: This endpoint requires access to Advanced Alert Routing. If you're unsure whether you have access to this feature, please contact Rootly customer support.** ## Optional Parameters - **show_nested_ids** (query parameter): When set to `true`, the response will include IDs for all nested resources (destinations, condition_groups, conditions). This is useful when you need to reference these nested resources for updates or deletions via PATCH requests. Example: `GET /v1/alert_routes/{id}?show_nested_ids=true` # List alert routes Source: https://docs.rootly.com/api-reference/alertroutes/list-alert-routes https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_routes List all alert routes for the current team with filtering and pagination. **Note: This endpoint requires access to Advanced Alert Routing. If you're unsure whether you have access to this feature, please contact Rootly customer support.** # Update an alert route Source: https://docs.rootly.com/api-reference/alertroutes/update-an-alert-route https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/alert_routes/{id} Update a specific alert route by id. **Note: This endpoint requires access to Advanced Alert Routing. If you're unsure whether you have access to this feature, please contact Rootly customer support.** ### Asynchronous Rule Creation For organizations with large numbers of routing rules, Rootly supports asynchronous rule processing to improve performance. When enabled, rule updates happen in the background. Asynchronous processing is also applied automatically, whether or not it is enabled for your organization, when a request carries a rule graph too large to save within the request timeout. Size is measured in total dependent records — rules plus their condition groups, conditions and destinations — and includes the rules already on the route, not just those in the payload, so a small payload against a large route may still be processed asynchronously. **Important**: Whenever rules are processed asynchronously, the rules list in the API response will not be up-to-date immediately after update. You should refetch the alert route, or poll the async rule creation status endpoint with the `request_id` you supplied, to confirm the rules have landed. If you experience slow operations when managing alert routes with many rules, contact Rootly customer support to enable asynchronous rule processing for your organization. # Update an alert route Source: https://docs.rootly.com/api-reference/alertroutes/update-an-alert-route-1 https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json patch /v1/alert_routes/{id} Updates an alert route. **Note: This endpoint requires access to Advanced Alert Routing. If you're unsure whether you have access to this feature, please contact Rootly customer support.** # Creates an alert routing rule Source: https://docs.rootly.com/api-reference/alertroutingrules/creates-an-alert-routing-rule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alert_routing_rules Creates a new alert routing rule from provided data. **Note: If you are an advanced alert routing user, you should use the Alert Routes endpoint instead of this endpoint. If you don't know whether you are an advanced user, please contact Rootly customer support.** # Delete an alert routing rule Source: https://docs.rootly.com/api-reference/alertroutingrules/delete-an-alert-routing-rule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/alert_routing_rules/{id} Delete a specific alert routing rule by id. **Note: If you are an advanced alert routing user, you should use the Alert Routes endpoint instead of this endpoint. If you don't know whether you are an advanced user, please contact Rootly customer support.** # List alert routing rules Source: https://docs.rootly.com/api-reference/alertroutingrules/list-alert-routing-rules https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_routing_rules List alert routing rules. **Note: If you are an advanced alert routing user, you should use the Alert Routes endpoint instead of this endpoint. If you don't know whether you are an advanced user, please contact Rootly customer support.** # Retrieves an alert routing rule Source: https://docs.rootly.com/api-reference/alertroutingrules/retrieves-an-alert-routing-rule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_routing_rules/{id} Retrieves a specific alert routing rule by id. **Note: If you are an advanced alert routing user, you should use the Alert Routes endpoint instead of this endpoint. If you don't know whether you are an advanced user, please contact Rootly customer support.** # Update an alert routing rule Source: https://docs.rootly.com/api-reference/alertroutingrules/update-an-alert-routing-rule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/alert_routing_rules/{id} Update a specific alert routing rule by id. **Note: If you are an advanced alert routing user, you should use the Alert Routes endpoint instead of this endpoint. If you don't know whether you are an advanced user, please contact Rootly customer support.** # Acknowledges an alert Source: https://docs.rootly.com/api-reference/alerts/acknowledges-an-alert https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alerts/{id}/acknowledge Acknowledges a specific alert by id # Attach alerts to an incident Source: https://docs.rootly.com/api-reference/alerts/attach-alerts-to-an-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents/{incident_id}/alerts Attach alerts to an incident from provided data # Creates an alert Source: https://docs.rootly.com/api-reference/alerts/creates-an-alert https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alerts Creates a new alert from provided data # Escalates an alert Source: https://docs.rootly.com/api-reference/alerts/escalates-an-alert https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alerts/{id}/escalate Escalates a specific alert to the next or specified level in its escalation policy # Get a receipt Source: https://docs.rootly.com/api-reference/alerts/get-a-receipt https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alerts/receipts/{id} Retrieve the delivery receipt for a notification by ID, including its state and (when applicable) failure reason and referenced resource. # List alerts Source: https://docs.rootly.com/api-reference/alerts/list-alerts https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alerts List alerts # List Incident alerts Source: https://docs.rootly.com/api-reference/alerts/list-incident-alerts https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incidents/{incident_id}/alerts List incident alerts # Resolves an alert Source: https://docs.rootly.com/api-reference/alerts/resolves-an-alert https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alerts/{id}/resolve Resolves a specific alert by id # Retrieves an alert Source: https://docs.rootly.com/api-reference/alerts/retrieves-an-alert https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alerts/{id} Retrieves a specific alert by id # Snoozes an alert Source: https://docs.rootly.com/api-reference/alerts/snoozes-an-alert https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alerts/{id}/snooze Snoozes a specific alert by id, extending the acknowledgment timeout # Update alert Source: https://docs.rootly.com/api-reference/alerts/update-alert https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json patch /v1/alerts/{id} Updates an alert # Creates an alert source Source: https://docs.rootly.com/api-reference/alertsources/creates-an-alert-source https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alert_sources Creates a new alert source from provided data # Delete an alert source Source: https://docs.rootly.com/api-reference/alertsources/delete-an-alert-source https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/alert_sources/{id} Delete a specific alert source by id # List alert sources Source: https://docs.rootly.com/api-reference/alertsources/list-alert-sources https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_sources List alert sources # Retrieves an alert source Source: https://docs.rootly.com/api-reference/alertsources/retrieves-an-alert-source https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_sources/{id} Retrieves a specific alert source by id # Update an alert source Source: https://docs.rootly.com/api-reference/alertsources/update-an-alert-source https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/alert_sources/{id} Update a specific alert source by id # Creates an alert urgency Source: https://docs.rootly.com/api-reference/alerturgencies/creates-an-alert-urgency https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/alert_urgencies Creates a new alert urgency from provided data # Delete an alert urgency Source: https://docs.rootly.com/api-reference/alerturgencies/delete-an-alert-urgency https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/alert_urgencies/{id} Delete a specific alert urgency by id # List alert urgencies Source: https://docs.rootly.com/api-reference/alerturgencies/list-alert-urgencies https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_urgencies List alert urgencies # Retrieves an alert urgency Source: https://docs.rootly.com/api-reference/alerturgencies/retrieves-an-alert-urgency https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/alert_urgencies/{id} Retrieves a specific alert urgency by id # Update an alert urgency Source: https://docs.rootly.com/api-reference/alerturgencies/update-an-alert-urgency https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/alert_urgencies/{id} Update a specific alert urgency by id # Creates an API key Source: https://docs.rootly.com/api-reference/api-keys/creates-an-api-key https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/api_keys Creates a new API key and returns it with the plaintext token. **The token is only returned once** — store it securely, as it cannot be retrieved again. **Kinds and required fields:** - `personal` — created for the authenticated user. No additional fields required. - `team` — scoped to a team (group). Requires `group_id`. A service account is automatically created with permissions derived from group membership. - `organization` — organization-wide access. Requires owner or admin role. Optionally set `role_id` and `on_call_role_id` to control the service account's permissions. **Expiration:** All keys require an `expires_at` date set in the future (maximum 5 years). Names must be unique within their kind and scope. # List API keys Source: https://docs.rootly.com/api-reference/api-keys/list-api-keys https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/api_keys List API keys for the current organization. Returns key metadata including name, kind, expiration, and last usage — the secret token value is never included in the response. **API key kinds:** - `personal` — tied to a specific user, inherits that user's permissions. - `team` — scoped to one or more teams (groups), creates a service account with permissions derived from group membership. - `organization` — organization-wide, creates a service account with a configurable role and on-call role. **Automated rotation workflow:** Use `filter[expires_at][lt]` to find keys approaching expiration, then call the rotate endpoint to issue a new token before the old one expires. Combine with `filter[active]=true` to exclude already-expired keys. **Sorting:** Use the `sort` parameter with a field name (e.g., `sort=expires_at`). Prefix with `-` for descending order (e.g., `sort=-created_at`). Allowed fields: `name`, `kind`, `created_at`, `updated_at`, `expires_at`, `last_used_at`. # Retrieves an API key Source: https://docs.rootly.com/api-reference/api-keys/retrieves-an-api-key https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/api_keys/{id} Retrieves a specific API key by its UUID. Returns key metadata including name, kind, expiration, last usage timestamp, and the grace period status — the secret token is never included. # Revoke an API key Source: https://docs.rootly.com/api-reference/api-keys/revoke-an-api-key https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/api_keys/{id} Revoke an API key. The key is immediately invalidated and can no longer be used for authentication. This action cannot be undone. For `team` and `organization` keys, the associated service account is also deleted. Any active sessions using this key will fail on the next request. # Rotate an API key Source: https://docs.rootly.com/api-reference/api-keys/rotate-an-api-key https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/api_keys/{id}/rotate Rotate an API key's token. Issues a new secret token and returns it — **the new token is only shown once**, so store it securely. **Self-only:** You can only rotate the API key that was used to authenticate this request. Attempting to rotate a different key returns `403 Forbidden`. **Grace period:** When enabled for your organization, the previous token remains valid after rotation, giving you time to deploy the new token without downtime. Pass `grace_period_minutes` (integer, 0–1440, default 30) to control how long the old token stays valid. Set to 0 to immediately invalidate the old token. The `grace_period_ends_at` field in the response confirms the exact time the old token will stop working. **Expiration:** Optionally provide a new `expires_at` date (ISO 8601, up to 5 years). Defaults to 90 days from now if omitted. Dates in the past are rejected. **Typical rotation workflow:** 1. Call this endpoint to get a new token (optionally with a custom `grace_period_minutes`). 2. Deploy the new token to your systems. 3. The old token continues working for `grace_period_minutes` (if grace period is enabled). 4. After the grace period, the old token is automatically invalidated. # Update an API key Source: https://docs.rootly.com/api-reference/api-keys/update-an-api-key https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/api_keys/{id} Update an API key's mutable attributes: `name`, `description`, and `expires_at`. The key's `kind`, `role_id`, `on_call_role_id`, and token cannot be changed after creation. To issue a new token, use the rotate endpoint. To change the role or kind, revoke the key and create a new one. The new `expires_at` must be in the future and within 5 years. # List audits Source: https://docs.rootly.com/api-reference/audits/list-audits https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/audits List audits # Creates an authorization Source: https://docs.rootly.com/api-reference/authorizations/creates-an-authorization https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/authorizations Creates a new authorization from provided data # Delete an authorization Source: https://docs.rootly.com/api-reference/authorizations/delete-an-authorization https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/authorizations/{id} Delete a specific authorization by id # List authorizations Source: https://docs.rootly.com/api-reference/authorizations/list-authorizations https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/authorizations List authorizations # Retrieves an authorization Source: https://docs.rootly.com/api-reference/authorizations/retrieves-an-authorization https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/authorizations/{id} Retrieves a specific authorization by id # Update an authorization Source: https://docs.rootly.com/api-reference/authorizations/update-an-authorization https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/authorizations/{id} Update a specific authorization by id # Creates a catalog checklist template Source: https://docs.rootly.com/api-reference/catalog-checklist-templates/creates-a-catalog-checklist-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/catalog_checklist_templates Creates a new catalog checklist template # Delete a catalog checklist template Source: https://docs.rootly.com/api-reference/catalog-checklist-templates/delete-a-catalog-checklist-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/catalog_checklist_templates/{id} Delete a specific catalog checklist template by id # List catalog checklist templates Source: https://docs.rootly.com/api-reference/catalog-checklist-templates/list-catalog-checklist-templates https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/catalog_checklist_templates List catalog checklist templates # Retrieves a catalog checklist template Source: https://docs.rootly.com/api-reference/catalog-checklist-templates/retrieves-a-catalog-checklist-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/catalog_checklist_templates/{id} Retrieves a specific catalog checklist template by id # Trigger an audit for a catalog checklist template Source: https://docs.rootly.com/api-reference/catalog-checklist-templates/trigger-an-audit-for-a-catalog-checklist-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/catalog_checklist_templates/{id}/trigger Triggers an audit for all applicable entities of the checklist template # Update a catalog checklist template Source: https://docs.rootly.com/api-reference/catalog-checklist-templates/update-a-catalog-checklist-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/catalog_checklist_templates/{id} Update a specific catalog checklist template by id # List catalog entity checklists Source: https://docs.rootly.com/api-reference/catalog-entity-checklists/list-catalog-entity-checklists https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/catalog_entity_checklists List catalog entity checklists # Retrieves a catalog entity checklist Source: https://docs.rootly.com/api-reference/catalog-entity-checklists/retrieves-a-catalog-entity-checklist https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/catalog_entity_checklists/{id} Retrieves a specific catalog entity checklist by id # Bulk delete Catalog Entities Source: https://docs.rootly.com/api-reference/catalogentities/bulk-delete-catalog-entities https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/catalogs/{catalog_id}/entities/bulk_delete Delete catalog entities by external_id list, or prune by managed_by source. Two mutually exclusive modes. # Bulk upsert Catalog Entities Source: https://docs.rootly.com/api-reference/catalogentities/bulk-upsert-catalog-entities https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/catalogs/{catalog_id}/entities/bulk_upsert Create or update multiple catalog entities by external_id. Only attributes present in the payload are written (managed-fields semantics). Transactional: all succeed or all fail. # Creates a Catalog Entity Source: https://docs.rootly.com/api-reference/catalogentities/creates-a-catalog-entity https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/catalogs/{catalog_id}/entities Creates a new Catalog Entity from provided data # Delete a Catalog Entity Source: https://docs.rootly.com/api-reference/catalogentities/delete-a-catalog-entity https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/catalog_entities/{id} Delete a specific Catalog Entity by id # List Catalog Entities Source: https://docs.rootly.com/api-reference/catalogentities/list-catalog-entities https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/catalogs/{catalog_id}/entities List Catalog Entities # Retrieves a Catalog Entity Source: https://docs.rootly.com/api-reference/catalogentities/retrieves-a-catalog-entity https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/catalog_entities/{id} Retrieves a specific Catalog Entity by id # Update a Catalog Entity Source: https://docs.rootly.com/api-reference/catalogentities/update-a-catalog-entity https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/catalog_entities/{id} Update a specific Catalog Entity by id # Creates a Catalog Entity Property Source: https://docs.rootly.com/api-reference/catalogentityproperties/creates-a-catalog-entity-property https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/catalog_entities/{catalog_entity_id}/properties **Deprecated:** This endpoint is deprecated, please use the `fields` attribute on catalog entities or native catalog endpoints (teams, services, functionalities, incident_types, causes, environments) to set field values instead. Creates a new Catalog Entity Property from provided data. # Delete a Catalog Entity Property Source: https://docs.rootly.com/api-reference/catalogentityproperties/delete-a-catalog-entity-property https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/catalog_entity_properties/{id} **Deprecated:** This endpoint is deprecated, please use the `fields` attribute on catalog entities or native catalog endpoints (teams, services, functionalities, incident_types, causes, environments) to set field values instead. Delete a specific Catalog Entity Property by id. # List catalog properties Source: https://docs.rootly.com/api-reference/catalogentityproperties/list-catalog-properties https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/catalog_entities/{catalog_entity_id}/properties **Deprecated:** This endpoint is deprecated, please use `include=fields` on catalog entities or native catalog endpoints (teams, services, functionalities, incident_types, causes, environments) to retrieve field values instead. List Catalog Entity Properties. # Retrieves a Catalog Entity Property Source: https://docs.rootly.com/api-reference/catalogentityproperties/retrieves-a-catalog-entity-property https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/catalog_entity_properties/{id} **Deprecated:** This endpoint is deprecated, please use `include=fields` on catalog entities or native catalog endpoints (teams, services, functionalities, incident_types, causes, environments) to retrieve field values instead. Retrieves a specific Catalog Entity Property by id. # Update a Catalog Entity Property Source: https://docs.rootly.com/api-reference/catalogentityproperties/update-a-catalog-entity-property https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/catalog_entity_properties/{id} **Deprecated:** This endpoint is deprecated, please use the `fields` attribute on catalog entities or native catalog endpoints (teams, services, functionalities, incident_types, causes, environments) to set field values instead. Update a specific Catalog Entity Property by id. # Creates a Catalog Property (alias for field) Source: https://docs.rootly.com/api-reference/catalogproperties/creates-a-catalog-property-alias-for-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/catalogs/{catalog_id}/properties Creates a new Catalog Property - returns catalog_properties type # Delete a catalog_property Source: https://docs.rootly.com/api-reference/catalogproperties/delete-a-catalog_property https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/catalog_properties/{id} Delete a specific catalog_property by id - returns catalog_properties type # List Catalog Properties (alias for fields) Source: https://docs.rootly.com/api-reference/catalogproperties/list-catalog-properties-alias-for-fields https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/catalogs/{catalog_id}/properties List Catalog Properties - returns catalog_properties type # Retrieves a Catalog Property (alias for field) Source: https://docs.rootly.com/api-reference/catalogproperties/retrieves-a-catalog-property-alias-for-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/catalog_properties/{id} Retrieves a specific Catalog Property by id - returns catalog_properties type # Update a catalog_property (alias for field) Source: https://docs.rootly.com/api-reference/catalogproperties/update-a-catalog_property-alias-for-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/catalog_properties/{id} Update a specific catalog_property by id - returns catalog_properties type # Creates a catalog Source: https://docs.rootly.com/api-reference/catalogs/creates-a-catalog https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/catalogs Creates a new catalog from provided data # Delete a catalog Source: https://docs.rootly.com/api-reference/catalogs/delete-a-catalog https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/catalogs/{id} Delete a specific catalog by id # List catalogs Source: https://docs.rootly.com/api-reference/catalogs/list-catalogs https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/catalogs List catalogs # Retrieves a catalog Source: https://docs.rootly.com/api-reference/catalogs/retrieves-a-catalog https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/catalogs/{id} Retrieves a specific catalog by id # Update a catalog Source: https://docs.rootly.com/api-reference/catalogs/update-a-catalog https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/catalogs/{id} Update a specific catalog by id # Creates a Catalog Property Source: https://docs.rootly.com/api-reference/causes/creates-a-catalog-property https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/causes/properties Creates a new Catalog Property from provided data # Creates a cause Source: https://docs.rootly.com/api-reference/causes/creates-a-cause https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/causes Creates a new cause from provided data # Delete a cause Source: https://docs.rootly.com/api-reference/causes/delete-a-cause https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/causes/{id} Delete a specific cause by id # List Catalog Properties Source: https://docs.rootly.com/api-reference/causes/list-catalog-properties https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/causes/properties List Cause Catalog Properties # List causes Source: https://docs.rootly.com/api-reference/causes/list-causes https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/causes List causes # Retrieves a cause Source: https://docs.rootly.com/api-reference/causes/retrieves-a-cause https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/causes/{id} Retrieves a specific cause by id # Update a cause Source: https://docs.rootly.com/api-reference/causes/update-a-cause https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/causes/{id} Update a specific cause by id # API Changelog Source: https://docs.rootly.com/api-reference/changelog Track the latest changes, deprecations, and breaking updates to the Rootly API, including new endpoints, payload changes, and version release notes. ## August 2026 ### August 13, 2026 * **deprecated:** `slug` is now read-only across API resources that derive it from `name`; submitted values are ignored and return `Deprecation: true` and an `X-API-Warn` header ### August 11, 2026 * **feat:** expose `sourceable_id` and `sourceable_attributes` for email alert sources * **feat:** allow configuring `max_tokens` for Anthropic chat completion workflow tasks * **fix:** alert source responses now reflect current built-in alert fields in `alert_template_attributes` ### August 10, 2026 * **feat:** add CRUD endpoints for status page announcements under `/v1/status-pages/{id}/announcements` and `/v1/announcements/{id}` * **feat:** accept and return affected component statuses through `status_page_components` on incident status page events ### August 9, 2026 * **feat:** add `filter[team_ids]` support to `GET /v1/schedules` ### August 6, 2026 * **feat:** expose cycle-based round robin configuration fields on escalation policy levels * **feat:** expose `resource_type` on custom fields and form fields, and reject form field placements across resource types * **fix:** serialize generic webhook alert source field mappings correctly in API and Terraform exports ### August 5, 2026 * **feat:** expose `page_reason: manual_reassignment` on paged alert events created by explicit ownership transfers, including additions or removals in a multi-target page * **feat:** add `public_description` to causes, environments, incident types, teams, and custom catalog entities ### August 4, 2026 * **fix:** preserve client-supplied `position` values when creating escalation policy paths ## July 2026 ### July 31, 2026 * **feat:** expose `retrigger_timeout_minutes` on alert urgencies and escalation policy paths ### July 29, 2026 * **feat:** add CRUD endpoints for status page components and component groups ### July 28, 2026 * **feat:** add status, creation date, and delivery date filters to `GET /v1/webhooks/deliveries`, and expose `status` and `response_status` * **fix:** enforce private incident permissions when changing an incident from public to private through the API ### July 20, 2026 * **fix:** malformed date filter operators and values now return 400 instead of silently returning unfiltered results * **fix:** `custom_fields.label` filters now target the underlying custom field name * **fix:** `not_eq` and `not_in` operators now work for `audits.item_type` ### July 17, 2026 * **feat:** add verified domain API endpoints (`GET/POST /v1/verified_domains`, `GET/DELETE /v1/verified_domains/{id}`) * **fix:** ignore incident-owned timestamp fields on retrospective updates instead of returning 500 ### July 15, 2026 * **feat:** allow renaming the default escalation policy path through the API * **feat:** expose and accept `external_id` on environments * **fix:** enforce operation-specific permissions for group membership API changes ### July 14, 2026 * **feat:** support action item forms in the form field positions API ### July 13, 2026 * **feat:** add CRUD endpoints for alert re-trigger rules (`/v1/alert_retrigger_rules`) ### July 3, 2026 * **feat:** expose `notify_via_sms`, `notify_via_push_notification`, and `informational_notification_message` on live call routers * **fix:** trim whitespace around comma-separated API filter values ### July 2, 2026 * **feat:** add `filter[sequential_id]` to `GET /v1/incidents` * **fix:** invalid `schedule_rotationable_type` values now return 422 ## June 2026 ### June 30, 2026 * **feat:** accept multiple paging destinations through `notification_targets` on `POST /v1/alerts` * **feat:** add `bulk_upsert` and `bulk_delete` endpoints for services, functionalities, environments, and teams ### June 29, 2026 * **feat:** add an endpoint to delete standalone meeting recording sessions ### June 26, 2026 * **fix:** allow functionality owners to be cleared with explicit empty owner arrays ### June 25, 2026 * **feat:** add JSON:API comparison, inclusion, exclusion, and null filter operators across supported API v1 list endpoints ### June 23, 2026 * **feat:** expose `unavailable_responder_message` on live call routers ### June 19, 2026 * **feat:** add shift coverage request API endpoints (`GET/POST /v1/shift_coverage_requests`, `GET/DELETE /v1/shift_coverage_requests/{id}`) * **feat:** expose `functionalities_permissions` on on-call roles * **feat:** expand alert event responses with incident details and schedule escalation policies ### June 18, 2026 * **feat:** add validated custom headers, including Liquid secret templates, to outgoing webhook endpoints * **feat:** expose actor identity and session ID in audit log API responses * **fix:** return only documented user fields for alert responders and action item assignees and creators ### June 17, 2026 * **feat:** add `external_id` and `managed_by` to catalog resources, plus `bulk_upsert` and `bulk_delete` endpoints for catalog entities * **feat:** add action item form field conditions API endpoints * **feat:** expose downloadable `video_url` values on meeting recordings ### June 15, 2026 * **breaking:** `GET /v1/alerts` no longer includes `incidents`, `notified_users`, `responders`, and `groups` by default. Use `?include=incidents,notified_users,responders,groups` to request them. Show, create, update, and action endpoints are unchanged. * **breaking:** default sort order changed from descending to ascending for 16 endpoints: causes, custom\_fields, environments, form\_fields, form\_field\_placements, form\_field\_placement\_conditions, functionalities, genius\_tasks, genius\_workflows, groups, incident\_roles, incident\_types, services, severities, catalog\_entities, catalog\_fields. Use `sort=-position` to restore previous behavior. * **fix:** pagination stability across 26 API v1 controllers by adding deterministic sorting tiebreakers (created\_at, id) to prevent duplicate records across pages * **fix:** custom\_forms endpoint now defaults to `created_at` sort (previously used non-existent `position` column) * **feat:** update permission sets for on-call roles, catalog entities, and group membership API resources ### June 12, 2026 * **feat:** add synchronous and streaming AI chat endpoints, session history, and session deletion with `ai.chat:read` and `ai.chat:write` OAuth scopes ### June 11, 2026 * **feat:** return action item custom fields in API responses * **feat:** add ability to disable alert sources without deletion via `enabled` field * **feat:** expose IP address, user agent, and request ID in audit logs API ### June 10, 2026 * **feat:** accept custom field values on action items public API ### June 8, 2026 * **fix:** allow OAuth tokens to manage phone numbers, emails, and notification rules * **fix:** correct `owner` parameter on `PATCH /v1/dashboards/:id` * **fix:** email addresses index now properly scoped by user authorization ### June 6, 2026 * **feat:** add `POST /v1/incidents/{id}/meeting_recordings/import` endpoint ### June 4, 2026 * **feat:** expose Microsoft Teams and Webex meeting fields in incidents API ### June 3, 2026 * **feat:** add regex search support to API v1 endpoints * **feat:** add Google Chat space fields to escalation policy levels API * **fix:** schedule rotation update error for nil and invalid params * **fix:** limit escalation policies per owning team ### June 2, 2026 * **feat:** add Google Chat space fields to incidents API ### June 1, 2026 * **feat:** alert source fields update with new field attributes ## May 2026 ### May 29, 2026 * **feat:** allow attaching Functionalities to alerts via API * **feat:** add Cloudflare alert source ### May 28, 2026 * **fix:** `/v1/users?include=teams` now correctly scoped to calling workspace ### May 27, 2026 * **fix:** return 403 when API callers lack permission to manage group membership via `user_ids`/`admin_ids` ### May 26, 2026 * **deprecated:** `source` field on alert writes is now deprecated * **feat:** source and related incidents conditions support in alert routing API ### May 22, 2026 * **feat:** add per-report timezone settings to on-call pay reports API * **feat:** emit timestamped events on incident-side alert attach and detach ### May 19, 2026 * **fix:** allow `started_at` on status page events API ### May 15, 2026 * **fix:** `filter[updated_at][gte]` returning wrong results due to timezone mismatch * **fix:** escalation paths index endpoint ### May 13, 2026 * **feat:** cursor-based pagination for incidents API (`page[after]`, `page[before]`) * **feat:** add catalog permissions to on-call roles * **fix:** prevent user-less API keys from being set as schedule owner ### May 12, 2026 * **feat:** add API support for more schedule attributes * **feat:** add sort parameter to alert events feed endpoint ### May 8, 2026 * **feat:** add flat alert events feed endpoint (`GET /v1/alert_events`) * **fix:** return 422 when updating name on default escalation path ### May 6, 2026 * **feat:** add `filter[team_ids]` to escalation policies API * **feat:** allow escalating to a different escalation policy and resolved alerts * **feat:** add `audit_log.created` webhook event for SIEM integration * **feat:** add OAuth2/OIDC provider with scope-based authorization ### May 5, 2026 * **feat:** add `updated_at` field to Alerts API response ### May 4, 2026 * **feat:** expand audit log event types and improve display names * **feat:** add members\_permissions RBAC for view/edit/delete members ## April 2026 ### April 29, 2026 * **feat:** incident bulk import API endpoint * **fix:** filter crashes from malformed query parameters in alerts index ### April 28, 2026 * **feat:** add Functionality as a valid notification target on alerts API * **fix:** preserve `repeat_condition_*` fields when omitted from PATCH requests ### April 24, 2026 * **fix:** `GET /v1/users` no longer returns duplicate records across pages ### April 23, 2026 * **feat:** add timezone and file download URLs to on-call pay report API * **feat:** allow live call routing phone tree with one escalation policy * **fix:** filter Slack channel writes from API/Terraform ### April 22, 2026 * **feat:** add pagination links to alerts API `index_v2` responses * **feat:** add `filter[notification_types]` to `/v1/oncalls` ### April 21, 2026 * **feat:** cursor-based pagination for alerts API (`page[after]`, `page[before]`) * **fix:** RFC 3339 Z-suffix timestamps silently returning 0 results on API date filters ### April 20, 2026 * **feat:** add `shift_shadow` include to List Shifts endpoint * **feat:** add delete video (keep transcript) for meeting recordings API ### April 16, 2026 * **feat:** meeting recordings API with multi-session support and live transcription ### April 15, 2026 * **fix:** alert status changes via PATCH API bypassing timeline events and paging cancellation ### April 13, 2026 * **fix:** default escalation policy business hours timezone to organization timezone ### April 10, 2026 * **feat:** alert urgency support in alert workflows API ### April 9, 2026 * **feat:** add team-level scoping to Heartbeats API ### April 8, 2026 * **feat:** add REST API for managing API keys (`GET/POST/PATCH/DELETE /v1/api_keys`) * **feat:** add Dynatrace alert source * **feat:** add API endpoints for on-call pay report generation ### April 6, 2026 * **feat:** allow SLAs to be re-ordered via API ### April 3, 2026 * **feat:** add Functionality as a destination in alert grouping rules * **feat:** add functionality option for live call router and heartbeats paging ### April 2, 2026 * **feat:** add `is_one_of` and `is_not_one_of` operators to escalation path JSON rules ### April 1, 2026 * **feat:** add pagination support to List Shifts API endpoint * **feat:** add HMAC signature validation for generic webhook alert sources * **fix:** `filter[search]` being ignored on List Users endpoint * **fix:** 500 error on `catalog_entity_checklists` with invalid status filter ## March 2026 ### March 31, 2026 * **fix:** catalog API now returns 422 instead of 404 when `scope_id` is missing ### March 27, 2026 * **feat:** add support for catalog API search * **fix:** SLA API fixes for edge cases ### March 26, 2026 * **fix:** escalation policy default path API overwrites for Terraform applies * **feat:** simplify checklist template API * **fix:** `updated_at` filter not normalizing timestamps on incidents API * **fix:** `external_domain_names` not persisted via API/Terraform ### March 25, 2026 * **feat:** add API support for SLAs (`GET/POST/PATCH/DELETE /v1/slas`) ### March 20, 2026 * **feat:** publish catalog-related API schema changes ### March 17, 2026 * **feat:** add autoset trigger and `catalog_entity_ids` to form field selections API * **feat:** add custom fields filtering in incidents API (`filter[custom_fields]`) ### March 16, 2026 * **feat:** add API for catalog entity checklists and audit triggers ### March 13, 2026 * **feat:** add REST API for catalog checklist templates * **feat:** retrigger alert when setting status via API * **fix:** escalation policy API fixes ### March 11, 2026 * **feat:** add `group_ids` filter to OnCalls API endpoint * **feat:** add escalation policy support to functionalities public API ### March 9, 2026 * **feat:** add preferred name field to User profile API ### March 5, 2026 * **feat:** implement PagerDuty-style `/v1/oncalls` API endpoint * **feat:** add 24-hour grace period for API key regeneration * **fix:** ensure rotation member positions are consecutive after API update ### March 3, 2026 * **feat:** add on-call shadow support within schedules API ### March 2, 2026 * **feat:** add better validation using schema on API endpoints ## February 2026 ### February 27, 2026 * **feat:** add `filter[slack_channel_id]` to `GET /v1/incidents` API * **feat:** add API endpoints for detach from parent and unmark as duplicate incidents * **breaking:** rename catalog `fields` API to `properties` (`/v1/catalogs/:id/properties`) ### February 20, 2026 * **feat:** update EscalationPolicyPaths API controller for deferral window CRUD ### February 19, 2026 * **feat:** add `path_type` filtering to escalation policy paths API index * **feat:** add deferral window rules to escalation policy paths API ### February 17, 2026 * **feat:** add `deferred` status filter to Alerts API ### February 12, 2026 * **feat:** support environment, causes, and incident type custom fields in API ### February 11, 2026 * **fix:** shifts user filter schedule nesting ### February 9, 2026 * **fix:** improve validation error messages on API responses ### February 7, 2026 * **feat:** make Edge Connector API JSON:API compatible ### February 3, 2026 * **feat:** add `update_title` field to status page templates API ### February 1, 2026 * **feat:** add escalation path field rule support in API ## January 2026 ### January 29, 2026 * **deprecated:** catalog entity properties API deprecated in favor of catalog properties * **feat:** support catalog fields in Environments API ### January 27, 2026 * **feat:** add `is_editable` and `is_deletable` attributes to API responses * **feat:** create `/v1/:resource/fields` APIs for resource field discovery * **feat:** allow filtering by name across API and Terraform endpoints ### January 23, 2026 * **feat:** allow resolving non-paging alerts via API * **feat:** add fields attribute to Services API * **feat:** update Communication Templates schema for Terraform compatibility ### January 22, 2026 * **feat:** add `catalog_type` to `/v1/catalogs/:id/fields` API * **feat:** add `fields` attribute to CatalogEntity API * **feat:** add `auto_set_by_catalog_field_ids` to form fields API * **fix:** `slack_id` returning same value for all teams in users API ### January 21, 2026 * **feat:** expose `notification_type` in notification rules API * **feat:** make Communication Template Stages API work for Terraform ### January 20, 2026 * **fix:** `/v1/workflows` API return responses ### January 16, 2026 * **feat:** add `required` attribute to catalog fields API ### January 15, 2026 * **feat:** API endpoint updates to support TipTap blocks for rich text ### January 14, 2026 * **feat:** allow overwriting schedule overrides via API * **feat:** add validation on alert source type matching notification system ### January 13, 2026 * **feat:** add configurable push notification sound for shift coverage requests ### January 8, 2026 * **feat:** add Rootly Edge Connector API ### January 6, 2026 * **fix:** restore `requested_includes` parameter for alert grouping associations ### January 5, 2026 * **breaking:** enforce `application/vnd.api+json` content type across all API endpoints * **fix:** API filter params with nil values no longer cause errors ## December 2025 ### December 19, 2025 * **feat:** add on-call role permissions to API * **feat:** add `muted_service_ids` to incidents API * **feat:** support alert fields and non-alert fields in alert source conditions * **deprecated:** legacy alert template attributes when alert fields are enabled ### December 17, 2025 * **feat:** add `kubernetes_deployment_name` to service creation API ### December 16, 2025 * **breaking:** remove undocumented alert grouping internal metadata fields from API response ### December 15, 2025 * **feat:** add `escalation_policy_id` to service API endpoint for Terraform compatibility ### December 12, 2025 * **fix:** ensure default business hours are applied when start/end times are blank * **fix:** delete existing resolution rule only if exists on alert source update ### December 11, 2025 * **fix:** alert grouping include parameters in alerts endpoint ### December 10, 2025 * **feat:** add API endpoint for incident statuses ### December 5, 2025 * **feat:** add assignee to shifts include options and deprecate user field * **feat:** add incident alerts to incident API response ### December 3, 2025 * **feat:** add created\_by field to Incident AI API ## November 2025 ### November 26, 2025 * **feat:** add mitigation\_message, resolution\_message, and cancellation\_message to incident update API ### November 7, 2025 * **fix:** remove timestamps from routing rule targets API response ### November 6, 2025 * **feat:** make slack\_channel nullable in schedules API ### November 4, 2025 * **feat:** add slack\_channel field to schedule endpoint ## October 2025 ### October 30, 2025 * **feat:** return UUID for custom\_field\_id in workflow custom field selections API ### October 29, 2025 * **feat:** make scheduled\_for and scheduled\_until fields not required, with auto defaults ### October 28, 2025 * **fix:** add rules back to alert routes API schema * **feat:** support large position values in API ### October 14, 2025 * **feat:** add additional information fields to Users API * **feat:** add auto\_add\_members\_when\_attached field to Teams API ### October 10, 2025 * **feat:** add project schedules support to schedules API ### October 7, 2025 * **feat:** add enhanced rotation details to schedule rotations API * **fix:** alert sources API schema validation errors ### October 6, 2025 * **fix:** add alert deduplication fields to alerts API response ### October 3, 2025 * **fix:** missing shifts in API response due to duplicate shift IDs by generating deterministic UUIDs ### October 2, 2025 * **fix:** timezone handling in escalation policy business\_hours API ### October 1, 2025 * **feat:** include substatus name with ID for incidents API * **feat:** update schedule rotations API to support schedule rotation members * **fix:** shifts API to return all shifts including duplicates by ID * **fix:** shift start time to respect API query time range ## September 2025 ### September 30, 2025 * **feat:** implement SAML authentication API endpoints for status pages * **feat:** add email-based heartbeat pinging support * **fix:** postmortem template update from API ### September 26, 2025 * **fix:** correct turn start for hourly rotations crossing DST ### September 25, 2025 * **fix:** schedule members being null in API response ### September 16, 2025 * **feat:** add `assignee_id` and `assignee_type` to shifts API ### September 12, 2025 * **fix:** search filters not working in heartbeats API ### September 11, 2025 * **feat:** add content\_raw field for markdown type post\_mortem\_templates * **fix:** missing rate limit headers in API responses ### September 10, 2025 * **feat:** add IANA timezone format to users API * **fix:** alert acknowledge/resolve endpoints to validate status transitions ### September 9, 2025 * **feat:** add alert\_description field to heartbeats API ### September 6, 2025 * **feat:** add comprehensive API support for SAML authentication configuration ### September 5, 2025 * **fix:** schedule\_rotation\_users API uses shift rendering v2 if enabled ### September 4, 2025 * **feat:** add alert field values to alerts using API ### September 3, 2025 * **fix:** return 400 for malformed request body ## August 2025 ### August 27, 2025 * **feat:** added event sourcing for remote MCP source ### August 22, 2025 * **feat:** Alert Routes API endpoints ### August 12, 2025 * **feat:** add non-editable form fields option in forms API ### August 7, 2025 * **fix:** undefined reference to current\_user.role in API responses ### August 6, 2025 * **feat:** allow owner/admin to manage UserNotificationRule for team members via API ### August 4, 2025 * **fix:** relax minimum escalation path restriction for Terraform * **feat:** add alert events to alerts API response ## July 2025 ### July 31, 2025 * **feat:** add custom fields and incident roles as columns in Table metrics panel API ### July 28, 2025 * **feat:** alert deduplication configuration, timeline events, and API endpoints ### July 23, 2025 * **feat:** email verification API endpoints ### July 22, 2025 * **fix:** include destination in alert routing rule API response * **fix:** rotation start/end timestamps now returned in UTC * **feat:** add disable auto adding members to incident channel feature in groups API ## June 2025 ### June 4, 2025 * **fix:** user\_ids\[] filtering on /v1/shifts endpoint * **feat:** add `slug` field to status pages API ### June 2, 2025 * **feat:** services API now accepts owner\_group\_ids parameter * **fix:** action items schema for assigned\_to field * **fix:** ensure user contact info is created for correct user ## May 2025 ### May 30, 2025 * **fix:** delete prior sourceable when updating attributes from the API ### May 28, 2025 * **feat:** remove verification attributes from email/phone number APIs * **feat:** remove primary attribute from user email addresses API * **feat:** add case-insensitive target\_type normalization ### May 27, 2025 * **feat:** add RESTful API endpoints for user phone numbers and email addresses ### May 26, 2025 * **feat:** add API support for advanced conditions in alert grouping ### May 15, 2025 * **feat:** allow automated invite of external emails into Slack incident channels ### May 5, 2025 * **feat:** add new escalate targets to public API schemas ## April 2025 ### April 30, 2025 * **feat:** ability to filter alerts by status via API ### April 29, 2025 * **feat:** return API timestamps in seconds ### April 18, 2025 * **fix:** API issue with assigning multiple users to role * **feat:** add `initial_delay` field to escalation policy API ### April 15, 2025 * **fix:** allow owner\_group\_ids parameter in API requests ### April 9, 2025 * **fix:** add missing urgency rules to alert sources API ### April 8, 2025 * **feat:** add email source settings to disable threaded emails ### April 4, 2025 * **fix:** typo in alert routes API ### April 3, 2025 * **feat:** team and organization API keys ## March 2025 ### March 31, 2025 * **fix:** API key search in audit logs section ### March 28, 2025 * **feat:** support resolution rule in alert source API ### March 26, 2025 * **fix:** specify required fields in routing rule schema * **fix:** routing rule schema fixes * **fix:** prevent crash from invalid SQL queries * **fix:** allow creating alert events with Rootly bot as user ### March 25, 2025 * **feat:** create/update/delete alert "note" events * **feat:** specify whether field can be computed in API schema ### March 20, 2025 * **fix:** alert routing API issues ### March 17, 2025 * **feat:** add API support for alert routes * **fix:** create cached Slack channel if necessary * **feat:** filter schedules and escalation policies by name * **fix:** validate and hydrate Slack channel targets * **fix:** return 422 for invalid record exceptions * **fix:** prevent duplicate active\_times when updating rotation ### March 14, 2025 * **feat:** add business hours support to escalation policy API * **fix:** schedule rotation update should return errors * **fix:** respect requested escalation level position (breaking change) * **fix:** replace urgency rules when updating source (breaking change) * **fix:** do not prevent deletion of schedule rotations (breaking change) * **fix:** prevent duplicate schedule rotation active times ### March 13, 2025 * **fix:** support for escalation level paging strategy ### March 11, 2025 * **feat:** expose sub-status configuration on teams API ## February 2025 ### February 26, 2025 * **fix:** API alert sources webhooks endpoint URL ### February 25, 2025 * **fix:** alert sources tags and operationId API schema * **feat:** add API support to mark alerts as noise ### February 17, 2025 * **feat:** track last updated user for schedule rotations * **feat:** track last updated user for schedule rotation users ### February 12, 2025 * **feat:** API support for new escalation policy target type "team" ## January 2025 ### January 30, 2025 * **feat:** API support for group admin\_ids ### January 17, 2025 * **fix:** schedules slack\_user\_group API schema ### January 10, 2025 * **feat:** API support for alert source urgency id and alert template ### January 7, 2025 * **feat:** API support for email alert creation ## December 2024 ### December 2, 2024 * **fix:** handle undocumented PagerDuty API schema ## October 2024 ### October 23, 2024 * **feat:** on-call shift calendar subscription ### October 14, 2024 * **feat:** handle "mitigated" status for workflow tasks when sub-status enabled * **feat:** add "Update Incident Status Timestamp" task to API schema ### October 10, 2024 * **feat:** allow sub\_status\_id for /v1/incidents/:id endpoint ### October 1, 2024 * **feat:** add missing API schema attribute for Terraform compatibility ## September 2024 ### September 25, 2024 * **feat:** API support for sub-statuses ### September 16, 2024 * **feat:** expose alert urgency to POST api.rootly.com/v1/alerts ### September 10, 2024 * **feat:** add alert notification target on alert updates ### September 4, 2024 * **feat:** add API support for alert groups ## August 2024 ### August 30, 2024 * **feat:** add API support for alert urgency ### August 29, 2024 * **feat:** add schedule rotation attributes to OpenAPI schema for Terraform compatibility * **feat:** add escalation policy path API support ## July 2024 ### July 19, 2024 * **fix:** escalation policy OpenAPI schema and add service\_ids, group\_ids ### July 2, 2024 * **fix:** /api/v1/dashboards/:id returning 404 when shared publicly *** ## Related resources * [Rootly API overview: authentication and conventions](/api-reference/overview) * [OAuth 2.0 & OpenID Connect](/api-reference/oauth2) * [Official SDKs](/api-reference/sdks) # Creates a communications group Source: https://docs.rootly.com/api-reference/communications-groups/creates-a-communications-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/communications/groups Creates a new communications group from provided data # Deletes a communications group Source: https://docs.rootly.com/api-reference/communications-groups/deletes-a-communications-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/communications/groups/{id} Deletes a communications group # Lists communications groups Source: https://docs.rootly.com/api-reference/communications-groups/lists-communications-groups https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/communications/groups Lists communications groups # Shows a communications group Source: https://docs.rootly.com/api-reference/communications-groups/shows-a-communications-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/communications/groups/{id} Shows details of a communications group # Updates a communications group Source: https://docs.rootly.com/api-reference/communications-groups/updates-a-communications-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json patch /v1/communications/groups/{id} Updates a communications group # Creates a communications stage Source: https://docs.rootly.com/api-reference/communications-stages/creates-a-communications-stage https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/communications/stages Creates a new communications stage from provided data # Deletes a communications stage Source: https://docs.rootly.com/api-reference/communications-stages/deletes-a-communications-stage https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/communications/stages/{id} Deletes a communications stage # Lists communications stages Source: https://docs.rootly.com/api-reference/communications-stages/lists-communications-stages https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/communications/stages Lists communications stages # Shows a communications stage Source: https://docs.rootly.com/api-reference/communications-stages/shows-a-communications-stage https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/communications/stages/{id} Shows details of a communications stage # Updates a communications stage Source: https://docs.rootly.com/api-reference/communications-stages/updates-a-communications-stage https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json patch /v1/communications/stages/{id} Updates a communications stage # Creates a communications template Source: https://docs.rootly.com/api-reference/communications-templates/creates-a-communications-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/communications/templates Creates a new communications template from provided data # Deletes a communications template Source: https://docs.rootly.com/api-reference/communications-templates/deletes-a-communications-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/communications/templates/{id} Deletes a communications template # Lists communications templates Source: https://docs.rootly.com/api-reference/communications-templates/lists-communications-templates https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/communications/templates Lists communications templates # Shows a communications template Source: https://docs.rootly.com/api-reference/communications-templates/shows-a-communications-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/communications/templates/{id} Shows details of a communications template # Updates a communications template Source: https://docs.rootly.com/api-reference/communications-templates/updates-a-communications-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json patch /v1/communications/templates/{id} Updates a communications template # Creates a communications type Source: https://docs.rootly.com/api-reference/communications-types/creates-a-communications-type https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/communications/types Creates a new communications type from provided data # Deletes a communications type Source: https://docs.rootly.com/api-reference/communications-types/deletes-a-communications-type https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/communications/types/{id} Deletes a communications type # Lists communications types Source: https://docs.rootly.com/api-reference/communications-types/lists-communications-types https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/communications/types Lists communications types # Shows a communications type Source: https://docs.rootly.com/api-reference/communications-types/shows-a-communications-type https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/communications/types/{id} Shows details of a communications type # Updates a communications type Source: https://docs.rootly.com/api-reference/communications-types/updates-a-communications-type https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json patch /v1/communications/types/{id} Updates a communications type # Creates a custom form Source: https://docs.rootly.com/api-reference/customforms/creates-a-custom-form https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/custom_forms Creates a new custom form from provided data # Delete a custom form Source: https://docs.rootly.com/api-reference/customforms/delete-a-custom-form https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/custom_forms/{id} Delete a specific custom form by id # List custom forms Source: https://docs.rootly.com/api-reference/customforms/list-custom-forms https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/custom_forms List custom forms # Retrieves a custom form Source: https://docs.rootly.com/api-reference/customforms/retrieves-a-custom-form https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/custom_forms/{id} Retrieves a specific custom form by id # Update a custom form Source: https://docs.rootly.com/api-reference/customforms/update-a-custom-form https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/custom_forms/{id} Update a specific custom form by id # Creates a dashboard panel Source: https://docs.rootly.com/api-reference/dashboardpanels/creates-a-dashboard-panel https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/dashboards/{dashboard_id}/panels Creates a new dashboard panel from provided data # Delete a dashboard panel Source: https://docs.rootly.com/api-reference/dashboardpanels/delete-a-dashboard-panel https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/dashboard_panels/{id} Delete a specific dashboard panel by id # Duplicates a dashboard panel Source: https://docs.rootly.com/api-reference/dashboardpanels/duplicates-a-dashboard-panel https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/dashboard_panels/{id}/duplicate Duplicates a dashboard panel # List dashboard panels Source: https://docs.rootly.com/api-reference/dashboardpanels/list-dashboard-panels https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/dashboards/{dashboard_id}/panels List dashboard panels # Retrieves a dashboard panel Source: https://docs.rootly.com/api-reference/dashboardpanels/retrieves-a-dashboard-panel https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/dashboard_panels/{id} Retrieves a specific dashboard panel by id # Update a dashboard panel Source: https://docs.rootly.com/api-reference/dashboardpanels/update-a-dashboard-panel https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/dashboard_panels/{id} Update a specific dashboard panel by id # Creates a dashboard Source: https://docs.rootly.com/api-reference/dashboards/creates-a-dashboard https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/dashboards Creates a new dashboard from provided data # Delete a dashboard Source: https://docs.rootly.com/api-reference/dashboards/delete-a-dashboard https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/dashboards/{id} Delete a specific dashboard by id # Duplicates a dashboard Source: https://docs.rootly.com/api-reference/dashboards/duplicates-a-dashboard https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/dashboards/{id}/duplicate Duplicates a dashboard # List dashboards Source: https://docs.rootly.com/api-reference/dashboards/list-dashboards https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/dashboards List dashboards # Retrieves a dashboard Source: https://docs.rootly.com/api-reference/dashboards/retrieves-a-dashboard https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/dashboards/{id} Retrieves a specific dashboard by id # Sets dashboard to user default Source: https://docs.rootly.com/api-reference/dashboards/sets-dashboard-to-user-default https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/dashboards/{id}/set_default Sets dashboard to user default # Update a dashboard Source: https://docs.rootly.com/api-reference/dashboards/update-a-dashboard https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/dashboards/{id} Update a specific dashboard by id # Create edge connector action Source: https://docs.rootly.com/api-reference/edge-connector-actions/create-edge-connector-action https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/edge_connectors/{edge_connector_id}/actions # Delete edge connector action Source: https://docs.rootly.com/api-reference/edge-connector-actions/delete-edge-connector-action https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/edge_connectors/{edge_connector_id}/actions/{id} # List edge connector actions Source: https://docs.rootly.com/api-reference/edge-connector-actions/list-edge-connector-actions https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/edge_connectors/{edge_connector_id}/actions # Show edge connector action Source: https://docs.rootly.com/api-reference/edge-connector-actions/show-edge-connector-action https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/edge_connectors/{edge_connector_id}/actions/{id} # Update edge connector action Source: https://docs.rootly.com/api-reference/edge-connector-actions/update-edge-connector-action https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json patch /v1/edge_connectors/{edge_connector_id}/actions/{id} # Create edge connector Source: https://docs.rootly.com/api-reference/edge-connectors/create-edge-connector https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/edge_connectors # Delete edge connector Source: https://docs.rootly.com/api-reference/edge-connectors/delete-edge-connector https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/edge_connectors/{id} # List edge connectors Source: https://docs.rootly.com/api-reference/edge-connectors/list-edge-connectors https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/edge_connectors # Show edge connector Source: https://docs.rootly.com/api-reference/edge-connectors/show-edge-connector https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/edge_connectors/{id} # Update edge connector Source: https://docs.rootly.com/api-reference/edge-connectors/update-edge-connector https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json patch /v1/edge_connectors/{id} # Bulk delete Environments Source: https://docs.rootly.com/api-reference/environments/bulk-delete-environments https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/environments/bulk_delete Delete environments by external_id list, or prune by managed_by source. Two mutually exclusive modes. # Bulk upsert Environments Source: https://docs.rootly.com/api-reference/environments/bulk-upsert-environments https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/environments/bulk_upsert Create or update multiple environments by external_id. Only attributes present in the payload are written (managed-fields semantics). Transactional: all succeed or all fail. Requires an API key with both create and update capability across the resource scope (team/org-scoped); record-scoped principals cannot use this endpoint (they receive 404), which also prevents the create-vs-update branch from leaking whether an external_id exists. # Creates a Catalog Property Source: https://docs.rootly.com/api-reference/environments/creates-a-catalog-property https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/environments/properties Creates a new Catalog Property from provided data # Creates an environment Source: https://docs.rootly.com/api-reference/environments/creates-an-environment https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/environments Creates a new environment from provided data # Delete an environment Source: https://docs.rootly.com/api-reference/environments/delete-an-environment https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/environments/{id} Delete a specific environment by id # List Catalog Properties Source: https://docs.rootly.com/api-reference/environments/list-catalog-properties https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/environments/properties List Environment Catalog Properties # List environments Source: https://docs.rootly.com/api-reference/environments/list-environments https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/environments List environments # Retrieves an environment Source: https://docs.rootly.com/api-reference/environments/retrieves-an-environment https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/environments/{id} Retrieves a specific environment by id # Update an environment Source: https://docs.rootly.com/api-reference/environments/update-an-environment https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/environments/{id} Update a specific environment by id # Delete an escalation level Source: https://docs.rootly.com/api-reference/escalationlevels/delete-an-escalation-level https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/escalation_levels/{id} Delete a specific escalation level by id # Retrieves an escalation level Source: https://docs.rootly.com/api-reference/escalationlevels/retrieves-an-escalation-level https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/escalation_levels/{id} Retrieves a specific escalation level by id # Update an escalation level Source: https://docs.rootly.com/api-reference/escalationlevels/update-an-escalation-level https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/escalation_levels/{id} Update a specific escalation level by id # Creates an escalation level for an Escalation Path Source: https://docs.rootly.com/api-reference/escalationlevelspath/creates-an-escalation-level-for-an-escalation-path https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/escalation_paths/{escalation_policy_path_id}/escalation_levels Creates a new escalation level from provided data # List escalation levels for an Escalation Path Source: https://docs.rootly.com/api-reference/escalationlevelspath/list-escalation-levels-for-an-escalation-path https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/escalation_paths/{escalation_policy_path_id}/escalation_levels List escalation levels # Creates an escalation level for an Escalation Policy Source: https://docs.rootly.com/api-reference/escalationlevelspolicies/creates-an-escalation-level-for-an-escalation-policy https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/escalation_policies/{escalation_policy_id}/escalation_levels Creates a new escalation level from provided data # List escalation levels for an Escalation Policy Source: https://docs.rootly.com/api-reference/escalationlevelspolicies/list-escalation-levels-for-an-escalation-policy https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/escalation_policies/{escalation_policy_id}/escalation_levels List escalation levels # Creates an escalation path Source: https://docs.rootly.com/api-reference/escalationpaths/creates-an-escalation-path https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/escalation_policies/{escalation_policy_id}/escalation_paths Creates a new escalation path from provided data # Delete an escalation path Source: https://docs.rootly.com/api-reference/escalationpaths/delete-an-escalation-path https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/escalation_paths/{id} Delete a specific escalation path by id # List escalation paths Source: https://docs.rootly.com/api-reference/escalationpaths/list-escalation-paths https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/escalation_policies/{escalation_policy_id}/escalation_paths List escalation paths # Retrieves an escalation path Source: https://docs.rootly.com/api-reference/escalationpaths/retrieves-an-escalation-path https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/escalation_paths/{id} Retrieves a specific escalation path by id # Update an escalation path Source: https://docs.rootly.com/api-reference/escalationpaths/update-an-escalation-path https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/escalation_paths/{id} Update a specific escalation path by id # Creates an escalation policy Source: https://docs.rootly.com/api-reference/escalationpolicies/creates-an-escalation-policy https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/escalation_policies Creates a new escalation policy from provided data # Delete an escalation policy Source: https://docs.rootly.com/api-reference/escalationpolicies/delete-an-escalation-policy https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/escalation_policies/{id} Delete a specific escalation policy by id # List escalation policies Source: https://docs.rootly.com/api-reference/escalationpolicies/list-escalation-policies https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/escalation_policies List escalation policies # Retrieves an escalation policy Source: https://docs.rootly.com/api-reference/escalationpolicies/retrieves-an-escalation-policy https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/escalation_policies/{id} Retrieves a specific escalation policy by id # Update an escalation policy Source: https://docs.rootly.com/api-reference/escalationpolicies/update-an-escalation-policy https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/escalation_policies/{id} Update a specific escalation policy by id # Creates FormField Options Source: https://docs.rootly.com/api-reference/formfieldoptions/creates-formfield-options https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/form_fields/{form_field_id}/options Creates a new form_field_option from provided data # Delete FormField Options Source: https://docs.rootly.com/api-reference/formfieldoptions/delete-formfield-options https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/form_field_options/{id} Delete a specific form_field_option by id # List FormField Options Source: https://docs.rootly.com/api-reference/formfieldoptions/list-formfield-options https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_fields/{form_field_id}/options List form_field_options # Retrieves FormField Options Source: https://docs.rootly.com/api-reference/formfieldoptions/retrieves-formfield-options https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_field_options/{id} Retrieves a specific form_field_option by id # Update FormField Options Source: https://docs.rootly.com/api-reference/formfieldoptions/update-formfield-options https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/form_field_options/{id} Update a specific form_field_option by id # Creates a Form Set Condition Source: https://docs.rootly.com/api-reference/formfieldplacementconditions/creates-a-form-set-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/form_field_placements/{form_field_placement_id}/conditions Creates a new form_field_placement_condition from provided data # Delete a Form Set Condition Source: https://docs.rootly.com/api-reference/formfieldplacementconditions/delete-a-form-set-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/form_field_placement_conditions/{id} Delete a specific form_field_placement_condition by id # List Form Set Conditions Source: https://docs.rootly.com/api-reference/formfieldplacementconditions/list-form-set-conditions https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_field_placements/{form_field_placement_id}/conditions List form_field_placement_conditions # Retrieves a Form Set Condition Source: https://docs.rootly.com/api-reference/formfieldplacementconditions/retrieves-a-form-set-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_field_placement_conditions/{id} Retrieves a specific form_field_placement_condition by id # Update a Form Set Condition Source: https://docs.rootly.com/api-reference/formfieldplacementconditions/update-a-form-set-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/form_field_placement_conditions/{id} Update a specific form_field_placement_condition by id # Creates a Form Field Placement Source: https://docs.rootly.com/api-reference/formfieldplacements/creates-a-form-field-placement https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/form_fields/{form_field_id}/placements Creates a new form_field_placement from provided data # Delete a Form Field Placement Source: https://docs.rootly.com/api-reference/formfieldplacements/delete-a-form-field-placement https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/form_field_placements/{id} Delete a specific form_field_placement by id # List Form Field Placements Source: https://docs.rootly.com/api-reference/formfieldplacements/list-form-field-placements https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_fields/{form_field_id}/placements List form_field_placements # Retrieves a Form Field Placement Source: https://docs.rootly.com/api-reference/formfieldplacements/retrieves-a-form-field-placement https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_field_placements/{id} Retrieves a specific form_field_placement by id # Update a Form Field Placement Source: https://docs.rootly.com/api-reference/formfieldplacements/update-a-form-field-placement https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/form_field_placements/{id} Update a specific form_field_placement by id # Creates FormField Positions Source: https://docs.rootly.com/api-reference/formfieldpositions/creates-formfield-positions https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/form_fields/{form_field_id}/positions Creates a new form field_position from provided data # Delete a FormFieldPosition Source: https://docs.rootly.com/api-reference/formfieldpositions/delete-a-formfieldposition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/form_field_positions/{id} Delete a specific form_field position by id # List FormField Position Source: https://docs.rootly.com/api-reference/formfieldpositions/list-formfield-position https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_fields/{form_field_id}/positions List form field positions # Retrieves a FormFieldPosition Source: https://docs.rootly.com/api-reference/formfieldpositions/retrieves-a-formfieldposition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_field_positions/{id} Retrieves a specific form field_position by id # Update a FormFieldPosition Source: https://docs.rootly.com/api-reference/formfieldpositions/update-a-formfieldposition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/form_field_positions/{id} Update a specific form_field position by id # Creates a Form Field Source: https://docs.rootly.com/api-reference/formfields/creates-a-form-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/form_fields Creates a new form_field from provided data # Delete a Form Field Source: https://docs.rootly.com/api-reference/formfields/delete-a-form-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/form_fields/{id} Delete a specific form_field by id # List Form Fields Source: https://docs.rootly.com/api-reference/formfields/list-form-fields https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_fields List form_fields # Retrieves a Form Field Source: https://docs.rootly.com/api-reference/formfields/retrieves-a-form-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_fields/{id} Retrieves a specific form_field by id # Update a Form Field Source: https://docs.rootly.com/api-reference/formfields/update-a-form-field https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/form_fields/{id} Update a specific form_field by id # Creates a Form Set Condition Source: https://docs.rootly.com/api-reference/formsetconditions/creates-a-form-set-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/form_sets/{form_set_id}/conditions Creates a new form_set_condition from provided data # Delete a Form Set Condition Source: https://docs.rootly.com/api-reference/formsetconditions/delete-a-form-set-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/form_set_conditions/{id} Delete a specific form_set_condition by id # List Form Set Conditions Source: https://docs.rootly.com/api-reference/formsetconditions/list-form-set-conditions https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_sets/{form_set_id}/conditions List form_set_conditions # Retrieves a Form Set Condition Source: https://docs.rootly.com/api-reference/formsetconditions/retrieves-a-form-set-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_set_conditions/{id} Retrieves a specific form_set_condition by id # Update a Form Set Condition Source: https://docs.rootly.com/api-reference/formsetconditions/update-a-form-set-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/form_set_conditions/{id} Update a specific form_set_condition by id # Creates a Form Set Source: https://docs.rootly.com/api-reference/formsets/creates-a-form-set https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/form_sets Creates a new form_set from provided data # Delete a Form Set Source: https://docs.rootly.com/api-reference/formsets/delete-a-form-set https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/form_sets/{id} Delete a specific form_set by id # List Form Sets Source: https://docs.rootly.com/api-reference/formsets/list-form-sets https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_sets List form_sets # Retrieves a Form Set Source: https://docs.rootly.com/api-reference/formsets/retrieves-a-form-set https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/form_sets/{id} Retrieves a specific form_set by id # Update a Form Set Source: https://docs.rootly.com/api-reference/formsets/update-a-form-set https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/form_sets/{id} Update a specific form_set by id # Bulk delete Functionalities Source: https://docs.rootly.com/api-reference/functionalities/bulk-delete-functionalities https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/functionalities/bulk_delete Delete functionalities by external_id list, or prune by managed_by source. Two mutually exclusive modes. # Bulk upsert Functionalities Source: https://docs.rootly.com/api-reference/functionalities/bulk-upsert-functionalities https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/functionalities/bulk_upsert Create or update multiple functionalities by external_id. Only attributes present in the payload are written (managed-fields semantics). Transactional: all succeed or all fail. Requires an API key with both create and update capability across the resource scope (team/org-scoped); record-scoped principals cannot use this endpoint (they receive 404), which also prevents the create-vs-update branch from leaking whether an external_id exists. # Creates a Catalog Property Source: https://docs.rootly.com/api-reference/functionalities/creates-a-catalog-property https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/functionalities/properties Creates a new Catalog Property from provided data # Creates a functionality Source: https://docs.rootly.com/api-reference/functionalities/creates-a-functionality https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/functionalities Creates a new functionality from provided data # Delete a functionality Source: https://docs.rootly.com/api-reference/functionalities/delete-a-functionality https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/functionalities/{id} Delete a specific functionality by id # Get functionality incidents chart Source: https://docs.rootly.com/api-reference/functionalities/get-functionality-incidents-chart https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/functionalities/{id}/incidents_chart Get functionality incidents chart # Get functionality uptime chart Source: https://docs.rootly.com/api-reference/functionalities/get-functionality-uptime-chart https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/functionalities/{id}/uptime_chart Get functionality uptime chart # List Catalog Properties Source: https://docs.rootly.com/api-reference/functionalities/list-catalog-properties https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/functionalities/properties List Functionality Catalog Properties # List functionalities Source: https://docs.rootly.com/api-reference/functionalities/list-functionalities https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/functionalities List functionalities # Retrieves a functionality Source: https://docs.rootly.com/api-reference/functionalities/retrieves-a-functionality https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/functionalities/{id} Retrieves a specific functionality by id # Update a functionality Source: https://docs.rootly.com/api-reference/functionalities/update-a-functionality https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/functionalities/{id} Update a specific functionality by id # Creates a heartbeat Source: https://docs.rootly.com/api-reference/heartbeats/creates-a-heartbeat https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/heartbeats Creates a new heartbeat from provided data # Delete a heartbeat Source: https://docs.rootly.com/api-reference/heartbeats/delete-a-heartbeat https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/heartbeats/{id} Delete a specific heartbeat by id # List heartbeats Source: https://docs.rootly.com/api-reference/heartbeats/list-heartbeats https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/heartbeats List heartbeats # Ping a heartbeat Source: https://docs.rootly.com/api-reference/heartbeats/ping-a-heartbeat https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/heartbeats/{heartbeat_id}/ping Ping a specific heartbeat by id # Retrieves a heartbeat Source: https://docs.rootly.com/api-reference/heartbeats/retrieves-a-heartbeat https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/heartbeats/{id} Retrieves a specific heartbeat by id # Update a heartbeat Source: https://docs.rootly.com/api-reference/heartbeats/update-a-heartbeat https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/heartbeats/{id} Update a specific heartbeat by id # Creates an incident action item Source: https://docs.rootly.com/api-reference/incidentactionitems/creates-an-incident-action-item https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents/{incident_id}/action_items Creates a new action item from provided data # Delete an incident action item Source: https://docs.rootly.com/api-reference/incidentactionitems/delete-an-incident-action-item https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/action_items/{id} Delete a specific incident action item by id # List all action items for an organization Source: https://docs.rootly.com/api-reference/incidentactionitems/list-all-action-items-for-an-organization https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/action_items List all action items for an organization # List incident action items Source: https://docs.rootly.com/api-reference/incidentactionitems/list-incident-action-items https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incidents/{incident_id}/action_items List incident action items # Retrieves an incident action item Source: https://docs.rootly.com/api-reference/incidentactionitems/retrieves-an-incident-action-item https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/action_items/{id} Retrieves a specific incident_action_item by id # Update an incident action item Source: https://docs.rootly.com/api-reference/incidentactionitems/update-an-incident-action-item https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/action_items/{id} Update a specific incident action item by id # Creates an incident event functionality Source: https://docs.rootly.com/api-reference/incidenteventfunctionalities/creates-an-incident-event-functionality https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/events/{incident_event_id}/functionalities Creates a new event functionality from provided data # Delete an incident event functionality Source: https://docs.rootly.com/api-reference/incidenteventfunctionalities/delete-an-incident-event-functionality https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incident_event_functionalities/{id} Delete a specific incident event functionality by id # List incident event functionalities Source: https://docs.rootly.com/api-reference/incidenteventfunctionalities/list-incident-event-functionalities https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/events/{incident_event_id}/functionalities List incident event functionalities # Retrieves an incident event functionality Source: https://docs.rootly.com/api-reference/incidenteventfunctionalities/retrieves-an-incident-event-functionality https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_event_functionalities/{id} Retrieves a specific incident_event_functionality by id # Update an incident event Source: https://docs.rootly.com/api-reference/incidenteventfunctionalities/update-an-incident-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incident_event_functionalities/{id} Update a specific incident event functionality by id # Creates an incident event Source: https://docs.rootly.com/api-reference/incidentevents/creates-an-incident-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents/{incident_id}/events Creates a new event from provided data # Delete an incident event Source: https://docs.rootly.com/api-reference/incidentevents/delete-an-incident-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/events/{id} Delete a specific incident event by id # List incident events Source: https://docs.rootly.com/api-reference/incidentevents/list-incident-events https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incidents/{incident_id}/events List incident events # Retrieves an incident event Source: https://docs.rootly.com/api-reference/incidentevents/retrieves-an-incident-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/events/{id} Retrieves a specific incident_event by id # Update an incident event Source: https://docs.rootly.com/api-reference/incidentevents/update-an-incident-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/events/{id} Update a specific incident event by id # Creates an incident event service Source: https://docs.rootly.com/api-reference/incidenteventservices/creates-an-incident-event-service https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/events/{incident_event_id}/services Creates a new event service from provided data # Delete an incident event functionalitu Source: https://docs.rootly.com/api-reference/incidenteventservices/delete-an-incident-event-functionalitu https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incident_event_services/{id} Delete a specific incident event service by id # List incident event services Source: https://docs.rootly.com/api-reference/incidenteventservices/list-incident-event-services https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/events/{incident_event_id}/services List incident event services # Retrieves an incident event service Source: https://docs.rootly.com/api-reference/incidenteventservices/retrieves-an-incident-event-service https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_event_services/{id} Retrieves a specific incident_event_service by id # Update an incident event Source: https://docs.rootly.com/api-reference/incidenteventservices/update-an-incident-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incident_event_services/{id} Update a specific incident event service by id # Creates an incident feedback Source: https://docs.rootly.com/api-reference/incidentfeedbacks/creates-an-incident-feedback https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents/{incident_id}/feedbacks Creates a new feedback from provided data # List incident feedbacks Source: https://docs.rootly.com/api-reference/incidentfeedbacks/list-incident-feedbacks https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incidents/{incident_id}/feedbacks List incident feedbacks # Retrieves an incident feedback Source: https://docs.rootly.com/api-reference/incidentfeedbacks/retrieves-an-incident-feedback https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/feedbacks/{id} Retrieves a specific incident_feedback by id # Update an incident feedback Source: https://docs.rootly.com/api-reference/incidentfeedbacks/update-an-incident-feedback https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/feedbacks/{id} Update a specific incident feedback by id # Creates an incident form field selection Source: https://docs.rootly.com/api-reference/incidentformfieldselections/creates-an-incident-form-field-selection https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents/{incident_id}/form_field_selections Creates a new incident form field selection from provided data # Delete an incident form field selection Source: https://docs.rootly.com/api-reference/incidentformfieldselections/delete-an-incident-form-field-selection https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incident_form_field_selections/{id} Delete a specific incident form field selection by id # List incident form field selections Source: https://docs.rootly.com/api-reference/incidentformfieldselections/list-incident-form-field-selections https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incidents/{incident_id}/form_field_selections List incident form field selections # Retrieves an incident form field selection Source: https://docs.rootly.com/api-reference/incidentformfieldselections/retrieves-an-incident-form-field-selection https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_form_field_selections/{id} Retrieves a specific incident form field selection by id # Update an incident form field selection Source: https://docs.rootly.com/api-reference/incidentformfieldselections/update-an-incident-form-field-selection https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incident_form_field_selections/{id} Update a specific incident form field selection by id # Creates an incident_permission_set_boolean Source: https://docs.rootly.com/api-reference/incidentpermissionsetbooleans/creates-an-incident_permission_set_boolean https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incident_permission_sets/{incident_permission_set_id}/booleans Creates a new incident_permission_set_boolean from provided data # Delete an incident_permission_set_boolean Source: https://docs.rootly.com/api-reference/incidentpermissionsetbooleans/delete-an-incident_permission_set_boolean https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incident_permission_set_booleans/{id} Delete a specific incident_permission_set_boolean by id # List incident_permission_set_booleans Source: https://docs.rootly.com/api-reference/incidentpermissionsetbooleans/list-incident_permission_set_booleans https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_permission_sets/{incident_permission_set_id}/booleans List incident_permission_set_booleans # Retrieves an incident_permission_set_boolean Source: https://docs.rootly.com/api-reference/incidentpermissionsetbooleans/retrieves-an-incident_permission_set_boolean https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_permission_set_booleans/{id} Retrieves a specific incident_permission_set_boolean by id # Update an incident_permission_set_boolean Source: https://docs.rootly.com/api-reference/incidentpermissionsetbooleans/update-an-incident_permission_set_boolean https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incident_permission_set_booleans/{id} Update a specific incident_permission_set_boolean by id # Creates an incident_permission_set_resource Source: https://docs.rootly.com/api-reference/incidentpermissionsetresources/creates-an-incident_permission_set_resource https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incident_permission_sets/{incident_permission_set_id}/resources Creates a new incident_permission_set_resource from provided data # Delete an incident_permission_set_resource Source: https://docs.rootly.com/api-reference/incidentpermissionsetresources/delete-an-incident_permission_set_resource https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incident_permission_set_resources/{id} Delete a specific incident_permission_set_resource by id # List incident_permission_set_resources Source: https://docs.rootly.com/api-reference/incidentpermissionsetresources/list-incident_permission_set_resources https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_permission_sets/{incident_permission_set_id}/resources List incident_permission_set_resources # Retrieves an incident_permission_set_resource Source: https://docs.rootly.com/api-reference/incidentpermissionsetresources/retrieves-an-incident_permission_set_resource https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_permission_set_resources/{id} Retrieves a specific incident_permission_set_resource by id # Update an incident_permission_set_resource Source: https://docs.rootly.com/api-reference/incidentpermissionsetresources/update-an-incident_permission_set_resource https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incident_permission_set_resources/{id} Update a specific incident_permission_set_resource by id # Creates an incident_permission_set Source: https://docs.rootly.com/api-reference/incidentpermissionsets/creates-an-incident_permission_set https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incident_permission_sets Creates a new incident_permission_set from provided data # Delete an incident_permission_set Source: https://docs.rootly.com/api-reference/incidentpermissionsets/delete-an-incident_permission_set https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incident_permission_sets/{id} Delete a specific incident_permission_set by id # List incident_permission_sets Source: https://docs.rootly.com/api-reference/incidentpermissionsets/list-incident_permission_sets https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_permission_sets List incident_permission_sets # Retrieves an incident_permission_set Source: https://docs.rootly.com/api-reference/incidentpermissionsets/retrieves-an-incident_permission_set https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_permission_sets/{id} Retrieves a specific incident_permission_set by id # Update an incident_permission_set Source: https://docs.rootly.com/api-reference/incidentpermissionsets/update-an-incident_permission_set https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incident_permission_sets/{id} Update a specific incident_permission_set by id # List incident retrospectives Source: https://docs.rootly.com/api-reference/incidentretrospectives/list-incident-retrospectives https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/post_mortems List incident retrospectives # Retrieves an incident retrospective Source: https://docs.rootly.com/api-reference/incidentretrospectives/retrieves-an-incident-retrospective https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/post_mortems/{id} List incidents retrospectives # Update an incident retrospective Source: https://docs.rootly.com/api-reference/incidentretrospectives/update-an-incident-retrospective https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/post_mortems/{id} Update a specific incident retrospective by id. The body may be written as `content` (or its alias `smart_content`) and is sanitized to the tags the retrospective editor supports. When no `title` is sent and the body opens with an `

`, that heading becomes the retrospective title, matching the editor. Once a retrospective has been opened in the collaborative editor that editor owns the body, and body writes are rejected with a 409. # Retrieves an incident retrospective step Source: https://docs.rootly.com/api-reference/incidentretrospectivesteps/retrieves-an-incident-retrospective-step https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_retrospective_steps/{id} Retrieves a specific incident retrospective step by id # Update an incident retrospective step Source: https://docs.rootly.com/api-reference/incidentretrospectivesteps/update-an-incident-retrospective-step https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incident_retrospective_steps/{id} Update a specific incident retrospective step by id # Creates an incident role Source: https://docs.rootly.com/api-reference/incidentroles/creates-an-incident-role https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incident_roles Creates a new incident role from provided data # Delete an incident role Source: https://docs.rootly.com/api-reference/incidentroles/delete-an-incident-role https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incident_roles/{id} Delete a specific incident_role by id # List incident roles Source: https://docs.rootly.com/api-reference/incidentroles/list-incident-roles https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_roles List incident roles # Retrieves an incident role Source: https://docs.rootly.com/api-reference/incidentroles/retrieves-an-incident-role https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_roles/{id} Retrieves a specific incident_role by id # Update an incident role Source: https://docs.rootly.com/api-reference/incidentroles/update-an-incident-role https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incident_roles/{id} Update a specific incident_role by id # Creates an incident role task Source: https://docs.rootly.com/api-reference/incidentroletasks/creates-an-incident-role-task https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incident_roles/{incident_role_id}/incident_role_tasks Creates a new task from provided data # Delete an incident role task Source: https://docs.rootly.com/api-reference/incidentroletasks/delete-an-incident-role-task https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incident_role_tasks/{id} Delete a specific incident_role task by id # List incident role tasks Source: https://docs.rootly.com/api-reference/incidentroletasks/list-incident-role-tasks https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_roles/{incident_role_id}/incident_role_tasks List incident_role tasks # Retrieves an incident role task Source: https://docs.rootly.com/api-reference/incidentroletasks/retrieves-an-incident-role-task https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_role_tasks/{id} Retrieves a specific incident_role_task by id # Update an incident role task Source: https://docs.rootly.com/api-reference/incidentroletasks/update-an-incident-role-task https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incident_role_tasks/{id} Update a specific incident_role task by id # Add subscribers to incident Source: https://docs.rootly.com/api-reference/incidents/add-subscribers-to-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents/{id}/add_subscribers Add subscribers to incident # Assign user to incident Source: https://docs.rootly.com/api-reference/incidents/assign-user-to-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents/{id}/assign_role_to_user Assign user to incident # Cancel an incident Source: https://docs.rootly.com/api-reference/incidents/cancel-an-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incidents/{id}/cancel Cancel a specific incident by id # Creates an incident Source: https://docs.rootly.com/api-reference/incidents/creates-an-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents Creates a new incident from provided data # Delete an incident Source: https://docs.rootly.com/api-reference/incidents/delete-an-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incidents/{id} Delete a specific incident by id # Detach an incident from its parent Source: https://docs.rootly.com/api-reference/incidents/detach-an-incident-from-its-parent https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incidents/{id}/detach_from_parent Detach a sub-incident from its parent incident # List incidents Source: https://docs.rootly.com/api-reference/incidents/list-incidents https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incidents List incidents # Mark an incident as a duplicate Source: https://docs.rootly.com/api-reference/incidents/mark-an-incident-as-a-duplicate https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incidents/{id}/duplicate Mark an incident as a duplicate # Mitigate an incident Source: https://docs.rootly.com/api-reference/incidents/mitigate-an-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incidents/{id}/mitigate Mitigate a specific incident by id # Remove assigned user from incident Source: https://docs.rootly.com/api-reference/incidents/remove-assigned-user-from-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incidents/{id}/unassign_role_from_user Remove assigned user from incident # Remove duplicate marking from an incident Source: https://docs.rootly.com/api-reference/incidents/remove-duplicate-marking-from-an-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incidents/{id}/unmark_as_duplicate Remove the duplicate marking from an incident # Remove subscribers from incident Source: https://docs.rootly.com/api-reference/incidents/remove-subscribers-from-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incidents/{id}/remove_subscribers Remove subscribers to incident # Resolve an incident Source: https://docs.rootly.com/api-reference/incidents/resolve-an-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incidents/{id}/resolve Resolve a specific incident by id # Restart an incident Source: https://docs.rootly.com/api-reference/incidents/restart-an-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incidents/{id}/restart Restart a specific incident by id # Retrieves an incident Source: https://docs.rootly.com/api-reference/incidents/retrieves-an-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incidents/{id} Retrieves a specific incident by id # Triage an incident Source: https://docs.rootly.com/api-reference/incidents/triage-an-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incidents/{id}/in_triage Set a specific incident by ID to triage state # Update an incident Source: https://docs.rootly.com/api-reference/incidents/update-an-incident https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incidents/{id} Update a specific incident by id # Creates an incident status page event Source: https://docs.rootly.com/api-reference/incidentstatuspageevents/creates-an-incident-status-page-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents/{incident_id}/status-page-events Creates a new event from provided data # Delete an incident status page event Source: https://docs.rootly.com/api-reference/incidentstatuspageevents/delete-an-incident-status-page-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/status-page-events/{id} Delete a specific incident status page event by id # List incident status page events Source: https://docs.rootly.com/api-reference/incidentstatuspageevents/list-incident-status-page-events https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incidents/{incident_id}/status-page-events List incident status page events # Retrieves an incident status page event Source: https://docs.rootly.com/api-reference/incidentstatuspageevents/retrieves-an-incident-status-page-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/status-page-events/{id} Retrieves a specific incident_status_page_event by id # Update an incident status page event Source: https://docs.rootly.com/api-reference/incidentstatuspageevents/update-an-incident-status-page-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/status-page-events/{id} Update a specific incident status page event by id # Creates a sub-status assignment Source: https://docs.rootly.com/api-reference/incidentsubstatuses/creates-a-sub-status-assignment https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents/{incident_id}/sub_statuses Creates a new sub-status assignment from provided data # Delete an incident_sub_status Source: https://docs.rootly.com/api-reference/incidentsubstatuses/delete-an-incident_sub_status https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incident_sub_statuses/{id} Delete a specific incident_sub_status by id # List incident_sub_statuses Source: https://docs.rootly.com/api-reference/incidentsubstatuses/list-incident_sub_statuses https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incidents/{incident_id}/sub_statuses List incident_sub_statuses # Retrieves incident_sub_status Source: https://docs.rootly.com/api-reference/incidentsubstatuses/retrieves-incident_sub_status https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_sub_statuses/{id} Retrieves a specific incident_sub_status by id # Update incident_sub_status Source: https://docs.rootly.com/api-reference/incidentsubstatuses/update-incident_sub_status https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incident_sub_statuses/{id} Update a specific incident_sub_status by id # Creates a Catalog Property Source: https://docs.rootly.com/api-reference/incidenttypes/creates-a-catalog-property https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incident_types/properties Creates a new Catalog Property from provided data # Creates an incident type Source: https://docs.rootly.com/api-reference/incidenttypes/creates-an-incident-type https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incident_types Creates a new incident_type from provided data # Delete an incident type Source: https://docs.rootly.com/api-reference/incidenttypes/delete-an-incident-type https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/incident_types/{id} Delete a specific incident_type by id # List Catalog Properties Source: https://docs.rootly.com/api-reference/incidenttypes/list-catalog-properties https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_types/properties List IncidentType Catalog Properties # List incident types Source: https://docs.rootly.com/api-reference/incidenttypes/list-incident-types https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_types List incident types # Retrieves an incident type Source: https://docs.rootly.com/api-reference/incidenttypes/retrieves-an-incident-type https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incident_types/{id} Retrieves a specific incident_type by id # Update an incident type Source: https://docs.rootly.com/api-reference/incidenttypes/update-an-incident-type https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/incident_types/{id} Update a specific incident_type by id # Retrieves IP ranges Source: https://docs.rootly.com/api-reference/ipranges/retrieves-ip-ranges https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/ip_ranges Retrieves the IP ranges for rootly.com services # Creates a Live Call Router Source: https://docs.rootly.com/api-reference/livecallrouters/creates-a-live-call-router https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/live_call_routers Creates a new Live Call Router from provided data # Delete a Live Call Router Source: https://docs.rootly.com/api-reference/livecallrouters/delete-a-live-call-router https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/live_call_routers/{id} Delete a specific Live Call Router by id # Generates a phone number for Live Call Router Source: https://docs.rootly.com/api-reference/livecallrouters/generates-a-phone-number-for-live-call-router https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/live_call_routers/generate_phone_number Generates a phone number for Live Call Router # List Live Call Routers Source: https://docs.rootly.com/api-reference/livecallrouters/list-live-call-routers https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/live_call_routers List Live Call Routers # Retrieves a Live Call Router Source: https://docs.rootly.com/api-reference/livecallrouters/retrieves-a-live-call-router https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/live_call_routers/{id} Retrieves a specific Live Call Router by id # Update a Live Call Router Source: https://docs.rootly.com/api-reference/livecallrouters/update-a-live-call-router https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/live_call_routers/{id} Update a specific Live Call Router by id # Create meeting recording Source: https://docs.rootly.com/api-reference/meeting-recordings/create-meeting-recording https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents/{incident_id}/meeting_recordings Invite a recording bot to the incident's meeting. If no previous recordings exist for the platform, a new bot is invited (session 1). If previous sessions exist, a new session is created (re-invite). The bot joins the meeting, records audio/video, and generates a transcript when the session ends. # Delete a meeting recording Source: https://docs.rootly.com/api-reference/meeting-recordings/delete-a-meeting-recording https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/meeting_recordings/{id} Delete a meeting recording. Only completed or failed recordings can be deleted. Active recordings (pending, recording, paused) must be stopped first. # Delete a standalone meeting recording Source: https://docs.rootly.com/api-reference/meeting-recordings/delete-a-standalone-meeting-recording https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/meeting_recordings/{id}/delete_session Delete a standalone meeting recording (not linked to an incident). Only the recording owner can delete it. Active recordings (pending, recording, paused) must be stopped first. Returns 404 for incident-linked recordings or recordings owned by another user. # Delete video from a meeting recording Source: https://docs.rootly.com/api-reference/meeting-recordings/delete-video-from-a-meeting-recording https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/meeting_recordings/{id}/delete_video Delete only the video file from a meeting recording. The transcript, summary, and all metadata are preserved. Only non-active recordings with an attached video can have their video deleted. # Get a meeting recording Source: https://docs.rootly.com/api-reference/meeting-recordings/get-a-meeting-recording https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/meeting_recordings/{id} Retrieve a single meeting recording session including its status, duration, speaker count, word count, and transcript summary. # Import a meeting recording Source: https://docs.rootly.com/api-reference/meeting-recordings/import-a-meeting-recording https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/incidents/{incident_id}/meeting_recordings/import Import an externally captured meeting recording and attach it to an incident. Video and transcript are fetched asynchronously. The existing POST /v1/incidents/{incident_id}/meeting_recordings endpoint invites a bot — this endpoint handles recordings that were captured outside of the bot flow. # Leave a meeting call Source: https://docs.rootly.com/api-reference/meeting-recordings/leave-a-meeting-call https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/meeting_recordings/{id}/leave Remove the recording bot from the meeting entirely. Unlike stop, this immediately disconnects the bot. The session will transition to analyzing and then completed once transcript processing finishes. # List all meeting recordings Source: https://docs.rootly.com/api-reference/meeting-recordings/list-all-meeting-recordings https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/meeting_recordings List meeting recordings across the organization. Returns the current user's standalone recordings plus incident-backed recordings the user can access. Supports filtering by status, platform, and created_by. # List meeting recordings Source: https://docs.rootly.com/api-reference/meeting-recordings/list-meeting-recordings https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/incidents/{incident_id}/meeting_recordings List all meeting recording sessions for an incident. Returns recordings sorted by session number. Each recording represents one bot session with its own transcript, status, and metadata. # Pause a meeting recording Source: https://docs.rootly.com/api-reference/meeting-recordings/pause-a-meeting-recording https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/meeting_recordings/{id}/pause Pause an active recording session. The bot remains in the meeting but stops capturing audio/video. Use the resume endpoint to continue recording. # Resume a meeting recording Source: https://docs.rootly.com/api-reference/meeting-recordings/resume-a-meeting-recording https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/meeting_recordings/{id}/resume Resume a paused recording session. The bot continues capturing audio/video from the meeting. # Start a recording session Source: https://docs.rootly.com/api-reference/meeting-recordings/start-a-recording-session https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/meeting_recordings/start_session Start a new desktop recording session. The server creates a recording record and returns a stream token the desktop client uses to send audio. No provider-specific configuration is needed from the client. # Stop a meeting recording Source: https://docs.rootly.com/api-reference/meeting-recordings/stop-a-meeting-recording https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/meeting_recordings/{id}/stop Stop an active or paused recording. The bot finishes processing, generates a transcript, and the session status transitions to completed. This is irreversible — to record again, create a new session. # OAuth 2.0 & OpenID Connect Source: https://docs.rootly.com/api-reference/oauth2 Authenticate with the Rootly API via OAuth 2.0 and OpenID Connect: browser login for CLIs, third-party app consent flows, and automation tokens. OAuth 2.0 is an alternative to [API keys](/api-reference/overview#how-to-generate-an-api-key). Both authentication methods are supported and accept the same `Authorization: Bearer ` header on every API endpoint. You can keep using API keys — nothing changes for existing integrations. ## When to use OAuth 2.0 Reach for OAuth 2.0 over API keys when you need any of the following: * **Browser-based login for CLI, TUI, or desktop tools** — end users sign in through Rootly and consent to scopes instead of copy-pasting a token. See the [CLI & TUI quick start](#quick-start-cli-tui-tools). * **Third-party applications** that act on behalf of a Rootly user and need scoped, revocable access. * **Unattended automation** (CI, internal services, MCP servers) that needs a user-independent token scoped to a specific team and permission set. * **OpenID Connect discovery** — MCP clients and SSO-style integrations that expect `.well-known/openid-configuration` and a signed ID token. ## Managing OAuth applications Team admins can create, edit, and revoke OAuth applications from **Organization Settings → OAuth Applications**. Both public and confidential auth-code clients can also self-register at runtime via [Dynamic Client Registration](#dynamic-client-registration-rfc-7591) — no admin setup required. Only client-credentials (server-to-server) apps must be created by an admin. ## Endpoints OAuth endpoints are served from `https://rootly.com` (the same host users log in to). API calls authenticated with the resulting token still go to `https://api.rootly.com`. | Purpose | Method | URL | | ---------------------------------------- | ------ | ----------------------------------------------------------- | | Authorization Server Metadata (RFC 8414) | `GET` | `https://rootly.com/.well-known/oauth-authorization-server` | | OpenID Connect Discovery | `GET` | `https://rootly.com/.well-known/openid-configuration` | | JWKS | `GET` | `https://rootly.com/oauth/discovery/keys` | | Authorization | `GET` | `https://rootly.com/oauth/authorize` | | Token | `POST` | `https://rootly.com/oauth/token` | | Token introspection | `POST` | `https://rootly.com/oauth/introspect` | | Token revocation | `POST` | `https://rootly.com/oauth/revoke` | | UserInfo (OIDC) | `GET` | `https://rootly.com/oauth/userinfo` | | Dynamic Client Registration (RFC 7591) | `POST` | `https://rootly.com/oauth/register` | Clients that support discovery can bootstrap from either `.well-known` document — all endpoint URLs, supported scopes, grant types, and signing algorithms are advertised there. ## Client types | Type | Client secret | Grant types | How to create | | ---------------- | ------------- | ------------------------------------------ | -------------------------------------------------------- | | **Public** | No (PKCE) | `authorization_code` | Self-register via `/oauth/register`, or in the Rootly UI | | **Confidential** | Yes | `authorization_code`, `client_credentials` | Self-register via `/oauth/register`, or in the Rootly UI | Public clients must use PKCE with `S256`. Native CLIs, desktop apps, and MCP clients should register as public. Confidential clients created via Dynamic Client Registration receive a `client_secret` in the registration response — it is returned **once** and cannot be retrieved again. Client-credentials apps (no redirect URI, server-to-server only) must be created by a team admin in the UI. ## Quick start: CLI & TUI tools Native CLIs and TUIs follow the [native app pattern](https://www.rfc-editor.org/rfc/rfc8252) — self-register at first launch, open the system browser for sign-in, and capture the authorization code on a local loopback port. No client secret, no copy-pasted tokens. The full flow: 1. **Register a public client** (once, cached on disk) via Dynamic Client Registration. 2. **Generate a PKCE pair** (`code_verifier` + `code_challenge`). 3. **Start a loopback HTTP listener** on an ephemeral port — its URL is the `redirect_uri`. 4. **Open the system browser** to `https://rootly.com/oauth/authorize` with the PKCE challenge. 5. **Receive the `code` on the loopback listener**, then exchange it at `/oauth/token`. 6. **Persist the access + refresh tokens** to a per-user secret store. End-to-end Python example: ```python theme={null} import http.server, secrets, hashlib, base64, urllib.parse, webbrowser, requests ROOTLY = "https://rootly.com" # 1. Register once — cache client_id on disk for subsequent runs. client = requests.post(f"{ROOTLY}/oauth/register", json={ "client_name": "My CLI", "redirect_uris": [f"http://127.0.0.1:0/callback"], # port set per-launch below "token_endpoint_auth_method": "none", "grant_types": ["authorization_code"], "response_types": ["code"], }).json() client_id = client["client_id"] # 2. PKCE verifier = secrets.token_urlsafe(64) challenge = base64.urlsafe_b64encode( hashlib.sha256(verifier.encode()).digest() ).rstrip(b"=").decode() state = secrets.token_urlsafe(16) # 3. Loopback listener — capture ?code=… on the redirect. code_holder = {} class Handler(http.server.BaseHTTPRequestHandler): def do_GET(self): qs = urllib.parse.urlparse(self.path).query code_holder.update(urllib.parse.parse_qs(qs)) self.send_response(200); self.end_headers() self.wfile.write(b"You can close this window.") def log_message(self, *_): pass server = http.server.HTTPServer(("127.0.0.1", 0), Handler) redirect_uri = f"http://127.0.0.1:{server.server_port}/callback" # 4. Open browser to /oauth/authorize. params = urllib.parse.urlencode({ "response_type": "code", "client_id": client_id, "redirect_uri": redirect_uri, "scope": "openid profile email ir.incidents:read", "state": state, "code_challenge": challenge, "code_challenge_method": "S256", }) webbrowser.open(f"{ROOTLY}/oauth/authorize?{params}") server.handle_request() # blocks until the redirect arrives assert code_holder["state"][0] == state, "state mismatch" # 5. Exchange code for tokens. tokens = requests.post(f"{ROOTLY}/oauth/token", data={ "grant_type": "authorization_code", "code": code_holder["code"][0], "redirect_uri": redirect_uri, "client_id": client_id, "code_verifier": verifier, }).json() # 6. Use the token against the resource API. me = requests.get( "https://api.rootly.com/v1/users/me", headers={"Authorization": f"Bearer {tokens['access_token']}"}, ).json() print(me) ``` **Where to store tokens.** Use the OS keychain — `keyring` on Python, `go-keyring` on Go, the system credential helpers on macOS/Windows/Linux. Never write tokens to a plaintext file in `$HOME` or check them into a repo. ### TUI tools that can't open a browser If the TUI runs over SSH or in a headless container, print the authorize URL and have the user open it on their workstation. Use SSH port forwarding so the loopback redirect still lands on the remote host: ```bash theme={null} ssh -L 7890:127.0.0.1:7890 your-server ``` Then register with `http://127.0.0.1:7890/callback` as the redirect URI — the browser redirects to the forwarded port, and the TUI captures the code locally. ### Token lifecycle in CLIs * Access tokens last **1 hour**. Refresh proactively on `401` or when expiry is \<5 min away. * Refresh tokens rotate on use — overwrite the cached refresh token after every refresh. * On logout, call `POST /oauth/revoke` with the refresh token and clear the keychain entry. ## Scopes Scopes are domain-prefixed and combine with your Rootly role to form a permission ceiling — **effective permissions = user RBAC ∩ granted scopes**. Granting a scope never elevates a user beyond what their role already allows. ### OIDC scopes | Scope | Purpose | | --------- | --------------------------------------------------------- | | `openid` | Required for OIDC flows; enables `id_token` issuance. | | `profile` | Adds `name`, `team_id`, `role`, `on_call_role` to claims. | | `email` | Adds `email` to claims. | ### Meta scopes | Scope | Grants | | -------- | ------------------------------------------------------------------------- | | `all` | Full read/write across every Incident Response, On-Call, and AI resource. | | `ir.all` | Full read/write across every Incident Response resource. | | `oc.all` | Full read/write across every On-Call resource. | Only `all` grants AI access. The `ir.all` and `oc.all` scopes don't include `ai.*` permissions. ### Incident Response (`ir.*`) Each resource exposes `:read` and `:write`. For example, `ir.incidents:read` or `ir.services:write`. `incidents`, `services`, `environments`, `functionalities`, `severities`, `incident_types`, `incident_roles`, `workflows`, `catalogs`, `groups`, `playbooks`, `retrospectives`, `status_pages`, `form_fields`, `pulses` ### On-Call (`oc.*`) Each resource exposes `:read` and `:write`. For example, `oc.alerts:read` or `oc.schedules:write`. `alerts`, `schedules`, `escalation_policies`, `alert_routing_rules`, `heartbeats`, `alert_sources`, `live_call_routing`, `shift_overrides` ### AI (`ai.*`) | Scope | Purpose | | --------------- | ------------------------------------------------------------------------- | | `ai.chat:read` | Read AI chat session message history. | | `ai.chat:write` | Create synchronous or streaming chats, delete sessions, and read history. | AI chat scopes work with authorization-code and client-credentials applications. Request `ai.chat:write` for chat mutations; it includes read access. `:write` includes read. Request the narrowest scope set your integration needs — users see the full list on the consent screen. ## Authorization Code flow (with PKCE) Use this flow for end-user sign-in. Required for public clients, recommended for confidential clients. ### 1. Register the client Either call the Dynamic Client Registration endpoint (see below) or have a team admin create the application in **Organization Settings → OAuth Applications**. ### 2. Redirect the user to `/oauth/authorize` ```text theme={null} https://rootly.com/oauth/authorize ?response_type=code &client_id= &redirect_uri= &scope=openid%20profile%20email%20ir.incidents:read &state= &code_challenge= &code_challenge_method=S256 ``` The user signs in, selects the team the token will operate against, and reviews the requested scopes on the consent screen. ### 3. Exchange the code for tokens Authorization codes are single-use and expire after **60 seconds** — exchange them immediately. **Public client** (PKCE, no secret): ```bash theme={null} curl --request POST \ --url https://rootly.com/oauth/token \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data grant_type=authorization_code \ --data code= \ --data redirect_uri= \ --data client_id= \ --data code_verifier= ``` **Confidential client** (authenticate with client secret via HTTP Basic; PKCE still recommended): ```bash theme={null} curl --request POST \ --url https://rootly.com/oauth/token \ --header 'Content-Type: application/x-www-form-urlencoded' \ --user ':' \ --data grant_type=authorization_code \ --data code= \ --data redirect_uri= \ --data code_verifier= ``` Response: ```json theme={null} { "access_token": "…", "token_type": "Bearer", "expires_in": 3600, "refresh_token": "…", "id_token": "…", "scope": "openid profile email ir.incidents:read" } ``` ### 4. Call the Rootly API ```bash theme={null} curl --request GET \ --header 'Content-Type: application/vnd.api+json' \ --header 'Authorization: Bearer ' \ --url https://api.rootly.com/v1/incidents ``` ### 5. Refresh the token Access tokens expire after **1 hour**. Refresh tokens rotate on use — the old refresh token is invalidated after a short grace period. **Public client:** ```bash theme={null} curl --request POST \ --url https://rootly.com/oauth/token \ --header 'Content-Type: application/x-www-form-urlencoded' \ --data grant_type=refresh_token \ --data refresh_token= \ --data client_id= ``` **Confidential client:** ```bash theme={null} curl --request POST \ --url https://rootly.com/oauth/token \ --header 'Content-Type: application/x-www-form-urlencoded' \ --user ':' \ --data grant_type=refresh_token \ --data refresh_token= ``` ## Client Credentials flow Use this flow for server-to-server automation where no end user is involved (CI jobs, scheduled tasks, internal services). Requires a **confidential** application created by a team admin. When the application is created, Rootly auto-provisions a dedicated service user in the team. The service user's `Role` and `OnCallRole` permissions are derived from the app's scopes, so the token's effective access is exactly what the scopes describe. ```bash theme={null} curl --request POST \ --url https://rootly.com/oauth/token \ --header 'Content-Type: application/x-www-form-urlencoded' \ --user ':' \ --data grant_type=client_credentials \ --data scope='ir.incidents:write oc.alerts:read' ``` Client-credentials applications must request at least one resource scope (`ir.*`, `oc.*`, or `ai.*`) or the `all` meta scope. ## Dynamic Client Registration (RFC 7591) CLIs, desktop apps, MCP clients, and third-party integrations can self-register without authentication. Both public and confidential auth-code clients are supported. **Public client** (no secret — typical for CLIs and native apps): ```bash theme={null} curl --request POST \ --url https://rootly.com/oauth/register \ --header 'Content-Type: application/json' \ --data '{ "client_name": "My CLI", "redirect_uris": ["http://127.0.0.1:7890/callback"], "token_endpoint_auth_method": "none", "grant_types": ["authorization_code"], "response_types": ["code"] }' ``` Response: ```json theme={null} { "client_id": "…", "client_id_issued_at": 1745000000, "client_secret_expires_at": 0, "client_name": "My CLI", "redirect_uris": ["http://127.0.0.1:7890/callback"], "token_endpoint_auth_method": "none", "grant_types": ["authorization_code"], "response_types": ["code"], "scope": "openid profile email ir.incidents:read ir.incidents:write …" } ``` **Confidential client** (secret returned once — typical for server-side web apps): ```bash theme={null} curl --request POST \ --url https://rootly.com/oauth/register \ --header 'Content-Type: application/json' \ --data '{ "client_name": "My Web App", "redirect_uris": ["https://myapp.example.com/callback"], "token_endpoint_auth_method": "client_secret_basic", "grant_types": ["authorization_code"], "response_types": ["code"] }' ``` The response includes a `client_secret` field — **store it immediately**, as it cannot be retrieved again. Client-credentials apps (server-to-server, no redirect URI) cannot be created via Dynamic Client Registration. A team admin must create them in **Organization Settings → OAuth Applications**. Rules: * `token_endpoint_auth_method` must be one of: `none`, `client_secret_post`, or `client_secret_basic`. * Redirect URIs must use HTTPS. HTTP is allowed for the loopback addresses `127.0.0.1`, `[::1]`, and `localhost` for local development. * If no `scope` is provided, the app is registered with all supported scopes. Meta scopes are expanded into individual permissions on the consent screen so the user can narrow access. * Meta scopes (`all`, `ir.all`, `oc.all`) and granular `ir.*`, `oc.*`, and `ai.*` scopes are accepted during registration. For least-privilege AI access, request `ai.chat:read` or `ai.chat:write` instead of `all`. * Registration is rate-limited to **10 requests per hour per IP**. * The team the application operates against is assigned when the first user authorizes it. ## UserInfo ```bash theme={null} curl --request GET \ --header 'Authorization: Bearer ' \ --url https://rootly.com/oauth/userinfo ``` Returned claims depend on the granted OIDC scopes: | Claim | Requires scope | Description | | -------------- | -------------- | ----------------------------------------- | | `sub` | `openid` | Rootly user ID. | | `email` | `email` | User email. | | `name` | `profile` | User full name. | | `team_id` | `profile` | Team the token is scoped to. | | `role` | `profile` | Incident Response role name on that team. | | `on_call_role` | `profile` | On-Call role name on that team. | ID tokens are signed with **RS256**. Fetch signing keys from `https://rootly.com/oauth/discovery/keys`. ## Authenticating API calls On Rootly's resource API (`https://api.rootly.com/v1/*`), OAuth 2.0 access tokens and API keys use the same `Authorization: Bearer …` header. The API tries API keys first, then OAuth tokens — you never need to tell Rootly which one you are sending. ```bash theme={null} curl --request GET \ --header 'Content-Type: application/vnd.api+json' \ --header 'Authorization: Bearer ' \ --url https://api.rootly.com/v1/incidents ``` This applies only to resource endpoints under `/v1/*`. The OAuth protocol endpoints on `rootly.com` (`/oauth/token`, `/oauth/authorize`, `/oauth/register`, `/.well-known/*`) use their own authentication rules described above. Rate limits, pagination, and the JSON:API contract are identical to the API-key path — see the [API Overview](/api-reference/overview). ## Using Rootly tokens with external services Rootly's OAuth 2.0 + OIDC server isn't only for authenticating to Rootly's API. Any external service that supports OAuth 2.0 token validation can accept Rootly-issued tokens and use Rootly's UserInfo response as the source of truth for user identity, team scope, and role. The pattern: 1. Your application obtains a Rootly OAuth token using one of the flows above. 2. The application sends the token as `Authorization: Bearer ` to the external service. 3. The external service validates the token by calling `https://rootly.com/oauth/userinfo` with that same `Authorization` header, then reads the returned claims (`sub`, `team_id`, `role`, `on_call_role`) for access decisions. Because Rootly's UserInfo claims align with the field names most OAuth-aware proxies expect by default, the gateway-side configuration is usually three or four environment variables plus a single config toggle. The example below walks through LiteLLM specifically; the same shape applies to any OAuth 2.0 token-validating proxy. ### Example: LiteLLM AI gateway [LiteLLM](https://docs.litellm.ai/) is an AI gateway proxy that supports [OAuth 2.0 token validation](https://docs.litellm.ai/docs/proxy/oauth2) as an Enterprise feature. Pointing it at Rootly's UserInfo endpoint lets your team reuse Rootly identities — and the existing Rootly role and team model — for AI-gateway access control, cost attribution, and rate limiting. Set LiteLLM's environment variables to point at Rootly's UserInfo endpoint and the matching claim names: ```bash theme={null} export OAUTH_TOKEN_INFO_ENDPOINT="https://rootly.com/oauth/userinfo" export OAUTH_USER_ID_FIELD_NAME="sub" export OAUTH_USER_ROLE_FIELD_NAME="role" export OAUTH_USER_TEAM_ID_FIELD_NAME="team_id" ``` Then enable OAuth 2.0 auth in LiteLLM's `config.yaml`: ```yaml theme={null} general_settings: master_key: sk-1234 enable_oauth2_auth: true ``` LiteLLM reads `sub`, `team_id`, and `role` from Rootly's UserInfo response. Those claims require the `openid` and `profile` scopes to be granted on the access token — see [OIDC scopes](#oidc-scopes). A typical scope set for gateway use: ```text theme={null} openid profile email ``` The token itself does not need any `ir.*` or `oc.*` resource scopes because the request never touches Rootly's resource API — only the UserInfo endpoint, which any valid token can call. Application code obtains a Rootly access token using whichever flow fits the deployment model: * **Interactive users** — Authorization Code with PKCE ([above](#authorization-code-flow-with-pkce)) * **Server-to-server automation** — Client Credentials ([above](#client-credentials-flow)) Then forwards the token to LiteLLM unchanged: ```bash theme={null} curl --request POST \ --url http://your-litellm-host:4000/chat/completions \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "gpt-4", "messages": [{"role": "user", "content": "summarize the incident postmortem"}] }' ``` LiteLLM calls Rootly's UserInfo endpoint with the same bearer token, extracts the user identity and team, and applies whatever per-user or per-team policies you've configured in LiteLLM (rate limits, allowed models, spend caps). ### Why this is useful | Outcome | How Rootly OAuth makes it work | | -------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | | One identity surface | A user added to Rootly automatically has gateway access; removal revokes both in lockstep. | | Per-team cost attribution | LiteLLM's spend tracking groups by `team_id` from the UserInfo response — same `team_id` Rootly already scopes incidents and on-call schedules to. | | Central revocation | Revoke a Rootly OAuth token via `POST /oauth/revoke` and the gateway stops honoring it immediately. | | No per-gateway credential sprawl | The gateway never holds long-lived API keys for individual users; it only validates short-lived OAuth tokens at request time. | LiteLLM's OAuth 2.0 token validation is a paid Enterprise feature. The Rootly-side OAuth 2.0 server is the same one documented above and is included in standard Rootly access — no additional plan tier is required on Rootly's side to use Rootly as the identity provider for an external service. # Creates an On-Call Pay Report Source: https://docs.rootly.com/api-reference/oncallpayreports/creates-an-on-call-pay-report https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/on_call_pay_reports Generates a new on-call pay report for the given date range. The report is generated asynchronously. # List On-Call Pay Reports Source: https://docs.rootly.com/api-reference/oncallpayreports/list-on-call-pay-reports https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/on_call_pay_reports List on-call pay reports # Regenerate an On-Call Pay Report Source: https://docs.rootly.com/api-reference/oncallpayreports/regenerate-an-on-call-pay-report https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/on_call_pay_reports/{id}/regenerate Triggers regeneration of an existing on-call pay report. # Retrieves an On-Call Pay Report Source: https://docs.rootly.com/api-reference/oncallpayreports/retrieves-an-on-call-pay-report https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/on_call_pay_reports/{id} Retrieves a specific on-call pay report by id # Update an On-Call Pay Report Source: https://docs.rootly.com/api-reference/oncallpayreports/update-an-on-call-pay-report https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/on_call_pay_reports/{id} Update a specific on-call pay report by id. Triggers report regeneration. # Creates an On-Call Role Source: https://docs.rootly.com/api-reference/oncallroles/creates-an-on-call-role https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/on_call_roles Creates a new On-Call Role from provided data # Delete an On-Call Role Source: https://docs.rootly.com/api-reference/oncallroles/delete-an-on-call-role https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/on_call_roles/{id} Delete a specific On-Call Role by id # List On-Call Roles Source: https://docs.rootly.com/api-reference/oncallroles/list-on-call-roles https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/on_call_roles List On-Call Roles # Retrieves an On-Call Role Source: https://docs.rootly.com/api-reference/oncallroles/retrieves-an-on-call-role https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/on_call_roles/{id} Retrieves a specific On-Call Role by id # Update an On-Call Role Source: https://docs.rootly.com/api-reference/oncallroles/update-an-on-call-role https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/on_call_roles/{id} Update a specific On-Call Role by id # List on-calls Source: https://docs.rootly.com/api-reference/oncalls/list-on-calls https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/oncalls List who is currently on-call, with support for filtering by escalation policy, schedule, and user. Returns on-call entries grouped by escalation policy level. # creates an shadow configuration Source: https://docs.rootly.com/api-reference/oncallshadows/creates-an-shadow-configuration https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/schedules/{schedule_id}/on_call_shadows Creates a new on call shadow configuration from provided data # List On Call Shadows for Shift Source: https://docs.rootly.com/api-reference/oncallshadows/list-on-call-shadows-for-shift https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/schedules/{schedule_id}/on_call_shadows List shadow shifts for schedule # Retrieves an On Call Shadow configuration by ID Source: https://docs.rootly.com/api-reference/oncallshadows/retrieves-an-on-call-shadow-configuration-by-id https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/on_call_shadows/{id} Retrieves a specific On Call Shadow configuration by ID # Update an On Call Shadow configuration Source: https://docs.rootly.com/api-reference/oncallshadows/update-an-on-call-shadow-configuration https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/on_call_shadows/{id} Update a specific on call shadow configuration by id # creates an override shift Source: https://docs.rootly.com/api-reference/overrideshifts/creates-an-override-shift https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/schedules/{schedule_id}/override_shifts Creates a new override shift from provided data. If any existing override shifts overlap with the specified time range, they will be automatically deleted and replaced by the new override. This endpoint is idempotent: re-sending an identical override (same user and same start/end time) returns the existing override with a 200 status and does not recreate it. # Delete an on call shadow configuration Source: https://docs.rootly.com/api-reference/overrideshifts/delete-an-on-call-shadow-configuration https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/on_call_shadows/{id} Delete a specific on call shadow configuration by id. Future shadows are hard-deleted. Active shadows (started in the past) have their end time truncated to preserve historical data. # Delete an override shift Source: https://docs.rootly.com/api-reference/overrideshifts/delete-an-override-shift https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/override_shifts/{id} Delete a specific override shift by id # List override shifts Source: https://docs.rootly.com/api-reference/overrideshifts/list-override-shifts https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/schedules/{schedule_id}/override_shifts List override shifts # Retrieves an override shift Source: https://docs.rootly.com/api-reference/overrideshifts/retrieves-an-override-shift https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/override_shifts/{id} Retrieves a specific override shift by id # Update an override shift Source: https://docs.rootly.com/api-reference/overrideshifts/update-an-override-shift https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/override_shifts/{id} Update a specific override shift by id # Rootly API overview: authentication and conventions Source: https://docs.rootly.com/api-reference/overview Learn how to authenticate with the Rootly API using bearer tokens, work with rate limits, pagination, filtering, and JSON:API endpoints. Download the OpenAPI/Swagger specification to explore the Rootly API endpoints or generate client libraries. Use the official Go and Python SDKs to integrate with the Rootly API. Browser-based login, scoped third-party access, and user-independent client credentials tokens. ## How to generate an API Key? To generate a new API key, navigate to: **Organization dropdown** > **Organization Settings** > **API Keys > Generate New API Key**. Rootly supports three scopes of API Keys: | API Key Type | Permissions | | ---------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Global API Key | Global API Keys are assigned an On-Call and Incident Response role when they're generated. The assigned role's permissions control the key's permissions. Global API Keys are able to interact with all entities within your Rootly instance. | | Team API Key | Team API Keys inherit the same permissions of a Team Admin. They have full read and edit access to any Rootly entity that team owns, such as the team's Schedules and Escalation Policies. | | Personal API Key | Personal API Keys inherit the permissions of the user who created the API key. | ## JSON:API Specification Rootly is using the **JSON:API** ([https://jsonapi.org](https://jsonapi.org)) specification: * JSON:API is a specification for how a client should request that resources be fetched or modified, and how a server should respond to those requests. * JSON:API is designed to minimize both the number of requests and the amount of data transmitted between clients and servers. This efficiency is achieved without compromising readability, flexibility, or discoverability. * JSON:API requires use of the JSON:API media type (**application/vnd.api+json**) for exchanging data. ## Authentication and Requests All API requests use the `Authorization: Bearer` header over HTTPS. Rootly supports two token types: | Method | Token source | Best for | | -------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------- | | **API Key** | Generated in **Organization Settings → API Keys** | Scripts, Terraform, Zapier, quick integrations | | **OAuth 2.0 Access Token** | Obtained via [OAuth 2.0 / OIDC](/api-reference/oauth2) flows | CLI/TUI tools, third-party apps, MCP clients, CI with scoped access | Both token types work with the same header — the API detects which one you sent automatically. ```bash theme={null} curl --request GET \ --header 'Content-Type: application/vnd.api+json' \ --header 'Authorization: Bearer YOUR-API-KEY-OR-OAUTH-TOKEN' \ --url https://api.rootly.com/v1/incidents ``` ## Rate limiting * There is a default limit of **3000** **GET**, **HEAD**, and **OPTIONS** calls **per API key** every minute. The limit is calculated over a **1-minute sliding window** looking back from the current time. While the limit can be configured to support higher thresholds, you must first contact your **Rootly Customer Success Manager** to make any adjustments. * There is a default limit of **3000** **POST**, **PUT**, **PATCH** or **DELETE** calls **per API key** every minute. Alert creation is limited to 50 per minute per API key. The limit is calculated over a **1-minute sliding window** looking back from the current time. While the limit can be configured to support higher thresholds, you must first contact your **Rootly Customer Success Manager** to make any adjustments. * Note: The default rate limit for Alert Creation is 50 alerts every minute, per API key or alert source. * When rate limits are exceeded, the API will return a **429 Too Many Requests** HTTP status code with the response: `{"error": "Rate limit exceeded. Try again later."}` * Rootly recommends configuring your Alert Sources to handle this response and retry to create your Alert in Rootly. * **X-RateLimit headers** are included in every API response, providing real-time rate limit information: * **X-RateLimit-Limit** - The maximum number of requests permitted and the time window (for example, "3000, 3000;window=60" for 3000 requests per minute) * **X-RateLimit-Remaining** - The number of requests remaining in the current rate limit window * **X-RateLimit-Used** - The number of requests already made in the current window * **X-RateLimit-Reset** - The time at which the current rate limit window resets, in UTC epoch seconds ## Pagination * Pagination is supported for all endpoints that return a **collection** of items. * Pagination is controlled by the **page** query parameter ## Example ```bash theme={null} curl --request GET \ --header 'Content-Type: application/vnd.api+json' \ --header 'Authorization: Bearer YOUR-TOKEN' \ --url https://api.rootly.com/v1/incidents?page[number]=1&page[size]=10 ``` # Creates a playbook Source: https://docs.rootly.com/api-reference/playbooks/creates-a-playbook https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/playbooks Creates a new playbook from provided data # Delete a playbook Source: https://docs.rootly.com/api-reference/playbooks/delete-a-playbook https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/playbooks/{id} Delete a specific playbook by id # List playbooks Source: https://docs.rootly.com/api-reference/playbooks/list-playbooks https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/playbooks List playbooks # Retrieves a playbook Source: https://docs.rootly.com/api-reference/playbooks/retrieves-a-playbook https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/playbooks/{id} Retrieves a specific playbook by id # Update a playbook Source: https://docs.rootly.com/api-reference/playbooks/update-a-playbook https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/playbooks/{id} Update a specific playbook by id # Creates a playbook task Source: https://docs.rootly.com/api-reference/playbooktasks/creates-a-playbook-task https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/playbooks/{playbook_id}/playbook_tasks Creates a new task from provided data # Delete a playbook task Source: https://docs.rootly.com/api-reference/playbooktasks/delete-a-playbook-task https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/playbook_tasks/{id} Delete a specific playbook task by id # List playbook tasks Source: https://docs.rootly.com/api-reference/playbooktasks/list-playbook-tasks https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/playbooks/{playbook_id}/playbook_tasks List playbook tasks # Retrieves a playbook task Source: https://docs.rootly.com/api-reference/playbooktasks/retrieves-a-playbook-task https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/playbook_tasks/{id} Retrieves a specific playbook_task by id # Update a playbook task Source: https://docs.rootly.com/api-reference/playbooktasks/update-a-playbook-task https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/playbook_tasks/{id} Update a specific playbook task by id # Creates a pulse Source: https://docs.rootly.com/api-reference/pulses/creates-a-pulse https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/pulses Creates a new pulse from provided data # List pulses Source: https://docs.rootly.com/api-reference/pulses/list-pulses https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/pulses List pulses # Retrieves a pulse Source: https://docs.rootly.com/api-reference/pulses/retrieves-a-pulse https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/pulses/{id} Retrieves a specific pulse by id # Update a pulse Source: https://docs.rootly.com/api-reference/pulses/update-a-pulse https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/pulses/{id} Update a specific pulse by id # List retrospective configurations Source: https://docs.rootly.com/api-reference/retrospectiveconfigurations/list-retrospective-configurations https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/retrospective_configurations List retrospective configurations # Retrieves a Retrospective Configuration Source: https://docs.rootly.com/api-reference/retrospectiveconfigurations/retrieves-a-retrospective-configuration https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/retrospective_configurations/{id} Retrieves a specific retrospective_configuration by id # Update a retrospective configuration Source: https://docs.rootly.com/api-reference/retrospectiveconfigurations/update-a-retrospective-configuration https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/retrospective_configurations/{id} Update a specific retrospective configuration by id # Creates a retrospective process Source: https://docs.rootly.com/api-reference/retrospectiveprocesses/creates-a-retrospective-process https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/retrospective_processes Creates a new retrospective process from provided data # Delete a retrospective process Source: https://docs.rootly.com/api-reference/retrospectiveprocesses/delete-a-retrospective-process https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/retrospective_processes/{id} Delete a specific retrospective process by id # List retrospective processes Source: https://docs.rootly.com/api-reference/retrospectiveprocesses/list-retrospective-processes https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/retrospective_processes List retrospective processes # Retrieves a retrospective process Source: https://docs.rootly.com/api-reference/retrospectiveprocesses/retrieves-a-retrospective-process https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/retrospective_processes/{id} Retrieves a specific retrospective process by id # Update a retrospective process Source: https://docs.rootly.com/api-reference/retrospectiveprocesses/update-a-retrospective-process https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/retrospective_processes/{id} Updates a specific retrospective process by id # Creates a retrospective process group Source: https://docs.rootly.com/api-reference/retrospectiveprocessgroups/creates-a-retrospective-process-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/retrospective_processes/{retrospective_process_id}/groups Creates a new retrospective process group from provided data # Delete a Retrospective Process Group Source: https://docs.rootly.com/api-reference/retrospectiveprocessgroups/delete-a-retrospective-process-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/retrospective_process_groups/{id} Delete a specific Retrospective Process Group by id # List Retrospective Process Groups Source: https://docs.rootly.com/api-reference/retrospectiveprocessgroups/list-retrospective-process-groups https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/retrospective_processes/{retrospective_process_id}/groups List Retrospective Process Groups # Retrieves a Retrospective Process Group Source: https://docs.rootly.com/api-reference/retrospectiveprocessgroups/retrieves-a-retrospective-process-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/retrospective_process_groups/{id} Retrieves a specific Retrospective Process Group by id # Update a Retrospective Process Group Source: https://docs.rootly.com/api-reference/retrospectiveprocessgroups/update-a-retrospective-process-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/retrospective_process_groups/{id} Update a specific Retrospective Process Group by id # Creates a retrospective process group step Source: https://docs.rootly.com/api-reference/retrospectiveprocessgroupsteps/creates-a-retrospective-process-group-step https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/retrospective_process_groups/{retrospective_process_group_id}/steps Creates a new retrospective process group step from provided data # Delete a RetrospectiveProcessGroup Step Source: https://docs.rootly.com/api-reference/retrospectiveprocessgroupsteps/delete-a-retrospectiveprocessgroup-step https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/retrospective_process_group_steps/{id} Delete a specific RetrospectiveProcessGroup Step by id # List RetrospectiveProcessGroup Steps Source: https://docs.rootly.com/api-reference/retrospectiveprocessgroupsteps/list-retrospectiveprocessgroup-steps https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/retrospective_process_groups/{retrospective_process_group_id}/steps List RetrospectiveProcessGroup Steps # Retrieves a RetrospectiveProcessGroup Step Source: https://docs.rootly.com/api-reference/retrospectiveprocessgroupsteps/retrieves-a-retrospectiveprocessgroup-step https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/retrospective_process_group_steps/{id} Retrieves a specific RetrospectiveProcessGroup Step by id # Update RetrospectiveProcessGroup Step Source: https://docs.rootly.com/api-reference/retrospectiveprocessgroupsteps/update-retrospectiveprocessgroup-step https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/retrospective_process_group_steps/{id} Update a specific RetrospectiveProcessGroup Step by id # Creates a retrospective step Source: https://docs.rootly.com/api-reference/retrospectivesteps/creates-a-retrospective-step https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/retrospective_processes/{retrospective_process_id}/retrospective_steps Creates a new retrospective step from provided data # Delete a retrospective step Source: https://docs.rootly.com/api-reference/retrospectivesteps/delete-a-retrospective-step https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/retrospective_steps/{id} Delete a specific retrospective step by id # List retrospective steps Source: https://docs.rootly.com/api-reference/retrospectivesteps/list-retrospective-steps https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/retrospective_processes/{retrospective_process_id}/retrospective_steps List retrospective steps # Retrieves a retrospective step Source: https://docs.rootly.com/api-reference/retrospectivesteps/retrieves-a-retrospective-step https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/retrospective_steps/{id} Retrieves a specific retrospective step by id # Update a retrospective step Source: https://docs.rootly.com/api-reference/retrospectivesteps/update-a-retrospective-step https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/retrospective_steps/{id} Update a specific retrospective step by id # Creates a retrospective template Source: https://docs.rootly.com/api-reference/retrospectivetemplates/creates-a-retrospective-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/post_mortem_templates Creates a new Retrospective Template from provided data # Delete a Retrospective Template Source: https://docs.rootly.com/api-reference/retrospectivetemplates/delete-a-retrospective-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/post_mortem_templates/{id} Delete a specific Retrospective Template by id # List Retrospective Templates Source: https://docs.rootly.com/api-reference/retrospectivetemplates/list-retrospective-templates https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/post_mortem_templates List Retrospective Templates # Retrieves a Retrospective Template Source: https://docs.rootly.com/api-reference/retrospectivetemplates/retrieves-a-retrospective-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/post_mortem_templates/{id} Retrieves a specific Retrospective Template by id # Update a Retrospective Template Source: https://docs.rootly.com/api-reference/retrospectivetemplates/update-a-retrospective-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/post_mortem_templates/{id} Update a specific Retrospective Template by id # Creates a role Source: https://docs.rootly.com/api-reference/roles/creates-a-role https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/roles Creates a new role from provided data # Delete a role Source: https://docs.rootly.com/api-reference/roles/delete-a-role https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/roles/{id} Delete a specific role by id # List roles Source: https://docs.rootly.com/api-reference/roles/list-roles https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/roles List roles # Retrieves a role Source: https://docs.rootly.com/api-reference/roles/retrieves-a-role https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/roles/{id} Retrieves a specific role by id # Update a role Source: https://docs.rootly.com/api-reference/roles/update-a-role https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/roles/{id} Update a specific role by id # Creates a schedule rotation active day Source: https://docs.rootly.com/api-reference/schedulerotationactivedays/creates-a-schedule-rotation-active-day https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/schedule_rotations/{schedule_rotation_id}/schedule_rotation_active_days Creates a new schedule rotation active day from provided data # Delete a schedule rotation active day Source: https://docs.rootly.com/api-reference/schedulerotationactivedays/delete-a-schedule-rotation-active-day https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/schedule_rotation_active_days/{id} Delete a specific schedule rotation active day # List schedule rotation active days Source: https://docs.rootly.com/api-reference/schedulerotationactivedays/list-schedule-rotation-active-days https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/schedule_rotations/{schedule_rotation_id}/schedule_rotation_active_days List schedule rotation active days # Retrieves a schedule rotation active day Source: https://docs.rootly.com/api-reference/schedulerotationactivedays/retrieves-a-schedule-rotation-active-day https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/schedule_rotation_active_days/{id} Retrieves a specific schedule rotation active day by id # Update a schedule rotation active day Source: https://docs.rootly.com/api-reference/schedulerotationactivedays/update-a-schedule-rotation-active-day https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/schedule_rotation_active_days/{id} Update a specific schedule rotation active day by id # Creates a schedule rotation Source: https://docs.rootly.com/api-reference/schedulerotations/creates-a-schedule-rotation https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/schedules/{schedule_id}/schedule_rotations Creates a new schedule rotation from provided data # Delete a schedule rotation Source: https://docs.rootly.com/api-reference/schedulerotations/delete-a-schedule-rotation https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/schedule_rotations/{id} Delete a specific schedule rotation by id # List schedule rotations Source: https://docs.rootly.com/api-reference/schedulerotations/list-schedule-rotations https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/schedules/{schedule_id}/schedule_rotations List schedule rotations # Retrieves a schedule rotation Source: https://docs.rootly.com/api-reference/schedulerotations/retrieves-a-schedule-rotation https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/schedule_rotations/{id} Retrieves a specific schedule rotation by id # Update a schedule rotation Source: https://docs.rootly.com/api-reference/schedulerotations/update-a-schedule-rotation https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/schedule_rotations/{id} Update a specific schedule rotation by id # Creates a schedule rotation user Source: https://docs.rootly.com/api-reference/schedulerotationusers/creates-a-schedule-rotation-user https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/schedule_rotations/{schedule_rotation_id}/schedule_rotation_users Creates a new schedule rotation user from provided data # Delete a schedule rotation user Source: https://docs.rootly.com/api-reference/schedulerotationusers/delete-a-schedule-rotation-user https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/schedule_rotation_users/{id} Delete a specific schedule rotation user by id # List schedule rotation users Source: https://docs.rootly.com/api-reference/schedulerotationusers/list-schedule-rotation-users https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/schedule_rotations/{schedule_rotation_id}/schedule_rotation_users # Retrieves a schedule rotation user Source: https://docs.rootly.com/api-reference/schedulerotationusers/retrieves-a-schedule-rotation-user https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/schedule_rotation_users/{id} Retrieves a specific schedule rotation user by id # Update schedule rotation user Source: https://docs.rootly.com/api-reference/schedulerotationusers/update-schedule-rotation-user https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/schedule_rotation_users/{id} Update a specific schedule rotation user by id # Creates a schedule Source: https://docs.rootly.com/api-reference/schedules/creates-a-schedule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/schedules Creates a new schedule from provided data # Delete a schedule Source: https://docs.rootly.com/api-reference/schedules/delete-a-schedule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/schedules/{id} Delete a specific schedule by id # List schedules Source: https://docs.rootly.com/api-reference/schedules/list-schedules https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/schedules List schedules # Retrieves a schedule Source: https://docs.rootly.com/api-reference/schedules/retrieves-a-schedule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/schedules/{id} Retrieves a specific schedule by id # Update a schedule Source: https://docs.rootly.com/api-reference/schedules/update-a-schedule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/schedules/{id} Updates a specific schedule by id # Official SDKs Source: https://docs.rootly.com/api-reference/sdks Official Rootly API client libraries for TypeScript, Rust, Python, Go, Swift, Ruby, Java, and Terraform to automate incident management workflows. Rootly provides official SDKs to help you integrate with the Rootly API in your preferred programming language. Official Go client library for the Rootly API Official Swift client library for the Rootly API Official Python client library for the Rootly API Type-safe TypeScript client for the Rootly API Strongly-typed Rust client for the Rootly API Follow the links above for installation instructions, usage examples, and detailed documentation — either in the dedicated docs page or the GitHub repository. # Creates a secret Source: https://docs.rootly.com/api-reference/secrets/creates-a-secret https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/secrets Creates a new secret from provided data # Delete a secret Source: https://docs.rootly.com/api-reference/secrets/delete-a-secret https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/secrets/{id} Delete a specific secret by id # List secrets Source: https://docs.rootly.com/api-reference/secrets/list-secrets https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/secrets List secrets # Retrieves a secret Source: https://docs.rootly.com/api-reference/secrets/retrieves-a-secret https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/secrets/{id} Retrieve a specific secret by id # Update a secret Source: https://docs.rootly.com/api-reference/secrets/update-a-secret https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/secrets/{id} Update a specific secret by id # Bulk delete Services Source: https://docs.rootly.com/api-reference/services/bulk-delete-services https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/services/bulk_delete Delete services by external_id list, or prune by managed_by source. Two mutually exclusive modes. # Bulk upsert Services Source: https://docs.rootly.com/api-reference/services/bulk-upsert-services https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/services/bulk_upsert Create or update multiple services by external_id. Only attributes present in the payload are written (managed-fields semantics). Transactional: all succeed or all fail. Requires an API key with both create and update capability across the resource scope (team/org-scoped); record-scoped principals cannot use this endpoint (they receive 404), which also prevents the create-vs-update branch from leaking whether an external_id exists. # Creates a Catalog Property Source: https://docs.rootly.com/api-reference/services/creates-a-catalog-property https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/services/properties Creates a new Catalog Property from provided data # Creates a service Source: https://docs.rootly.com/api-reference/services/creates-a-service https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/services Creates a new service from provided data # Delete a service Source: https://docs.rootly.com/api-reference/services/delete-a-service https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/services/{id} Delete a specific service by id # Get service incidents chart Source: https://docs.rootly.com/api-reference/services/get-service-incidents-chart https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/services/{id}/incidents_chart Get service incidents chart # Get service uptime chart Source: https://docs.rootly.com/api-reference/services/get-service-uptime-chart https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/services/{id}/uptime_chart Get service uptime chart # List Catalog Properties Source: https://docs.rootly.com/api-reference/services/list-catalog-properties https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/services/properties List Service Catalog Properties # List services Source: https://docs.rootly.com/api-reference/services/list-services https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/services List services # Retrieves a service Source: https://docs.rootly.com/api-reference/services/retrieves-a-service https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/services/{id} Retrieves a specific service by id # Update a service Source: https://docs.rootly.com/api-reference/services/update-a-service https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/services/{id} Update a specific service by id # Creates a severity Source: https://docs.rootly.com/api-reference/severities/creates-a-severity https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/severities Creates a new severity from provided data # Delete a severity Source: https://docs.rootly.com/api-reference/severities/delete-a-severity https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/severities/{id} Delete a specific severity by id # List severities Source: https://docs.rootly.com/api-reference/severities/list-severities https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/severities List severities # Retrieves a severity Source: https://docs.rootly.com/api-reference/severities/retrieves-a-severity https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/severities/{id} Retrieves a specific severity by id # Update a severity Source: https://docs.rootly.com/api-reference/severities/update-a-severity https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/severities/{id} Update a specific severity by id # creates shift coverage requests Source: https://docs.rootly.com/api-reference/shiftcoveragerequests/creates-shift-coverage-requests https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/schedules/{schedule_id}/shift_coverage_requests Creates coverage requests for the shifts overlapping the requested time range. A range can span multiple consecutive shifts (e.g. across a handoff), so one or more coverage requests may be created; the response is always a list. A coverage request broadcasts to schedule members so someone can volunteer to cover the shift. # deletes a shift coverage request Source: https://docs.rootly.com/api-reference/shiftcoveragerequests/deletes-a-shift-coverage-request https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/shift_coverage_requests/{id} Deletes a shift coverage request. # list shift coverage requests Source: https://docs.rootly.com/api-reference/shiftcoveragerequests/list-shift-coverage-requests https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/schedules/{schedule_id}/shift_coverage_requests List active shift coverage requests for a schedule. # retrieves a shift coverage request Source: https://docs.rootly.com/api-reference/shiftcoveragerequests/retrieves-a-shift-coverage-request https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/shift_coverage_requests/{id} Retrieves a specific shift coverage request. # List shifts Source: https://docs.rootly.com/api-reference/shifts/list-shifts https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/shifts List shifts # Retrieves a schedule shifts Source: https://docs.rootly.com/api-reference/shifts/retrieves-a-schedule-shifts https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/schedules/{id}/shifts Retrieves schedule shifts # Creates an SLA Source: https://docs.rootly.com/api-reference/slas/creates-an-sla https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/slas Creates a new SLA from provided data # Delete an SLA Source: https://docs.rootly.com/api-reference/slas/delete-an-sla https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/slas/{id} Delete a specific SLA by id # List SLAs Source: https://docs.rootly.com/api-reference/slas/list-slas https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/slas List SLAs # Retrieves an SLA Source: https://docs.rootly.com/api-reference/slas/retrieves-an-sla https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/slas/{id} Retrieves a specific SLA by id # Update an SLA Source: https://docs.rootly.com/api-reference/slas/update-an-sla https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/slas/{id} Update a specific SLA by id # List Statuses Source: https://docs.rootly.com/api-reference/statuses/list-statuses https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/statuses List Statuses # Retrieves a Status Source: https://docs.rootly.com/api-reference/statuses/retrieves-a-status https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/statuses/{id} Retrieves a specific Status by id # Creates a status page announcement Source: https://docs.rootly.com/api-reference/statuspageannouncements/creates-a-status-page-announcement https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/status-pages/{status_page_id}/announcements Posts an announcement to a status page and notifies its subscribers unless notify_subscribers is false # Delete a status page announcement Source: https://docs.rootly.com/api-reference/statuspageannouncements/delete-a-status-page-announcement https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/announcements/{id} Delete a specific status page announcement by id # List status page announcements Source: https://docs.rootly.com/api-reference/statuspageannouncements/list-status-page-announcements https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/status-pages/{status_page_id}/announcements List status page announcements # Retrieves a status page announcement Source: https://docs.rootly.com/api-reference/statuspageannouncements/retrieves-a-status-page-announcement https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/announcements/{id} Retrieves a specific status page announcement by id # Update a status page announcement Source: https://docs.rootly.com/api-reference/statuspageannouncements/update-a-status-page-announcement https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/announcements/{id} Update a specific status page announcement by id # Creates a status page component group Source: https://docs.rootly.com/api-reference/statuspagecomponentgroups/creates-a-status-page-component-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/status-pages/{status_page_id}/component-groups Creates a new status page component group from provided data # Delete a status page component group Source: https://docs.rootly.com/api-reference/statuspagecomponentgroups/delete-a-status-page-component-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/component-groups/{id} Delete a status page component group together with its components # List status page component groups Source: https://docs.rootly.com/api-reference/statuspagecomponentgroups/list-status-page-component-groups https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/status-pages/{status_page_id}/component-groups List status page component groups # Retrieves a status page component group Source: https://docs.rootly.com/api-reference/statuspagecomponentgroups/retrieves-a-status-page-component-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/component-groups/{id} Retrieves a status page component group # Update a status page component group Source: https://docs.rootly.com/api-reference/statuspagecomponentgroups/update-a-status-page-component-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/component-groups/{id} Update a status page component group # Creates a status page component Source: https://docs.rootly.com/api-reference/statuspagecomponents/creates-a-status-page-component https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/status-pages/{status_page_id}/components Creates a new status page component from provided data # Delete a status page component Source: https://docs.rootly.com/api-reference/statuspagecomponents/delete-a-status-page-component https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/components/{id} Delete a status page component # List status page components Source: https://docs.rootly.com/api-reference/statuspagecomponents/list-status-page-components https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/status-pages/{status_page_id}/components List status page components # Retrieves a status page component Source: https://docs.rootly.com/api-reference/statuspagecomponents/retrieves-a-status-page-component https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/components/{id} Retrieves a status page component # Update a status page component Source: https://docs.rootly.com/api-reference/statuspagecomponents/update-a-status-page-component https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/components/{id} Update a status page component # Creates a status page Source: https://docs.rootly.com/api-reference/statuspages/creates-a-status-page https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/status-pages Creates a new status page from provided data # Delete a status page Source: https://docs.rootly.com/api-reference/statuspages/delete-a-status-page https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/status-pages/{id} Delete a specific status page by id # Get overall status of a status page Source: https://docs.rootly.com/api-reference/statuspages/get-overall-status-of-a-status-page https://rootly-heroku.s3.amazonaws.com/swagger/status_page/v1/swagger.json get /api/v1/status.json Returns the overall status indicator and active incidents for the status page identified by the custom domain. When the team has the status-page-v3-phase-1 feature enabled, the response additionally carries the page's components and component groups. # List active incidents for a status page Source: https://docs.rootly.com/api-reference/statuspages/list-active-incidents-for-a-status-page https://rootly-heroku.s3.amazonaws.com/swagger/status_page/v1/swagger.json get /api/v1/incidents.json Returns a paginated list of active incidents for the status page identified by the custom domain. # List status pages Source: https://docs.rootly.com/api-reference/statuspages/list-status-pages https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/status-pages List status pages # Retrieves a status page Source: https://docs.rootly.com/api-reference/statuspages/retrieves-a-status-page https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/status-pages/{id} Retrieves a specific status page by id # Update a status page Source: https://docs.rootly.com/api-reference/statuspages/update-a-status-page https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/status-pages/{id} Update a specific status page by id # Creates a status page template Source: https://docs.rootly.com/api-reference/statuspagetemplates/creates-a-status-page-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/status-pages/{status_page_id}/templates Creates a new template from provided data # Delete a incident event Source: https://docs.rootly.com/api-reference/statuspagetemplates/delete-a-incident-event https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/templates/{id} Delete a specific template event by id # List status page templates Source: https://docs.rootly.com/api-reference/statuspagetemplates/list-status-page-templates https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/status-pages/{status_page_id}/templates List status page templates # Retrieves a status page template Source: https://docs.rootly.com/api-reference/statuspagetemplates/retrieves-a-status-page-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/templates/{id} Retrieves a specific status_page_template by id # Update status page template Source: https://docs.rootly.com/api-reference/statuspagetemplates/update-status-page-template https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/templates/{id} Update a specific template event by id # Creates a Sub-Status Source: https://docs.rootly.com/api-reference/substatuses/creates-a-sub-status https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/sub_statuses Creates a new Sub-Status from provided data # Delete a Sub-Status Source: https://docs.rootly.com/api-reference/substatuses/delete-a-sub-status https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/sub_statuses/{id} Delete a specific Sub-Status by id # List Sub-Statuses Source: https://docs.rootly.com/api-reference/substatuses/list-sub-statuses https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/sub_statuses List Sub-Statuses # Retrieves a Sub-Status Source: https://docs.rootly.com/api-reference/substatuses/retrieves-a-sub-status https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/sub_statuses/{id} Retrieves a specific Sub-Status by id # Update a Sub-Status Source: https://docs.rootly.com/api-reference/substatuses/update-a-sub-status https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/sub_statuses/{id} Update a specific Sub-Status by id # Bulk delete Teams Source: https://docs.rootly.com/api-reference/teams/bulk-delete-teams https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/teams/bulk_delete Delete teams by external_id list, or prune by managed_by source. Two mutually exclusive modes. # Bulk upsert Teams Source: https://docs.rootly.com/api-reference/teams/bulk-upsert-teams https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/teams/bulk_upsert Create or update multiple teams by external_id. Only attributes present in the payload are written (managed-fields semantics). Transactional: all succeed or all fail. Requires an API key with both create and update capability across the resource scope (team/org-scoped); record-scoped principals cannot use this endpoint (they receive 404), which also prevents the create-vs-update branch from leaking whether an external_id exists. # Creates a Catalog Property Source: https://docs.rootly.com/api-reference/teams/creates-a-catalog-property https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/teams/properties Creates a new Catalog Property from provided data # Creates a team Source: https://docs.rootly.com/api-reference/teams/creates-a-team https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/teams Creates a new team from provided data # Delete a team Source: https://docs.rootly.com/api-reference/teams/delete-a-team https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/teams/{id} Delete a specific team by id # Get team incidents chart Source: https://docs.rootly.com/api-reference/teams/get-team-incidents-chart https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/teams/{id}/incidents_chart Get team incidents chart # List Catalog Properties Source: https://docs.rootly.com/api-reference/teams/list-catalog-properties https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/teams/properties List Group Catalog Properties # List teams Source: https://docs.rootly.com/api-reference/teams/list-teams https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/teams List teams # Retrieves a team Source: https://docs.rootly.com/api-reference/teams/retrieves-a-team https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/teams/{id} Retrieves a specific team by id # Update a team Source: https://docs.rootly.com/api-reference/teams/update-a-team https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/teams/{id} Update a specific team by id # Creates a user email address Source: https://docs.rootly.com/api-reference/useremailaddresses/creates-a-user-email-address https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/users/{user_id}/email_addresses Creates a new user email address from provided data # Delete user email address Source: https://docs.rootly.com/api-reference/useremailaddresses/delete-user-email-address https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/email_addresses/{id} Deletes a user email address # Resends verification email Source: https://docs.rootly.com/api-reference/useremailaddresses/resends-verification-email https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/email_addresses/{id}/resend_verification Resends verification email for an email address # Retrieves user email addresses Source: https://docs.rootly.com/api-reference/useremailaddresses/retrieves-user-email-addresses https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/users/{user_id}/email_addresses Retrieves all email addresses for the specified user # Show user email address Source: https://docs.rootly.com/api-reference/useremailaddresses/show-user-email-address https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/email_addresses/{id} Retrieves a specific user email address # Update user email address Source: https://docs.rootly.com/api-reference/useremailaddresses/update-user-email-address https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/email_addresses/{id} Updates a user email address # Verifies an email address with token Source: https://docs.rootly.com/api-reference/useremailaddresses/verifies-an-email-address-with-token https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/email_addresses/{id}/verify Verifies an email address using a verification token # Creates an user notification rule Source: https://docs.rootly.com/api-reference/usernotificationrules/creates-an-user-notification-rule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/users/{user_id}/notification_rules Creates a new user notification rule from provided data # Delete an user notification rule Source: https://docs.rootly.com/api-reference/usernotificationrules/delete-an-user-notification-rule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/notification_rules/{id} Delete a specific user notification rule by id # List user notification rules Source: https://docs.rootly.com/api-reference/usernotificationrules/list-user-notification-rules https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/users/{user_id}/notification_rules List user notification rules # Retrieves an user notification rule Source: https://docs.rootly.com/api-reference/usernotificationrules/retrieves-an-user-notification-rule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/notification_rules/{id} Retrieves a specific user notification rule by id # Update an user notification rule Source: https://docs.rootly.com/api-reference/usernotificationrules/update-an-user-notification-rule https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/notification_rules/{id} Update a specific user notification rule by id # Creates a user phone number Source: https://docs.rootly.com/api-reference/userphonenumbers/creates-a-user-phone-number https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/users/{user_id}/phone_numbers Creates a new user phone number from provided data # Delete user phone number Source: https://docs.rootly.com/api-reference/userphonenumbers/delete-user-phone-number https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/phone_numbers/{id} Deletes a user phone number # Resend verification code Source: https://docs.rootly.com/api-reference/userphonenumbers/resend-verification-code https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/phone_numbers/{id}/resend_verification Resends a verification code to the phone number. SMS sends are limited per recipient to 3 per hour and 5 per day. An application rate-limit 429 response includes Retry-After with the remaining wait in seconds. # Retrieves user phone numbers Source: https://docs.rootly.com/api-reference/userphonenumbers/retrieves-user-phone-numbers https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/users/{user_id}/phone_numbers Retrieves all phone numbers for the specified user # Send verification code Source: https://docs.rootly.com/api-reference/userphonenumbers/send-verification-code https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/phone_numbers/{id}/verify Sends a verification code to the phone number. SMS sends are limited per recipient to 3 per hour and 5 per day. An application rate-limit 429 response includes Retry-After with the remaining wait in seconds. # Show user phone number Source: https://docs.rootly.com/api-reference/userphonenumbers/show-user-phone-number https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/phone_numbers/{id} Retrieves a specific user phone number # Update user phone number Source: https://docs.rootly.com/api-reference/userphonenumbers/update-user-phone-number https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/phone_numbers/{id} Updates a user phone number # Delete an user Source: https://docs.rootly.com/api-reference/users/delete-an-user https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/users/{id} Delete a specific user by id # Get current user Source: https://docs.rootly.com/api-reference/users/get-current-user https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/users/me Get current user # List users Source: https://docs.rootly.com/api-reference/users/list-users https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/users List users # Retrieves an user Source: https://docs.rootly.com/api-reference/users/retrieves-an-user https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/users/{id} Retrieves a specific user by id # Update a user Source: https://docs.rootly.com/api-reference/users/update-a-user https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/users/{id} Update a specific user by id # Create a verified domain Source: https://docs.rootly.com/api-reference/verified-domains/create-a-verified-domain https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/verified_domains # Delete a verified domain Source: https://docs.rootly.com/api-reference/verified-domains/delete-a-verified-domain https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/verified_domains/{id} # List verified domains Source: https://docs.rootly.com/api-reference/verified-domains/list-verified-domains https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/verified_domains # Show a verified domain Source: https://docs.rootly.com/api-reference/verified-domains/show-a-verified-domain https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/verified_domains/{id} # List webhook deliveries Source: https://docs.rootly.com/api-reference/webhooksdeliveries/list-webhook-deliveries https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/webhooks/endpoints/{endpoint_id}/deliveries List webhook deliveries for given endpoint # Retries a webhook delivery Source: https://docs.rootly.com/api-reference/webhooksdeliveries/retries-a-webhook-delivery https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/webhooks/deliveries/{id}/deliver Retries a webhook delivery # Retrieves a webhook delivery Source: https://docs.rootly.com/api-reference/webhooksdeliveries/retrieves-a-webhook-delivery https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/webhooks/deliveries/{id} Retrieves a specific webhook delivery by id # Creates a webhook endpoint Source: https://docs.rootly.com/api-reference/webhooksendpoints/creates-a-webhook-endpoint https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/webhooks/endpoints Creates a new webhook endpoint from provided data # Delete a webhook endpoint Source: https://docs.rootly.com/api-reference/webhooksendpoints/delete-a-webhook-endpoint https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/webhooks/endpoints/{id} Delete a specific webhook endpoint by id # List webhook endpoints Source: https://docs.rootly.com/api-reference/webhooksendpoints/list-webhook-endpoints https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/webhooks/endpoints List webhook endpoints # Retrieves a webhook endpoint Source: https://docs.rootly.com/api-reference/webhooksendpoints/retrieves-a-webhook-endpoint https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/webhooks/endpoints/{id} Retrieves a specific webhook endpoint by id # Update a webhook endpoint Source: https://docs.rootly.com/api-reference/webhooksendpoints/update-a-webhook-endpoint https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/webhooks/endpoints/{id} Update a specific webhook endpoint by id # Creates a workflow action item form field condition Source: https://docs.rootly.com/api-reference/workflowactionitemformfieldconditions/creates-a-workflow-action-item-form-field-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/workflows/{workflow_id}/action_item_form_field_conditions Creates a new workflow action item form field condition from provided data # Delete a workflow action item form field condition Source: https://docs.rootly.com/api-reference/workflowactionitemformfieldconditions/delete-a-workflow-action-item-form-field-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/workflow_action_item_form_field_conditions/{id} Delete a specific workflow action item form field condition by id # List workflow action item form field conditions Source: https://docs.rootly.com/api-reference/workflowactionitemformfieldconditions/list-workflow-action-item-form-field-conditions https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflows/{workflow_id}/action_item_form_field_conditions List workflow action item form field conditions # Retrieves a workflow action item form field condition Source: https://docs.rootly.com/api-reference/workflowactionitemformfieldconditions/retrieves-a-workflow-action-item-form-field-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflow_action_item_form_field_conditions/{id} Retrieves a specific workflow action item form field condition by id # Update a workflow action item form field condition Source: https://docs.rootly.com/api-reference/workflowactionitemformfieldconditions/update-a-workflow-action-item-form-field-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/workflow_action_item_form_field_conditions/{id} Update a specific workflow action item form field condition by id # Creates a workflow form field condition Source: https://docs.rootly.com/api-reference/workflowformfieldconditions/creates-a-workflow-form-field-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/workflows/{workflow_id}/form_field_conditions Creates a new workflow form field condition from provided data # Delete a workflow_form field condition Source: https://docs.rootly.com/api-reference/workflowformfieldconditions/delete-a-workflow_form-field-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/workflow_form_field_conditions/{id} Delete a specific workflow form field condition by id # List workflow form field conditions Source: https://docs.rootly.com/api-reference/workflowformfieldconditions/list-workflow-form-field-conditions https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflows/{workflow_id}/form_field_conditions List workflow form field conditions # Retrieves a workflow form field condition Source: https://docs.rootly.com/api-reference/workflowformfieldconditions/retrieves-a-workflow-form-field-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflow_form_field_conditions/{id} Retrieves a specific workflow form field condition by id # Update a workflow form field condition Source: https://docs.rootly.com/api-reference/workflowformfieldconditions/update-a-workflow-form-field-condition https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/workflow_form_field_conditions/{id} Update a specific workflow form field condition by id # Creates a workflow group Source: https://docs.rootly.com/api-reference/workflowgroups/creates-a-workflow-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/workflow_groups Creates a new workflow group from provided data # Delete a workflow_group Source: https://docs.rootly.com/api-reference/workflowgroups/delete-a-workflow_group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/workflow_groups/{id} Delete a specific workflow group by id # List workflow groups Source: https://docs.rootly.com/api-reference/workflowgroups/list-workflow-groups https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflow_groups List workflow groups # Retrieves a workflow group Source: https://docs.rootly.com/api-reference/workflowgroups/retrieves-a-workflow-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflow_groups/{id} Retrieves a specific workflow group by id # Update a workflow group Source: https://docs.rootly.com/api-reference/workflowgroups/update-a-workflow-group https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/workflow_groups/{id} Update a specific workflow group by id # Creates a workflow run Source: https://docs.rootly.com/api-reference/workflowruns/creates-a-workflow-run https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/workflows/{workflow_id}/workflow_runs Creates a new workflow run from provided data # List workflow runs Source: https://docs.rootly.com/api-reference/workflowruns/list-workflow-runs https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflows/{workflow_id}/workflow_runs List workflow runs # Creates a workflow Source: https://docs.rootly.com/api-reference/workflows/creates-a-workflow https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/workflows Creates a new workflow from provided data # Delete a workflow Source: https://docs.rootly.com/api-reference/workflows/delete-a-workflow https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/workflows/{id} Delete a specific workflow by id # List workflows Source: https://docs.rootly.com/api-reference/workflows/list-workflows https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflows List workflows # Retrieves a workflow Source: https://docs.rootly.com/api-reference/workflows/retrieves-a-workflow https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflows/{id} Retrieves a specific workflow by id # Update a workflow Source: https://docs.rootly.com/api-reference/workflows/update-a-workflow https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/workflows/{id} Update a specific workflow by id # Creates a workflow task Source: https://docs.rootly.com/api-reference/workflowtasks/creates-a-workflow-task https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json post /v1/workflows/{workflow_id}/workflow_tasks Creates a new workflow task from provided data # Delete a workflow task Source: https://docs.rootly.com/api-reference/workflowtasks/delete-a-workflow-task https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json delete /v1/workflow_tasks/{id} Delete a specific workflow task by id # List workflow tasks Source: https://docs.rootly.com/api-reference/workflowtasks/list-workflow-tasks https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflows/{workflow_id}/workflow_tasks List workflow tasks # Retrieves a workflow task Source: https://docs.rootly.com/api-reference/workflowtasks/retrieves-a-workflow-task https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json get /v1/workflow_tasks/{id} Retrieves a specific workflow_task by id # Update a workflow task Source: https://docs.rootly.com/api-reference/workflowtasks/update-a-workflow-task https://rootly-heroku.s3.amazonaws.com/swagger/v1/swagger.json put /v1/workflow_tasks/{id} Update a specific workflow task by id # Catalog Sync CLI Source: https://docs.rootly.com/catalog-sync Use the rootly-catalog-sync CLI to keep services, teams, and metadata in your Rootly Catalog continuously synced from GitHub, Backstage, APIs, and more. `rootly-catalog-sync` is a standalone CLI tool that reconciles external sources of truth into Rootly's Catalog. It pulls data from your existing systems — GitHub repos, Backstage, internal APIs, CSV files, or any command — and syncs it one-way into Rootly, keeping services, teams, and metadata up to date automatically. Rootly Catalog ## Why use Catalog Sync? * **Single source of truth** — your service catalog lives in GitHub, Backstage, or a database. Rootly mirrors it automatically. * **No manual data entry** — add a service to your repo, it appears in Rootly on the next sync. * **Safe by default** — deletes are opt-in, empty sources abort, prune ratio thresholds prevent mass deletion. * **Terraform-style workflow** — `plan` to preview, `apply` to execute, `status` to check drift. ## Install ```bash theme={null} # Homebrew brew install rootlyhq/tap/rootly-catalog-sync # Go go install github.com/rootlyhq/rootly-catalog-sync/cmd/rootly-catalog-sync@latest # Docker (mount your config + catalog data) docker run --rm -e ROOTLY_API_KEY \ -v $PWD/rootly-catalog-sync.yaml:/config.yaml:ro \ -v $PWD/catalog:/catalog:ro \ rootlyhub/rootly-catalog-sync sync --config=/config.yaml # Helm (Kubernetes) helm repo add rootly https://rootlyhq.github.io/helm-charts helm install catalog-sync rootly/rootly-catalog-sync \ --set rootly.apiKey=$ROOTLY_API_KEY \ --set-file configYaml=rootly-catalog-sync.yaml ``` ## Quick start ```bash theme={null} export ROOTLY_API_KEY=rootly_... # Option 1: Scaffold a complete working example (recommended) rootly-catalog-sync init --demo # Option 2: Create a minimal config to customize # rootly-catalog-sync init # Then run: rootly-catalog-sync doctor # verify auth + connectivity rootly-catalog-sync plan # preview changes rootly-catalog-sync sync # apply ``` ## Authentication Two methods are supported, in priority order: ### API key (CI / non-interactive) ```bash theme={null} export ROOTLY_API_KEY=rootly_... ``` Create an API key at **Settings → API Keys** in your Rootly dashboard. ### OAuth 2.0 (interactive) ```bash theme={null} # Login via browser (Authorization Code + PKCE) rootly-catalog-sync login # Tokens saved to ~/.rootly-catalog-sync/config.yaml # Auto-refreshed transparently on expiry # Clear stored tokens rootly-catalog-sync logout ``` If `ROOTLY_API_KEY` is set, it always takes precedence over OAuth tokens. ## Configuration The sync tool uses a declarative config file (v2 format) that defines **sync entries** — each entry connects a source to a catalog or native resource target. ```yaml YAML theme={null} version: 2 sync: - from: local: files: ["catalog/*.yaml"] to: Services map: external_id: "{{ .id }}" name: "{{ .name }}" owner: "{{ .owner }}" tier: "{{ .tier }}" ``` ```yaml YAML (v1) theme={null} version: 1 sync_id: services pipelines: - sources: - local: files: ["catalog/*.yaml"] outputs: - catalog: "Services" external_id: "{{ .id }}" name: "{{ .name }}" fields: owner: "{{ .owner }}" tier: "{{ .tier }}" ``` ```jsonnet Jsonnet theme={null} { version: 2, sync: [ { from: { "local": { files: ["catalog/*.yaml"], }, }, to: "Services", map: { external_id: "{{ .id }}", name: "{{ .name }}", owner: "{{ .owner }}", tier: "{{ .tier }}", }, }, ], } ``` ```hcl HCL theme={null} version = 2 sync { from { local { files = ["catalog/*.yaml"] } } to = "Services" map = { external_id = "{{ .id }}" name = "{{ .name }}" owner = "{{ .owner }}" tier = "{{ .tier }}" } } ``` Config files are detected by extension: `.yaml` (default), `.jsonnet`, or `.hcl`. Credentials use `$(ENV_VAR)` substitution. ## Sources | Source | Description | | ----------- | -------------------------------------------------------- | | `inline` | Entries defined directly in config | | `local` | YAML/JSON files from disk (glob patterns) | | `github` | Files from GitHub repositories (supports `**` patterns) | | `exec` | Run a command, parse stdout as JSON/YAML | | `backstage` | Backstage catalog API with pagination | | `graphql` | Arbitrary GraphQL endpoint with cursor/offset pagination | | `csv` | CSV files with header row | | `url` | Fetch YAML/JSON from remote URLs | | `http` | Generic REST API with JSONPath extraction | ### Inline source ```yaml theme={null} from: inline: entries: - id: payments name: Payments Service owner: platform-team tier: critical - id: auth name: Auth Service owner: security-team tier: critical ``` ### Local source ```yaml theme={null} from: local: files: ["catalog/*.yaml", "services/**/*.json"] ``` ### GitHub source ```yaml theme={null} from: github: token: "$(GITHUB_TOKEN)" owner: acme repos: ["payments", "auth", "gateway"] files: ["**/catalog.yaml"] ref: main ``` Omit `repos` to scan all repositories in the org. Set `archived: true` to include archived repos. ### Backstage source ```yaml theme={null} from: backstage: url: https://backstage.internal.com token: "$(BACKSTAGE_TOKEN)" kind: Component filter: "kind=Component,metadata.annotations.rootly.com/sync=true" ``` ### Exec source ```yaml theme={null} from: exec: command: bq args: ["query", "--format=json", "SELECT id, name, owner FROM dataset.services"] ``` ### GraphQL source ```yaml theme={null} from: graphql: url: https://api.internal.com/graphql headers: Authorization: "Bearer $(API_TOKEN)" query: | query($cursor: String) { services(after: $cursor) { nodes { id name owner tier } pageInfo { hasNextPage endCursor } } } result: data.services.nodes paginate: cursor: data.services.pageInfo.endCursor has_next: data.services.pageInfo.hasNextPage ``` ### CSV source ```yaml theme={null} from: csv: files: ["data/services.csv"] delimiter: "," ``` The first row is used as field names. Each subsequent row becomes an entry. ### URL source ```yaml theme={null} from: url: urls: - https://internal.company.com/catalog/services.yaml - https://internal.company.com/catalog/teams.json headers: Authorization: "Bearer $(API_TOKEN)" ``` ### HTTP source ```yaml theme={null} from: http: url: https://api.internal.com/v1/services method: GET headers: Authorization: "Bearer $(API_TOKEN)" result: data.services ``` ## Output targets Each sync entry uses `to:` to specify the target. The value of `to:` determines whether entries go to a custom catalog or a native Rootly resource. * **Native resource**: use a lowercase type name — `to: service`, `to: team`, `to: functionality`, `to: environment` * **Custom catalog**: use the catalog display name — `to: "Services"`, `to: "Tiers"` ### Custom catalog Creates entities in a named Rootly catalog with arbitrary fields. ```yaml theme={null} sync: - from: local: files: ["catalog/*.yaml"] to: "Services" map: external_id: "{{ .id }}" name: "{{ .name }}" owner: "{{ .owner }}" tier: "{{ .tier }}" ``` ### Native resources Sync directly to built-in Rootly resource types. | Type | Description | | --------------- | ---------------------- | | `service` | Rootly services | | `functionality` | Rootly functionalities | | `environment` | Rootly environments | | `team` | Rootly teams | ```yaml theme={null} sync: - from: local: files: ["catalog/services.yaml"] to: service map: external_id: "{{ .id }}" name: "{{ .name }}" description: "{{ .description }}" pagerduty_id: "{{ .pagerduty_id }}" github_repository_name: "{{ .repo }}" ``` ```yaml theme={null} sync: - from: local: files: ["catalog/teams.yaml"] to: team map: external_id: "{{ .id }}" name: "{{ .name }}" description: "{{ .description }}" opsgenie_id: "{{ .opsgenie_id }}" slack_channel: "{{ .slack_channel }}" ``` For native resources, known attributes (like `description`, `pagerduty_id`, `github_repository_name`) are set directly on the resource. Custom properties are auto-created on first sync for SDK-supported kinds (text, boolean, group, service, etc.). Reference properties are auto-created when the referenced catalog exists. ## Custom properties Native resources (services, teams, functionalities, environments) support custom properties that extend the built-in attributes. These properties are managed automatically during sync. ### Auto-created properties Text properties are auto-created on first sync. Simply include them in your `map:` and they will appear on the resource: ```yaml theme={null} sync: - from: local: files: ["catalog/services.yaml"] to: service map: external_id: "{{ .id }}" name: "{{ .name }}" description: "{{ .description }}" cost_center: "{{ .cost_center }}" # Auto-created as text property documentation_url: "{{ .docs_url }}" # Auto-created as text property ``` ### Reference properties Reference properties link native resources to catalog entities. To use them, first sync the referenced catalog, then reference it in the native resource mapping. For example, to link services to a "Tiers" catalog: ```yaml tiers.yaml theme={null} - id: critical name: Critical sla: 99.99% - id: standard name: Standard sla: 99.9% ``` ```yaml rootly-catalog-sync.yaml theme={null} version: 2 sync: - from: local: files: ["tiers.yaml"] to: "Tiers" map: external_id: "{{ .id }}" name: "{{ .name }}" sla: "{{ .sla }}" - from: local: files: ["catalog/services.yaml"] to: service map: external_id: "{{ .id }}" name: "{{ .name }}" tier: value: "{{ .tier }}" reference: Tiers ``` The `reference: Tiers` shorthand tells the sync tool to resolve the human-readable tier name to the corresponding catalog entity UUID. Matching is case-sensitive and compares the field value against the catalog entity's `name` (not `external_id`). The referenced catalog ("Tiers" in this example) must exist — sync it in an earlier sync entry so it is available when the service entry runs. ## Template syntax Field mappings use Go template syntax to transform source entries into output fields. ### Field access ```yaml theme={null} map: name: "{{ .name }}" # Direct field access owner: "{{ get .metadata \"team\" }}" # Nested map access slug: "{{ .org }}/{{ .name }}" # String concatenation tier: "{{ default .tier \"unknown\" }}" # Fallback for nil/empty values region: us-east-1 # Static value (no template needed) ``` ### Conditionals ```yaml theme={null} environment: "{{ if .production }}prod{{ else }}staging{{ end }}" ``` Templates are compiled with `missingkey=error` — a missing field in the source data causes an immediate error rather than a silent empty string. ## Commands | Command | Description | | ----------------- | ----------------------------------------------------------------------------------------------------- | | `plan` | Preview changes (creates a saved plan file) | | `apply ` | Apply a saved plan (validates freshness first) | | `sync` | Plan + apply in one step | | `status` | Read-only drift check (`--fail-on-drift` for CI gates) | | `init` | Create a config file (add `--interactive` for guided wizard, `--demo` for a complete working example) | | `init --demo` | Scaffold a complete working example with sample data and config | | `validate` | Check config syntax | | `doctor` | Verify API key, connectivity, and permissions | | `sources inspect` | Dump raw source entries before mapping | | `explain ` | Trace one entry through source → mapping → diff | | `adopt` | Claim existing UI entries under sync management | | `import` | One-shot seed (no prune, no lock) | | `watch` | Continuous sync loop (`--interval=5m`) | | `tui` | Interactive terminal UI for selective apply | | `login` | Authenticate via browser OAuth 2.0 (PKCE) | | `logout` | Clear stored OAuth tokens | ## Safety guarantees * **Deletes are opt-in** — `--allow-prune` required, off by default * **Empty source aborts** — never wipes a catalog on a source failure * **Prune ratio threshold** — aborts if deletes exceed 20% of live entities (configurable via `--prune-threshold`) * **Manual entries are safe** — only entries with `external_id` (created by sync) are prunable * **Order: create/update first, delete last** — no window where entries are missing * **Plan freshness** — `apply` validates that live state hasn't changed since the plan was created ## CI/CD integration ### GitHub Actions ```yaml theme={null} name: Catalog Sync on: push: branches: [main] paths: - "catalog/**" - "rootly-catalog-sync.yaml" jobs: sync: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: go-version: stable - run: | go install github.com/rootlyhq/rootly-catalog-sync/cmd/rootly-catalog-sync@latest $(go env GOPATH)/bin/rootly-catalog-sync sync env: ROOTLY_API_KEY: ${{ secrets.ROOTLY_API_KEY }} ``` ### Dry-run on PRs ```yaml theme={null} - run: rootly-catalog-sync plan --dry-run --output=json env: ROOTLY_API_KEY: ${{ secrets.ROOTLY_API_KEY }} ``` ### Nightly drift detection ```yaml theme={null} - run: rootly-catalog-sync status --fail-on-drift env: ROOTLY_API_KEY: ${{ secrets.ROOTLY_API_KEY }} ``` ## Kubernetes deployment Deploy catalog sync to Kubernetes using the official Helm chart: ```bash theme={null} helm repo add rootly https://rootlyhq.github.io/helm-charts helm install catalog-sync rootly/rootly-catalog-sync \ --set rootly.apiKey=$ROOTLY_API_KEY \ --set-file configYaml=rootly-catalog-sync.yaml ``` By default the chart creates a **CronJob** that runs every 30 minutes. To run in **watch mode** (continuous sync loop): ```bash theme={null} helm install catalog-sync rootly/rootly-catalog-sync \ --set rootly.apiKey=$ROOTLY_API_KEY \ --set-file configYaml=rootly-catalog-sync.yaml \ --set mode=watch \ --set watch.interval=5m ``` To include local data files referenced by your config, use a values file: ```yaml theme={null} # values.yaml rootly: apiKey: rootly_... configYaml: | version: 2 sync: - from: local: files: ["/data/services.yaml"] to: service map: external_id: "{{ .id }}" name: "{{ .name }}" dataFiles: services.yaml: | - id: api-gateway name: API Gateway ``` ```bash theme={null} helm install catalog-sync rootly/rootly-catalog-sync -f values.yaml ``` ## Environment variables | Variable | Description | Default | | ----------------- | ---------------------------------- | ------------------------ | | `ROOTLY_API_KEY` | API key (or use `login` for OAuth) | — | | `ROOTLY_API_URL` | Override base URL | `https://api.rootly.com` | | `ROOTLY_API_PATH` | Override API path prefix | `/v1` | ## Interactive TUI The `tui` command launches a full-screen terminal UI for reviewing and selectively applying changes: * Browse changes with colored badges (CREATE/UPDATE/DELETE/NOOP) * Toggle individual changes with `space`, expand field diffs with `enter` * Filter by operation type (`c`/`u`/`d`) or search (`/`) * Detail pane shows full entity fields on wide terminals * Apply only selected changes with `A` ## Resources * [GitHub repository](https://github.com/rootlyhq/rootly-catalog-sync) * [Helm chart](https://github.com/rootlyhq/helm-charts/tree/master/charts/rootly-catalog-sync) * [Docker Hub](https://hub.docker.com/r/rootlyhub/rootly-catalog-sync) * [Troubleshooting guide](https://github.com/rootlyhq/rootly-catalog-sync/blob/master/docs/troubleshooting.md) * [Template syntax reference](https://github.com/rootlyhq/rootly-catalog-sync/blob/master/docs/templates.md) * [Working examples](https://github.com/rootlyhq/rootly-catalog-sync/tree/master/docs/examples) # Catalogs Source: https://docs.rootly.com/catalogs Define and manage the entities that matter to your business, like services, teams, and regions, as a structured source of truth for incident response. Catalog is the central place in Rootly where you define the entities that matter most to your business, things like Services, Teams, Product Areas, Regions, or any other concept that shapes how your organization works and responds to incidents. Rather than managing this data in spreadsheets or relying on people to fill in the right values from memory, Catalog gives you a structured, reusable source of truth. Once your entities are defined, you can use them everywhere: on incident fields, in workflows, in reports, and more. **Why this matters** When an incident hits, responders need to quickly capture what’s impacted — which service, which region, which team. Without Catalog, this is manual and error-prone. With Catalog, that data is structured, consistent, and can even be filled in automatically. Rootly has always allowed you to manage a catalog of Services, Teams, Functionalities, Types, Environments, and Causes. Now, you’re able to add custom catalogs that represent additional business entities that are relevant to your incident response efforts. Clean Shot2026 03 30at15 35 17@2x ## **Key concepts** Here are the main building blocks you’ll work with: * **Catalog**: A collection of related entities. For example, a "Services" Catalog contains all the services your organization runs. * **Entity**: A single item within a Catalog. For example, "Payments API" is an entity in the Services Catalog. * **Properties**: Attributes that describe each entity. For example, each Service might have an "Owning Team" property. ## Getting started Begin setting up your Catalogs by navigating to the **Catalog section** from the left-hand navigation. When you open the Catalog for the first time, Rootly comes pre-loaded with a set of common Catalogs to help you hit the ground running: Services, Teams, Functionalities, Causes, Types, and Environments. These should look familiar to you: all of your existing Services, Teams, Functionalities etc. are now accessible from the Catalog page. **You can also access these Catalogs from the Rootly > Configuration section**. Now, you can continue to use these built-in Catalogs as is, or customize them to match your setup. Nothing is locked in, everything is editable. Clean Shot2026 03 30at15 38 33@2x # Checklists Source: https://docs.rootly.com/checklists Create checklists to verify that every entity in your catalog has the required properties, and run audits to track completeness across your organization. Checklists help you make sure that every entity in your Catalog has the information it needs to participate in your incident response and on-call processes. As your organization grows and reorganizes, it’s easy for Catalog data to go stale: teams change ownership, services get deprecated, runbooks go out of date. Checklists give you a structured way to define what "complete" looks like for each type of entity, and to periodically verify that every entity meets that standard. You can create an "On-Call Ready" checklist for your Teams Catalog, specifying that every Team must have an escalation policy, a goalie, and a support tier defined. You then kick off an audit to check all of your teams at once — any team that’s missing information will show up as incomplete, with a clear owner responsible for filling in the gaps. ## **Key concepts** * **Checklist**: A definition of the properties that must be filled out on a Catalog entity for it to be considered complete. You give it a name, a description, and select the specific properties it covers. * **Checklist owner**: The person responsible for completing the checklist for a given entity. This can be a specific user, or dynamically determined from a property on the entity (for example, the entity’s assigned Goalie or Owning Team’s admin). * **Audit**: An instance of a checklist created for each entity in a Catalog. Triggering an audit kicks off a checklist for every entity at once. * **Audit status**: Tracks where each entity stands in the review process: Not Started, In Progress, or Complete. ## **Creating a checklist** You can create checklists on both built-in Catalogs (like Services and Teams) and any custom Catalogs you’ve defined. **For now, you can only create one checklist per Catalog.** Clean Shot2026 03 30at21 37 11@2x 1. Navigate to your Catalog and open the **Checklists** tab, and click **Add checklist**. 2. Give it a name (for example, "On-Call Ready") and optional instructions so others know what it covers. 3. Optionally, assign a checklist owner (see below for more details). 4. Select the properties from that Catalog that must be filled out for an entity to pass the checklist. 5. Save the checklist. ### **Assigning a checklist owner** The checklist owner is the person responsible for completing the checklist for each entity. You have a few options for how ownership is determined: * **A specific user:** One person is responsible for completing the checklist for every entity in the Catalog. * **A team property on the entity:** The owner is the admin of the team associated with the entity. For example, if each Service has an "Owning Team" property, the checklist owner would be the admin of that team. Checklists can have more than one owner. However, you’re not required to assign ownership if it doesn’t make sense for your workflow. ### **Editing a checklist definition** As your Catalog evolves (for example, if you add a new "Tier" property to your Services), you can edit an existing checklist to include the new property: you don’t need to create a new checklist. **Note on in-progress audits**: If you edit a checklist definition while an audit is already in progress, the active audit will not be changed. It will continue to reflect the checklist definition that was in place when that audit was triggered. ### **Deleting a checklist** You can delete a checklist at any time. When you do, Rootly retains any historical references to it and any active audits will continue and can still be completed. The checklist itself will no longer be available for future audits. ## **Triggering and managing audits** When it’s time to review and validate all entities in your Catalog, you can kick off an audit! An audit creates a fresh checklist for every entity in a Catalog at once. If you defined a checklist owner, they are all responsible for completing the audit of their entities.  To trigger an audit: 1. Open the Catalog you want to audit. Click the **Checklists** tab from the overview page to see the available checklists. 2. Select the checklist you want to run. 3. Click **Initiate checklist review**. Rootly will create a new checklist instance for every entity in the Catalog.  Clean Shot2026 03 30at21 40 09@2x **Note on in-progress audits**: If an entity already has a checklist in "In Progress" status when you trigger an audit, Rootly will not create a new one for that entity and will not close the existing one. ## **Completing an audit** Once an audit has been triggered for your entity, you’ll find it in the Catalog on that entity’s page. Here’s how to work through it. Clean Shot2026 03 30at21 41 44@2x ### **Viewing audit statuses** On the Catalog’s overview page, you can see the audit status for every entity at a glance. Entities that haven’t been started show a "Start Review" prompt; entities in progress show an "In Progress" indicator. ### **Reviewing and checking off items** Each item in the audit corresponds to a property from the checklist definition. For each item, you’ll see the current value of that property on the entity. 1. Review the current value for each property. If the value is correct, check it off. Rootly records who checked it off and what the value was at the time. 2. If the value needs to be updated, make the change to the entity and then check off the item. 3. You can save your progress at any point and come back to finish later. 4. Once every item is checked off, click "Complete" to finalize the audit. **Completed audits are locked**: Once you mark an audit as complete, it cannot be edited by anyone. All checkboxes must be checked before you can complete the audit. Rootly records who completed it and when. ### **Multiple people working on the same audit** More than one person can work on the same audit at the same time. Rootly tracks who checks off each individual item, so you’ll have a clear record of who reviewed what, even when the work is shared across a team. ## **Tracking audit progress** Audits can have the following statuses: * **Not Started:** The audit has been created but no items have been reviewed yet. * **In Progress**: At least one item has been reviewed and checked off. * **Complete**: All items have been checked off and the audit has been finalized. ## **Viewing audit history** Rootly keeps a record of every completed audit for each entity. In the entity’s audit history, you can see: * Who triggered the audit and when it was started. * Which properties were included in the checklist at the time of the audit. * The values those properties had when each item was checked off. * Who checked off each item, and when. * Who completed the audit, and when. This gives you a clear, time-stamped record of the state of each entity at each review point: useful for compliance, retrospectives, or just understanding how your Catalog has evolved over time. # Exporting Retrospectives Source: https://docs.rootly.com/collaborative-retrospectives/exporting-retrospectives Export retrospective content to external documentation providers like Google Docs, Confluence, Notion, SharePoint, Quip, Coda, and other knowledge bases. ## Overview Rootly can export retrospective content to external documentation providers, allowing teams to use their preferred tools while benefiting from Rootly's incident management features. ### Supported Providers Rootly supports the following external document providers: * Google Docs * Confluence * Notion * SharePoint * Dropbox Paper * Coda * Quip * Datadog Each provider has its own authentication and configuration requirements. Contact your administrator if you need access to a specific provider. ## Rootly Editor vs External Providers ### When to Use the Rootly Editor The built-in collaborative editor is ideal when: * Multiple team members need to edit simultaneously * You want data blocks and variables that update automatically * You prefer keeping incident data within Rootly ### When to Use External Providers External providers work well when: * Your organization standardizes on a specific documentation tool * You need to share retrospectives with stakeholders outside Rootly * You want documents accessible in your existing knowledge base * Compliance or governance requires specific storage locations ### Using Both Many teams combine approaches: 1. **Draft in Rootly:** Use the Rootly Editor for initial drafting and collaboration 2. **Export for distribution:** Export to an external provider when ready to share broadly 3. **Link back:** The external document links back to the incident in Rootly Exporting happens at specific points (when you click Export) rather than in real-time. *** ### What Gets Exported When exporting to your external providers, Rootly processes your retrospective content to ensure compatibility. ### Content That Exports | Content Type | How It's Handled | | :------------------- | :----------------------------------------------------------- | | **Rich text** | Formatting preserved (bold, italic, headings, lists) | | **Tables** | Converted to provider-native table format | | **Data blocks** | Rendered as static content at export time | | **AI blocks** | Rendered as static text (the generated draft) at export time | | **Liquid variables** | Resolved to actual values at export time | | **Code blocks** | Formatted appropriately for each provider | | **Links** | Preserved as clickable hyperlinks | ### Incident Data Blocks in External Documents If your retrospective document contains data blocks: * **Timeline:** Rendered as a formatted table with event date, source, user, and description * **Follow-ups:** Rendered as a list with title, priority, status, assignee, and due date Data blocks become static content in external documents. They won't update automatically if the incident data changes after export. ### Provider-Specific Formatting Rootly adjusts content formatting for each provider: | Provider | Special Handling | | :-------------- | :------------------------------------------ | | **Confluence** | Inline code converted to Confluence macros | | **Google Docs** | Tables formatted with borders and styling | | **Notion** | Content structured for Notion's block model | | **Others** | Standard HTML-to-provider conversion | *** ## How to Export The **Export** button in the editor header provides access to all export options for your retrospective. ### Export Dropdown Click **Export** in the editor header to access these options: | Option | Description | | :--------------------------- | :--------------------------------------------------------------------------------------------- | | **Publish retrospective** | Publishes the retrospective, making it accessible via a sharable URL and notifying subscribers | | **Export to new document** | Opens a modal to create a new export to any connected provider | | **Update exported document** | Opens a modal to update a previously exported document (only visible if exports exist) | Once a retrospective is published, the Export dropdown updates to include additional options: | Option | Description | | :------------------------------- | :-------------------------------------------------------------------------------------------------------------- | | **View published retrospective** | Opens the published retrospective in a new tab | | **Copy link** | Copies the published retrospective URL to your clipboard | | **Save as PDF** | Downloads the published retrospective as a PDF file | | **Document settings** | Customize what gets appended to the published document (for example, timeline, action items, incident metadata) | If you have no external integrations configured, click **Manage integrations** to connect a document provider. Contact your administrator to set up integrations in **Configuration → Integrations**. *** ## Publishing a Retrospective Publishing makes your retrospective accessible to your team. ### How to Publish Click **Export** in the editor header. If the incident has already been resolved, the retrospective is published immediately. If the incident is still active, a confirmation dialog asks you to confirm that you want to publish before the incident is resolved. ### What Happens When You Publish * The retrospective status changes from **Draft** (yellow chip) to **Published** (green chip) in the editor header * The published document is accessible via an internal URL for non-private incidents * Subscribers are notified that the retrospective has been published * The Export dropdown updates to show additional options: view the published document, copy its link, save as PDF, and access document settings ### Document Settings After publishing, you can customize the published retrospective by clicking **Document settings** in the Export dropdown. Document settings let you control what gets appended to your published document: Include the incident timeline in the published document. Include the incident's action items and follow-ups. Include severity, services, roles, and timestamps. This allows teams to tailor what stakeholders see in the published version without modifying the editor content. ### Re-publishing If you make changes to the retrospective after publishing, your published document gets updated automatically. The published URL remains the same — only the content is updated. Publishing and exporting are independent actions. Publishing makes the retrospective available via a Rootly URL. Exporting pushes the content to an external provider like Confluence or Google Docs. You can do both. *** ### Exporting to a New Document To export your retrospective to an external provider for the first time: Click **Export** in the editor header. This opens a modal where you can configure the export. Select the provider (Confluence, Google Docs, Notion, etc.) from the dropdown. Each provider shows its icon for easy identification. The title defaults to "Retrospective - \[Incident Title]". You can customize it. Some providers require additional configuration: * **Confluence:** Select a space key for the destination * **Notion:** Select a parent page * Other providers may have their own options The export is created in the background. You'll be notified when it completes. ### Updating an Existing Export If you've already exported the retrospective and want to push updated content: Click **Export** in the editor header. This option only appears if you have previously exported the retrospective. Select the export you want to update from the list. Each entry shows the provider name and document title. A warning confirms that the external document's content will be replaced with the current retrospective content. Click **Update** to proceed. Updating an export overwrites the external document with the current retrospective content. This is a one-way operation — changes made in the external document will be replaced. ### Working with Exported Documents Once a retrospective is exported to an external provider: * A link to the external document is stored on the incident * The document lives in your external provider's system * You can open external documents directly from the **More actions** menu in the editor header * Edits in the external document do **not** sync back to Rootly ### Document Links After exporting, you can reference external document URLs using Liquid variables: * `{{ incident.confluence_page_url }}` * `{{ incident.google_drive_url }}` * `{{ incident.notion_page_url }}` * `{{ incident.sharepoint_page_url }}` ### Managing Integrations Click **Manage integrations** in the Export dropdown to go to **Configuration → Integrations** (Docs & Retrospective category), where you can connect or configure document providers. ### How Workflows and Exporting Work Together Workflows and the Export button serve different purposes: * **Workflows** can automatically create external documents (for example, in Confluence or Google Docs) when an incident resolves or another trigger fires. These workflows do not create or modify the Rootly document — they only affect external providers. * **The Export button** in the editor lets you manually export the Rootly document's content to a new external document or update an existing one at any time. If you want the Rootly document to be created automatically, set up a separate **Create Rootly Retrospective** workflow. Otherwise, create it manually from the Retrospective tab. The Rootly document and external documents are independent paths. A workflow that creates a Confluence page will not write to or create the Rootly document, and vice versa. If you create the Rootly document before a workflow fires, the workflow will not override it. *** ### Best Practices * **Set up workflows for initial creation:** Configure workflows to automatically create external documents when incidents resolve, so you don't have to manually export each time. * **Use Update for changes:** After editing a retrospective, use **Update external document** to push changes to the existing export. * **Include data blocks before exporting:** Add Timeline and Follow-ups blocks before exporting so they're rendered in the external document. * **Verify liquid variables have values:** Empty variables create gaps in the external document. Check that referenced fields exist for the incident. ## Frequently Asked Questions The connection to the external provider may have expired. Re-authenticate the integration in **Configuration → Integrations** or contact your administrator. Data blocks must have data to render. If the incident has no timeline events or follow-ups, the blocks may appear empty. Add data to the incident before exporting. Ensure the incident has the expected data. Variables without values resolve to N/A. Check that referenced fields (Jira ticket, assigned roles, etc.) exist for this incident. Export is one-way. Edits made directly in the external provider don't sync back to Rootly. Make edits in Rootly and use **Update external document** to push changes. Click **Export** in the editor header and select **Update external document**. Choose the export you want to update from the list and confirm. The external document will be overwritten with the current retrospective content. Yes. Use **Export to new document** for each provider you want to export to. Each export is tracked independently and can be updated separately. *** ## Related Pages The umbrella page covering how the editor works end-to-end. Author the retrospective content that this page shows how to export. Variables render to their live values in the exported document. # Liquid Variables in Retrospectives Source: https://docs.rootly.com/collaborative-retrospectives/liquid-variables Use Liquid templating in retrospective documents to dynamically populate incident data, custom fields, action items, and timeline events. ## Overview Rootly supports the [Liquid](https://shopify.github.io/liquid/) templating engine in retrospective documents and templates. Liquid allows you to insert dynamic placeholders like `{{ incident.title }}` or `{{ incident.severity }}` that automatically resolve to actual incident data when the retrospective is published or exported. This is especially valuable because retrospective documents often reference the same incident data repeatedly (title, severity, duration, commander, etc.), and the most common failure mode is simple: people copy-paste incorrectly or forget to update values when the incident changes. Typical uses include: * Pre-filling retrospective templates with incident metadata * Referencing incident data without manual copy-paste * Ensuring consistency when exporting to external systems (Google Docs, Confluence, Notion) * Creating reusable templates that adapt to each incident automatically Liquid variables in retrospectives use the same syntax and variable names as Incident Variables in Workflows. If you're familiar with Liquid in Workflows, the same variables are available in the retrospective editor. ## Liquid Variables vs Liquid Blocks Rootly provides two ways to use Liquid in retrospectives: | Feature | Liquid Variables | Liquid Blocks | | -------------- | --------------------------------------- | --------------------------------------------- | | **Insert via** | Type `{{` | Type `/liquid` | | **Scope** | Inline (within text) | Block-level (standalone section) | | **Syntax** | `{{ variable }}` with filters | Full Liquid: `{% if %}`, `{% for %}`, filters | | **Display** | Inline chip | Edit/Preview panel | | **Best for** | Inserting dynamic values into sentences | Conditional content, loops, multi-line logic | **Use Liquid Variables when** you need to insert a single dynamic value into your text, like "The incident commander was `{{ incident.commander.name }}`." **Use Liquid Blocks when** you need conditional logic, loops, or multi-line templates—for example, showing different content based on severity or listing all action items. *** ## How to Insert Liquid Variables ### In the Editor 1. **Start typing a variable:** Type `{{` anywhere in the editor to trigger the variable autocomplete. 2. **Filter and select:** Continue typing to filter available variables (for example, `{{ incident.ti` shows `incident.title`). 3. **Insert the variable:** Click or press Enter to insert the selected variable. 4. **Variable appears as a chip:** The variable displays as a visual chip in the editor, showing the variable name. ### In Templates Templates support Liquid variables in the same way. When a template is inserted into a retrospective, variables remain as placeholders until the retrospective is published or exported. Variables in templates allow you to create reusable structures that automatically adapt to each incident to help eliminate manual data entry and reduce errors. ### Examples #### Get the incident title and severity Expression: `{{ incident.title }} ({{ incident.severity }})` Sample result: "Database connection timeout (SEV1)" #### Format a timestamp Expression: `{{ incident.started_at | date: "%Y-%m-%d %H:%M" }}` Sample result: "2024-03-15 14:32" [Reference](https://shopify.github.io/liquid/filters/date/) #### Get the incident commander's name Expression: `{{ incident.commander.name }}` Sample result: "Jane Smith" #### Build a resource link Expression: `[Slack Channel]({{ incident.slack_channel_url }})` Sample result: "[Slack Channel](https://slack.com/archives/C123456)" Liquid variables are organized by the data they reference. For the complete list of available variables use the [Liquid Markup explorer](https://rootly.com/account/help/liquid-explorer). *** ## Liquid Blocks Liquid Blocks are standalone template sections that support the full Liquid templating language, including conditionals (`{% if %}`), loops (`{% for %}`), and all Liquid filters. They're ideal when you need more than simple variable substitution. ### How to Insert a Liquid Block 1. **Open the slash menu:** Type `/liquid` anywhere in the editor. 2. **Select Liquid Block:** Choose "Liquid Block" from the slash command menu. 3. **Write your template:** Enter your Liquid code in the editor panel that appears. 4. **Preview your output:** Click **Preview** to see the rendered result with real incident data. 5. **Edit as needed:** Toggle back to **Edit** to make changes. The preview updates each time you switch. The Preview mode renders your template using actual incident data, so you can verify your logic works correctly before publishing. ### When to Use Liquid Blocks Liquid Blocks are particularly useful for: * **Conditional content** based on incident properties (severity, status, etc.) * **Looping through collections** like action items, services, or team members * **Complex formatting** that requires multiple variables and logic * **Reusable template sections** that adapt based on incident context ### Examples #### Conditional severity messaging ```liquid theme={null} {% if incident.severity == "critical" %} 🚨 **CRITICAL INCIDENT** - This incident required immediate escalation and executive notification. {% elsif incident.severity == "high" %} ⚠️ **High Priority** - This incident impacted production systems and required urgent response. {% else %} 📋 This incident followed standard response procedures. {% endif %} ``` #### Loop through action items ```liquid theme={null} ### Action Items {% for item in incident.action_items %} - [{{ item.status }}] {{ item.summary }} - **Owner:** {{ item.owner.name }} - **Due:** {{ item.due_at | date: "%B %d, %Y" }} {% endfor %} ``` #### Conditional sections with fallbacks ```liquid theme={null} {% if incident.resolved_at %} **Resolution Time:** {{ incident.resolved_at | date: "%B %d, %Y at %I:%M %p" }} **Total Duration:** {{ incident.duration }} {% else %} ⏳ *This incident is still ongoing.* {% endif %} ``` #### Dynamic team summary ```liquid theme={null} ### Response Team {% if incident.commander %} - **Incident Commander:** {{ incident.commander.name }} {% endif %} {% if incident.communication_lead %} - **Communication Lead:** {{ incident.communication_lead.name }} {% endif %} {% for responder in incident.responders %} - {{ responder.name }} ({{ responder.role }}) {% endfor %} ``` Liquid Blocks have access to all the same variables available to Liquid Variables. Use the [Liquid Markup explorer](https://rootly.com/account/help/liquid-explorer) to see the complete list. ### Error Handling If your Liquid template contains a syntax error, the Preview mode will display an error message describing the issue. Common errors include: * Unclosed tags (`{% if %}` without `{% endif %}`) * Undefined variables (check spelling and availability) * Invalid filter syntax Fix the error in Edit mode and preview again to verify. *** ## How Variables Resolve In the editor, variables appear as visual **chips** showing their names, and Liquid Blocks show as editable panels. When you publish or export (to Google Docs, Confluence, etc.), both resolve to their current values, so the final document shows real data instead of placeholders. Variables always resolve to the **current** value at the time of publish or export. If incident data changes after publishing, the retrospective retains the original resolved values. ## Best Practices * **Use variables for inline values, blocks for logic:** Keep simple insertions as Liquid Variables; use Liquid Blocks when you need conditionals or loops. * **Use variables in templates:** Templates with variables create consistent retrospectives that auto-populate incident data, eliminating manual entry and reducing errors. * **Prefer data blocks for timeline/follow-ups:** The `/timeline` and `/followups` data blocks provide richer, interactive display compared to timeline variables. * **Use the `default` filter for optional data:** If a variable might be empty (for example, no Jira ticket), use `{{ incident.jira_issue_url | default: "N/A" }}` to provide a fallback. * **Use role variables for accountability:** Including `{{ incident.commander.name }}` makes ownership clear in the published document. * **Keep templates DRY:** Define common sections once in a template and let variables fill in the incident-specific details. * **Preview Liquid Blocks before publishing:** Use the Preview toggle to verify conditional logic and loops render correctly with your incident data. ## Frequently Asked Questions The referenced data doesn't exist for this incident. For example, `{{ incident.jira_issue_url }}` is empty if no Jira ticket is linked. Use the `default` filter to provide a fallback value. Yes! Use **Liquid Blocks** for full Liquid logic including conditionals and loops. Type `/liquid` to insert a Liquid Block. Standard **Liquid Variables** (inserted via `{{`) support only variable interpolation and filters. Yes. Retrospective Liquid variables use the same syntax and variable names as Incident Variables in Workflows. If you're familiar with Liquid in Workflows, the same variables work in retrospectives. Yes. Use the `date` filter with a format string: `{{ incident.started_at | date: "%B %d, %Y" }}` produces "March 15, 2024". See the [Liquid date filter reference](https://shopify.github.io/liquid/filters/date/) for format options. Liquid Variables are inline placeholders for single values (inserted via `{{`). Liquid Blocks are standalone sections that support full Liquid templating including conditionals and loops (inserted via `/liquid`). Use variables for simple value insertion; use blocks when you need logic. No, Liquid Blocks are atomic units in the editor. However, you can use nested Liquid logic (like `{% if %}` inside `{% for %}`) within a single Liquid Block. *** ## Related Pages The umbrella page covering how the editor works end-to-end. Insert Liquid variables into the retrospective from the editor toolbar. Variables render to their live values in the exported document. # Collaborative retrospective editor overview Source: https://docs.rootly.com/collaborative-retrospectives/overview Explore the Rootly collaborative retrospective editor with real-time co-authoring, dynamic data blocks, Liquid variables, and inline action item tracking. ## Writing Retrospectives Once an incident resolves, you can write your retrospective using either: 1. Rootly's document editor 2. An external document editor like Notion, Confluence or Google Docs. Many teams use a hybrid approach by drafting in the Rootly document editor and exporting a copy to their external editor of choice. Integrations are configured by your administrator. Check Configuration → Integrations for a full list of external document providers available to you. ## Using The Rootly Editor Rootly includes a rich text editor in retrospectives that supports live incident data and real-time collaboration - all without leaving the platform. When an incident is resolved, the retrospective workflow begins. The editor is where your team can capture what happened, why it happened, and what improvements your team intends to make to prevent the incident from recurring. ## How Teams Collaborate with The Editor Writing retrospectives is a core part of the incident lifecycle, but it often breaks team momentum. Important context lives across emails, documents, Slack threads, Zoom calls, and knowledge base tools like Notion or Confluence. Teams are forced to hunt for details, manually copy and paste information into a document, and reformat it every time. As a result, collaboration slows down, context gets lost, and it becomes harder to maintain a single, reliable source of truth for how the incident was resolved. **The Rootly editor solves these problems by providing:** * **Incident metadata** that resolves to actual values and stays in sync as you write * **Dynamic data blocks** that pull in live updates to your incident from Timelines and Action Items * **Real-time collaboration** so multiple authors can work together and contribute * **Inline comments** for feedback and discussion in context * **@mentions** to tag users and reference incidents directly in the document It's also packed with a host of features to make retrospective documents pleasant to write and collaborate in. ## Key Features at a Glance | Feature | Description | | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------- | | Variable Incident Metadata | Dynamic placeholders like `{{ incident.title }}` that resolve to actual values | | Complex Incident Metadata | Insert rich liquid variable blocks with conditional syntax that resolve to their actual values | | Data Blocks | Insert dynamic Timeline and Follow-ups blocks that pull live data from the incident | | AI Blocks | Auto-draft sections (Summary, Impact, Root Cause, and more) from incident data, Slack, and bridge-call transcripts | | Real-time Collaboration | Multiple users edit simultaneously with live cursors and presence indicators | | Comments | Inline feedback and threaded discussions on selected text | | @Mentions | Tag users and reference incidents directly in the document with interactive popovers | | Export & Sync | Export content to Google Docs, Confluence, Notion, and other providers. Download as PDF or copy as Markdown | | Document Status | Draft and Published states with visual status indicators and publish confirmation flows | | Invite Collaborators | Invite team members via Slack or email to collaborate on the retrospective | | Templates | Pre-built content structures inserted via slash commands | | Version history and analytics | Full visibility into viewers and editors of a document. Track document changes and revert to previous versions with a click. | ## Where the Editor Fits in the Incident Lifecycle The retrospective editor is part of the broader retrospective workflow that begins when an incident is resolved. The editor is primarily used in the Write the **Retrospective** step, although teams can start writing their document at any point before or after the incident resolves. ### Retrospective Workflow Steps 1. **Gather and Confirm Data:** Collect incident metadata, impacted services, and initial findings 2. **Write the Retrospective:** Write the retrospective document using the Rootly document editor 3. **Create Follow-ups:** Define action items to prevent recurrence 4. **Publish and Export the Retrospective:** Publish the retrospective document to make it accessible, export to external providers, and notify your team to review ## External Document Editors Rootly supports integrations with Notion, Google Docs, Confluence, SharePoint, Dropbox Paper, Coda and Quip. If you have workflows set up to create retrospective documents in an external editor, you can find links to your external documents under the Exports section in the Retrospectives tab. If you'd like to try the Rootly document editor, you can create a Rootly document from the Retrospective tab at any time. The Rootly document and external documents are independent — workflows that create external documents (for example, in Confluence) do not create or modify the Rootly document. You can choose to use the Rootly document editor, an external document editor, or both depending on your team's needs. External providers are configured in Configuration → Integrations. ### How the Rootly Document Is Created The Rootly document is created in one of two ways: * **Manually:** Click the **Create Rootly Document** button in the Retrospective tab to create a document on demand. You can start from a blank document or choose a template. * **Via workflow:** Set up a **Create Rootly Retrospective** workflow to automatically create the Rootly document when an incident resolves (or another trigger fires). Workflows that export to external providers (like Confluence or Google Docs) do not create or write to the Rootly document. These are separate paths. If you want both, configure separate workflows for each. *** ## Where to Go Next These pages provide detailed guidance on specific aspects of the retrospective editor: * **Using the Editor:** Formatting, slash commands, data blocks, and templates * **Live Incident Variables:** Dynamic content placeholders and available variables * **Real-Time Collaboration:** Multi-user editing, comments, and presence * **Exporting Retrospectives:** Export to external providers, download as PDF, and sync workflows * **[AI in Retrospectives](/ai/ai-in-retrospectives/overview):** Auto-draft sections with AI blocks and build AI-powered templates *** ## Frequently Asked Questions Yes. The editor supports real-time collaboration with live cursors showing where each user is working. Changes from all users are merged automatically without conflicts. The editor automatically saves changes every second. If you lose connection, your changes are preserved locally and will sync when connectivity is restored. Yes. Rootly supports external document editors like Confluence, Google Docs, and Notion. If you have a workflow that creates documents in an external editor, those will continue to work as before. The Rootly document editor is optional and independent — workflows for external providers don't affect it. The Rootly document can be created manually by clicking **Create Rootly Document** in the Retrospective tab, or automatically via a **Create Rootly Retrospective** workflow. Workflows that export to external providers (like Confluence) do not create or modify the Rootly document — these are separate paths. If you create the document manually before a workflow fires, the workflow will not override your document. Click the **Export** button in the editor header and select **Export to new document**. Choose your destination provider, set a title, and configure any provider-specific options. You can also update previously exported documents by selecting **Update external document** from the same dropdown. Use data blocks by typing /timeline or /followups in the editor. These blocks pull live data from the incident and update automatically. You can also use liquid variables like `{{ incident.title }}` for individual data points, or a liquid variable block to display conditional outputs or data types like arrays. Yes. Type `@` in the editor to search for and mention users or incidents. User mentions display an interactive popover showing the person's name, avatar, email, teams, and incident roles. This depends on your team's configuration. Retrospective workflows can be configured to trigger based on severity, incident type, or other conditions. Some steps can be marked as skippable while others are required. Select any text in the editor and click the comment button to start a discussion thread. Team members can reply, resolve, or delete their comments. Comments are synced in real-time for all collaborators. Yes. The editor shows presence indicators with user avatars/initials for everyone currently viewing or editing the document. Collaborative cursors with names show exactly where each person is working. # Real-Time Collaboration Source: https://docs.rootly.com/collaborative-retrospectives/real-time-collaboration Work together on retrospectives with real-time editing, collaborative cursors, presence indicators, inline comments, and live co-authoring across teams. ## How Real-Time Collaboration Works The retrospective editor supports simultaneous editing by multiple team members. Changes sync instantly across all connected users, eliminating version conflicts and enabling true collaborative writing. Collaboration features include: * **Real-time editing:** See changes as others make them * **Collaborative cursors:** See where each person is working * **@Mentions:** Tag users and reference incidents directly in the document * **Inline comments:** Discuss specific sections without leaving the editor * **Invite collaborators:** Share the retrospective via Slack or email * **Document status:** Visual Draft/Published indicators so teams know where things stand * **Activity sidebar:** See who recently viewed or edited the document * **Version history:** See how your document evolved based on edits made by your team Real-time collaboration uses conflict-free replicated data types (CRDTs) to merge changes automatically. No manual conflict resolution is required. *** ## Collaborative Editing When multiple users open the same retrospective, all changes sync automatically in real-time. ### What You'll Experience * **Instant updates** — Text typed by others appears immediately * **No conflicts** — Edits from all users merge automatically * **Shared state** — Everyone sees the same document at all times Even if two users edit the same paragraph simultaneously, changes merge correctly without overwriting each other's work. ### Presence Indicators Shows who's viewing or editing the retrospective with user avatars, colored indicators, and real-time updates. ### Collaborative Cursors See exactly where other users are working in the document with real-time feedback for typing, text selection and navigation. ## Inviting Collaborators You can invite team members to collaborate on the retrospective directly from the editor. ### Invite via Slack Post an invitation to the incident's Slack channel so team members can quickly jump into the editor. ### Invite via Email Send an email notification to the incident team with a link to the retrospective editor. ### Copy URL Copy the retrospective editor URL to share it directly via any channel. Invite options are available from the editor header. Slack invitations are only available when the incident has a linked Slack channel. *** ## Document Status Retrospectives have two states that are visible to all collaborators via a status chip in the editor header. ### Draft A yellow **Draft** chip indicates the retrospective is still being worked on. In this state, the document is only accessible to team members with edit access. ### Published A green **Published** chip indicates the retrospective has been finalized. Published retrospectives: * Display the publication timestamp (for example, "Last published at Mar 15, 2026 at 2:30pm UTC") * Can still be edited and re-published If the incident has not yet been resolved, publishing requires confirmation. This ensures retrospectives aren't accidentally published for ongoing incidents. *** ## Activity Sidebar The Activity sidebar shows who has recently viewed or edited the retrospective, giving you visibility into document engagement. To open the Activity sidebar, click **More actions → Show activity** in the editor header. *** ## Comments Add inline comments to discuss specific parts of the retrospective with your team. ### Creating a Comment Highlight the text you want to comment on. Click the **comment** button in the toolbar, or use the keyboard shortcut. Type your comment in the dialog that appears. Press Enter or click Submit to create the comment thread. ### Viewing Comments Comments appear in three ways: * **Node indicators:** Comments appear inline, attached to the relevant node in the editor. * **Highlighted text:** Commented text is highlighted in the document. On narrower screens, click the highlight to view the comment. * **Comments side panel:** View all open and resolved comment threads via the comments panel triggered from the actions dropdown in the header. Access resolved threads anytime by clicking **More actions → Show resolved comments** in the editor header. ### Comment Actions | Action | Description | | ------------- | ----------------------------------------------------------------------------- | | **Reply** | Add a response to an existing thread | | **Resolve** | Mark the comment as addressed (hides from active view) | | **Unresolve** | Mark the comment as unaddressed (visible in the All Comments side panel view) | | **Delete** | Remove the comment entirely | | **Edit** | Modify your own comment text | ### Comments Panel On wider screens, comments display in a dedicated panel alongside the editor. * **All threads:** See all active comment threads in one place * **Click to navigate:** Click a thread to jump to that location in the document * **Reply inline:** Respond to comments directly in the panel * **Filter options:** View open/resolved comments #### What Happens When Someone Comments * The comment appears immediately for all users viewing the document * The comments panel updates with the new thread * The commented text becomes highlighted #### What Happens When Someone Replies * The reply appears in the thread for all users * Users viewing the thread see the new reply instantly Comments are stored with the document and persist across sessions. Team members who open the document later will see all existing comments. *** ### Collaboration Best Practices #### For Effective Teamwork * **Communicate your focus area:** If working with others simultaneously, let them know which section you're editing to avoid stepping on each other's work. * **Use comments for async feedback:** Comments are ideal for review cycles where not everyone is online at the same time. * **Resolve comments when addressed:** Keep the comments panel clean by resolving threads once feedback is incorporated. * **Check presence before major edits:** Glance at who's online before restructuring or deleting large sections. #### For Comments * **Be specific:** Select the exact text you're commenting on rather than commenting on a general area. * **Use threads for discussions:** Reply to existing comments rather than creating new threads for the same topic. * **Resolve, don't delete:** Resolving preserves the history of feedback; deleting removes it permanently. * **Tag specific questions:** Make it clear if you need a response by phrasing comments as questions. *** ## Visibility and Permissions ### User Permissions * All users with **edit access** to the incident can collaborate on its retrospective * Users with **view-only access** can read but not edit or comment * **Private incidents** restrict access to assigned users ### Comment Visibility * Comments are visible to all users who can access the retrospective * There are no private comments. All threads are shared Collaboration access is determined by incident permissions. Check with your administrator if you need access to a specific incident's retrospective. ### Troubleshooting There may be a brief delay (a few seconds) before a user's presence indicator disappears after they close the document. This is normal behavior. Yes. The editor supports @mentions in the document body — type `@` to mention users or incidents. Hovering over a mention shows a popover with details like name, avatar, teams, and incident roles. @mentions in comment threads are not currently supported. Users can only edit or delete their own comments. To remove someone else's comment, ask them to delete it or contact an administrator. *** ## Related Pages The umbrella page covering how the editor works end-to-end. The features co-authors use while collaborating in the document. Once collaboration is done, publish the retrospective to an external doc. # Using the Retrospective Editor Source: https://docs.rootly.com/collaborative-retrospectives/using-the-editor Use the collaborative retrospective editor's formatting tools, slash commands, data blocks, and templates for post-incident reviews. ## How the Editor Works The new retrospective editor provides a rich text editing experience with real-time collaboration, dynamic data blocks, and template support. This page covers everything you need to know to create and edit retrospectives effectively. The editor is designed to be intuitive. You can type naturally, use slash commands for quick actions, and let autosave handle the rest. ## Getting Started with the Editor ### Where to Find the Editor Navigate to the incident from the incidents list or a direct link. Click the **Retrospective** tab on the incident page. Click anywhere in the document preview to open the editor. The editor opens with your team's default template pre-appended to the document. Start typing or use slash commands to add content. Retrospective documents automatically populate with your team's default template. You can configure this template in **Retrospectives → Document Templates**. ### Quick Start * Type naturally to add text * Press **Enter** to create new nodes in the document * Type `/` to open the slash command menu * Select text and use the toolbar for formatting * Drag and reposition nodes of content in your document * All changes save automatically *** ## Rich Text Formatting The editor supports standard rich text formatting through the toolbar, keyboard shortcuts, and slash commands. ### Text Formatting | Format | Keyboard Shortcut | | :---------------- | :--------------------- | | **Bold** | `Cmd/Ctrl + B` | | *Italic* | `Cmd/Ctrl + I` | | ~~Strikethrough~~ | `Cmd/Ctrl + Shift + X` | | `Inline Code` | `Cmd/Ctrl + E` | ### Headings | Level | Keyboard Shortcut | **Slash Command** | Description | | :-------- | :---------------- | :---------------- | :-------------------- | | Heading 1 | `#` | `/h1` | Main section headers | | Heading 2 | `##` | `/h2` | Subsection headers | | Heading 3 | `###` | `/h3` | Minor section headers | ### Lists | Type | Keyboard Shortcut | Description | | :------------ | :---------------- | :-------------------------------- | | Bullet List | `-` | Unordered list with bullet points | | Numbered List | `1.` | Ordered list with numbers | ### Other Blocks | Block | Slash Command | Description | | :--------- | :------------ | :--------------------------------------- | | Blockquote | `/blockquote` | Indented quote block for callouts | | Code Block | `/codeblock` | Multi-line code with syntax highlighting | | Table | `/table` | Insert a 3x3 table (expandable) | | Image | `/image` | Upload and insert an image | ## Slash Commands Slash commands provide quick access to all editor features. Type `/` anywhere in the editor to open the command menu. ### AI Blocks AI blocks are sections Rootly drafts for you from the incident's data, Slack channel, and bridge-call transcripts. Type `/` and choose a block (or `/ai`) to insert one; it generates in place and stays fully editable. | Block | What it drafts | | -------------------- | ------------------------------------------------------------------------ | | **Summary** | A concise overview of what happened, the impact, and how it was resolved | | **Impact** | Who and what was affected — customers, services, scope, and duration | | **Root Cause** | The underlying cause and contributing factors | | **Mitigation** | The immediate steps taken to reduce or stop the impact | | **Resolution** | How the incident was fully resolved | | **Curated Timeline** | A readable, narrative timeline of the key moments | | **Custom** | Any section you define with your own title and prompt | See [AI in Retrospectives](/ai/ai-in-retrospectives/using-ai-blocks) for the full guide. ### Incident Data Blocks With incident data blocks, you can insert dynamic content that pulls data from the incident. | Command | Description | | ------------------- | -------------------------------------------------------------------------------------------------- | | `/timeline` | Insert the incident timeline block | | `/followups` | Insert the follow-ups (action items) block | | `/liquid-variables` | Insert a single liquid variable into the document | | `/liquid-block` | Insert a code block that renders outputs from more complex liquid syntax or conditional variables. | #### Basic Blocks Basic blocks insert standard document elements. | Command | Description | | -------------- | -------------------- | | `/text` | Insert a paragraph | | `/h1` | Insert Heading 1 | | `/h2` | Insert Heading 2 | | `/h3` | Insert Heading 3 | | `/bulletList` | Insert bullet list | | `/orderedList` | Insert numbered list | | `/blockquote` | Insert blockquote | | `/code` | Toggle inline code | | `/codeBlock` | Insert code block | | `/table` | Insert 3x3 table | | `/bold` | Toggle bold | | `/italic` | Toggle italic | | `/strike` | Toggle strikethrough | The slash command menu filters as you type. For example, typing /time will show the timeline command at the top. *** ## Incident Data Blocks Incident Data Blocks are dynamic elements that pull live data from the incident. They update automatically when the underlying data changes. ### Timeline Block The Timeline block displays all events from the incident timeline, including user actions, system events, and status changes. #### **To insert a Timeline block:** 1. Type `/timeline` in the editor 2. Press **Enter** or click the command #### **Timeline block features:** * Shows event date/time, source, user, and description * Pagination controls help keep the document compact * Drag the block to reposition it in the document * Click the node to select the entire block, then use backspace to delete The Timeline block pulls live data from the incident. If new events are added to the timeline, the block updates automatically. ### Follow-ups Block The Follow-ups block displays action items associated with the incident. #### **To insert a Follow-ups block:** 1. Type `/followups` in the editor 2. Press **Enter** or click the command #### **Follow-ups block features:** * Shows action item title, priority, status, assignee, and due date * Sort options: **Due Date**, **Priority**, or **Status** * Drag the block to reposition it in the document * Click the node to select the entire block, then use backspace to delete When follow-ups are added or updated on the incident, the block reflects those changes automatically. ### Working with AI blocks Like data blocks, AI blocks live in the document and stay editable — see the [AI Blocks](#ai-blocks) table above for the full list of block types. #### **To insert an AI block:** 1. Type `/ai` in the editor (or pick a block from the slash menu) 2. The block is inserted and starts generating in place #### **AI block features:** * Content streams in live as it generates * Open the block's details to see its sources and the prompt behind it * Edit the generated text inline, regenerate it, or convert it to plain text * Rate the output with 👍 / 👎 AI blocks can also be built into your team's templates so every retrospective generates them automatically. See [AI in Retrospectives](/ai/ai-in-retrospectives/using-ai-blocks) for the full guide. ## How Data Blocks Render on Export When you publish or export the retrospective to an external provider, data blocks are rendered as static content at the time of export. This includes: * Timeline events formatted as a table * Follow-ups formatted as a list with metadata * Liquid variables or blocks resolved to their actual values * AI block content rendered as static text (the generated draft is frozen at export time) *** ## Using Templates Templates provide pre-built content structures that ensure consistency across retrospectives. ### Inserting a Template Type `/` in the editor. Click **Template** from the dropdown. Browse your team's available templates and click to insert. The template content is inserted at your cursor position. Edit as needed. ### What Templates Can Include * Headings and sections (Summary, Root Cause, Timeline, etc.) * Placeholder text to guide authors * Liquid variables (for example, `{{ incident.title }}`) * Data blocks (`/timeline`, `/followups`) * Formatting and structure Templates are configured by administrators in **Retrospectives → Document Templates**. Contact your admin to create or modify templates. *** ## Liquid Variables Liquid variables are dynamic placeholders that resolve to actual values from the incident. ### Inserting Liquid Variables 1. Type `{{` to start a liquid variable 2. Continue typing to filter available variables 3. Select from the autocomplete dropdown 4. The variable appears as a chip in the editor #### Common Variables | Variable | Description | | ------------------------------- | ------------------------- | | `{{ incident.title }}` | Incident title | | `{{ incident.severity }}` | Severity level | | `{{ incident.status }}` | Current status | | `{{ incident.started_at }}` | Start timestamp | | `{{ incident.resolved_at }}` | Resolution timestamp | | `{{ incident.duration }}` | Total incident duration | | `{{ incident.commander.name }}` | Incident commander's name | | `{{ incident.slack_channel }}` | Slack channel name | | `{{ post_mortem.title }}` | Retrospective title | Liquid variables display as visual chips in the editor. On publish or export, they resolve to their actual values. ## Liquid Blocks Liquid Blocks are standalone template blocks that support the full Liquid templating language, including conditionals, loops, and complex logic. ### Liquid Block vs Liquid Variable | Feature | Liquid Variable | Liquid Block | | ------------- | ------------------------ | --------------------------------------------- | | **Scope** | Inline (within text) | Block-level (standalone) | | **Syntax** | `{{ variable }}` only | Full Liquid: `{% if %}`, `{% for %}`, filters | | **Rendering** | Inline chip | Edit/Preview panel with live rendering | | **Best for** | Inserting dynamic values | Conditional content, loops, complex logic | Use **Liquid Variables** for simple value substitution inline within your text. Use **Liquid Blocks** when you need conditionals, loops, or multi-line template logic. ### Inserting a Liquid Block 1. Type `/liquid` to open the slash command menu 2. Select **Liquid Block** from the options 3. Write your Liquid template in the editor panel 4. Click **Preview** to see the rendered output with real incident data 5. Toggle back to **Edit** to make changes #### Example Use Cases **Conditional severity messaging:** ```liquid theme={null} {% if incident.severity == "critical" %} 🚨 CRITICAL INCIDENT - Immediate escalation required {% elsif incident.severity == "high" %} ⚠️ High priority incident - Review within 1 hour {% else %} 📋 Standard incident - Follow normal procedures {% endif %} ``` **Loop through action items:** ```liquid theme={null} {% for item in incident.action_items %} - [{{ item.status }}] {{ item.summary }} (Owner: {{ item.owner.name }}) {% endfor %} ``` **Conditional content with filters:** ```liquid theme={null} {% if incident.resolved_at %} Resolved on {{ incident.resolved_at | date: "%B %d, %Y at %I:%M %p" }} Duration: {{ incident.duration }} {% else %} ⏳ Incident is still ongoing {% endif %} ``` Click **Preview** at any time to see how your template renders with actual incident data. Syntax errors will be displayed with helpful error messages. ### When to Use Each Use Liquid Variables when: * Inserting a single dynamic value into a sentence * You need a simple inline placeholder * Example: "The incident commander is `{{ incident.commander.name }}`" Use Liquid Blocks when: * You need conditional logic (`{% if %}...{% endif %}`) * You need to loop over collections (`{% for %}...{% endfor %}`) * You have multi-line template content * You need complex formatting with multiple variables * Example: Showing different content based on incident severity ## @Mentions Mention users and incidents directly in the document to create clear accountability and cross-references. ### Mentioning Users 1. Type `@` anywhere in the editor 2. Search for a user by name 3. Select the user from the dropdown 4. The mention appears as an interactive chip in the document Hovering over a user mention shows a popover with their avatar, name, email, teams, and incident roles. ### Mentioning Incidents You can also `@`-mention other incidents to cross-reference related events in your retrospective. @mentions in the document body are interactive — readers can hover to see details without leaving the editor. *** ## Collaboration Multiple users can edit the retrospective simultaneously. For full details on collaboration features, see [Real-Time Collaboration](/collaborative-retrospectives/real-time-collaboration). ### What You'll See * **Presence indicators:** Avatars/initials of users currently viewing the document * **Collaborative cursors:** Colored cursors showing where each user is working * **Real-time updates:** Changes from other users appear instantly * **@mentions:** Tag users and incidents inline with interactive popovers ### Comments Select text and click the **comment** button to start a discussion: 1. Select the text you want to comment on 2. Click the **comment** button in the toolbar 3. Type your comment and submit 4. Others can reply, creating a threaded conversation 5. Mark comments as **resolved** when addressed Comments are visible to all collaborators and sync in real-time. Use them for async review and feedback. *** ### Best Practices * **Use slash commands for speed:** Typing `/` is faster than reaching for the toolbar, especially for common actions. * **Insert data blocks instead of copying:** Timeline and Follow-ups blocks stay in sync with the incident. Manual copy-paste becomes stale. * **Use templates for consistency:** Starting from a template ensures all retrospectives follow the same structure. * **Add comments for review feedback:** Instead of sending feedback in Slack, add comments directly in the document for better context. * **Use headings to structure content:** Clear section headers (Summary, Timeline, Root Cause, Action Items) make retrospectives easier to scan. *** ### Troubleshooting Make sure your cursor is in an editable area of the document, not inside a data block or at an invalid position. Try clicking in a paragraph and typing `/` again. This usually means the block couldn't fetch data from the incident. Check your network connection and refresh the page. If the problem persists, the incident may not have any data for that block type (for example, no timeline events or follow-ups). Ensure you have permission to access retrospective templates. If templates aren't appearing, contact your administrator to verify templates are configured for your team. Use `Cmd/Ctrl + Z` to undo recent changes. You can also access version history to restore a previous version of the retrospective. # Communications Source: https://docs.rootly.com/communications/overview Send targeted incident updates to the stakeholders who need them, by email, SMS, or Slack, from templates your team prepared in advance. The **Communications module** sends incident updates directly to the people who need them — by email, SMS, or Slack — rather than broadcasting to everyone. Responders pick a prepared template, the incident's details fill themselves in, and the message reaches only the stakeholder groups whose conditions the incident matches. It is the targeted counterpart to a [status page](/configuration/status-pages). A status page tells anyone who looks; Communications tells a specific audience, and can require review before anything goes out. Communications is enabled per organization. If the **Communications** tab does not appear on your incidents, contact your account team. *** ## Where to Start The responder flow: pick a template and stage, edit it, send it for review, and send it. Define who hears about what, and the conditions that decide when they do. Prepare the messages in advance, one per stage of an incident. The addresses and numbers your messages come from, and getting them allowlisted. *** ## The Moving Parts Four pieces fit together. Set them up in this order — each depends on the one before it: A category of communication, such as customer updates or internal leadership updates. Everything else hangs off a type: groups belong to one, and so do templates. The phases of an incident you communicate at — for example initial, investigating, resolved. Stages are shared across the organization. The prepared message for a type, with separate content per stage and per channel. Liquid variables pull in the incident's own details. Who receives a type of communication, and under what conditions — a severity, a service, a functionality, a team, or an incident type. With those in place, sending during an incident is a matter of choosing a template and a stage, checking the text, and sending. *** ## What a Responder Does During an incident, the **Communications** tab lists everything already sent, with its delivery status, and lets you create the next update. The same flow is available in Slack with `/rootly comms new`. Rootly suggests the template that fits the incident, and the recipients are worked out from the groups whose conditions the incident matches — so a responder is choosing what to say, not who to say it to. The decision about *who* hears about an incident belongs in your group conditions, made calmly in advance. Leaving it to the person writing an update at 3am is how the wrong stakeholders get paged, or the right ones get missed. *** ## Review Before Sending Any draft can be shared to a Slack channel for review before it goes out. The request is clearly marked as needing review, so approval happens where your team already works rather than in a separate tool. A sent communication cannot be recalled. For anything customer-facing, or anything a regulator or executive will read, route it through review — and remember that SMS in particular has no correction path once delivered. *** ## Best Practices * **Decide your audiences before your messages.** Groups and their conditions are the hard part; templates are easy once you know who is listening. * **Write one template per type, not per incident.** Stages handle the difference between "we're investigating" and "it's resolved". * **Use Liquid for anything factual.** Severity, title, summary, and timestamps should come from the incident record rather than being retyped under pressure. * **Make review the default for external audiences.** Internal updates can go direct; customer-facing ones benefit from a second reader. * **Allowlist Rootly's sending addresses and numbers early.** Discovering a spam filter mid-incident is an avoidable failure — see [Communication Sources](/communications/sources). * **Revisit conditions after reorganizations.** Groups scoped to services or teams drift when ownership changes. *** ## Related Resources Broadcast status publicly, for anyone who looks. Post incident updates to a status page. Every incident value a template can pull in. Automate notifications that do not need a human author. *** ## Frequently Asked Questions Reach and intent. A status page is public and passive — anyone can look, nobody is notified. Communications is targeted and active: it pushes a message by email, SMS, or Slack to defined groups. Most teams use both, with the status page as the public record and Communications for the audiences who need telling directly. A [workflow](/workflows/workflows) fires automatically with no author, which suits mechanical notifications. A communication is written or approved by a person, so it suits messages where the wording matters and someone should be accountable for it. Yes. Groups can contain external members, which is the point — customers, executives, and support leads generally are not Rootly users. Yes. Types, stages, templates, and groups all have Terraform resources. See [Terraform](/integrations/terraform). # Recipient Groups Source: https://docs.rootly.com/communications/recipient-groups Define who receives each type of incident communication, and the conditions that decide which incidents reach them. A **recipient group** is a list of people who should hear about a particular kind of incident, plus the conditions that decide which incidents qualify. Groups are what make communications targeted: a responder chooses the message, and the groups decide the audience. Getting groups right is the substantive work in setting up Communications. Templates are easy once you know who is listening. *** ## What a Group Holds What this audience is, in the terms your organization uses. "Enterprise customer success" beats "Group 2" when someone is checking who a message reached. Every group belongs to one [type](/communications/templates-and-stages#types). This is what connects an audience to the messages it can receive — a group under "Customer updates" only ever receives customer-update communications. Rootly users and external people. External members are the point of the feature: customers, executives, and support leads generally do not have Rootly accounts. A group holds up to 50 participants. How this group is reached. Match the channel to the audience rather than the message — executives may want SMS for severity 0 and email for everything else, which is two groups, not one. A **private** group is managed by admins: membership is deliberate. A **public** group can be subscribed to, so stakeholders opt themselves in. Public groups suit broad internal audiences; private groups suit anything external or sensitive. The 50-participant limit is per group, not per communication. A message reaching several matching groups reaches all of their members. Split large audiences by what they care about — which usually produces better-targeted conditions anyway. *** ## Conditions Conditions decide which incidents reach a group. Without them, a group would hear about everything. A condition matches an incident property against values you choose: | Property | Use it to reach people who care about… | | ----------------- | ------------------------------------------------------------------------------------------------------- | | **Severity** | Only serious incidents — the usual first condition for executive or customer audiences. | | **Service** | A specific system, for the team or customers who depend on it. | | **Functionality** | A user-facing capability, which often maps better to what customers recognize than a service name does. | | **Team** | Incidents owned by a particular team. | | **Incident type** | A class of incident, such as security. | ### All or Any A group matches on **all** of its conditions or **any** of them, and the difference is large: * **All** — every condition must match. `Severity is SEV0` *and* `Service is Payments` reaches this group only for severity-0 payments incidents. Narrow and predictable. * **Any** — one match is enough. The same two conditions now reach the group for *every* SEV0 anywhere, *and* every payments incident at any severity. Much broader than it looks when writing it. Setting a group to **any** with several conditions is the most common way stakeholders end up over-notified. Start with **all**, confirm the group is being reached when it should be, and widen only if it is missing incidents it should hear about. *** ## Public Groups and Self-Subscription A public group can be subscribed to rather than administered. This works well when the audience is large, internal, and self-selecting — the people who want to know about payments incidents usually know who they are. Keep external and sensitive audiences private. Anything a customer receives should have deliberate membership. Public groups reduce the maintenance burden that kills communication setups. A private group nobody updates after a reorganization quietly sends to the wrong people; a public one lets its members fix that themselves. *** ## Designing a Group Structure Groups multiply quickly. A structure that stays manageable usually follows the audience, not the org chart: 1. **Start from the question "who needs to know?"** for two or three realistic incidents. That produces your first groups. 2. **Separate by channel only when the channel genuinely differs.** An audience that wants SMS for severity 0 and email otherwise is two groups with different conditions. 3. **Prefer functionality over service for customer-facing groups.** Customers recognize "Checkout" more readily than the services behind it. 4. **Keep executive groups narrow.** A severity condition alone is usually right; adding services tends to produce gaps. 5. **Review after reorganizations.** Conditions referencing services or teams drift when ownership moves. *** ## Troubleshooting Check the incident against the group's conditions rather than the message. The usual causes: the incident's severity is below the threshold, the affected service or functionality is not attached to the incident, or the group's conditions are set to **all** and only some matched. Conditions are probably set to **any**. Switch to **all** and add the narrowing condition that was missing, most often severity. A group holds up to 50 participants. Split it along the lines its conditions already suggest — by service or functionality — rather than raising the count. Groups belong to a communication type, and a type in use cannot be removed while groups or templates depend on it. Detach or remove those first. The group is private. Only public groups accept self-subscription. *** ## Related Resources The messages these groups receive. How groups are resolved when an update goes out. # Sending a Communication Source: https://docs.rootly.com/communications/sending-communications Create an incident update from a template, edit it with live incident detail, send it for review, and deliver it to the right stakeholders. During an incident, the **Communications** tab is where updates to stakeholders are written, reviewed, and sent. Everything already sent is listed there with its delivery status, so a responder joining late can see what has gone out before adding to it. The same flow is available in Slack with `/rootly comms new`, which matters when the incident is being run in a channel rather than in the web interface. *** ## Reviewing What Has Already Gone Out Before writing anything, check the record. The **Completed** list shows each communication that has been sent, and opening one shows: * Where it originated * Which recipient groups received it, including any Slack channels * Its delivery state — sent, partially sent, or still sending * Any drafts associated with it Read the last update before writing the next one. Stakeholder trust is lost faster by contradicting a previous message than by saying nothing, and the previous message is rarely the one you remember sending. *** ## Creating an Update Select **Create New** in the incident's Communications tab, or run `/rootly comms new` in Slack. Rootly suggests the template that fits the incident. Every available template is in the dropdown if the suggestion is not the right one. Stages represent where the incident has reached — an initial notification reads differently from a resolution notice. Selecting a stage loads that stage's prepared content. See [Templates and Stages](/communications/templates-and-stages). This opens the editor with the template rendered against the live incident. *** ## The Editor The editor shows the message alongside the facts about it. **On the left**, the details of the communication itself: its status, the type and template it came from, the stage, who created it, the addresses and numbers it will send from, and the recipient groups it will reach. **On the right**, the message. Template content arrives already filled in — Liquid variables have pulled the incident's title, summary, severity, and timestamps out of the record rather than asking you to retype them. Each channel is edited separately, so the email body, the SMS text, and the Slack message can each say what suits that medium. Editing here changes this message only; the template is untouched. SMS is capped near 160 characters, so the SMS version of an update is not a shortened email — it is a different message. Write it as a pointer: what is wrong, who is affected, and where to read more. *** ## Sending, Saving, or Requesting Review Three actions, and choosing between them is mostly about audience: Deliver now, to every group whose conditions the incident matches. Requires permission to send. There is no recall. Keep the message without sending. Useful when you have written an update ahead of a decision that has not been made yet, or when handing the incident to the next responder. Send the draft to a Slack channel or specific people for review. The request is clearly marked as needing review, so approvers see it as a task rather than another notification. *** ## Getting a Communication Reviewed Review exists because the cost of a wrong external message is much higher than the cost of a delayed one. Choose the channel or people who should read it. They see the message as recipients will. Discussion happens in Slack, next to the incident, rather than in a separate approval tool. Apply any changes in the editor, then send. The draft and the sent message both stay on the record. Review is worth its delay for anything customer-facing, anything a regulator or executive will read, and any message stating a cause or a restoration time. Internal "we are on it" updates rarely need it. *** ## Delivery Once sent, a communication moves through delivery rather than completing instantly. The Communications tab shows whether it is still sending, fully sent, or only partially delivered. Partial delivery usually means individual recipients failed rather than the message failing — a bounced address, an unreachable number. Check the affected recipients rather than resending to everyone, which would deliver the message twice to people who already have it. *** ## Troubleshooting Recipients come from group conditions, not from the message. If no group's conditions match this incident, there is nobody to send to. Check the incident's severity, service, functionality, team, and type against your [group conditions](/communications/recipient-groups#conditions). A group's conditions are broader than intended. Conditions can require all criteria to match or any of them — a group set to "any" reaches far more incidents than one set to "all". Almost always filtering rather than delivery. Confirm Rootly's sending addresses are allowlisted — see [Communication Sources](/communications/sources) — and check whether the recipient's provider quarantined it. A Liquid variable that does not resolve renders empty. Usually the field is genuinely blank on the incident — a summary that was never written, for instance. Fill it on the incident and recreate the communication. Sending is permission-gated. Save the draft and share it for preview so someone with permission can send it. *** ## Related Resources Why a given incident reaches a given audience. Prepare the messages this flow draws on. # Communication Sources Source: https://docs.rootly.com/communications/sources Configure the email addresses and phone numbers your incident communications send from, and get them allowlisted before you need them. A **communication source** is the address or number a message arrives from. Email communications send from addresses you configure; SMS communications send from numbers Rootly provides. This is the least interesting part of the module and the most common reason a communication fails. A message that is written, reviewed, and sent still fails if the recipient's mail provider quarantines it. Allowlist Rootly's sending addresses and numbers as part of setup, not after the first missed update. Filtering is silent — Rootly reports the message as sent, because it was; it simply never reached the inbox. *** ## Email Sources Email sources are the **from** addresses your communications use. Which address a message arrives from shapes whether it is trusted, read, and replied to correctly. What recipients see as the sender. One source is selected as the default for outgoing communications. Choosing an address is mostly about the audience: * **Customer-facing communications** should come from an address customers recognize and could plausibly reply to. An unfamiliar domain mid-incident invites suspicion at exactly the wrong moment. * **Internal communications** can use a more operational address, since colleagues will recognize it. Use an address that is monitored, or one that makes clear it is not. Recipients reply to incident updates — with questions, with impact reports, sometimes with information you need. Replies into an unwatched mailbox are lost signal. *** ## SMS Sources Rootly provides the phone numbers SMS communications send from. They are listed in the Communications configuration so your team can distribute and allowlist them. SMS is the highest-attention channel and the least forgiving: * **It cannot be recalled or corrected.** An email can be followed by a correction that lands in the same thread; an SMS correction is a second alarm. * **It arrives out of context.** No subject, no thread — just text on a lock screen, often at night. * **It is length-limited.** Around 160 characters per segment, so it is a pointer rather than a summary. Reserve SMS for audiences and severities where waking someone is proportionate. An executive group scoped to severity 0 is a good use; a service-team group scoped to any severity will produce fatigue and get muted — after which it carries no signal at all. *** ## Getting Rootly Allowlisted Do this once, ahead of time, with whoever runs your mail and mobile device management: Both are listed in the Communications configuration area. Ask for them to bypass spam filtering and quarantine for internal recipients. An unknown number sending an urgent message is exactly what people are trained to ignore. Telling stakeholders in advance which numbers are Rootly's makes the difference. Use a low-severity or test incident and confirm the message arrives in the inbox rather than the spam folder, and that the SMS reaches a real handset. Test with a recipient outside your own team. Internal mail between colleagues is filtered far more leniently than mail to a customer's provider, so a successful internal test proves less than it appears to. *** ## Troubleshooting Delivery and receipt are different things. If Rootly reports the message sent, it left successfully — so the problem is downstream. Check the recipient's spam or quarantine folder, confirm the sending address is allowlisted, and ask their mail administrator whether it was filtered. External providers apply stricter filtering than your own. Sending from a domain the recipient recognizes helps most; consult whoever manages your email authentication about the sending domain's reputation. Confirm the recipient's number is correct and reachable internationally if they are outside your usual region, and check whether their carrier or device is blocking unknown numbers. Sharing Rootly's numbers with recipients in advance prevents most of this. Replies go to the from address. If it is unmonitored, either monitor it or choose a source address that routes somewhere a human reads. Some recipients failed while others succeeded — usually a bad address or unreachable number rather than a problem with the message. Investigate the affected recipients rather than resending to the whole group, which would deliver twice to everyone who already received it. *** ## Related Resources Who receives communications, and on which channel. The flow these sources deliver. # Templates and Stages Source: https://docs.rootly.com/communications/templates-and-stages Prepare incident messages in advance: define communication types, map your incident lifecycle to stages, and write templates that fill themselves in. Templates are the messages your team writes calmly in advance so nobody is drafting customer-facing prose during an incident. Each template belongs to a **type**, carries separate content for each **stage** of an incident, and uses Liquid variables so the incident's own details fill themselves in. Set these up in order: types, then stages, then templates. *** ## Types A **communication type** is a category of message with a distinct audience and purpose — customer updates, internal leadership updates, support-team briefings. Types are the organizing principle for the whole module. Both [recipient groups](/communications/recipient-groups) and templates belong to a type, which is what connects an audience to the messages it can receive. What this category of communication is. Name it for the audience and purpose together — "Customer status updates" rather than "External". A visual marker so responders can tell types apart at a glance when choosing a template mid-incident. A type that has groups or templates attached cannot be deleted. Detach or remove them first — which is deliberate, since deleting a type in use would orphan both an audience and the messages meant for it. Resist creating a type per team. Types multiply the templates you must maintain, because each type needs its own template with content for every stage. Most organizations need three or four. *** ## Stages A **stage** is a phase of an incident that you communicate at. Stages are defined once for the organization and shared across every type, so "Resolved" means the same thing everywhere. Typical stages map to how an incident actually unfolds: | Stage | What the message does | | ----------------- | ---------------------------------------------------------------------------------------------------------- | | **Initial** | Acknowledges the problem and says what is known. Deliberately short — it exists to be first, not complete. | | **Investigating** | Confirms work is ongoing, states impact more precisely, and sets the next update time. | | **Monitoring** | A fix is in place and being watched. Signals near-resolution without declaring it. | | **Resolved** | Service is restored, with a brief statement of what happened. | | **Follow-up** | Post-incident detail, such as a link to the published retrospective. | Stages are your own — name them to match how your organization already talks about incidents rather than adopting a standard set that nobody recognizes. Setting the next update time in every stage before Resolved is what keeps stakeholders from chasing you. A message that says nothing except "still working, next update at 15:00" is a good message. *** ## Templates A **template** holds the prepared content for one type, with separate text for each stage and each channel. The type determines which audiences can receive it. Within the template, each stage gets its own message. A template without content for a stage cannot be used at that stage. Email subject and body, SMS text, and Slack message are authored independently, because they are read very differently. Title, summary, severity, affected services, and timestamps should come from the incident record. ### Writing for Each Channel The same update needs three different shapes: * **Email** carries the full message — context, impact, what is being done, when the next update comes. Subject lines can be long, but the useful part belongs at the front, since that is all a phone preview shows. * **SMS** is capped near 160 characters. Treat it as a pointer, not a summary: what is wrong, who is affected, where to read more. Longer messages split into multiple segments. * **Slack** sits between the two, and can carry links comfortably. Email subject, header, and footer have generous limits — thousands of characters — so the practical constraint is what a reader will tolerate, not what the field accepts. SMS is the one channel where the limit genuinely bites. *** ## Liquid Variables Liquid is what makes a prepared template specific to the incident it is sent from. Instead of typing the severity into the message, the template references it and Rootly fills it in at send time. Use variables for anything that exists on the incident record — title, summary, severity, status, affected services and functionalities, timestamps, and links. [Incident variables](/liquid/incident-variables) lists everything available. A variable referencing a field the incident has not filled renders empty, which produces a message with a gap where the summary should be. For customer-facing templates, keep the sentence readable if a variable resolves to nothing, and make sure the incident fields your templates depend on are ones your process actually populates. Preview a template against a real past incident before relying on it. Reading it filled in is the only way to catch a variable that resolves to something technically correct and completely unhelpful — an internal service slug in a customer email, for instance. *** ## Keeping Templates Usable * **Fewer, better templates.** One well-written template per type covering every stage beats a dozen situational ones nobody can choose between under pressure. * **Write for the reader, not the responder.** Customer-facing templates should avoid internal service names, severity numbers, and team names. * **Say what is being done, not how.** "We have identified the cause and are deploying a fix" ages better than implementation detail that may turn out wrong. * **Review templates after real incidents.** The retrospective is the moment to notice a template that read badly, while the discomfort is fresh. * **Manage them as code if your configuration is stable.** Types, stages, and templates all have [Terraform](/integrations/terraform) resources. *** ## Troubleshooting The template has no content for that stage. Add content for it, or pick a stage the template covers. The variable name does not match an available one, or the syntax is malformed. Check it against [incident variables](/liquid/incident-variables). A variable resolved to nothing because that field is empty on the incident — most often the summary. Fill it on the incident, then recreate the communication. Groups or templates still reference it. Remove or reassign those first. It exceeded a single segment. Rewrite the SMS content as a pointer with a link rather than a condensed version of the email. *** ## Related Resources The audiences a type's templates reach. Every incident value a template can reference. # What Is an Incident Commander? Source: https://docs.rootly.com/concepts/incident-commander An incident commander leads the response to an incident—coordinating people, decisions, and communication. Learn the role, skills, and how to assign one. An **incident commander** is the person who leads the response to an incident. They coordinate responders, drive decisions, and keep the response organized so that everyone else can focus on investigating and fixing the problem. The incident commander does not need to be the most senior engineer in the room—their job is to run the response, not to personally resolve the issue. The role originated in emergency services (the Incident Command System used by firefighters and disaster responders) and was adopted by software teams because it solves the same problem: when something is on fire, someone needs to be clearly in charge. ## What does an incident commander do? During an incident, the commander owns the *process* of the response. While a technical lead digs into logs and a communications lead drafts status updates, the incident commander maintains the big picture: What do we know? What are we trying next? Who is doing what? When do we update stakeholders? Without a commander, incidents tend to drift. Multiple people investigate the same theory, no one updates the status page, and decisions stall because nobody feels authorized to make them. A commander removes that ambiguity—every question about the response has a clear owner. ## Incident commander responsibilities The exact scope varies by organization, but incident commanders typically: * **Declare and scope the incident** — confirm severity, impact, and which services are affected. * **Assemble the response team** — pull in the right responders and assign roles like technical lead, communications lead, and scribe. * **Drive decisions** — choose between mitigation options, approve risky actions like rollbacks or failovers, and break ties when responders disagree. * **Manage communication cadence** — make sure stakeholders, support teams, and customers get timely updates, even if someone else writes them. * **Track the state of the response** — keep a running picture of what has been tried, what is in progress, and what comes next. * **Manage responder workload** — rotate people out of long incidents and escalate when the team needs more help. * **Hand off cleanly** — brief the next commander during long-running incidents, and kick off the retrospective once the incident is resolved. ## What makes a good incident commander? Good incident commanders are calm under pressure, decisive with incomplete information, and comfortable delegating. Deep technical knowledge of the affected system helps but is not required—in fact, commanders who dive into debugging themselves usually stop commanding, which is the failure mode the role exists to prevent. Look for people who: * Communicate clearly and summarize well, especially in writing * Ask direct questions ("What do we know? What's blocking you?") rather than speculating * Make timeboxed decisions instead of waiting for perfect information * Stay blameless and keep the response focused on mitigation, not fault Many teams train a rotating pool of incident commanders rather than relying on one or two heroes. This spreads the load, avoids single points of failure, and builds incident skills across the organization. ## Incident commander vs. incident manager vs. on-call engineer These titles are often used loosely, but they describe different things: * **Incident commander** — leads a *specific incident* from declaration to resolution. It's a temporary, per-incident role, not a job title. * **Incident manager** — often a permanent job function focused on the incident *program*: process design, tooling, metrics, and post-incident follow-through. In some organizations "incident manager" is simply their name for the commander role. * **On-call engineer** — the person paged first when something breaks. They triage and often resolve small incidents alone. For larger incidents, they may become the incident commander, or they may declare the incident and hand command to someone else while they investigate as technical lead. The key distinction: on-call determines *who responds first*, while incident command determines *who runs the response*. They can be the same person, but for high-severity incidents it is usually better to separate them. ## How to assign incident commanders automatically Manually figuring out who should command an incident at 3 a.m. wastes the minutes that matter most. In Rootly, incident commander is a configurable [incident role](/incidents/incident-roles/incident-roles)—alongside roles like technical lead, communications lead, and scribe—with clear ownership visible in the incident sidebar, Slack summaries, and the incident timeline. You can fill the role automatically using [workflows](/workflows/workflows), Rootly's automation engine. A workflow can assign the incident commander based on severity, impacted services, incident type, or the current on-call schedule—so the moment a SEV1 is declared, command is already assigned and announced in the incident channel. Responders can also assign or reassign the role directly from Slack, and every change is tracked in the timeline for the retrospective. You can also just ask. Mention `@Rootly` in the incident channel and tell the [Rootly AI agent](/ai/rootly-in-slack/overview) to assign roles—"make me the incident commander" or "assign Priya as communications lead"—and it applies the change and announces it, without opening a form. To get started, see [Managing Incident Roles Through the Web Interface](/incidents/incident-roles/managing-incident-roles-through-the-web) or [Managing Incident Roles Through Slack](/incidents/incident-roles/managing-incident-roles-through-slack). # How to Run an Incident Retrospective Source: https://docs.rootly.com/concepts/incident-retrospective An incident retrospective is a blameless review of what happened, why, and what to change. Learn how to run one step by step and what to include. An **incident retrospective** is a structured review that a team runs after an incident to understand what happened, why it happened, and what to change so it happens less often—or hurts less when it does. The output is usually a written document plus a set of owned, dated action items. Done well, retrospectives turn incidents from pure cost into your most reliable source of learning. The single most important property of a good retrospective is that it is **blameless**. The goal is to understand how reasonable people, given what they knew at the time, made the decisions they made—not to find who to blame. Teams that punish honesty get incomplete timelines and repeat incidents. ## Retrospective vs. postmortem: is there a difference? In practice, the terms describe the same activity: a post-incident review. "Postmortem" is the older, more common term; "retrospective" has gained ground because it avoids the morbid framing and emphasizes learning over autopsy. Some teams draw a soft distinction—using *postmortem* for the written document and *retrospective* for the meeting and process around it—but there is no industry-standard difference. Pick one term, define it, and use it consistently. ## How to run an incident retrospective ### 1. Schedule it quickly Hold the retrospective within a few business days of resolution—ideally within a week. Memory decays fast, and the details that matter most (what people saw, what they believed, why they acted) are the first to go. Invite the responders who were actually involved, not just their managers. ### 2. Build the timeline Reconstruct what happened in order: when the issue started, when it was detected, key decisions, mitigation attempts, and resolution. Pull from your incident channel, monitoring alerts, deploy logs, and the incident timeline. A shared, factual timeline grounds the whole discussion—disagreements about "what happened" should be settled here, before anyone discusses "why." ### 3. Identify contributing factors Resist the urge to find *the* root cause. Real incidents almost always have several contributing factors: a latent bug, a gap in monitoring, an ambiguous runbook, a risky deploy window. Ask "what made this possible?" and "what made this worse?" for each phase—detection, diagnosis, and mitigation. Slow detection and slow mitigation are findings just as much as the triggering defect. ### 4. Write a blameless narrative Document the incident from the responders' point of view: what they knew, what they saw, and why their actions made sense at the time. Avoid counterfactuals ("they should have checked the dashboard") and name systems, not people, as points of failure. If the narrative reads like an indictment of a person, rewrite it. ### 5. Assign action items Turn findings into concrete follow-ups: fix the bug, add the missing alert, update the runbook, add a guardrail to the deploy pipeline. Every action item needs a single owner and a due date—a list of good intentions without owners is where retrospectives go to die. Prioritize ruthlessly; three completed action items beat fifteen abandoned ones. ### 6. Share the learnings Publish the retrospective where the whole engineering organization can read it, and announce it—in a team meeting, a newsletter, or a dedicated channel. Other teams likely share the same failure modes. An unread retrospective only teaches the people who were already there. ## What to include in the document A solid retrospective document covers: * **Summary** — a few sentences: what broke, the impact, and the fix * **Impact** — duration, affected services, customer-facing effects, and any SLA/SLO implications * **Timeline** — timestamped sequence from first signal to resolution, including detection and escalation times * **Contributing factors** — the conditions that made the incident possible and prolonged it * **What went well** — effective responses worth reinforcing (fast detection, a good runbook, a clean handoff) * **What could be improved** — gaps in tooling, process, or knowledge * **Action items** — each with an owner, a due date, and a priority ## Common mistakes * **Skipping retrospectives for "small" incidents.** Near-misses are cheap lessons. You don't need the full process for every blip, but a lightweight review beats none. * **Blame in disguise.** "Human error" as a root cause, or timelines written as accusations. If a person "caused" the incident, the system that let one mistake cause an outage is the real finding. * **Root-cause tunnel vision.** Stopping at the first plausible cause and missing the detection and response gaps around it. * **Action items with no follow-through.** Unowned, undated items quietly expire. Review open items regularly. * **Waiting weeks to run it.** Stale memories produce vague timelines and generic conclusions. * **Writing it and telling no one.** The document is a means; the learning is the point. ## Automating retrospectives in Rootly Most retrospective failures are process failures—steps forgotten, documents never started, action items never tracked. Rootly automates that scaffolding. [Retrospective processes](/retrospectives/retrospectives) let you define ordered steps (gather data, write the document, host the review, create action items, share the report) with due dates, assignees based on incident roles, and reminders. You can right-size the process by severity, team, or incident type, so a SEV1 gets a full review while a minor incident gets a lightweight one—see [Configuring Retrospective Processes](/retrospectives/configuring-retrospective-processes). [Retrospective workflows](/workflows/retrospective-workflows) trigger on retrospective lifecycle events—for example, when a retrospective is published, automatically create the doc in Confluence or Google Docs, notify leadership channels, and open follow-up tickets. And [action items](/incidents/action-items/action-items) give every follow-up an owner, a due date, and a status, with exports and dashboards so open items stay visible long after the incident channel goes quiet. The biggest time sink—writing the draft—is where [Rootly AI in retrospectives](/ai/ai-in-retrospectives/overview) does the heavy lifting. It drafts the retrospective from the incident's real data (timeline, Slack discussion, and bridge-call transcripts), suggests contributing factors and a summary, and fills AI blocks in your retrospective template, so the review starts from a complete first draft instead of a blank page. Reviewers still edit and own the narrative—the agent removes the busywork, not the judgment. # Audit Log for compliance and change tracking Source: https://docs.rootly.com/configuration/audit-log Track configuration changes, integration updates, and incident actions in Rootly with a filterable audit log and JSON:API export for compliance evidence. ## Overview Rootly's Audit Log captures every create, update, and delete action across your organization — configuration changes, integration updates, incident actions, workflow edits, role assignments, and more. Each entry records who made the change, what changed, when, from where (web, API, mobile, Slack, SCIM, OAuth), and the exact before-and-after values of the modified fields. Built on PaperTrail under the hood with \~60 resource types instrumented, the audit log is the compliance evidence layer SOC2 and ISO27001 auditors look for. It's also a real operational tool — answer "who deleted this severity?" or "when did the escalation policy change?" without paging anyone. Every create, update, and delete across configuration, integrations, incidents, workflows, and on-call settings. Captures before-and-after field values. Filter by date range, user, source (web/API/mobile/Slack/SCIM/OAuth), item type, action, or API key. Click any row to see the full diff. Pull audit events programmatically via the public API — useful for compliance archival, custom dashboards, and scheduled exports into long-term storage. Passwords, tokens, API keys, and other credentials are automatically redacted in the UI and API responses. *** ## Who Can View the Audit Log Access is role-based. Two paths grant audit-log read access: Grants visibility into all audit events across the organization. Configured under **Configuration → Roles & Permissions** by enabling the **Audits — read** permission on the role. Grants visibility into audit events for on-call resources only — Alerts, Alert Routes, Schedules, Escalation Policies, and related items. Useful when on-call leads need visibility into on-call configuration changes without seeing the full organizational audit history. Users without either permission don't see the **Audit Log** sidebar entry under Configuration → Organization. *** ## What Gets Logged Roughly 60 resource types are instrumented. Highlights: API Keys, Secrets, Roles, On-Call Roles, Memberships, Severities, Environments, Custom Fields, Custom Forms. Incidents, Action Items, Incident Events, Post-Mortems, Incident Permission Sets. Genius Workflows, Workflow Runs, Workflow Groups — including create, edit, enable/disable. Slack, PagerDuty, Opsgenie, Jira, Datadog, GitHub, ServiceNow, Zoom, and every other integration's connection and configuration changes. Schedules, Escalation Policies, Alerts, Alert Routes, Alert Routing Rules. Services, Functionalities, Groups (Teams), Environments, Causes. Each entry captures: | Field | What It Means | | ------------------------- | ----------------------------------------------------------------------------- | | `whodunnit` | User ID of the actor who triggered the change | | `item_type` and `item_id` | The resource that was modified | | `event` | One of `create`, `update`, `destroy` | | `source` | Where the action came from — `web`, `api`, `mobile`, `slack`, `scim`, `oauth` | | `api_key_id` | If the action came from the API, which key triggered it | | `request_id` | HTTP request ID for tracing through Rootly's logs and external systems | | `metadata.ip` | IP address of the actor, when available | | `object_changes` | Before-and-after values for every modified field, with humanized field names | **Sign-in and sign-out events are tracked separately** from the main audit log, in Rootly's login activity store. The main audit log focuses on configuration and operational changes, not authentication events. For a unified authentication + audit view, pair the JSON:API export with sign-in events from your IdP (Okta, Azure AD, Google Workspace). *** ## View the Audit Log in Rootly In Rootly, go to **Configuration → Organization → Audit Log**. The full event history loads in reverse-chronological order. Use the filter row at the top of the table to narrow down: Start and end timestamps. Actor who triggered the change. `web`, `api`, `mobile`, `slack`, `scim`, or `oauth`. The resource that changed (for example, `Incident`, `EscalationPolicy`, `Severity`). `create`, `update`, or `destroy`. Filter by the actions of a specific automation. Click any audit entry to open the detail drawer. It shows the full before-and-after values for every field that changed, with humanized field names and timezone-aware timestamps. **Looking for user permission changes specifically?** Set the **Item type** filter to `Role`, `OnCallRole`, or `Membership` — those three resource types capture role assignments, on-call role changes, and team membership updates respectively. If the affected user is managed via SCIM, also try setting **Source** to `scim` to surface IdP-driven provisioning events; web-UI and API changes appear with `source` set to `web` or `api`. Without an item-type filter, role changes can be hard to spot in a busy audit feed full of incident and workflow events. *** ## Programmatic Access via API For compliance exports, evidence collection, or building your own audit dashboards, query the audit log through the JSON:API endpoint. ```http theme={null} GET /api/v1/audits Authorization: Bearer ``` Filter to a specific resource type. Examples: `Incident`, `Severity`, `EscalationPolicy`, `ApiKey`. Filter to actions taken by a specific user. Filter to actions triggered by a specific API key — useful for auditing automations. One of `web`, `api`, `mobile`, `slack`, `scim`, `oauth`. Supports `gt`, `gte`, `lt`, `lte` operators for time-range queries. Example: `filter[created_at][gte]=2026-01-01T00:00:00Z`. `created_at` for ascending order, `-created_at` for descending. Default is descending (most recent first). JSON:API standard pagination. Maximum page size depends on your plan; iterate through pages for full exports. Response includes all the same fields the UI shows (`whodunnit`, `item_type`, `event`, `source`, `object_changes`, etc.) plus the resource's full prior and current state where applicable. Sensitive fields (passwords, tokens, API keys, OAuth secrets) are redacted by the serializer before the response leaves Rootly. For full API authentication and pagination details, see the [API Reference](/api-reference/overview). *** ## Sensitive Field Redaction The UI and API responses redact sensitive field values before they leave Rootly. Redaction applies to fields whose names match common credential patterns — `password`, `api_key`, `token`, `secret`, `credentials`, and similar. What you'll see in place of redacted values: * Field appears in the diff but the value is replaced with `[REDACTED]` * The fact that the field changed is still recorded (useful for "rotated the API key on Oct 5") * The new value is never visible — only that it was modified This matters for compliance: rotating a secret or updating an integration's API key still generates a complete audit trail, without exposing the new credential to anyone who can read the audit log. *** ## Retention Rootly retains audit logs indefinitely by default — there's no automatic deletion policy. For long-term compliance archival, use the JSON:API to pull events on a schedule into storage your auditors already own. *** ## Frequently Asked Questions No — authentication events are tracked separately from the configuration audit log. For a unified view of auth + audit, pair the JSON:API export with sign-in events from your IdP (Okta, Azure AD, Google Workspace). Not directly from the UI. Use the JSON:API endpoint (`GET /api/v1/audits`) to pull the data and convert it to CSV in whatever tool fits your workflow. Most teams pull on a schedule for compliance archival rather than ad-hoc CSV export. No. Passwords, API keys, OAuth tokens, and other credential-like fields are automatically redacted in the UI and API responses. The audit log records that the field was changed — never the new value. Only if their role has the **Audits — read** permission on the base role. The on-call role's audit permission scopes visibility to on-call resources only (Alerts, Schedules, Escalation Policies). Grant the base-role audit read permission for full visibility. Yes. Incidents, action items, post-mortems, incident events, and permission sets all generate audit entries on create, update, and delete. Useful for reconstructing exactly what happened during incident response. Their historical actions stay in the audit log — the user reference is preserved. Future actions can't be attributed to that user because they no longer have access, but everything they did while active remains traceable. *** ## Next Steps Authenticate and query the `/api/v1/audits` endpoint for programmatic export. Grant the **Audits — read** permission to roles that need audit visibility. Configure custom roles with scoped audit permissions for on-call leads, compliance officers, and other audiences. *** ## Related Pages Broader tenant hardening — SSO, RBAC, API hygiene, session controls, and integration hygiene. Route incident, alert, workflow, and status-page events out to any HTTP endpoint — the outgoing counterpart to audit visibility. The umbrella page covering incident properties, fields, and configuration surface. # Built-In Fields Source: https://docs.rootly.com/configuration/built-in-fields The pre-configured incident properties Rootly ships with — Severity, Environments, Services, Teams, Incident Types — and how to enable or rename them. ## Overview **Built-in fields** are the pre-configured incident properties Rootly ships with — Severity, Environments, Services, Teams, Incident Types, Incident Causes, Functionalities, and a handful of behavioral toggles like `Backfill Incident` and `Mark as Triage`. Every built-in field is designed to capture a common piece of incident metadata that drives workflows, metrics, and status page updates. You can turn built-in fields on or off, rename them (Severity → "Priority", if that matches your team's vocabulary), and — for many of them — change their behavior (single-select vs multi-select, default values, whether they appear on the incident details page). What you **can't** do is add net-new dimensions to the built-in schema; for that, use [Custom Fields](/configuration/custom-fields). Access built-in fields in **Configuration → Fields → Built-In Fields**. **Built-in vs Custom:** Built-in fields are baked into Rootly and integrate with everything (workflows, metrics, retrospectives, status pages) automatically. [Custom Fields](/configuration/custom-fields) are extensions you define — they're just as usable in workflows, but their integration surface is what you wire up yourself. Reach for a built-in field first; drop to a custom field only when the built-in schema doesn't cover what you need. *** ## Built-In Fields Reference | Field | Type | Purpose | Configurable | | ----------------------------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------- | | **[Severity](/configuration/severities)** | Select | How bad the incident is (SEV0–SEV3) | Values, colors, Slack channels, aliases, notify emails | | **[Environments](/configuration/environments)** | Select or Multi-Select | Which deployment tier is affected (Production, Staging, Dev) | Values, colors, field type (select/multi), attached channels/aliases/emails | | **[Incident Types](/configuration/incident-types)** | Select or Multi-Select | Category of incident (UI Bug, Infrastructure, Security Event, etc.) | Values, colors, field type (select/multi), attached channels/aliases/emails | | **[Incident Causes](/configuration/incident-causes)** | Multi-Select | Root causes captured during retrospective | Values, colors | | **[Services](/configuration/services)** | Select or Multi-Select | Infrastructure components impacted | Values, colors, ownership, field type (select/multi) | | **[Functionalities](/configuration/functionalities)** | Select or Multi-Select | Product capabilities impacted | Values, colors, field type (select/multi) | | **[Teams](/configuration/teams)** | Select or Multi-Select | Team ownership and routing | Values, membership, field type (select/multi) | | **Summary** | Text | Human-readable incident description | Enabled / disabled | | **Status Page Title** | Text | The incident title as it appears on status pages | Enabled / disabled | | **Notify Emails** | Multi-Select (emails) | Per-incident additional email recipients | Enabled / disabled | | **Mark as Triage** | Checkbox | Whether to open the incident in Triage status | Enabled / disabled, default value | | **Backfill Incident** | Checkbox | Retroactively documenting an already-resolved incident | Enabled / disabled, default value | | **Private** | Checkbox | Restrict incident visibility (see [Private Incidents](/incidents/private-incidents/private-incidents)) | Enabled / disabled, default value | | **Not a real emergency** | Checkbox | Marks as test/training without changing Kind | Enabled / disabled, default value | This reference list captures the most common built-in fields. Your Rootly workspace may show additional fields depending on which integrations are enabled — for example, PagerDuty and Opsgenie integrations expose their own built-in fields for cross-referenced IDs. *** ## Managing Built-In Fields Navigate to **Configuration → Fields → Built-In Fields** to see the full list. Every built-in field has an enable/disable toggle and — for most fields — an edit pane where you can rename, change the field type, set defaults, and control display behavior. ### Enable Or Disable A Field Only enabled fields are live — they appear on incident forms, on the incident details page, and can be updated by workflows. Disabled fields are hidden from users and unavailable to workflow actions. Use the toggle next to the field name in the list view. Disabling a built-in field that's already referenced by workflows or Liquid templates doesn't remove those references — they just start failing silently. Before disabling a heavily-used field, audit your workflows and templates for references to it. ### Edit A Field's Configuration Click the edit icon on the right side of any field row to open the Edit Form Field pane. The edit pane exposes the settings below. Not all settings apply to every field — a checkbox field like `Backfill Incident` has no `Field Type` setting because it's inherently a boolean. Unique identifier generated at field creation. **Not customizable.** Used in API calls and Liquid references. Display label shown on incident forms and the incident details page. Renaming affects the **UI only** — Liquid references and API paths remain unchanged. For example, renaming `Severity` to `Priority` in the UI still leaves the Liquid reference as `{{ incident.severity }}`, not `{{ incident.priority }}`. For fields that support both modes — Environments, Incident Types, Services, Functionalities, and Teams — you can choose whether responders pick one or many values. Severity is always single-select; Incident Causes is always multi-select; checkbox and text fields don't expose this setting. Changing the field type is one-way in practice — moving from multi-select to select truncates existing multi-value incidents to their first value. Default value that pre-populates on new incident forms. Common uses: default Severity to `SEV3`, default Environment to `Production`, default `Mark as Triage` to `true` for a triage-first workflow. Defaults only apply to new incidents — changing a default doesn't retroactively update existing incidents. When enabled, the field is live on the incident form, in workflows, and on the incident details page. Disabled fields are hidden from users and inaccessible to workflow actions. This is the same toggle as the enable/disable switch in the list view. Controls whether the field appears in the **Details** section of the incident details page. Hiding does **not** disable the field — workflows can still read and write it. Users may still be able to edit the field from other surfaces (creation forms, update forms) unless you also hide or restrict it there. Common use: a "system-managed" flag that workflows set automatically and shouldn't clutter the Details view. To make it fully non-editable to humans, also remove it from the relevant [Incident Forms](/configuration/built-in-forms) or restrict form access. *** ## Common Configuration Patterns If your team uses "Priority" or "Impact Level" instead of "Severity", edit the built-in Severity field and change the Name. The values (SEV0–SEV3, or your custom Severity names) stay the same, but the field label changes across every incident form. Remember: renaming the field name does NOT change the Liquid reference. `{{ incident.severity }}` still works; `{{ incident.priority }}` does not. If most of your incidents are Production incidents, set the Environment field's default value to Production. Responders only need to change it for the exceptional cases (Staging, Dev). This is one of the fastest ways to reduce the number of unspecified-Environment incidents. Not every built-in field is relevant to every team. If your team doesn't use Functionalities (because you don't yet have them defined) or Notify Emails (because everything routes through Slack), disable those fields. Fewer fields on the incident form means faster triage and lower cognitive load for responders. Audit workflow references before disabling, per the warning above. Some teams use a built-in field as a workflow-controlled system flag — for example, an internal "escalated to exec team" boolean that gets set by a workflow when specific conditions are met. Disable "Display This Field in the Incident Details" to remove it from the Details section. To keep it out of human hands entirely, also remove it from the creation and update [Incident Forms](/configuration/built-in-forms). Teams sometimes start with multi-select Incident Types and later realize they always want exactly one Type per incident. Switching to Select is a one-way change: existing multi-value incidents get truncated to their first value. Confirm you're ready for the truncation, or bulk-update multi-value incidents to a single Type before switching. *** ## Best Practices * **Reach for built-in fields first; use custom fields only when built-ins don't cover the case.** Built-in fields have first-class integration with workflows, metrics, retrospectives, and status pages. Custom fields work everywhere too, but you're building the integrations yourself. * **Rename cautiously.** Renaming a field changes what responders see but not what workflows and Liquid templates reference. If you're changing the display name of a heavily-referenced field, audit the templates that use its old name in prose (not the Liquid reference itself) so they don't drift. * **Default the fields that are usually the same value.** Environment (usually Production), Severity (usually SEV2 or SEV3 as a default before triage), and Mark as Triage (true if your team starts every incident in Triage) are all good candidates. Defaults reduce keystrokes; unspecified-value incidents route to the wrong workflows. * **Audit disabled fields quarterly.** Fields that were disabled six months ago and haven't been re-enabled probably aren't coming back. Consider whether the workflow references pointing at them are still needed. * **Prefer built-in Field Type changes over custom-field replacements.** If a built-in field can be reconfigured (for example, Environment from multi to single), that's simpler than disabling the built-in and creating a custom field to replace it. Every workflow and template that references the built-in continues to work. *** ## Troubleshooting Check that the field is enabled in Configuration → Fields → Built-In Fields. Also verify the field is enabled on the specific incident form you're using — form-level field configuration can override the built-in-field-level enable state. Renaming a built-in field affects **only the UI label**, not the Liquid reference. If your template broke after a rename, something else changed — check the actual Liquid syntax against the field's reference (see the individual field docs like [Severity](/configuration/severities) or [Environments](/configuration/environments) for exact syntax). Working as designed. When you switch a multi-value field to single-select, existing incidents with multiple values keep only their first value. This is not reversible — the additional values are removed at conversion time. If you need to preserve historical multi-value data, export incident data before switching. Alternatively, bulk-update multi-value incidents to a single canonical value before making the field type change. Disabling a built-in field doesn't remove workflow references — those references just start failing silently or with runtime errors when the workflow tries to read or write the disabled field. Re-enable the field, or audit and update the referencing workflows in **Configuration → Workflows** — use the search box to filter by the field's slug or Liquid variable name. Confirm the default is set on the built-in field configuration (not just the form-level configuration — those are separate). If it's set at the field level and still not applying, check for a workflow that runs on Incident Created and overwrites the default value. *** ## Frequently Asked Questions **Built-in fields** are pre-configured properties Rootly ships with — Severity, Environments, Services, Teams, Incident Types, and similar. They have first-class integration with workflows, metrics, retrospectives, and status pages. **[Custom Fields](/configuration/custom-fields)** are extensions you define — same usability in workflows, but you wire up the integrations yourself. Use built-ins for common dimensions (impact, tier, category); use custom fields for organization-specific dimensions the built-in schema doesn't cover. No. The built-in field set is defined by Rootly. If you need a new dimension, use a [Custom Field](/configuration/custom-fields). Custom fields work in workflows and Liquid templates the same way built-in fields do — the main difference is you configure the integration behavior yourself. No — built-in fields can be disabled but not deleted. This preserves the field's data on historical incidents. If you don't want a field surfaced anywhere in the UI, disable it and hide it from incident details. No. API paths and Liquid references are based on the field's stable slug (assigned at creation), not the display name. Renaming Severity to Priority in the UI doesn't change `/incidents/{id}/severity` in the API or `{{ incident.severity }}` in Liquid. Configurable field type: Environments, Incident Types, Services, Teams, Functionalities. Fixed: Severity is always single-select; Incident Causes is always multi-select; checkbox fields (Backfill Incident, Mark as Triage, Private) are always booleans. Yes, via form-level configuration. Each incident-creation form can have its own default values that override the field-level defaults. This lets a Frontend team default Environment to `Web`, while an Infra team defaults it to `Production` — with the same underlying built-in field. Workflows that reference the disabled field will fail or silently no-op at runtime. Rootly does not automatically detect and update dependent workflows. Audit workflow references before disabling any heavily-used built-in field. *** ## Related Pages Add fields the built-in schema doesn't cover. Both built-in and custom fields work in the same workflows and templates. Filter workflow runs on built-in field values — the interactive evaluator lets you test conditions against a sample incident. The umbrella page linking every incident property doc, including all built-in fields covered here. # Default Forms Source: https://docs.rootly.com/configuration/built-in-forms Configure Rootly's built-in forms that guide users through incident creation, updates, resolution, maintenance, and post-incident processes. ## **Overview** Rootly comes with a set of essential, built-in forms that cannot be deleted. The forms each cover a different stage of an incident and scheduled maintenance lifecycle. You can access the built-in forms by navigating to **Configuration > Forms**. ## Form Types The New Incident form is displayed whenever the user first declares an incident on Slack (via `/rootly new` command) or on the Rootly web UI (via `Create Incident` button). The Update Incident form is displayed whenever the user attempts to update an incident on Slack (via `/rootly update` command or `Update` button) or on the Rootly web UI (via `Edit` button). The Incident Mitigation form is displayed whenever the user attempts to mitigate an incident on Slack (via `/rootly mitigate` command) or on the Rootly web UI (via `Mitigate` button). The Incident Resolution form is displayed whenever the user attempts to resolve an incident on Slack (via `/rootly resolve` command) or on the Rootly web UI (via `Resolve` button). The Incident Cancellation form is displayed whenever the user attempts to cancel an incident on Slack (via `/rootly cancel` command) or on the Rootly web UI (via `Cancel` button). The Incident Retrospective Form is displayed after the incident is resolved and the user enters the **Gather & Confirm Data** step of the retrospective. This form is only accessible from the Rootly web UI. The New Maintenance Incident form is displayed whenever the user first declares a scheduled maintenance on Slack (via `/rootly maintenance` command) or on the Rootly web UI (via `Schedule Maintenance` button). The Update Maintenance Incident form is displayed whenever the user attempts to update a scheduled maintenance on Slack (via `/rootly update` command or Update button) or on the Rootly web UI (via `Edit` button). The Incident Follow Up form is displayed whenever the user adds or edits a follow-up on an incident, on Slack (via `/rootly followup` or the action items dialog) or on the Rootly web UI (via the **Follow-ups** tab). The follow-up's standard fields (title, description, assignee, priority, status, due date) are always part of the form; the fields you can add and configure on it are **custom fields** — see [Custom Fields on Action Items](/incidents/action-items/action-item-custom-fields). The Incident Task form is displayed whenever the user adds or edits a task on an incident, on Slack (via `/rootly task` or `/rootly add action item`) or on the Rootly web UI. Like the Incident Follow Up form, its standard fields are always present and the fields you can add and configure on it are **custom fields** — see [Custom Fields on Action Items](/incidents/action-items/action-item-custom-fields). The Task and Follow Up forms are independent, so a field placed on one isn't added to the other. Both forms appear once custom fields for action items are enabled for your organization. You'll notice that the trigger points for scheduled maintenance are exactly the same as for incidents. Rootly will be able to recognize the context and display the appropriate form. For example, when `/rootly update` is run, * If it was run **in an incident channel**, then **Update Incident** form will be displayed * If it was run in a **maintenance channel**, then the **Update Maintenance Incident** form will be displayed ## Sub-Status Forms If your Rootly instance has access to **Rootly's Custom Lifecycle feature**, which allows you to customize your incident statuses, Rootly will generate default forms for each of your incident substatuses. This allows you to fully customize the information your responders provide throughout the incident's lifecycle, attuned to your business processes. You'll find these forms under the **Sub-Status Forms** tab. Sub Status Form Get started with Rootly's custom lifecycle feature by reaching out to your account representative. ## **Edit Form** To begin editing a form, select the Configure button under the form you'd like to edit. You'll be navigated to the edit form page of the selected form. The **left side of the page is the edit pane** where you can edit what fields are displayed and how they are displayed. The **right side of the page is the preview** of the form. You can create separate versions of the form for Slack and Rootly Web/Mobile by toggling between the tabs on the left hand side. To ensure incident data is captured consistently, Rootly recommends keeping the fields for each channel in sync. ## Adding Fields to a Form Add new fields to your form by selecting the **Add Fields** button. Select all of the fields you'd like to add to the form, then **Add Fields**. Once these fields are added to your form, you can drag and drop them to reorder the form. Remove a field by selecting the **minus** button on the right hand side of the field. ## Editing Fields on a Form Once a field is added to a form, you can edit how and when the field is filled out. Select the edit button on the field you want to make changes to. ### Conditionally Display and Require a Field Once a field is added to a form, you can control when the field is displayed and if it is required. Select the edit button on the field that you want to make changes to. If you only want the field to display under certain conditions or be required under certain conditions, select the **Conditionally** option under **Display this field** or **Require this field**. Form fields can be displayed or required conditionally depending on the value of any field set above the field that you're editing. For example, if the first field on your form called "Teams" is set to a certain value, your second field can be conditionally displayed depending on the team's value. ### Read-Only Fields A field can be set to 'read-only', which means that the value cannot be overwritten by your users. This is particularly useful when you want to set a field value on an incident, but do not want it to be manually set by your team. When this setting is turned on, the field value will always be set to the default value. You cannot turn this setting on unless the field has a default value: this can be edited in the Fields section of the dashboard. This setting only impacts the Form experience. Field values can still be overwritten in the Rootly Web UI on the Incident's details page. ## Preview The preview on the right-hand side is interactive and generated in real-time. This is a great way to test out the user experience of your form, and ensure behavior of each field is correct. *** ## Related Pages Author additional forms beyond the built-in set — surfaced via buttons and Slack modals. The umbrella concept covering built-in, custom, and dynamic forms alongside custom fields. Form variants that adapt based on incident type, team, or severity. # Incident properties and configuration overview Source: https://docs.rootly.com/configuration/configuration Configure incident properties, custom fields, and settings to characterize incidents, trigger workflows, and filter metrics across your organization. ## Overview Every incident created in Rootly is characterized by a structured set of **properties**. These properties define how an incident behaves, how it progresses through its lifecycle, how it interacts with workflows and automation, and how it appears in reporting and analytics. Incident properties serve several critical purposes: * Help characterize each incident (for example, `kind = normal`) * Trigger workflow automations (for example, Status Updated) * Define conditional logic for workflow execution (for example, Severity is SEV0) * Enable filtering and segmentation of metrics * Allow structured access through **Liquid syntax** Properties fall into three primary categories: * **Fixed Properties** — system-defined and not customizable * **Configurable Properties** — built-in but organization-customizable * **Custom Fields** — fully defined and managed by your organization *** ## Fixed Properties Fixed properties are intentionally restricted to maintain lifecycle integrity, automation consistency, and reporting standardization across the Rootly platform. Fixed properties cannot be modified or deleted. They define the foundational lifecycle and structural behavior of every incident. *** ## Incident Kind The **Kind** property determines the classification and structural behavior of an incident at creation time — whether it's a real production incident, a test, a backfill, or a scheduled maintenance window. Kind is immutable after declaration and governs workflow execution, status page eligibility, and metrics inclusion. For the full kind reference (all seven kinds, behavior matrix, choosing the right kind, and Kind-related troubleshooting), see **[Incident Kind](/configuration/incident-kind)**. *** ## Incident Status The **Status** property defines the lifecycle stage of an incident — from Triage through Started, Mitigated, Resolved, Closed, or Cancelled. Status transitions are validated to preserve chronological and logical integrity. Scheduled Maintenance incidents follow a separate lifecycle (Scheduled / In Progress / Completed) with its own rules. For the full status reference (transition rules, timestamp validation, sub-statuses, the Scheduled Maintenance lifecycle, and Status-related troubleshooting), see **[Incident Status](/configuration/incident-status)**. *** ## Configurable Properties Configurable properties are built-in fields that organizations can customize to reflect their operational structure, severity model, and reporting taxonomy. | Property | Description | | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | [Environments](/configuration/environments) | Characterizes incidents by environment (for example, Development, Staging, Production). Commonly used to prioritize production-impacting incidents and to filter metrics and workflow conditions. | | [Severities](/configuration/severities) | Defines impact levels (for example, SEV0–SEV3). Drives escalation logic, workflow triggers, and reporting analysis. | | [Incident Types](/configuration/incident-types) | Custom categorization distinct from Kind. Allows organizations to define taxonomy such as UI Bug, Infrastructure Failure, Security Event, etc. | | [Incident Roles](/configuration/incident-roles) | Defines structured responder roles (Incident Commander, Communications Lead, etc.) to coordinate responsibilities during response. | | [Teams](/configuration/teams) | Assigns ownership and organizational routing responsibility to teams or groups. | | [Services](/configuration/services) | Identifies impacted infrastructure components. Used for service-level reporting and status page communication. | | [Functionalities](/configuration/functionalities) | Identifies impacted product capabilities (for example, login, checkout). Enables feature-level transparency. | | [Incident Causes](/configuration/incident-causes) | Categorizes root causes to support retrospective analysis and long-term reliability improvements. | *** ## Property Order The ordering of values within configurable properties determines how they appear in dropdown menus and forms. Ordering is **global** and affects all users. You can: * Drag and drop values manually * Sort values alphabetically Property order example *** ## Custom Fields When built-in properties are insufficient to meet your organization’s needs, you can create **Custom Fields** to extend the incident schema. Custom Fields allow you to: * Capture structured or unstructured metadata * Apply validation and defaults * Power advanced workflow automation * Reference values using Liquid syntax * Enforce organization-specific incident taxonomy For full configuration details, see the [Custom Fields](/configuration/custom-fields) documentation. *** ## Frequently Asked Questions No. Fixed properties (**Kind** and **Status**) are system-defined and cannot be modified, deleted, or customized. They exist to ensure consistency across the platform and maintain the integrity of workflow automation and reporting. If you need different categorization options, use **Configurable Properties** (like Incident Types) or **Custom Fields**, which can be fully customized to meet your organization's needs. Yes. Custom fields can be referenced in workflow run conditions and Liquid templates, allowing you to create sophisticated automation based on organization-specific data. Custom fields are accessible via Liquid syntax: ```liquid theme={null} {{ incident.custom_fields | find: 'custom_field.slug', 'your-field-slug' | get: 'value' }} ``` This enables workflows to react to custom field values, trigger actions based on custom data, and include custom field information in notifications and integrations. Property ordering is **global**, meaning changes affect all users immediately. When you reorder values (for example, Severities or Environments), the new order appears in: * Dropdown menus when creating or editing incidents * Form fields across the platform * Any interface where that property is displayed You can reorder manually via drag-and-drop or sort alphabetically. *** **Need help or have a question?** Contact us anytime at **[support@rootly.com](mailto:support@rootly.com)**, use the `/rootly support` Slack command, or visit **Getting Help** to start a chat. *** ## Related Pages The fixed set of incident properties Rootly ships with — severity, environment, service, team. Fully customizable fields for organization-specific incident metadata. How incident forms are configured, including built-in, custom, and dynamic form variants. # Creating a Status Page Source: https://docs.rootly.com/configuration/creating-a-status-page Set up and customize public status pages in Rootly to communicate service health, incident updates, and scheduled maintenance to your customers. Creating a status page only takes about a minute. Before you do so, Rootly recommends you have at least one [service](/configuration/services) configured in Rootly that you can display on your status page. You can do this by visiting **Configuration > Services** or if you have the [PagerDuty integration](/integrations/pagerduty/pagerduty) configured, you can easily import services directly from PagerDuty then add them to your status page. To create a new status page: In the Rootly navigation bar, click on **Configuration**, then **Status Pages**. Click **Add New Status Page**. Give your status page a name and description. These are internal to Rootly, and will not be used on the actual Status Page. ## **Customize Your Status Page** Once you've created your status page, you're able to customize the look and feel of the page to tailor the contents to your end users. ## **Setup** Under setup, you're able to make changes to the name and description of your status page. Remember: these are internal only so should be descriptive for other Rootly admins to know what the status page is. Here, you can also determine if the page will be private or publicly available. Learn more about [public and private status pages](/configuration/status-pages#public-or-private). In the Advanced Settings, you can also customize the domain name of the status page. By default, Rootly will assign each Status Page a URL in the following format: `rootly.com/teams/[your-org-name]/status-pages/[status-page-name]/[public/private]` Configure your own custom domain by following: [Custom Domain Names for Status Pages](/configuration/custom-domain-names-for-status-pages). Note: for custom external domain names, you may need to talk with the team at your organization to have them help you configure a custom domain name and associated DNS.  Setup Status Page ## **Customize** Customize the default content and look-and-feel of your status page in the Customize tab. As you make changes to the settings in this tab, the right-hand preview of your status page will reflect your latest updates. Customize Status Page ## **Components** Use the Components section to choose what appears under the 'System Status' section of your page. You can add three kinds of components: * **Services** — any Rootly [service](/configuration/services). * **Functionalities** — a [functionality](/configuration/functionalities) represents a higher-level, customer-facing capability (like "Login" or "Checkout") that can be backed by many underlying services. Add a functionality when you want to show a single customer-facing component instead of a long list of internal services. * **Third party services** — any external service your organization depends on. Functionalities are useful when you maintain a large number of services but only want to expose a small set of product components publicly. Map your services to a functionality on the [functionality](/configuration/functionalities) itself, then add only that functionality to the page. A component is shown as impacted under 'System Status' when an incident that is published to this status page is associated with that component. For a functionality, that means the incident is tagged with the functionality (or the component is selected when publishing the status page update). Associating a service with a functionality does not by itself change the functionality's status. The status is always driven by the incident. If you don't see Functionalities as a component option, reach out to [support](mailto:support@rootly.com) to have the Functionalities field enabled for your organization. To tag functionalities automatically, use a [workflow](/workflows/workflows) that runs on incident create or update, conditions it on the severities and services you care about, and adds the matching functionality with the Update Incident action. Be aware that this action replaces the incident's entire functionality list rather than adding to it, so it also clears any functionalities set earlier by another workflow or by hand. That reaches beyond the status page — a functionality dropped from an incident also stops driving its [ownership, escalation policy, and notification settings](/configuration/functionalities) for that incident. It is only safe when a single workflow run can determine the complete set of functionalities for the incident. If several workflows could tag different components on the same incident, select the affected components manually when you publish the update instead. You'll be able to add third party services to your status page after you've created the status page. Status Page Component ## **Templates** Standardize the incident updates your teams share with Status Templates. When a commander publishes an incident update to a status page, they'll be able to use the templates defined in this section to help write their update. Templates Status Page ## Go-Live Checklist Setup spans several pages. Work through this before you point customers at the page. Public or private — the choice drives everything below it. See [Overview](/configuration/status-pages). Add the services, functionalities and third party services customers care about, and put them in the order you want them displayed. A page listing every internal service is harder to read than one listing a handful of customer-facing functionalities. Templates are what a commander reaches for mid-incident. Writing them under pressure is how inconsistent updates happen. A private page is limited to people logged in to Rootly, and needs nothing further. A public page is reachable by anyone with the URL — if that is too open, add password or SAML [authentication](/configuration/status-page-authentication-methods), which is available on public pages only. Public pages usually want a [custom domain](/configuration/custom-domain-names-for-status-pages). Both the CNAME and the CAA record are required, and DNS changes take time to propagate — do this before you need it, not during an incident. Publish a low-severity incident, confirm it renders the way you expect, then resolve it. See [Publishing Incidents](/configuration/publishing-incidents). If the test incident appears with the right components marked as impacted, the page is ready. *** ## Related Pages The umbrella concept — what public and private status pages are and when to use each. Point your own domain at a Rootly status page with CNAME + CAA records. How incident updates get pushed to a status page from Web or Slack. # Custom Domain Names for Status Pages Source: https://docs.rootly.com/configuration/custom-domain-names-for-status-pages Configure custom domain names for your public status pages to maintain brand consistency and provide a seamless customer experience. ## Overview You can attach one or multiple custom domain names such as status.acme.me using the custom domain names input. This allows you to brand your status page with your own domain while maintaining all the functionality of Rootly's status page system. **Note**: External domain names are only configurable for public status pages. Private status pages cannot use custom domain names and will only be accessible through the default Rootly URL. ## Prerequisites Before setting up a custom domain, ensure you have: * Administrative access to your domain's DNS settings * A public status page configured in Rootly (private pages are not supported) * Access to your DNS provider's management interface ## Getting Your CNAME Target Once you save your page, you can obtain the CNAME target by clicking on the link for the status page you want to configure. The CNAME is shown at the bottom of the screen on the right side. It provides the **Domain** you entered along with the **Value** needed for your DNS records. ## How Custom Domains Work 1. You set up the CNAME record in your DNS provider with: * **Domain**: test.statuspage.net * **Value**: (rootly-provided-value).external-sp.rootly.com 2. When someone visits test.statuspage.net: * The DNS system looks up the CNAME record and directs the request to (rootly-provided-value).external-sp.rootly.com. 3. Rootly serves the corresponding status page associated with the unique identifier in the CNAME. ## DNS Configuration Steps Set up the CNAME record in your DNS provider with the values obtained from Rootly: * **Domain**: Your custom domain (for example, status.your-domain.com) * **Value**: The Rootly-provided CNAME target (for example, unique-id.external-sp.rootly.com) You must add a CAA (Certificate Authority Authorization) record to your DNS configuration for SSL certificate validation to work properly. Add a CAA record to your **parent domain** (not the subdomain) with the following format: ```text theme={null} 0 issue "pki.goog; cansignhttpexchanges=yes" ``` For example, if your custom domain is `status.your-domain.com`, add the CAA record to `your-domain.com`. **Important**: Place the CAA record on the parent domain because domains with CNAME records cannot have other record types. The Certificate Authority will check for CAA records starting from the subdomain and work up to the parent domain, stopping at the first CAA record it finds. Test your CAA record configuration using the `dig` command: ```bash theme={null} dig +short CAA your-domain.com ``` This CAA record authorizes Google's PKI to issue certificates for your domain and enables HTTP Exchange signing, which can improve performance for your status page. After setting up both records, verify your configuration: * **Test CNAME resolution**: ```bash theme={null} dig +short CNAME status.your-domain.com ``` * **Check SSL certificate**: ```bash theme={null} curl -I https://status.your-domain.com ``` * **Verify page accessibility**: Visit your custom domain in a browser. ## Provider-Specific Configuration Guides To configure the DNS records, you will need to either work with your company's DNS administrator or configure it yourself if you have access. Since configuring DNS varies by provider, here are guides for the most common services: * [Amazon Web Services Route 53](https://aws.amazon.com/premiumsupport/knowledge-center/route-53-create-alias-records/ "Amazon Web Services Route 53") * [Azure DNS](https://docs.microsoft.com/en-us/azure/dns/dns-web-sites-custom-domain "Azure DNS") * [Google Cloud Identity](https://cloud.google.com/identity/docs/add-cname "Google Cloud Identity") * [GoDaddy Domains DNS](https://www.godaddy.com/help/add-a-cname-record-19236 "GoDaddy Domains DNS") ## Troubleshooting ### Common Issues #### Domain Not Resolving * Verify CNAME record is correctly configured * Check DNS propagation (can take up to 48 hours) * Ensure there are no conflicting A records * Remember: domains with CNAME records cannot have other record types on the same subdomain #### SSL Certificate Errors * Confirm CAA record is properly set on the parent domain (not subdomain) * Wait for certificate provisioning (can take up to 24 hours) * Verify the CAA record uses the correct format: `0 issue "pki.goog; cansignhttpexchanges=yes"` * Check that the CAA record is placed on the parent domain, not the subdomain with the CNAME #### Page Shows "Not Found" Error * Double-check the CNAME target value from Rootly * Ensure the status page is set to public * Verify the custom domain is correctly entered in Rootly ### DNS Propagation Check Use these tools to check DNS propagation across different regions: * [What's My DNS](https://www.whatsmydns.net/) * [DNS Checker](https://dnschecker.org/) ### Getting Help If you continue experiencing issues: 1. Check the Rootly status page configuration 2. Verify DNS records with your provider 3. Contact Rootly support with your domain and error details *** ## Related Pages Set up the status page you'll point your custom domain at. Password or SAML auth for public status pages behind your custom domain. The umbrella concept — public vs private status pages. # Custom incident fields configuration Source: https://docs.rootly.com/configuration/custom-fields Create organization-specific incident fields with custom data types, validation rules, and integration mappings to meet unique incident management requirements. ## Overview Rootly carefully selected the built-in properties based on common attributes used to characterize incidents. However, not all organizations are built the same and sometimes the built-in properties are not enough to meet everyone's requirements. To enable a fully bespoke experience, Rootly introduced custom properties that can be set up to meet the exact specifications of your organization's incident management requirements. Custom fields aren't limited to incidents — the same fields can be placed on your action item forms (Incident Task and Incident Follow Up) to capture metadata on tasks and post-incident work. See [Custom Fields on Action Items](/incidents/action-items/action-item-custom-fields). ## Managing Custom Fields ### Create Field Select the Create New Form Field button to create a new custom field. The following details can be edited on a field: This is a unique identifier for the form field. It is automatically generated for you upon field creation and cannot be edited. This ID will be used to reference the specific form field in API calls and Liquid syntax. This field can be edited. The value entered here will be the value that appears on user-facing forms. Renaming a custom field will change the slug of the field, which in turn **WILL** break any Liquid references that use the previous slug. This is because, unlike built-in fields, a custom field's slug is mutable. Each time the field is renamed, its slug is regenerated from the new name, lower-cased and hyphenated. \ \ Existing references that use the custom field's ID instead of its slug will not be affected. `{{ incident.custom_fields | find: 'custom_field.slug', 'your-custom-field-slug' | get: 'value' }}` This field can be used to display a description for the custom field. This is particularly helpful if you want to give your users some instruction on how to fill in the custom field. This field allows you to select the field type, which will dictate how the user interacts with this field. For example, a checkbox type will be a boolean field while a select type will ask the user to select one out of many options. For more details on the available field types, please scroll down to the [Supported Field Types](/configuration/custom-fields) section. This field allows you to define selectable options for Select and Multiple Select field types when the 'Custom text' field value is selected. 1. Enter the **value of the option.** 2. Select the **color of the option.** This is reflected on metrics graphs. 3. Drag and drop to **re-order the options** as they appear in dropdowns. 4. **Delete** an option. 5. **Copy** the `form_field_option_id`. This is used in API calls and Liquid syntax. 6. **Add** more options. Custom fields can be configured to have a default value. For example, if you want all your incidents to default to Zone 1 for the Zone custom field, then you can set it here. This is the same setting as the toggle described in the **Enable/Disable Field** section above. Only enabled fields are considered to be live fields - meaning they can appear on UI screens and be updated during incidents. Disabled fields are NOT usable during incidents and cannot be updated by workflows either. You can use the toggle switch next to the field name to enable/disable it. This switch allows you to display or hide the specific field on the **Details** section of the **Incident Details** page. **Hiding a field** from being displayed in the **Details** section **does not mean this field is turned off**. It just means users cannot edit it from the UI. This is typically used when teams want to configure a custom flag that gets systematically set by workflows, not manually by users. This field allows you to select the value type for select and multiple select fields. The following Value types are available: Custom text, Teams, Services, Users, Functionalities, and Catalog. * **Custom text** allows user input to determine what values are available for selection. * **Teams, Services, Users, Functionalities, or Catalog** allow the custom field to pull from one of the existing fields populated in Rootly. For example, an organization may want to identify both an 'Owning Team' as well as a set of 'Impacted Teams.' A new custom field could be created for 'Impacted Teams' and the existing 'Teams' field could be renamed to 'Owning Team.' ### Delete Field Custom fields can be deleted by clicking the trash symbol. Deleted fields cannot be recovered. It is highly recommended that you disable unused custom fields instead of deleting them. Deletion should be reserved for only when you're sure that it won't be used in the response process anymore. Custom fields can be referenced in Liquid using either the field **slug** or **ID**.\ The `find` filter returns a custom field object, from which you can access different attributes depending on the field type and configured Value Type. *** ## Supported Field Types Below are all supported custom field types and the recommended Liquid syntax for each. ### Text A single-line free-form text field that allows users to enter short text values such as names, identifiers, or brief descriptions. This field type is ideal for capturing simple, unstructured text data. This Liquid syntax retrieves the text value stored in the custom field: ```liquid theme={null} # By SLUG {{ incident.custom_fields | find: 'custom_field.slug', 'your-custom-field-slug' | get: 'value' }} # By ID {{ incident.custom_fields | find: 'custom_field.id', 'your-field-uuid' | get: 'value' }} ``` ### Textarea A multi-line free-form text field that allows users to enter longer text content such as detailed descriptions, notes, or comments. Unlike the Text field, Textarea supports multiple lines of text input. This Liquid syntax retrieves the multi-line text value stored in the custom field: ```liquid theme={null} # By SLUG {{ incident.custom_fields | find: 'custom_field.slug', 'your-custom-field-slug' | get: 'value' }} # By ID {{ incident.custom_fields | find: 'custom_field.id', 'your-field-uuid' | get: 'value' }} ``` ### Rich Text A formatted text field that supports rich text formatting (bold, italic, lists, links, etc.) using HTML markup. This field type is stored as an HTML string and is ideal for formatted content that needs to preserve styling. This Liquid syntax retrieves the HTML-formatted text value stored in the custom field: ```liquid theme={null} # By SLUG {{ incident.custom_fields | find: 'custom_field.slug', 'your-custom-field-slug' | get: 'value' }} # By ID {{ incident.custom_fields | find: 'custom_field.id', 'your-field-uuid' | get: 'value' }} ``` Rich text values may contain HTML markup. Be mindful when rendering these values in notifications or external systems. ### Tags **Tags is no longer available in the field type dropdown when you create a custom field in the UI.** To create a Tags field, use the API: send a `POST` to `/api/v1/form_fields` with `"input_kind": "tags"` (see the [form field API reference](/api-reference/formfields/creates-a-form-field)). To stay in the UI, create a **Multiple Select** field instead — you define the allowed options upfront, so it suits a known set of values rather than free-form tags. Existing Tags fields keep working and use the Liquid syntax below. A multi-value tag field that allows users to add multiple tags or labels to an incident. Tags are stored as a JSON array string, making them useful for categorization, filtering, or labeling incidents with multiple attributes. This Liquid syntax retrieves the JSON array string containing all tags: ```liquid theme={null} # By SLUG {{ incident.custom_fields | find: 'custom_field.slug', 'your-custom-field-slug' | get: 'value' }} # By ID {{ incident.custom_fields | find: 'custom_field.id', 'your-field-uuid' | get: 'value' }} ``` Tags values are stored as a JSON array string (for example, `["tag1", "tag2", "tag3"]`). You may need to parse this JSON string depending on your use case. ### Number A numeric input field that enforces numeric values only. This field type is useful for capturing quantities, counts, percentages, or any numeric data. The value is stored as a string representation of the number. This Liquid syntax retrieves the numeric value stored in the custom field: ```liquid theme={null} # By SLUG {{ incident.custom_fields | find: 'custom_field.slug', 'your-custom-field-slug' | get: 'value' }} # By ID {{ incident.custom_fields | find: 'custom_field.id', 'your-field-uuid' | get: 'value' }} ``` Number values may be stored as strings. Use Liquid math filters if numeric operations are required. ### Checkbox A boolean field that stores a checked ("1") or unchecked ("0") state. This field type is ideal for yes/no questions, flags, or binary choices that need to be tracked. This Liquid syntax retrieves the checkbox value and checks whether it's checked: ```liquid theme={null} # By SLUG {% assign v = incident.custom_fields | find: 'custom_field.slug', 'your-custom-field-slug' | get: 'value' %} # By ID {% assign v = incident.custom_fields | find: 'custom_field.id', 'your-field-uuid' | get: 'value' %} {% if v == "1" %} true {% else %} false {% endif %} ``` ### Date A date picker field that allows users to select a specific date. The value is stored as an ISO date string, making it easy to format and use in date calculations or comparisons. This Liquid syntax retrieves the date value stored in the custom field: ```liquid theme={null} # By SLUG {{ incident.custom_fields | find: 'custom_field.slug', 'your-custom-field-slug' | get: 'value' }} # By ID {{ incident.custom_fields | find: 'custom_field.id', 'your-field-uuid' | get: 'value' }} ``` This Liquid syntax formats the date value for display: ```liquid theme={null} # By SLUG {{ incident.custom_fields | find: 'custom_field.slug', 'your-custom-field-slug' | get: 'value' | date: '%B %d, %Y' }} # By ID {{ incident.custom_fields | find: 'custom_field.id', 'your-field-uuid' | get: 'value' | date: '%B %d, %Y' }} ``` ### Datetime A date and time picker field that allows users to select both a date and a specific time. The value is stored as an ISO datetime string, making it suitable for scheduling, timestamps, or any scenario requiring precise date and time tracking. This Liquid syntax retrieves the datetime value stored in the custom field: ```liquid theme={null} # By SLUG {{ incident.custom_fields | find: 'custom_field.slug', 'your-custom-field-slug' | get: 'value' }} # By ID {{ incident.custom_fields | find: 'custom_field.id', 'your-field-uuid' | get: 'value' }} ``` This Liquid syntax formats the datetime value for display: ```liquid theme={null} # By SLUG {{ incident.custom_fields | find: 'custom_field.slug', 'your-custom-field-slug' | get: 'value' | date: '%B %d, %Y at %I:%M %p' }} # By ID {{ incident.custom_fields | find: 'custom_field.id', 'your-field-uuid' | get: 'value' | date: '%B %d, %Y at %I:%M %p' }} ``` ### Catalog A Catalog field only accepts the entities configured in the related Catalog. Use this field type when you want to track the impact of an incident against one of your business entities configured as a Catalog, like Teams, Services, or any custom Catalogs. Catalog Fields can be automatically set based on properties in your Catalog. For example, any `Services` Catalog field could be automatically set by a `Team` Catalog field, as long as the Team Catalog has a Services property. This would allow you to automatically track the Services an incident is impacting as your users add teams to the incident. ### Select A single-choice field that allows users to select one value from a predefined list of options. ### Multiple Select A multi-choice field that allows users to select one or more values from a predefined list of options. Storage follows the same pattern as Select, but may contain multiple values. The storage format and available attributes depend on the configured **Value Type**. ## Best Practices * Prefer referencing custom fields by **ID** in Liquid to avoid breaking changes when field names change. * Use field **Descriptions** to guide responders toward consistent data entry. * Hide workflow-managed fields from the Incident Details UI to reduce manual edits. * Ensure you reference the correct `selected_*` attribute based on the field’s **Value Type**. *** ## Related Pages The fixed set of Rootly incident properties — the fields you extend with custom ones. Place custom fields on additional forms beyond the built-in set. The umbrella page covering incident properties, fields, and configuration surface. # Custom Forms Source: https://docs.rootly.com/configuration/custom-forms Build tailored forms with specific field combinations to collect targeted incident data at different stages of the response lifecycle. Throughout the lifecycle of an incident, teams might want to prompt responders to input various incident properties outside of the [standard built-in forms](/configuration/built-in-forms). Custom forms enable teams to define their own forms that can be triggered either through a custom Slack command or a button within a custom Slack block. You can access the custom forms by navigating to **Configuration >** [**Forms**](https://rootly.com/account/forms) and scrolling to the bottom of the page. ## **Example Use Cases** * **Targeted Data Collection**: Create a form specifically for the Comms Lead, which only displays fields that are important to the leadership (for example, `status`, `summary`, `severity`). This streamlines the communication process by helping teams only focus on the relevant information. * **Guided Response:** Create various forms that collect specific sets of data at specific points of the incident life cycle. Dynamically display each custom form to guide responders through their response effort. ## **Create Custom Form** Click on the `Create Form` button to initiate the form creation wizard. A dialogue will appear requesting the following fields: Assign the custom form a name. Define a Slack command that would prompt to open the form in Slack. The full command you would enter in Slack is `/rootly customform your-custom-slack-command`. You only need to enter the `your-custom-slack-command` portion in this field. You can provide an optional description for your custom form. After providing the necessary details, click on `Save`. You’ll be redirected to the following page where you can begin customizing the new form. ## **Edit Custom Form** To begin editing a form, select the Configure button under the form you'd like to edit. You'll be navigated to the edit form page of the selected form. The **left side of the page is the edit pane** where you can edit what fields are displayed and how they are displayed. The **right side of the page is the preview** of the form. You can create separate versions of the form for Slack and Rootly Web/Mobile by toggling between the tabs on the left hand side. To ensure incident data is captured consistently, Rootly recommends keeping the fields for each channel in sync. ## Adding Fields to a Form Add new fields to your form by selecting the **Add Fields** button. Select all of the fields you'd like to add to the form, then **Add Fields**. Once these fields are added to your form, you can drag and drop them to reorder the form. Remove a field by selecting the **minus** button on the right hand side of the field. ## Editing Fields on a Form Once a field is added to a form, you can control when the field is displayed and if it is required. Select the edit button on the field that you want to make changes to. If you only want the field to display under certain conditions or be required under certain conditions, select the **Conditionally** option under **Display this field** or **Require this field**. Form fields can be displayed or required conditionally depending on the value of any field set above the field that you're editing. For example, if the first field on your form called "Teams" is set to a certain value, your second field can be conditionally displayed depending on the team's value. ## Preview The preview on the right-hand side is interactive and generated in real-time. This is a great way to test out the user experience of your form, and ensure behavior of each field is correct. ## Trigger Custom Form Custom forms can be triggered in various ways: Slack command, custom Slack block, or web UI. ## Prompt Form via Slack Command A custom form can be prompted in an incident Slack channel via manual command. The command can be found on the edit screen of the specific form. When you write the command in an incident Slack channel, you'll be prompted with the custom form. ## Prompt Form via Slack Block A custom form can also be prompted in an incident Slack channel via a button in a custom block. ## Prompt Form via Web UI Lastly, a custom form can also be prompted from the Rootly web UI. First navigate to a specific incident and then select the Custom Form dropdown at the top. The dropdown will contain all custom forms that have been configured in the organization. *** ## Related Pages Rootly's ship-with-defaults forms — the baseline custom forms live alongside. Form variants that adapt based on incident type, team, or severity. Add organization-specific fields to appear on custom forms. # Custom Statuses Source: https://docs.rootly.com/configuration/custom-statuses Define custom incident lifecycle stages beyond the default Active, Mitigated, and Resolved statuses to match your organization's response processes. Custom Statuses allow you to fully customize the statuses that represent your incident's lifecycles. By default, Rootly incidents progress through Active > Mitigated > Resolved. However, some organizations have much more granular statuses to represent key moments in the incident's lifecycle. Custom Statuses allow you to add, reorder, and capture key information on the incident throughout the incident lifecycle. ## Adding and editing statuses Navigate to **Configuration > Lifecycle** to begin customizing your Rootly statuses. Each substatus requires a name and description to give your responders context on what the lifecycle stage represents. When an incident's status is updated to reflect a new status, Rootly marks the date and time of the status change and stores it in the status' `Marked At` field to support any postmortem analyses. When a new status is added, Rootly will generate a new substatus form for you to customize in the Form configuration section. This allows you to capture incident data at any phase of the incident's lifecycle. ## Lifecycle Preferences Rootly gives you full control over how your incidents progress through the Lifecycle statuses. Control if your responders are able to move an incident across many statuses at once, or if incidents must progress through every status in a defined order. Navigate to **Configuration > Lifecycle > Preferences** to update these settings. Rootly Lifecycle Preferences page with custom status ordering settings If your Rootly instance requires incidents to progress through Active or Resolved in order, your responders will only be able to update the incident's status to the next status defined in your Lifecycle configuration. Responders are able to move an incident backward to any previous status. If they do so, they'll have to progress the incident through each status again. Get started with Custom Statuses by reaching out to your Rootly account representative today. *** ## Related Pages Where custom statuses fit in the incident properties model. The deliberate publish flow for pushing incident updates to a status page. Retrospectives are created when an incident resolves — pair status design with your retrospective process. # Dynamic Forms Source: https://docs.rootly.com/configuration/dynamic-forms Configure form variations that adapt based on incident properties like type, team, or severity to collect contextually relevant information. Rootly's dynamic forms allow for more granularity based on different incident types, different teams, or different severities that require different versions of the same forms. You can access the dynamic forms by navigating to **Configuration >** [**Forms**](https://rootly.com/account/forms). The Dynamic Forms feature is not enabled out of the box, but if you’d like to try it out, reach out to your Rootly point of contact or support team. [Video Example of Use Case](https://www.loom.com/share/11b9503c6bd94043bfafc6cdd5166021?sid=35cd9955-d742-45f3-b99f-b2840b3e0a74) Document image ## Incident Property Field The incident property is what is used to **base** the dynamic forms from. The options include Incident Type, Team, or Severity. This field is important — it drives the property you build your dynamic forms from. Once an incident property is selected, click `+ New Form Set` to create a dynamic form. ## **Creating Form Set** A unique name for this form set. The condition that decides when the form set applies — driven off incident type, team, or severity depending on the property you picked above. Then choose which default forms you would like to customize — only the forms you pick will diverge from the defaults; everything else stays inherited. ### Example Use Case One of the main use cases for this is when you want to give more granularity on different teams, incident types, or severities, but you want them to have different versions of the same form. For example, when the information I want to collect for the `security teams` incidents is different than the information I want to collect for the `infrastructure teams` incidents. But within that, within the `security teams` forms, I actually want certain fields different based on if it’s a SEV0 incident. Click 'Create Form Set'. Once created, you'll see the newly built 'Security Team Forms' on the left and the form types you wish to customize. These new forms will only show when `Team` is `Security`. Next, get more granular and only show these forms when the `Team` is `Security` **AND** the `Severity` is a `SEV0`. To do this, click 'Configure' on the form type you would like to edit. The form will start empty, minus your incident property field, which in this case is `Teams`. Add any custom or built-in fields by clicking 'Add Fields'. When the required fields are selected, click 'Add Fields'. Edit each field and choose when to display and/or require this field — at this stage you can add conditions. Set the field to only display when the incident is a `SEV0`, and **REQUIRE** the field. Click Save once the conditions are defined. ### To Test Create a new incident and set the team to `Security`. Once `` is selected, the form will auto-refresh with the dynamic 'Security Team Form'. ### Removing An Existing Dynamic Form Editing and deleting can be done by clicking on the ellipsis. Only one property can be selected at a time. Removing the existing incident property selection will delete all existing dynamic forms. You will be prompted with a warning message prior. ### Want to use dynamic forms? Reach out to your Rootly point of contact or support team to request access. *** ## Related Pages The baseline concept — dynamic forms are variants of custom forms driven by incident properties. The default forms dynamic variants extend. The umbrella concept covering every form variant and custom fields. # Environments Source: https://docs.rootly.com/configuration/environments Define environment values (Production, Staging, Development) to distinguish incident scope, drive workflow conditions, and segment metrics in Rootly. ## Overview **Environments** classify incidents by the deployment tier they impact — most commonly Production, Staging, and Development, though larger organizations often extend the list to include Sandbox, QA, Preview, or region-specific tiers like `prod-us-east` and `prod-eu-west`. Environment is often the second field responders reach for after Severity, because it's the fastest way to answer "does this need to page people right now?" A SEV0 in Development is a bug to triage during business hours; the same SEV0 in Production is an all-hands emergency. Environment is what carries that distinction into every downstream automation. *** ## How Environments Are Used Environments drive routing, urgency, and reporting throughout Rootly: | Feature | How Environment is used | | ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **[Workflow conditions](/workflows/conditions)** | The most common paging pattern is "Severity is SEV0 **and** Environments contains Production" — Environment scopes urgency to real customer-impacting tiers. | | **Slack channel + alias notifications** | Each Environment can be linked to Slack channels and user groups. Workflows use these to route Production incidents to `#incidents-prod` and non-production incidents to a lower-priority channel. | | **Notify emails** | Each Environment can be linked to email addresses. Useful for stakeholder groups that only care about Production events (executive comms, customer support). | | **Metrics + reporting** | Environment is a top-level filter in every dashboard. MTTR-by-Environment reveals whether your Production incidents resolve faster than Staging ones (they should — otherwise your Production incident response process isn't working). | | **Status page publication** | Not automatic — status page publication is decided by workflow conditions that typically check both Severity and Environment. Most teams auto-publish SEV0/SEV1 **in Production only**. | | **Retrospective triggers** | Different Environments can trigger different retrospective templates. Production incidents get the full customer-impact review; Staging incidents get a lightweight regression tracker. | Because Environment gates so much automation urgency, **an incorrectly-tagged Environment is the fastest way to page the wrong people (or nobody at all)**. Making sure responders can tell the Environment field from the Severity field on the incident form matters — see Best Practices below. *** ## Choosing Your Environment List Most teams start with three environments and add more as their infrastructure grows. ### Standard Three-Tier The default for most SaaS teams: * **Production** — live, customer-facing infrastructure. All customer-visible urgency lives here. * **Staging** — pre-production tier used for release verification. Incidents here delay releases but don't affect customers directly. * **Development** — engineering-owned tier used for feature work. Incidents here are usually contained to internal workflows. If you're just starting out, three is enough. Adding more environments only pays off when your organization actually operates them distinctly (different on-call rotations, different SLAs, different notification patterns). ### Extended Sets Larger organizations extend the list for real operational reasons — not just to add labels: | Additional Environment | When it's worth adding | | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Sandbox** | You give customers or partners isolated test environments that can have their own incidents. | | **QA** | Your QA team owns a distinct pre-release tier separate from Staging. | | **Preview** | Branch- or PR-specific ephemeral environments (Vercel, Netlify, Heroku pipeline apps). Rarely worth incidents unless you have production customers on Preview URLs. | | **`prod-us-east`, `prod-eu-west`, etc.** | You operate genuinely regional Production stacks with independent on-call rotations. Adding regions as separate Environments lets workflows route by geography. | | **Internal / Corporate** | Employee-facing internal systems (HR platforms, expense tools) that are distinct from customer-facing infrastructure. | ### Single-Select vs Multi-Select Environment can be configured as **single-select** (one Environment per incident) or **multi-select** (multiple Environments per incident). Which you choose changes both the picker and the workflow conditions available. * **Single-select** — cleaner and matches most teams' actual usage. An outage is either in Production or it isn't. Workflows filter with `is` / `is one of`. * **Multi-select** — useful when incidents span multiple deployment tiers simultaneously (for example, a shared dependency failing across `prod-us-east` and `prod-eu-west`). Workflows filter with `contains any of` / `contains all of`. Most teams start single-select. Switch to multi-select only when you regularly have incidents affecting more than one tier at once. *** ## Field Type Configure Environment as either **single-select** or **multi-select** in **Configuration → Environments**. The setting affects all new incidents; historical incidents keep their existing values. Liquid syntax differs slightly between the two modes. Single-select uses `{{ incident.raw_environments | get: '' }}` for the one value. Multi-select uses `{{ incident.raw_environments[index] | get: '' }}` where `index` references a specific Environment in the list. Both are covered in the attribute reference below. *** ## Configuring Environment Attributes Each Environment can be configured with the attributes below. All are available in Liquid syntax for use in workflows, retrospective templates, and status page updates. Unique identifier assigned automatically by Rootly on creation. **Not customizable.** Used in Liquid references and API calls. ```liquid theme={null} {{ incident.environment_ids }} {{ incident.raw_environments | get: 'id' }} {/* single-select */} {{ incident.raw_environments[0] | get: 'id' }} {/* multi-select, first Environment */} ``` The display name shown throughout the Rootly UI. Fully customizable — `Production`, `Prod`, `Live`, `prod-us-east`, whatever your team calls it. ```liquid theme={null} {{ incident.environments }} {{ incident.raw_environments | get: 'name' }} {{ incident.raw_environments[0] | get: 'name' }} ``` Auto-generated by lower-casing and hyphenating the name. Used in Liquid references and in workflow condition matches. **Slugs regenerate when you rename an Environment.** Anything referencing the old slug — workflow conditions, saved metrics dashboards, third-party integrations that filter by slug — needs to be updated after a rename. ```liquid theme={null} {{ incident.environment_slugs }} {{ incident.raw_environments | get: 'slug' }} {{ incident.raw_environments[0] | get: 'slug' }} ``` Additional context shown alongside the Environment in the UI. Best used to remind responders what "Production" means specifically for your team ("prod-us-east handling all US customer traffic" vs. a vague "Prod"). ```liquid theme={null} {{ incident.raw_environments | get: 'description' }} {{ incident.raw_environments[0] | get: 'description' }} ``` Six-digit hex color code used for Environment-tinted UI accents and metrics-graph color coding. Convention: red or brand red for Production, orange/yellow for Staging, blue/gray for Development. ```liquid theme={null} {{ incident.raw_environments | get: 'color' }} {{ incident.raw_environments[0] | get: 'color' }} ``` Rootly expects six-digit hex codes (for example, `#c4231c`). Use a color picker if you're not sure — [color-hex.com](https://www.color-hex.com/) is a common choice. One or more Slack channels linked to the Environment. **Linking alone doesn't post to the channels** — a workflow action (typically "Attached Environment Channels") reads this list and performs the notification. ```liquid theme={null} {{ incident.raw_environments | get: 'slack_channels' }} {{ incident.raw_environments[0] | get: 'slack_channels' }} ``` One or more Slack user groups (aka aliases) linked to the Environment. **Linking alone doesn't invite users** — a workflow action (typically "Attached Environment Aliases") reads this list and performs the invitation. ```liquid theme={null} {{ incident.raw_environments | get: 'slack_aliases' }} {{ incident.raw_environments[0] | get: 'slack_aliases' }} ``` One or more email addresses linked to the Environment. **Linking alone doesn't send email** — a workflow action reads this list and sends the notification. ```liquid theme={null} {{ incident.raw_environments | get: 'notify_emails' }} {{ incident.raw_environments[0] | get: 'notify_emails' }} ``` For workflow-driven use, most teams reference the flattened list: ```liquid theme={null} {{ incident.raw_environments | map: 'notify_emails' | flatten | join: ',' }} ``` *** ## Best Practices * **Always require Environment on incident creation.** An unspecified Environment is the fastest way to route a Production incident to the wrong Slack channel. Make Environment a required field on your incident-creation forms. * **Use color to reinforce Environment on the incident details view.** Red for Production, orange for Staging, blue for Development is the standard convention. Responders read the color before the label — a mis-colored Environment gets miscategorized more often. * **Gate every high-urgency workflow on Environment.** Workflows that page on-call, send stakeholder emails, or auto-publish the status page should always include an Environment condition. `Severity is SEV0` alone will page the team for a SEV0 in Dev, which nobody wants. * **Don't invent Environments for scope you don't operate distinctly.** Adding "QA" as an Environment only pays off if your QA team has an on-call rotation, distinct SLAs, or a separate notification pattern. Otherwise it's just a tag that fragments metrics. * **Test workflow conditions with Test Incidents in each Environment.** After adding a new Environment or reworking existing ones, `/rootly test` in each Environment and confirm the workflows route correctly. Do this before the next real incident hits the new definitions. * **Audit rare Environments quarterly.** If an Environment sees fewer than 5% of incidents over 90 days, it's probably not distinct enough — consider merging it with a peer or removing it. *** ## Troubleshooting Confirm the Environment is enabled under Configuration → Environments. Archived Environments remain visible on historical incidents but don't appear as options on new incidents. Also check team-level restrictions — some teams scope which Environments their responders can select. Two common causes: (1) the workflow's condition uses `is` on a multi-select Environment field — switch to `contains any of` (see [Workflow Conditions](/workflows/conditions) for the operator reference); (2) the Environment slug was regenerated after a rename and the workflow still references the old slug. Update the workflow condition to match the new slug. Linking a Slack channel to an Environment doesn't cause auto-notification on its own — a workflow with an "Attached Environment Channels" action is required. Check that the workflow exists, is enabled, and has run conditions that match the Environment you're testing. The Environment Updated trigger is a good candidate. The metrics dashboard filters by Environment slug (not name). If your dashboard is grouping incidents incorrectly, check the filter query — it may still reference the pre-rename slug. Environment renames don't automatically update saved dashboards. Two common fixes: (1) Add a description on each Environment that clarifies what qualifies — "Production = live customer traffic. Not Staging, even if Staging is in-warranty." (2) Reorder the picker so Production is at the top (most common) and less-common Environments are further down. Alphabetical ordering isn't always the right default. *** ## Frequently Asked Questions Most teams start with three (Production, Staging, Development) and add more only when their operations actually differentiate. Adding Environments is only worth it if each new Environment has a distinct on-call rotation, SLA, or notification pattern — otherwise it's just a label that fragments metrics. Yes. Adding regions as separate Environments (for example, `prod-us-east`, `prod-eu-west`, `prod-asia`) is a common pattern for teams with independent regional on-call rotations. Workflows can then route incidents to the right regional team based on the Environment field. Yes. Environment is fully mutable — change it via the incident details page or a workflow action. Changes are logged in the incident timeline. This is different from Kind, which is immutable after declaration. Historical incidents keep the Environment value they were created with, even after the Environment is deleted from the picker. Only new incidents lose access to the removed Environment. For overhauls, archive rather than delete so historical metrics stay readable. Yes — Environments belong to a Team. Each team maintains its own Environment list, and the picker on an incident form shows the Environments defined for that incident's team. If your workspace uses multiple teams, define the Environments each team actually deploys to; there's no single org-wide Environment list. No. Test incidents (declared via `/rootly test`) are excluded from production metrics regardless of Environment. This is a Kind-level behavior — see [Incident Kind](/configuration/incident-kind) for the full exclusion matrix. Yes. In your incident-creation form (Configuration → Forms), mark the Environment field as required. This prevents responders from creating incidents without an Environment tag, which is important because Environment gates so much downstream routing. *** ## Related Pages The other most-used incident field. Severity + Environment together drive most workflow conditions. Use Environment in workflow run conditions to route Production incidents differently from non-Production. The customizable classification for what's broken, complementing Environment's answer to where it's broken. # Event Payloads Source: https://docs.rootly.com/configuration/event-payloads Reference documentation for webhook event payload structures used in Rootly integrations and custom automations, including incident, alert, and pulse events. ## alert.\* Alert webhook payloads contain the current alert and its timeline in `data.events`. Rootly emits `alert.updated` when the alert itself changes or a timeline event is added. Use the top-level `event.id` to deduplicate webhook delivery retries. Because the timeline is cumulative, use each `data.events[].id` to avoid reprocessing the same timeline entry across successive payloads. Events are ordered by `created_at`, oldest first. Adding a timeline event emits `alert.updated`; editing or deleting an existing timeline event does not. ### Alert Ownership Changes Manual ownership transfers preserve the existing `kind: action` and `action: paged` contract. They add `page_reason: manual_reassignment` so consumers can distinguish an explicit destination change from other pages. For multi-target pages, adding or removing a destination counts as an ownership change, and each successful page event from that request includes the reason. The same `page_reason` discriminator is available on alert events returned by the public API and mobile API. | `kind` | `action` | `page_reason` | Meaning | | -------- | -------- | --------------------- | --------------------------------------------------------------------------------------------------- | | `action` | `paged` | `manual_reassignment` | A user manually changed an existing alert's notification target or target set | | `action` | `paged` | Not present | An initial or automated page occurred, or the alert progressed within its current escalation policy | Progression between levels of the current escalation policy does not include `page_reason: manual_reassignment`. For a manual page, Rootly suppresses intermediate `alert.updated` deliveries and sends one update after the page operation settles. When the page creates a new alert, Rootly emits the normal `alert.created` event and also emits this settled `alert.updated`; subscribe to `alert.updated` for the resulting page event and ownership metadata. For a multi-target page, Rootly determines `page_reason` from the destinations that were successfully paged, and the cumulative timeline contains every successful page event from the request, including corrected metadata on earlier events when a later success changes the batch reason. Use the top-level `event.id` to deduplicate retries and each timeline event's `id` to reconcile the cumulative `data.events` list. Ownership-change timeline events include: * `user`: The complete user associated with the event. For an action event this is the actor; for a notification event this is the recipient. `user_id` remains available for compatibility. * `paged_user`: For a user-group page that fans out to an individual on-call user, the complete recipient user. This keeps the selected group in `notification_target` while identifying who was actually paged. The field is omitted for other target types. * `notification_target`: On the manual-page event, the notification target originally selected by the actor. Supported manual-reassignment types are `escalation_policy`, `group`, `service`, `functionality`, and `user`. `group` is the serialized target type for a Team selected in the Rootly interface. Every `notification_target` includes stable `type` and `id` fields. When the selected resource still exists, Rootly also includes its standard outgoing webhook fields: | `type` | Additional fields | | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | `escalation_policy` | `name`, `description`, `created_at`, `updated_at` | | `group` | `name`, `description`, `color`, notification configuration, integration identifiers, `created_at`, `updated_at` | | `service` | `name`, `slug`, descriptions, `color`, notification and repository configuration, integration identifiers, `created_at`, `updated_at` | | `functionality` | `name`, `slug`, descriptions, `color`, notification configuration, integration identifiers, `created_at`, `updated_at` | | `user` | `name`, `email`, `preferred_name`, `full_name`, `full_name_with_team`, `slack_id` | Downstream notification events can also identify the channel or space that received a notification. These are not manual-reassignment targets: | `type` | Additional fields | | ------------------------- | ----------------- | | `slack_channel` | `name` | | `microsoft_teams_channel` | `name` | | `google_chat_space` | `name` | If the referenced resource was deleted or is otherwise unavailable when the webhook is generated, `notification_target` remains present with only its stored `type` and `id`. Consumers should therefore treat all additional fields as optional. When an alert is transferred to an escalation policy with no pageable targets, the manual-page event still identifies the selected policy and the resulting `alert.updated` payload reports `data.status` as `open`. If the alert was previously non-`open`, the timeline also includes a `kind: status_update` event with `action: open`; an alert that was already `open` does not record another status transition. ### `alert.updated` Manual Reassignment Example The following representative payload shows the output of Rootly's outgoing alert serializer for a manual transfer to an escalation policy with no pageable targets. Optional fields may vary by alert and serializer version: ```json JSON theme={null} { "event": { "id": "39ad7696-7e4c-4114-88c9-258c4211d630", "type": "alert.updated", "issued_at": "2026-08-05T17:00:01.000-07:00" }, "data": { "id": "826a9d01-3745-468c-977d-05a64202881e", "source": "datadog", "status": "open", "summary": "API latency is above threshold", "labels": [], "services": [], "environments": [], "data": {}, "started_at": "2026-08-05T16:55:00.000-07:00", "ended_at": null, "created_at": "2026-08-05T17:00:00.000-07:00", "updated_at": "2026-08-05T17:00:01.000-07:00", "events": [ { "id": "276e87ef-1f2a-4b54-9267-feba4d7a2960", "alert_id": "826a9d01-3745-468c-977d-05a64202881e", "kind": "informational", "source": "datadog", "action": "created", "details": null, "user": null, "user_id": null, "notification_target": null, "incident_ids": [], "created_at": "2026-08-05T17:00:00.000-07:00", "updated_at": "2026-08-05T17:00:00.000-07:00" }, { "id": "b722de6d-55a6-4814-a576-e5e5e353745b", "alert_id": "826a9d01-3745-468c-977d-05a64202881e", "kind": "status_update", "source": "datadog", "action": "triggered", "details": null, "user": null, "user_id": null, "notification_target": null, "incident_ids": [], "created_at": "2026-08-05T17:00:00.001-07:00", "updated_at": "2026-08-05T17:00:00.001-07:00" }, { "id": "e626c88b-1bd7-4856-96c2-f95af0901457", "alert_id": "826a9d01-3745-468c-977d-05a64202881e", "kind": "action", "source": "web", "action": "paged", "details": "Escalating to the secondary policy", "user": { "id": 129, "name": "Ada Lovelace", "email": "ada@example.com", "preferred_name": null, "full_name": "Ada Lovelace", "full_name_with_team": "[Acme] Ada Lovelace", "slack_id": null }, "user_id": 129, "notification_target": { "type": "escalation_policy", "id": "9f8c123b-49fa-41c0-8ecf-7b1bef55f99c", "name": "Secondary escalation policy", "description": "Fallback ownership policy", "created_at": "2026-07-15T09:30:00.000-07:00", "updated_at": "2026-08-05T16:45:00.000-07:00" }, "incident_ids": [], "created_at": "2026-08-05T17:00:00.500-07:00", "updated_at": "2026-08-05T17:00:00.500-07:00", "page_reason": "manual_reassignment" }, { "id": "c213a7f1-9c8e-4c53-a427-ca2f8cb0e8a0", "alert_id": "826a9d01-3745-468c-977d-05a64202881e", "kind": "status_update", "source": "web", "action": "open", "details": null, "user": null, "user_id": null, "notification_target": null, "incident_ids": [], "created_at": "2026-08-05T17:00:01.000-07:00", "updated_at": "2026-08-05T17:00:01.000-07:00" } ] } } ``` *** ## genius\_workflow\_run.\* ```json JSON theme={null} { "event":{ "id":"88a53013-05dc-44df-bb4f-c68d890f8bf9", "type":"genius_workflow_run.queued", "issued_at":"2022-12-19T08:02:03.067-08:00" }, "data":{ "id":"daf992ed-df23-41df-a72c-438616b4f6dc", "kind":"incident", "status":"queued", "status_message": null, "user_id":3186, "genius_workflow_id":"a1b76e56-e1ab-4b36-856f-b6481251c698", "genius_workflow_name":"Send Email when incident starts", "queued_at":"2022-12-19T08:02:03.031-08:00", "started_at":null, "completed_at":null, "failed_at":null, "canceled_at":null, "triggered_by":"system", "created_at":"2022-12-19T08:02:03.031-08:00", "updated_at":"2022-12-19T08:02:03.031-08:00", "incident_id":"5c80f5a1-9389-4970-bb49-8268acf2954f", "incident_action_item_id":null, "incident_post_mortem_id":null, "alert_id":null, "pulse_id":null } } ``` ```json JSON theme={null} { "event":{ "id":"76376d80-29e4-4aaf-8295-c12f111cf5eb", "type":"genius_workflow_run.started", "issued_at":"2022-12-19T08:04:55.249-08:00" }, "data":{ "id":"ff3021be-6ac2-4253-afbe-ae866c0c75a3", "kind":"incident", "status":"started", "status_message": null, "user_id":3186, "genius_workflow_id":"a1b76e56-e1ab-4b36-856f-b6481251c698", "genius_workflow_name":"Send Email when incident starts", "queued_at":"2022-12-19T08:04:55.196-08:00", "started_at":"2022-12-19T08:04:55.220-08:00", "completed_at":null, "failed_at":null, "canceled_at":null, "triggered_by":"user", "status":"started", "created_at":"2022-12-19T08:04:55.196-08:00", "updated_at":"2022-12-19T08:04:55.226-08:00", "incident_id":"5c80f5a1-9389-4970-bb49-8268acf2954f", "incident_action_item_id":null, "incident_post_mortem_id":null, "alert_id":null, "pulse_id":null } } ``` ```json JSON theme={null} { "event":{ "id":"ae55dd1a-9bde-4a98-bd42-61df1e8dd80f", "type":"genius_workflow_run.completed", "issued_at":"2022-12-19T08:06:35.911-08:00" }, "data":{ "id":"4cd6046c-9ed9-423e-8145-a1891f82ac57", "kind":"incident", "status":"completed", "status_message": null, "user_id":3186, "genius_workflow_id":"678fbb8a-23bc-4fcf-8d46-b1833698b75b", "genius_workflow_name":"Send Email when incident starts", "queued_at":"2022-12-19T08:06:33.493-08:00", "started_at":"2022-12-19T08:06:33.512-08:00", "completed_at":"2022-12-19T08:06:35.887-08:00", "failed_at":null, "canceled_at":null, "triggered_by":"user", "created_at":"2022-12-19T08:06:33.493-08:00", "updated_at":"2022-12-19T08:06:35.887-08:00", "incident_id":"5c80f5a1-9389-4970-bb49-8268acf2954f", "incident_action_item_id":null, "incident_post_mortem_id":null, "alert_id":null, "pulse_id":null } } ``` ```json JSON theme={null} { "event":{ "id":"1562f78b-18fa-4d9f-a765-24e6dfba9794", "type":"genius_workflow_run.failed", "issued_at":"2022-12-19T08:08:18.521-08:00" }, "data":{ "id":"3ceebcf1-e82f-4dfe-97da-69cd0678696d", "kind":"incident", "status":"failed", "status_message": null, "user_id":3186, "genius_workflow_id":"a1b76e56-e1ab-4b36-856f-b6481251c698", "genius_workflow_name":"Send Email when incident starts", "queued_at":"2022-12-19T08:08:17.890-08:00", "started_at":"2022-12-19T08:08:17.908-08:00", "completed_at":null, "failed_at":"2022-12-19T08:08:18.498-08:00", "canceled_at":null, "triggered_by":"user", "created_at":"2022-12-19T08:08:17.890-08:00", "updated_at":"2022-12-19T08:08:18.498-08:00", "incident_id":"5c80f5a1-9389-4970-bb49-8268acf2954f", "incident_action_item_id":null, "incident_post_mortem_id":null, "alert_id":null, "pulse_id":null } } ``` ```json JSON theme={null} { "event":{ "id":"4b3d9e46-1a59-44a7-914d-b1758216b8d5", "type":"genius_workflow_run.canceled", "issued_at":"2022-12-19T11:09:16.508-05:00" }, "data":{ "id":"e9269feb-1f2b-4d35-9181-f6842361ec62", "kind":"incident", "status":"canceled", "status_message": null, "user_id":3186, "genius_workflow_id":"554f0a33-c05b-4352-87d4-1ec0332431bd", "genius_workflow_name":"Send Email when incident starts", "queued_at":"2022-12-19T11:02:04.659-05:00", "started_at":null, "completed_at":null, "failed_at":null, "canceled_at":"2022-12-19T11:09:16.480-05:00", "triggered_by":"system", "created_at":"2022-12-19T11:02:04.659-05:00", "updated_at":"2022-12-19T11:09:16.480-05:00", "incident_id":"5c80f5a1-9389-4970-bb49-8268acf2954f", "incident_action_item_id":null, "incident_post_mortem_id":null, "alert_id":null, "pulse_id":null } } ``` *** ## incident.\* ```json JSON theme={null} { "event": { "id": "9839c4ca-5e7b-416d-ad95-d09ae0c8eead", "type": "incident.created", "issued_at": "2022-11-27T19:44:33.633-08:00", }, "data": { "id": "b7eed587-50e6-44fe-b010-7a2bb05d737a", "sequential_id": 19, "title": "Sparkling Frost", "slug": "sparkling-frost", "kind": "normal", "private": false, "summary": null, "status": "started", "url": "http://localhost:3000/account/incidents/19-sparkling-frost", "short_url": null, "mitigation_message": null, "resolution_message": null, "cancellation_message": null, "public_title": null, "zoom_meeting_id": null, "zoom_meeting_start_url": null, "zoom_meeting_join_url": null, "shortcut_story_id": null, "shortcut_story_url": null, "shortcut_task_id": null, "shortcut_task_url": null, "asana_task_id": null, "asana_task_url": null, "github_issue_id": null, "github_issue_url": null, "jira_issue_id": null, "jira_issue_url": null, "google_meeting_id": null, "google_meeting_url": null, "trello_card_id": null, "trello_card_url": null, "linear_issue_id": null, "linear_issue_url": null, "zendesk_ticket_id": null, "zendesk_ticket_url": null, "slack_channel_name": null, "slack_channel_id": null, "slack_channel_url": null, "slack_channel_short_url": null, "service_now_incident_id": null, "service_now_incident_key": null, "service_now_incident_url": null, "opsgenie_incident_id": null, "opsgenie_incident_url": null, "opsgenie_alert_id": null, "opsgenie_alert_url": null, "victor_ops_incident_id": null, "victor_ops_incident_url": null, "pagerduty_incident_id": null, "pagerduty_incident_url": null, "mattermost_channel_id": null, "mattermost_channel_name": null, "mattermost_channel_url": null, "confluence_page_id": null, "confluence_page_url": null, "quip_page_id": null, "quip_page_url": null, "airtable_base_key": null, "airtable_table_name": null, "airtable_record_id": null, "airtable_record_url": null, "google_drive_id": null, "google_drive_url": null, "datadog_notebook_id": null, "datadog_notebook_url": null, "freshservice_ticket_id": null, "freshservice_ticket_url": null, "freshservice_task_id": null, "freshservice_task_url": null, "started_at": "2022-11-27T19:36:00.000-08:00", "detected_at": null, "acknowledged_at": null, "mitigated_at": null, "resolved_at": null, "cancelled_at": null, "created_at": "2022-11-27T19:36:49.779-08:00", "updated_at": "2022-11-27T19:36:49.779-08:00", "labels": { }, "severity": null, "user": { "id": 7, "name": "John Doe", "email": "demo@rootly.com", "full_name": "John Doe", "full_name_with_team": "[rootly.com] John Doe", "slack_id": null }, "started_by": { "id": 7, "name": "John Doe", "email": "demo@rootly.com", "full_name": "John Doe", "full_name_with_team": "[rootly.com] John Doe", "slack_id": null }, "mitigated_by": null, "resolved_by": null, "cancelled_by": null, "roles": [ { "id": "e5c83728-78b9-495f-bdc5-55b3db047339" }, { "id": "45602201-6cb9-4567-abd6-293096d880ef" } ], "environments": [ ], "incident_types": [ ], "services": [ ], "functionalities": [ ], "groups": [ ], "events": [ { "id": "01608451-5926-41ea-88b0-5af2f3cf5f79", "event": "John Doe created this incident", "event_raw": "John Doe created this incident", "kind": "event", "source": "web", "visibility": "external", "occurred_at": "2022-11-27T19:36:49.779-08:00", "created_at": "2022-11-27T19:36:49.779-08:00", "updated_at": "2022-11-27T19:36:49.884-08:00" }, { "id": "42a1a95d-5ae2-4b74-a8dd-af675311769a", "event": "Started date has been set to November 27 7:36 PM PST", "event_raw": "Started date has been set to November 27 7:36 PM PST", "kind": "trail", "source": "web", "visibility": "internal", "occurred_at": "2022-11-27T19:36:49.955-08:00", "created_at": "2022-11-27T19:36:49.955-08:00", "updated_at": "2022-11-27T19:36:49.955-08:00" } ], "action_items": [ { "id": "a3121c52-39a8-4ba4-aef4-e33e6c6bcbdc", "incident_id": "b7eed587-50e6-44fe-b010-7a2bb05d737a", "description": null, "summary": "Tasks can be customized in Rootly", "kind": "task", "priority": "medium", "status": "open", "due_date": null, "jira_issue_id": null, "jira_issue_url": null, "asana_task_id": null, "asana_task_url": null, "github_issue_id": null, "github_issue_url": null, "shortcut_story_id": null, "shortcut_story_url": null, "shortcut_task_id": null, "shortcut_task_url": null, "trello_card_id": null, "trello_card_url": null, "linear_issue_id": null, "linear_issue_url": null, "zendesk_ticket_id": null, "zendesk_ticket_url": null, "airtable_base_key": null, "airtable_table_name": null, "airtable_record_id": null, "airtable_record_url": null, "freshservice_ticket_id": null, "freshservice_ticket_url": null, "freshservice_task_id": null, "freshservice_task_url": null, "created_at": "2022-11-27T19:15:07.651-08:00", "updated_at": "2022-11-27T19:15:07.651-08:00" }, { "id": "70ef7704-aecb-401a-833d-edaf8aaa9d86", "incident_id": "b7eed587-50e6-44fe-b010-7a2bb05d737a", "description": null, "summary": "Update `/incident summary`", "kind": "task", "priority": "medium", "status": "open", "due_date": null, "jira_issue_id": null, "jira_issue_url": null, "asana_task_id": null, "asana_task_url": null, "github_issue_id": null, "github_issue_url": null, "shortcut_story_id": null, "shortcut_story_url": null, "shortcut_task_id": null, "shortcut_task_url": null, "trello_card_id": null, "trello_card_url": null, "linear_issue_id": null, "linear_issue_url": null, "zendesk_ticket_id": null, "zendesk_ticket_url": null, "airtable_base_key": null, "airtable_table_name": null, "airtable_record_id": null, "airtable_record_url": null, "freshservice_ticket_id": null, "freshservice_ticket_url": null, "freshservice_task_id": null, "freshservice_task_url": null, "created_at": "2022-11-27T19:15:07.626-08:00", "updated_at": "2022-11-27T19:15:07.651-08:00" }, { "id": "368921f4-419c-4df3-92a2-006c3882dc70", "incident_id": "b7eed587-50e6-44fe-b010-7a2bb05d737a", "description": null, "summary": "Ensure roles are assigned", "kind": "task", "priority": "medium", "status": "open", "due_date": null, "jira_issue_id": null, "jira_issue_url": null, "asana_task_id": null, "asana_task_url": null, "github_issue_id": null, "github_issue_url": null, "shortcut_story_id": null, "shortcut_story_url": null, "shortcut_task_id": null, "shortcut_task_url": null, "trello_card_id": null, "trello_card_url": null, "linear_issue_id": null, "linear_issue_url": null, "zendesk_ticket_id": null, "zendesk_ticket_url": null, "airtable_base_key": null, "airtable_table_name": null, "airtable_record_id": null, "airtable_record_url": null, "freshservice_ticket_id": null, "freshservice_ticket_url": null, "freshservice_task_id": null, "freshservice_task_url": null, "created_at": "2022-11-27T19:15:07.601-08:00", "updated_at": "2022-11-27T19:15:07.651-08:00" } ], "form_field_selections": [ ], "feedbacks": [ ], "incident_post_mortem": null } } ``` When [custom fields on action items](/incidents/action-items/action-item-custom-fields) are enabled for your team, each action item in the `action_items` array carries a `custom_field_selections` array for the fields placed on its form. Each entry looks like: ```json JSON theme={null} "custom_field_selections": [ { "id": "b1e0c1a2-9f3c-4a7e-8d21-4f2a6b7c8d90", "value": "Payments", "form_field": { "id": "9f3c4a7e-8d21-4f2a-6b7c-8d90b1e0c1a2", "name": "Business Unit", "slug": "business-unit" }, "selected_options": [], "selected_users": [], "selected_groups": [], "selected_services": [], "selected_functionalities": [], "selected_catalog_entities": [], "selected_environments": [], "selected_causes": [], "selected_incident_types": [] } ] ``` Free-text, number, and date fields populate `value`; reference-type fields (user, team, service, catalog entity, environment, cause, incident type) populate the matching `selected_*` array instead. *** ## incident\_post\_mortem.\* ```json JSON theme={null} { "event": { "id": "9839c4ca-5e7b-416d-ad95-d09ae0c8eead", "type": "incident_post_mortem.created", "issued_at": "2022-11-27T19:36:00.000-08:00", }, "data": { "id": "2c7497e5-5d15-4fa4-aeac-cac063aafe19", "incident_id": "b7eed587-50e6-44fe-b010-7a2bb05d737a", "title": "Sparkling Frost", "status": "draft", "url": "http://rootly.com/account/incidents/19-sparkling-frost/postmortem_url", "short_url": null, "content": "

{{incident.created_at | date: \"%Y-%m-%d\"}} - {{incident.title}}

\n

Leadup

\n
Describe the circumstances that led to this incident

\n

Fault

\n
Describe what failed to work as expected

\n

Detection

\n
Describe how the incident was detected

\n

Root causes

\n
Run a 5-whys analysis to understand the true causes of the incident

\n

Mitigation and resolution

\n
What steps did you take to resolve this incident?

\n

Lessons learnt

\n
What went well? What could have gone better? What else did you learn?

", "published_at": null, "started_at": "2022-11-27T19:36:00.000-08:00", "mitigated_at": "2022-11-27T19:44:32.156-08:00", "resolved_at": "2022-11-27T19:44:32.156-08:00", "cancelled_at": null, "show_timeline": true, "show_timeline_starred_only": false, "show_timeline_genius": true, "show_timeline_trail": true, "show_timeline_tasks": true, "show_timeline_action_items": true, "show_functionalities_impacted": true, "show_services_impacted": true, "show_groups_impacted": true, "show_action_items": true, "created_at": "2022-11-27T19:36:49.779-08:00", "updated_at": "2022-11-27T19:44:32.177-08:00" } } ``` *** ## pulse.\* ```json JSON theme={null} { "event": { "id": "9839c4ca-5e7b-416d-ad95-d09ae0c8eead", "type": "pulse.created", "issued_at": "2022-11-27T19:15:30.995-08:00", }, "data": { "id": "aa1cab03-00e7-4578-b1ae-72ad9ae417c6", "team_id": 1, "pulse_trail_id": "b59bfcb7-89ed-4641-b288-5ce1bb3dd801", "summary": "Deployed to Kubernetes", "labels": [ { "key": "label1", "value": "value1" }, { "key": "label2", "value": "value2" } ], "data": { "hello": "world" }, "external_id": null, "started_at": "2022-11-27T19:15:30.995-08:00", "ended_at": null, "deleted_at": null, "created_at": "2022-11-27T19:15:30.995-08:00", "updated_at": "2022-11-27T19:15:30.995-08:00", "webhook_type": null, "webhook_id": null, "webhook_idempotency_key": null, "external_url": null, "source": "k8s", "refs": [ { "key": "image", "value": "registry.rootly.com/rootly/my-service:cd6214" } ] } } ``` # Example Usage With Incidents Source: https://docs.rootly.com/configuration/example-usage-with-incidents Learn how playbooks automatically attach relevant action items and response procedures when incident types are assigned during incident response. This example appends a playbook to a newly created incident. If I was in Slack for example I would do this by clicking the "Update" button (Seen below). Document image Let's say this was a security related incident. Once I append "Security" to the types field that would then automatically attach the related playbooks that were associated with the "Security" types. Document image As you can see below the action items have increased from 3 to 6 because the Security type action items were appended. Clicking the Action Items button gives us a full list of all the action items. Document image Document image You can also modify incidents in the Rootly UI as well by navigating to the Incidents tab and clicking edit on the appropriate incident. Modifying incidents in the UI will also automatically attach any relevant playbooks associated with the changes. Document image # Forms and custom fields overview Source: https://docs.rootly.com/configuration/forms-and-fields Configure incident data collection forms and custom fields in Rootly to control when and how information is captured during the incident response lifecycle. Use Forms in Rootly to capture incident data throughout your incident's lifecycle. Forms can be filled out at key moments during your incident lifecycle across Slack and web. The form can be completely customized depending on the stage and type of incident using fields. Start configuring your forms by logging into the Rootly web app and navigating to **Configuration > Forms**. Rootly Forms configuration page ## **Default Forms** Rootly comes with a series of built-in forms that cannot be deleted. These forms are used to capture information about your incident at standard moments in your incident lifecycle, such as when the incident is created, updated, or cancelled. The information captured on these forms can be completely customized by updating the form and adding or removing additional fields. Learn about customizing these default forms on the [Built-In Forms](/configuration/built-in-forms) page. ## **Custom Forms** Create a custom form to capture information outside of when your incident progresses or the lifecycle status changes. Custom forms can be opened and filled out through a Slack command or using a Slack block button. To learn about how to create and manage custom forms, please see the [Custom Forms](/configuration/custom-forms) page. ## Sub-Status Forms For customers with access to Custom Lifecycles, Rootly creates a separate form for each custom substatus that you configure in the Lifecycle section of the application. These can be edited in the same way that default and custom forms can be under the substatus forms tab. ## Follow-Up Form The **Incident Follow Up** form controls which custom fields appear when a follow-up is added or edited on an incident—on the web and in Slack. Use it to capture organization-specific metadata (like product area or business unit) on your post-incident work. To learn how to configure it, see [Custom Fields on Action Items](/incidents/action-items/action-item-custom-fields). ## **Built-In Fields** Rootly comes with a series of built-in incident properties that are typically collected during incident responses. To learn about what can be customized and how to customize built-in fields, please see the [Built-In Fields](/configuration/built-in-fields) page. ## **Custom Fields** If the built-in properties are not enough to address your requirements, Rootly offers the ability to create custom incident properties in various data types. To learn about how to create custom fields, please see the [Custom Fields](/configuration/custom-fields) page. *** ## Related Pages Rootly's default forms. Author additional forms with your own field selection. Add organization-specific fields that appear on any form. # Functionalities Source: https://docs.rootly.com/configuration/functionalities Configure functionality categories in Rootly to identify impacted product features during incidents, route to appropriate teams, and surface ownership context. ## Overview **Functionalities** allow you to specify the impacted features during an incident. This can help you identify which responders to bring in, which on-call to page, which customers to inform, etc. Individual functionalities can be mapped to your status pages. ## Adding Properties While Functionalities in Rootly comes with built-in properties, additional properties can be added. This allows you to build automations and workflows for your incident response processes using this information: for example, quickly identifying the customer impact of an incident based on the related functionality. To add custom properties, open **Functionalities**, click **Edit catalog**, and click **Add Property**. You can choose from several property types, including text, boolean, and importantly references to other Catalogs. For each Functionality, you'll be able to find the values of these properties in the **Custom Properties** tab. ## Configuring Functionalities Begin editing the properties of your Functionalities by selecting the '...', then Edit. ## Basics Update the information in this tab to set the fundamental details about your functionality. Auto-generated. Use it when referring to the functionality from Rootly's API. A descriptive name other Rootly users see when they select or search for the functionality. Internal description shown to Rootly users — for example, in the functionality picker. External-facing description shown to visitors on your Rootly Status Page. ## Ownership Assign the responsible stakeholders of your functionality. The values in these fields can be used to automate tasks and processes using Workflows in Rootly. For example, update an incident with the functionality's `Team` when a functionality is added to an incident. ## Connections Add connections between other entities in Rootly, like Environments, Services, Playbooks, and Escalation Policies. This information can be used to automate tasks and processes using Workflows in Rootly. For example, post a message in the incident channel linking to the functionality's playbook when a functionality is added to an incident. ### Paging Functionalities Functionalities can be paged when things go wrong. When a functionality is paged (either by an Alert Source, or manually by another user), the functionality's escalation policy will fire. Functionalities can only be paged if they have an assigned escalation policy. Make sure to set this up in the Functionality's Connection tab in Rootly. ## Alerting & Notifications Add relevant channel properties to the functionality to automate communications and processes using Workflows in Rootly. For example, use the `Slack Channel` property to post a message in a Slack channel dedicated to the functionality when it is added to an incident. ## Custom Properties Add the values to your custom properties in this section. Learn more about adding custom properties [in this section](/configuration/functionalities). ## On-Call Configure what happens when this Functionality is paged in Rootly On-Call. When this Functionality is paged either manually by a user, or through an Alert Source, the Escalation Policy selected here will fire. ## Incident Fields **Functionalities** can be customized to be either a **select** or **multi-select** field type. This means you can configure it to allow only one functionality value to be selected per incident or allow multiple functionality values to be selected per incident. ## Attributes **Functionalities** can be configured with the following attributes. Each functionality attribute can be referenced via Liquid syntax. Since the functionality field can be either a **select** or **multi-select** field type, the Liquid syntax to reference each field type will differ. Select will follow a single-value syntax `{{incident.raw_functionalities | get: ''}}` Multi-select will follow an array syntax. Where i references the specific functionality object in the list of functionalities. `{{incident.raw_functionalities[index] | get: ''}}` ### ID This is the unique identifier of the functionality. This field **cannot be customized**. Rootly will automatically assign the *ID* upon creation. It is typically used in Liquid references and API calls. The following Liquid syntax will allow you to list out the functionality *ID*(s) that are selected for an incident: `{{ incident.functionality_ids }}` **OR** * `{{ incident.raw_functionalities | get: 'id'}}` for the select field type * `{{ incident.raw_functionalities[index] | get: 'id' }}` for a multi-select field type ### Name This is the value that is displayed on the UI for the functionality. This field is customizable. The following Liquid syntax will allow you to list out the functionality *name*(s) that are selected for an incident: `{{ incident.functionalities }}` **OR** * `{{ incident.raw_functionalities | get: 'name'}}` for the select field type * `{{ incident.raw_functionalities[index] | get: 'name' }}` for a multi-select field type ### Slug This is the string that is used to reference the functionality in Liquid references. This field is automatically generated by lower-casing and hyphenating the functionality *name*. The following Liquid syntax will allow you to list out the functionality *slug*(s) that are selected for an incident: `{{ incident.functionality_slugs }}` **OR** * `{{ incident.raw_functionalities | get: 'slug'}}` for the select field type * `{{ incident.raw_functionalities[index] | get: 'slug' }}` for a multi-select field type ### Description This value is displayed on the UI to further explain each functionality. This field is customizable. The following Liquid syntax will allow you to list out the functionality *description*(s) that are selected for an incident: * `{{ incident.raw_functionalities | get: 'description'}}` for the select field type * `{{ incident.raw_functionalities[index] | get: 'description' }}` for a multi-select field type ### Color Each functionality can be assigned a color, which will be used for color-coding on metrics graphs. Rootly uses **color-hex codes**. For example, #000000 is black, #ffffff is white. Use [color-hex.com](https://www.color-hex.com/) to find the exact hex code for the color you want. The following Liquid syntax will allow you to list out the functionality *color*(s) that are selected for an incident: * `{{ incident.raw_functionalities | get: 'color'}}` for the select field type * `{{ incident.raw_functionalities[index] | get: 'color' }}` for a multi-select field type ### Slack Channels Each functionality can be linked to one or more Slack channels. By default, Rootly does not notify the linked channel(s) when a functionality is selected for an incident. Notification needs to be explicitly called out as Attached Functionality Channels in workflow configurations. Systematically, each Slack channel is stored as an object containing an ID and name. The following Liquid syntax will allow you to list out the functionality *Slack Channel*(s) that are selected for an incident: * `{{ incident.raw_functionalities | get: 'slack_channels'}}` for the select field type * `{{ incident.raw_functionalities[index] | get: 'slack_channels' }}` for a multi-select field type ### Slack Aliases Each functionality can be linked to one or more Slack user groups (aka aliases). By default, Rootly does not invite users in the linked user group(s) when a functionality is selected for an incident. Invitations need to be explicitly called out as Attached Functionality Aliases in workflow configurations. The following Liquid syntax will allow you to list out the functionality *Slack Alias*(es) that are selected for an incident: * `{{ incident.raw_functionalities | get: 'slack_aliases'}}` for the select field type * `{{ incident.raw_functionalities[index] | get: 'slack_aliases' }}` for a multi-select field type ### Notify Emails Each functionality can be linked to one or more emails. By default, Rootly does not send emails to the linked address(es) when a functionality is selected for an incident. Notification needs to be explicitly called out as `{{ incident.raw_functionalities | map: 'notify_emails' | flatten | join: ',' }}` in workflow configurations. The following Liquid syntax will allow you to list out the functionality *Notify Email*(s) that are selected for an incident: * `{{ incident.raw_functionalities | get: 'notify_emails'}}` for the select field type * `{{ incident.raw_functionalities[index] | get: 'notify_emails' }}` for a multi-select field type ## Import Functionalities Instead of creating functionalities from scratch, Rootly allows you to import functionalities from **PagerDuty** or **Opsgenie**. Imported functionalities will be automatically kept in sync on a daily basis. The ability to import functionalities will only become available once you have PagerDuty or Opsgenie installed on the [integrations page](https://rootly.com/account/integrations). The following Liquid syntax will allow you to list out the corresponding IDs from each of the external paging applications: **PagerDuty** * `{{ incident.raw_functionalities | get: 'pagerduty_id' }}` for the select field type * `{{ incident.raw_functionalities\[0\] | get: 'pagerduty_id' }}` for a multi-select field type **Opsgenie** * `{{ incident.raw_functionalities | get: 'opsgenie_id' }}` for the select field type * `{{ incident.raw_functionalities\[0\] | get: 'opsgenie_id' }}` for a multi-select field type *** ## Related Pages Functionalities group services into higher-level customer-facing capabilities. Functionalities can be owned by teams that get paged when the functionality is impacted. Functionalities are the customer-facing components most status pages display. # GitHub Configuration Source: https://docs.rootly.com/configuration/github Configure GitHub integration to automatically capture push events and pull request merges as contextual pulses during incident triage and analysis. The GitHub integration records repository activity as [pulses](/configuration/pulses) in Rootly, giving responders a timeline of recent code changes alongside their incidents. When something breaks, pulses help you correlate the incident with the pushes and pull requests that landed just before it. Rootly will **automatically** add the following GitHub events as pulses: * Push to any repositories * Merged pull requests * More to come... ## How It Works Once the GitHub integration is connected, Rootly receives push, pull request, and issue events from your repositories and surfaces them as pulses on the incident timeline and service activity feed. No extra configuration is needed for individual events — activity is captured automatically as it happens. Beyond pulses, the GitHub integration also lets you create and update GitHub issues from incident workflows, fetch recent commits across repositories during an incident, and automatically enrich GitHub pull request links shared in incident Slack channels with live status updates. ## Getting the most out of GitHub pulses * Use pulses during triage to answer "what changed?" — a deploy or merge shortly before an incident is often the fastest lead. * Pair the integration with [workflows](/workflows/workflows) to automate issue creation and keep GitHub in sync as incidents progress. Ready to configure the GitHub integration? See [GitHub integration setup](/integrations/github/github). ## Related pages * [GitHub integration setup](/integrations/github/github) — installation, permissions, and workflow actions * [Pulses](/configuration/pulses) — how change events appear in Rootly * [Workflows](/workflows/workflows) — automate incident response with GitHub actions *** ## Related Pages Where GitHub push and merge events appear as change events on incident timelines. Link services to specific GitHub repositories so pulses land on the right incident context. Full installation guide, permissions, and workflow actions. # GitLab Configuration Source: https://docs.rootly.com/configuration/gitlab Configure GitLab integration to automatically track repository pushes and merge requests as contextual pulses for enhanced incident analysis. The GitLab integration records repository activity as [pulses](/configuration/pulses) in Rootly, giving responders a timeline of recent code changes alongside their incidents. When something breaks, pulses help you correlate the incident with the pushes and merge requests that landed just before it. Rootly will **automatically** add the following GitLab events as pulses: * Push to any repositories * Merged merge requests * More to come... ## How It Works Once the GitLab integration is connected, Rootly receives webhook events from your tracked repositories and records them as pulses on the incident timeline and service activity feed. Push events, merged merge requests, and deployment events each produce a pulse with labels and refs identifying the repository, branch, and commit. You can limit tracking to specific repositories in the integration settings to reduce noise. Beyond pulses, the GitLab integration also lets you create and update GitLab issues from incident and action item workflows, fetch recent commits during an incident, and enrich GitLab merge request links pasted into incident Slack channels with live status cards. ## Getting the most out of GitLab pulses * Use pulses during triage to answer "what changed?" — a merge or deployment shortly before an incident is often the fastest lead. * Pair the integration with [workflows](/workflows/workflows) to automate GitLab issue creation and keep issues in sync as incidents progress. Ready to configure the GitLab integration? See [GitLab integration setup](/integrations/gitlab). ## Related pages * [GitLab integration setup](/integrations/gitlab) — installation, OAuth setup, and workflow actions * [Pulses](/configuration/pulses) — how change events appear in Rootly * [Workflows](/workflows/workflows) — automate incident response with GitLab actions *** ## Related Pages Where GitLab push and merge events appear as change events on incident timelines. Link services to specific GitLab repositories so pulses land on the right incident context. Full installation guide and setup details. # Heroku Configuration Source: https://docs.rootly.com/configuration/heroku Configure Heroku integration to automatically capture build events and release deployments as contextual pulses for incident correlation. The Heroku integration records build and release events from your Heroku apps as [pulses](/configuration/pulses) in Rootly, so responders can correlate deployments with incidents directly on the incident timeline. If an incident starts shortly after a release, the pulse feed makes that connection obvious. Rootly will **automatically** add the following Heroku events as pulses: * A build starts * A build ends ( Failed or succeeded ) * A release is deployed * More to come... ## How It Works Once connected via OAuth, Rootly creates webhooks on the Heroku apps you list in the integration settings and ingests their build and release events. Each pulse includes context like the commit SHA and the user who triggered the build, and pulses are automatically linked to Rootly [services](/configuration/services) with a matching **Heroku App Name** field — set this field on each service you want correlated with deployments. Only explicitly listed apps are monitored, so you control exactly which deployment activity shows up in Rootly. Beyond pulses, the integration also provides a **Run Command on Heroku** workflow action that executes one-off commands on a dyno — useful for rollbacks or diagnostic scripts mid-incident — and posts the output to Slack. Ready to configure the Heroku integration? See [Heroku integration setup](/integrations/heroku). ## Related pages * [Heroku integration setup](/integrations/heroku) — installation, pulse events, and the Run Command action * [Pulses](/configuration/pulses) — how deployment events appear in Rootly * [Services](/configuration/services) — link Heroku apps to the services they power *** ## Related Pages Where Heroku build and release events appear as change events on incident timelines. Link services to specific Heroku apps via the Heroku App Name field. Full installation guide plus the Run Command workflow action. # Incident Causes Source: https://docs.rootly.com/configuration/incident-causes Track root causes across incidents to surface systemic patterns, prioritize reliability work, and give retrospectives a shared, customizable vocabulary. ## Overview **Incident Causes** are the shared vocabulary your team uses to describe *why* an incident happened. Where [Severity](/configuration/severities) captures how bad an incident was and [Types](/configuration/incident-types) captures what category it fell into, Causes capture the underlying failure mode — `Third-party outage`, `Configuration drift`, `Deployment regression`, `Insufficient monitoring`. Causes are the field most retrospectives circle back to. Their real value shows up over the long term: three months of tagged Causes reveals whether your team is losing time to the same failure modes repeatedly, and gives reliability planning something concrete to point at. *** ## How Incident Causes Are Used Unlike Severity or Environment (set at incident creation), Causes are typically populated **during the retrospective process** — after mitigation, when the responding team has enough evidence to say what actually went wrong. The field is a multi-select because most real incidents have more than one contributing cause. | Feature | How Causes are used | | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Retrospective form** | The Causes field is added to the [Incident Retrospective Form](/configuration/built-in-forms) so responders pick Causes during the Gather & Confirm Data step. This is where most Causes get set. | | **Metrics + reporting** | Causes surface as a top-level filter in metrics dashboards. "Causes over the last 90 days" is one of the most-referenced reliability planning reports. | | **[Workflow conditions](/workflows/conditions)** | Filter workflows on Cause. Common patterns: auto-add a specific responder team when `Third-party outage` is tagged, or trigger a supplemental review workflow when `Insufficient monitoring` is tagged. | | **Retrospective templates** | Reference Causes in template Liquid — for example, a `{% if incident.causes contains 'Data integrity' %}` block that expands into a data-loss impact section. | | **API + Liquid references** | Causes are available as `{{ incident.causes }}` (names) and `{{ incident.cause_ids }}` (IDs) in workflow templates, retrospective templates, and API payloads. | Because Causes are the primary input to reliability planning, **the shape of your Cause list directly shapes what your team can improve on**. An overly generic list (`Bug`, `Human Error`) hides the actual failure modes; an overly granular one (`OAuth expiry on service X`) splinters data across too many buckets to see patterns. *** ## Choosing Your Cause Taxonomy Causes should describe **failure modes**, not incidents. The distinction matters — "Payment API returned 500s" is an incident description; `Third-party outage` and `Insufficient retry logic` are causes. ### How Many Causes Most teams land on **8–15 causes**. Fewer and everything collapses into `Other`. More and the causes stop being meaningfully different — responders default to the top-of-picker choices, and metrics lose signal. If a Cause hasn't been used in 90 days, retire it. If a single Cause accounts for more than 25% of incidents over 90 days, it's probably too broad and needs to be split. ### Common Cause Categories Causes that describe how systems broke, regardless of what the trigger was. | Cause | When to use | | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | | **Third-party outage** | An external service (Stripe, Twilio, an SSO provider, a cloud provider) failed and cascaded. | | **Deployment regression** | A recent release caused the incident. Recovery usually involves rollback. | | **Configuration drift** | A settings change (feature flag, DNS, environment variable) caused the incident. Often intentional, unintentionally impactful. | | **Capacity / scaling** | Traffic or workload exceeded provisioned capacity — auto-scaling failed to keep up, or wasn't configured. | | **Data integrity** | Data loss, corruption, or unintended exposure occurred. Almost always warrants a dedicated retrospective section. | | **Race condition** | Concurrent operations produced a wrong result. Hard to reproduce, easy to hand-wave, tag explicitly so you can track. | Causes that describe what your team could have done differently before the incident. | Cause | When to use | | --------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | | **Insufficient monitoring** | The team didn't know something was broken until a customer reported it. | | **Insufficient alerting** | Monitors existed, but nobody was paged in time. Threshold too high, wrong severity, alert going to a stale channel. | | **Runbook gap** | The responder didn't have documented steps for this scenario. Add to the retrospective's action items. | | **Test coverage gap** | Code that broke wasn't covered by tests that would have caught the failure mode. | | **Change management** | A change was rolled out without proper review, review didn't catch the issue, or rollout process didn't include a safe rollback path. | Causes that describe factors outside the team's direct control. | Cause | When to use | | -------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | **Vendor incident** | Different from third-party outage — this is a vendor-side bug or change that impacted your system, not just their infrastructure being down. | | **Regulatory / compliance change** | An external requirement changed, and your systems weren't updated in time. | | **User-triggered / expected behavior** | The incident wasn't a bug — a customer's usage pattern crossed a threshold that should have been documented or bounded. | *** ## Creating Incident Causes Manage Causes from **Configuration → Incident Causes** in the Rootly dashboard sidebar. (The Catalogs section is for service/component catalogs from tools like Backstage and Cortex — it does not create incident causes.) In the Rootly sidebar, navigate to **Configuration → Incident Causes**. The page lists every cause already defined for your organization. Click **Add New** (or the equivalent create button at the top of the list). Fill in: The display label that responders see on the incident form (for example, `Database deadlock`, `Third-party outage`, `Deployment regression`). Optional context shown when the cause is selected. Best used to disambiguate similar-sounding causes. Optional visual tag for dashboards and reports. The **Slug** is generated automatically from the Name by lower-casing and hyphenating — used in Liquid references and the API. Click **Save**. The new cause becomes immediately available as an option on the incident form's **Causes** multi-select field for all team members. Causes are multi-select per incident — responders can attach more than one cause when the root cause is genuinely shared between failure modes (for example, `Third-party outage` and `Insufficient monitoring`). Keep the list short and orthogonal to encourage selection rather than freeform notes. *** ## Field Type **Incident Causes** is a **multi-select** field type only. Every incident can have zero, one, or many causes attached — reflecting the reality that most incidents have multiple contributing factors. *** ## Configuring Cause Attributes Each Cause can be configured with the attributes below. All are available in Liquid syntax for use in workflows, retrospective templates, and status page updates. Unique identifier assigned automatically by Rootly on creation. **Not customizable.** Used in Liquid references and API calls. ```liquid theme={null} {{ incident.cause_ids }} {%- comment -%} first cause {%- endcomment -%} {{ incident.raw_causes[0] | get: 'id' }} ``` The display name shown throughout the Rootly UI. Fully customizable — pick names that describe failure modes, not incident descriptions. ```liquid theme={null} {{ incident.causes }} {{ incident.raw_causes[0] | get: 'name' }} ``` Auto-generated by lower-casing and hyphenating the name. Used in Liquid references and stable across name changes. ```liquid theme={null} {{ incident.cause_slugs }} {{ incident.raw_causes[0] | get: 'slug' }} ``` Additional context shown alongside the Cause in the UI. Best used to disambiguate similar-sounding Causes — for example, "Third-party outage: use when the external service itself is down. Use Vendor incident for cases where the vendor is up but their code introduced a bug in your system." ```liquid theme={null} {{ incident.raw_causes[0] | get: 'description' }} ``` Six-digit hex color code used for Cause-tinted UI accents and metrics-graph color coding. Group related causes with similar shades (for example, all "system" causes in blue, all "process" causes in orange). ```liquid theme={null} {{ incident.raw_causes[0] | get: 'color' }} ``` Rootly expects six-digit hex codes (for example, `#c4231c`). Use a color picker if you're not sure — [color-hex.com](https://www.color-hex.com/) is a common choice. Iterating over all Causes on an incident (for a Liquid template in a retrospective or workflow message): ```liquid theme={null} {% for cause in incident.raw_causes %} - {{ cause.name }}: {{ cause.description }} {% endfor %} ``` *** ## Best Practices * **Populate Causes during the retrospective, not at incident creation.** At creation time you don't know what caused the incident — you know a symptom. Wait until mitigation is done and the responding team has enough evidence to attach real causes. * **Design Causes to describe failure modes.** `Payment API returned 500s` is an incident description; `Third-party outage` and `Insufficient retry logic` are causes. The rewrite test: if the Cause could describe two different incidents in the same category, it's a good failure-mode Cause. * **Encourage multi-select.** Most real incidents have more than one cause. A single-cause tagging pattern usually means responders are collapsing complex root causes into whichever tag is dominant, which loses signal. * **Keep the list short and orthogonal.** Aim for 8–15 causes. If two Causes overlap conceptually (for example, `Deploy failure` and `Deployment regression`), merge them. If a Cause hasn't been used in 90 days, archive it. * **Retire and split based on data.** Every quarter, look at Cause frequency. Rare Causes (\<5% of incidents) get archived; dominant Causes (>25% of incidents) get split into more specific failure modes. * **Pair Causes with action items.** Cause tagging without follow-up work isn't reliability improvement — it's data collection. Each recurring Cause should have at least one open action item aimed at reducing its frequency. *** ## Troubleshooting Confirm the Cause is enabled under Configuration → Incident Causes. Archived Causes remain visible on historical incidents but don't appear as options on new incidents. Also check whether team-level restrictions are in play — some teams scope which Causes their responders can select. Two common causes: (1) responders are defaulting to a single Cause because the list is too long or badly ordered — reorder so most-common Causes are at the top; (2) responders aren't populating Causes at all because the field isn't on the retrospective flow. Add the Causes field to the [Incident Retrospective Form](/configuration/built-in-forms) so it appears in the Gather & Confirm Data step. Metrics queries filter by the Cause `slug`, not name. Renaming a Cause keeps the slug stable, so historical incidents remain grouped correctly. If a report is grouping incorrectly after a rename, refresh the dashboard cache — some reports lag one query cycle after configuration changes. The workflow's trigger needs to be **Causes Added** (or **Causes Updated**), and the run conditions need to reference the specific Cause you're tagging. See [Workflow Conditions](/workflows/conditions) for the operator reference — Causes is a multi-select field, so use `contains any of`, not `is`. They shouldn't. Deleting a Cause keeps the historical association intact on incidents that had it tagged; the Cause name just won't render on the current UI (it appears as archived). If you're seeing Causes disappear entirely from historical incidents, contact support — that's not expected behavior. *** ## Frequently Asked Questions **Type** captures *what kind of thing* the incident is — UI Bug, Infrastructure, Security Event. **Cause** captures *why the incident happened* — Third-party outage, Configuration drift, Insufficient monitoring. Type is usually set at incident creation; Cause is usually set during the retrospective. See [Incident Types](/configuration/incident-types) for the Type reference. After. During an active incident, responders don't yet know what caused the issue — they know symptoms. Wait until mitigation is done and the responding team has enough evidence. Most teams populate Causes as part of the retrospective template. Most teams land on 8–15. Fewer and everything collapses into `Other`. More and the causes stop being meaningfully different in practice. Audit quarterly and archive rare Causes (\<5% usage). Yes. Causes can be added programmatically via the incident update API and by workflow actions (Update Incident action → set Causes). This is useful for auto-tagging based on integration data — for example, automatically add `Third-party outage` when a specific external monitor triggered the incident. The Causes list is org-wide, but teams can restrict which Causes their responders can select. A shared Cause list with team-specific defaults is usually cleaner than maintaining separate lists per team. No. Test incidents (declared via `/rootly test`) are excluded from production metrics regardless of Cause. This is a Kind-level behavior; see [Incident Kind](/configuration/incident-kind) for the full exclusion matrix. Yes. Add the Causes field to the [Incident Retrospective Form](/configuration/built-in-forms) and mark it required. Since the form runs during the Gather & Confirm Data step, the retrospective can't advance past that step without at least one Cause selected. *** ## Related Pages Where most Causes get populated. The retrospective template is your primary Cause-collection surface. Use Causes in workflow conditions to trigger auto-responses (add responder team, spawn action items) when specific failure modes are tagged. The what-kind-of-incident field, distinct from Cause (why-it-happened). Read this to disambiguate the two. # Incident Kind Source: https://docs.rootly.com/configuration/incident-kind The Incident Kind property is the immutable classification that decides how an incident behaves, which workflows fire, and status page eligibility. ## Overview The **Kind** property determines the classification and structural behavior of an incident at the time it is created. It governs workflow triggers, lifecycle expectations, status page eligibility, and whether the incident contributes to production metrics. Kind is a **fixed property** — it's immutable after declaration. Choosing the right kind at creation matters because there's no way to convert a Test Incident into a Normal Incident, or a Scheduled Maintenance into a standard incident, after the fact. Kind answers "what kind of incident is this structurally?" — distinct from [Incident Types](/configuration/incident-types), which answers "what category does this incident fall into for our organization?". Types are fully customizable; Kind is system-defined and fixed. *** ## Available Kinds | Kind | Description | Data Value | | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | | **Incident** | Standard production incidents declared via `/rootly new`. These represent real operational events requiring coordinated response. They trigger normal workflow execution and are eligible for publication on status pages (when not cancelled). | `normal` | | **Sub Incident** | Child incidents created under a parent incident using `/rootly sub`. They inherit contextual linkage from the parent incident and are useful for tracking parallel workstreams or related issues within a broader event. Eligible for status page publication (when not cancelled). | `normal_sub` | | **Test Incident** | Training or simulation incidents declared via `/rootly test`. They behave functionally like normal incidents but are excluded from status page publication and production metrics. Primarily used to test workflows, integrations, and team processes safely. | `test` | | **Sub Test Incident** | Child incidents created under test incidents. Used exclusively for training and simulation. Not eligible for status page publication. | `test_sub` | | **Backfill Incident** | Retroactively documented incidents created after resolution has already occurred. Backfill incidents are automatically created in a **resolved** state. Workflows triggered on Incident Created still execute, but active lifecycle stages such as Started or Mitigated are skipped. Eligible for status page publication (when not cancelled). | `backfilled` | | **Scheduled Maintenance** | Planned maintenance windows declared via `/rootly maintenance`. These incidents follow a distinct maintenance lifecycle separate from normal incident statuses. Used to proactively communicate planned changes via status pages. | `scheduled` | | **Sub Scheduled Maintenance** | Child incidents created under scheduled maintenance incidents. These follow the same maintenance lifecycle as their parent scheduled incident. | `scheduled_sub` | Normal incidents default to **in\_triage** status when the team setting "Incidents must start in the In-Triage status" is enabled. Otherwise, they default to **started** status upon creation. *** ## Behavior Differences at a Glance Each Kind selects a different mix of behavior — knowing the mix up front prevents the most common mistakes (declaring a test incident that pages on-call, declaring a normal incident for a maintenance window). | Kind | Triggers Workflows | Counts in Metrics | Eligible for Status Page | Has Active Lifecycle (Started/Mitigated) | | ------------------------- | ------------------ | ----------------- | ------------------------ | ---------------------------------------- | | Incident (`normal`) | Yes | Yes | Yes (when not cancelled) | Yes | | Sub Incident | Yes | Yes | Yes (when not cancelled) | Yes | | Test Incident | Yes | No | No | Yes | | Sub Test Incident | Yes | No | No | Yes | | Backfill Incident | Yes (on creation) | Yes | Yes (when not cancelled) | No (created already resolved) | | Scheduled Maintenance | Yes | No | Yes | No (uses maintenance lifecycle) | | Sub Scheduled Maintenance | Yes | No | Yes | No (uses maintenance lifecycle) | *** ## Choosing the Right Kind * **Use `normal` (Incident)** for the vast majority of real production issues — anything you'd want metrics, retrospectives, and on-call paging for. * **Use `test`** when validating workflows, training a new team member, or running a tabletop. Test incidents fire workflows so you can verify automation end-to-end, but they don't contaminate metrics or page customers via status pages. * **Use `backfilled`** when documenting an incident that already happened and was resolved outside of Rootly. The incident lands in `resolved` status; workflows that key off Incident Created still run, but Started/Mitigated transitions are skipped because they're already in the past. * **Use `scheduled`** for planned maintenance windows you want to communicate via status pages. Scheduled Maintenance follows a different lifecycle (Scheduled → In Progress → Completed) — don't try to fit a maintenance window into the normal Started/Mitigated/Resolved flow. * **Use `normal_sub`, `test_sub`, or `scheduled_sub`** when tracking a parallel workstream under an existing parent incident. Sub-incidents inherit the parent's context and are tracked together. *** ## Best Practices * **Pick the kind carefully on creation — it's immutable.** If you accidentally declare a real production incident as a Test Incident, you'll need to cancel it and re-declare as `normal`. The metrics and status page implications of getting this wrong are non-trivial. * **Default to `/rootly new` for ambiguous situations.** A real incident accidentally tagged Test is invisible in metrics. A test accidentally tagged Normal is recoverable by cancelling. Err toward the recoverable failure mode. * **Lock down `/rootly maintenance` to operators who actually run maintenance.** Status-page-publishing Scheduled Maintenance incidents are customer-facing — limit who can publish. * **Use Sub Incidents for workstream tracking, not categorization.** If you find yourself creating sub-incidents to label severity or component, you want [Incident Types](/configuration/incident-types) or [Custom Fields](/configuration/custom-fields) instead. *** ## Troubleshooting Test incidents do trigger workflows by default — if you have a workflow that pages on-call on Incident Created without a Kind filter in its run conditions, it will fire for test incidents too. Scope the workflow to real incidents by filtering on Kind. If you want to page for both top-level incidents *and* sub-incidents, use `Kind is one of: Incident, Sub Incident` (which corresponds to `normal, normal_sub`). If you only want to page for top-level incidents, use `Kind is: Incident` (which corresponds to `normal`) — this excludes sub-incidents, which are often used for parallel workstreams under a parent that already paged. Check the incident's Kind. Test (`test`, `test_sub`) and Scheduled Maintenance (`scheduled`, `scheduled_sub`) kinds are excluded from production metrics by design. If the incident was accidentally created as a Test, cancel it and re-declare with `/rootly new`. Kind is immutable. The only path is to cancel the existing incident and declare a new one with the correct kind. If the incident has a long timeline you don't want to lose, document the original incident ID in the new one's description so the history stays traceable. By design — backfill incidents are created already in `resolved` state, so the Started lifecycle stage is skipped. Only workflows triggered on Incident Created run for backfilled incidents. If you need a workflow to run for backfills, key it off Incident Created and add a `Kind is backfilled` condition. *** ## Frequently Asked Questions No. The **Kind** property is immutable after an incident is created. It determines the incident's structural behavior, workflow triggers, and status page eligibility at creation time. If you need a different kind, you must create a new incident with the desired kind. For example, you cannot convert a **Test Incident** to a **normal** incident, or change a **Scheduled Maintenance** to a standard incident after creation. **Kind** is a fixed, system-defined property that controls how an incident behaves structurally (for example, `normal`, `test`, `scheduled`). It cannot be customized and determines workflow execution, lifecycle, and status page eligibility. **Type** ([Incident Types](/configuration/incident-types)) is a configurable property that allows organizations to define their own categorization taxonomy (for example, "UI Bug", "Infrastructure Failure", "Security Event"). Types are fully customizable and can be used for filtering, reporting, and workflow conditions, but they don't affect the fundamental behavior of the incident. Think of **Kind** as "what kind of incident is this structurally?" and **Type** as "what category does this incident fall into for our organization?" Yes. Test incidents trigger workflows just like normal incidents, allowing you to test workflow automation safely without affecting production metrics or status pages. However, test incidents are excluded from status page publication and production reporting. This makes test incidents ideal for: * Validating workflow configurations * Training team members on incident response * Testing integrations without production impact Backfill incidents are designed to document incidents retroactively — after they've already been resolved. Since the incident has already concluded, they are created directly in a **Resolved** state. Workflows triggered on **Incident Created** still execute for backfill incidents, but active lifecycle stages (like **Started** or **Mitigated**) are skipped because the incident is already resolved. No. Scheduled Maintenance incidents follow a separate lifecycle with dedicated statuses (**Scheduled**, **In Progress**, **Completed**). They cannot use standard incident statuses like **Started**, **Mitigated**, or **Resolved**. This separation exists because maintenance windows have different lifecycle requirements than unplanned incidents. *** ## Related Pages The companion fixed property — controls lifecycle stage and progression rules. Customizable categorization, distinct from Kind. The umbrella page for all incident properties and configuration. # Configuring Incident Roles Source: https://docs.rootly.com/configuration/incident-roles Define and manage incident response roles with clear responsibilities, tasks, and hierarchies to ensure effective team coordination during incidents. When the next incident hits, your team should feel prepared. With Incident Roles, you can quickly and efficiently assign responsibilities to your team and define the hierarchy of command. A swift response will help reduce the impact. By adding descriptions and tasks ahead of time, you can ensure your team knows exactly what to do. ## Built-in Roles Rootly comes with four roles that are essential for effective incident response. ### Commander The individual responsible for the overall management of the incident from start to finish. Delegation of tasks across the response team and final decision-making authority. ### Communications Lead The individual responsible for managing internal and external communications to stakeholders outside of the response team. ### Executive Sponsor The individual responsible for complex decision making, often used for high-severity or sensitive incidents. ### Retrospective Owner The individual responsible for driving the post-incident retrospective process to completion. ## Add an Incident Role Go to **Configuration** > **Roles.** Select **+ New Role.** Add a name, description, and a list of responsibilities for the role. **Example** Name: Commander Description: The person who takes charge of the incident, assigns tasks, and has the deciding vote on proceeding. Responsibilities: * Declare and classify the severity of the incident in Rootly * Assign roles (for example, Communications Lead, Subject Matter Experts) * Lead regular status updates in the Slack incident channel * Escalate to executives or external teams if needed * Make "go/no-go" decisions on customer communications and mitigation steps Toggle "make this role optional" if it's not required for every incident. Switch to the *Advanced settings* tab to adjust the incident permission set and "allow multiple users" to be assigned this role. Select **Create Role** to continue. Tasks can be added after a role has been created. ## Add Tasks to an Incident Role Go to **Configuration** > **Roles**. Find the role you want to add tasks to in the table. Click the pencil icon on the left side to edit. Switch to the Tasks tab to see existing tasks. Click **+ Add Task**. Add a name (required) and description. Set the Priority to low, medium, or high. Click **Add** to save. Example Name (required): Declare and classify the severity of the incident in Rootly Description: Review the incident alerts, customer reports, and system status to assign an incident severity. Priority: High ## Edit an Incident Role Go to **Configuration** > **Roles.** Find the role you want to edit in the table. Click the pencil icon on the left side to edit. There are three tabs: **Basics** Auto-generated by Rootly. Use it when referencing the role via API or Liquid. The role's display name — shown in the responder picker and the role assignment audit trail. A short summary of the role. Appears next to the name in role pickers. What the role is expected to do during an incident. Rendered on the responder's role card. When enabled, responders can leave this role unassigned on incidents where it isn't needed. **Tasks** Manage existing tasks or add new ones for this role. **Advanced** Which incident actions the role is authorized to take. When enabled, more than one responder can hold this role on the same incident simultaneously. Once the desired edits are complete, click **Update** to save. ## Delete an Incident Role Go to **Configuration** > **Roles.** Find the role you want to edit in the table. Click the trashcan icon on the left side to delete. Deleting an incident role will also remove its associated data. This can't be undone. Select **Delete** to delete the role and all associated data, or click **Discard changes** to keep the role. ## **Get Help** For help, use the slash command **/rootly help** in Slack or email [support@rootly.com](mailto:support@rootly.com). *** ## Related Pages How the roles configured here get used during incident response. Roles are typically assigned to team members — Teams is the underlying identity primitive. The umbrella page covering incident properties and configuration surface. # Incident Status Source: https://docs.rootly.com/configuration/incident-status The Incident Status lifecycle — Triage, Started, Mitigated, Resolved, Closed, Cancelled — with transition rules, timestamps, and sub-statuses. ## Overview The **Status** property defines the lifecycle stage of an incident and governs how it progresses from investigation through closure. Status transitions are validated to preserve chronological and logical integrity — you can't skip from Triage to Resolved, and `mitigated_at` can never precede `started_at`. Status is a **fixed property**: the set of statuses (Triage, Started, Mitigated, Resolved, Closed, Cancelled) is system-defined and can't be customized. If you need additional state inside a status, use [Sub-Statuses](#sub-statuses) (this page) or [Custom Statuses](/configuration/custom-statuses). Scheduled Maintenance incidents follow a separate lifecycle with their own statuses — see [Scheduled Maintenance Statuses](#scheduled-maintenance-statuses) below. *** ## Standard Incident Statuses | Status | Description | Data Value | | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | | **Triage** | An investigative state used to determine whether an issue should escalate into an active incident. This allows teams to evaluate signals before formally beginning response. Timestamped at `in_triage_at`. | `in_triage` | | **Started** | Marks the official activation of incident response. This is the primary active state during which coordination, mitigation, and communication occur. Timestamped at `started_at`. | `started` | | **Mitigated** | Indicates that user-facing impact has been halted or reduced, but remediation, validation, or cleanup work may still be ongoing. Timestamped at `mitigated_at`, which must be after or equal to `started_at`. | `mitigated` | | **Resolved** | Signifies the completion of active incident response. At this stage, service impact has ended and retrospective processes typically begin. Timestamped at `resolved_at`. | `resolved` | | **Closed** | Optional terminal status (team-configurable) used to mark incidents as fully finalized after review. **Requires the incident to already be in Resolved status.** Timestamped at `closed_at`. | `closed` | | **Cancelled** | Terminal status used for false positives or duplicate incidents. Cancelling prevents further lifecycle progression unless the incident is reopened. Timestamped at `cancelled_at`. | `cancelled` | *** ## Terminal Statuses **Resolved**, **Closed**, and **Cancelled** are terminal statuses. They prevent further lifecycle progression unless the incident is explicitly reopened to **Started**, which restarts active response tracking. Cancellation is for incidents that turn out to be false positives or duplicates — they shouldn't appear in production metrics or status pages. Resolution and closure are for incidents that ran their full course. *** ## Status Transition Rules **Lifecycle Constraints** * Incidents in **Triage** or **Cancelled** cannot transition directly to **Mitigated**, **Resolved**, or **Closed**. * **Closed** can only be reached from **Resolved**. * Terminal statuses (**Resolved**, **Closed**, **Cancelled**) may be reopened to **Started**. The constraints exist because Rootly's metrics and retrospective workflows assume an incident in a terminal status actually ran through active response. Skipping Started would produce nonsense lifecycle durations (for example, MTTR of zero). *** ## Timestamp Validation Rules **Chronological Integrity** Status timestamps are validated to preserve lifecycle order: * `mitigated_at` ≥ `started_at` * `resolved_at` ≥ `started_at` * `closed_at` ≥ `started_at` If you attempt to set a timestamp that violates this order — for example, backdating `mitigated_at` to before `started_at` — Rootly rejects the change and surfaces a validation error. *** ## Sub-Statuses When enabled via team configuration, statuses may contain **sub-statuses** for more granular tracking within a parent lifecycle stage. For example: * **Started** may include multiple Active sub-statuses (up to 8 per team). * **Resolved** may include structured post-incident stages such as "Retrospective". Sub-statuses let teams enforce structured workflows, capture finer lifecycle detail, and introduce controlled progression within major stages. Workflows that trigger on **Status Updated** fire when the parent status changes, regardless of sub-status transitions — but sub-statuses are available in workflow **run conditions**, so you can write workflows that only fire on a specific sub-status. See [Custom Statuses](/configuration/custom-statuses) for the full sub-status configuration guide. *** ## Scheduled Maintenance Statuses Scheduled Maintenance incidents follow a separate lifecycle from standard incidents. Their statuses describe the state of the maintenance window itself, not a response process. | Status | Description | Data Value | | --------------- | ------------------------------------------------------------------------------------------------------ | ------------- | | **Scheduled** | Indicates that the maintenance window has been planned and formally created but has not yet begun. | `scheduled` | | **In Progress** | Indicates that maintenance work is actively underway. | `in_progress` | | **Completed** | Indicates that maintenance activities have concluded successfully. This is the default terminal state. | `completed` | Scheduled Maintenance incidents cannot use standard incident statuses (Started, Mitigated, Resolved). The separation exists because maintenance windows have different lifecycle requirements than unplanned incidents. For more on when to use Scheduled Maintenance, see [Incident Kind](/configuration/incident-kind). *** ## Best Practices * **Use Triage for ambiguous signals, not for active incidents.** Triage is the "is this even an incident?" stage. Once a responder commits to active mitigation, move it to Started so the lifecycle clock starts. * **Default to Resolved over Closed for most teams.** Closed adds an extra review step that's only worth the overhead if you have a formal post-incident review gate. If you don't, leave Closed disabled — Resolved is the natural terminal state. * **Reserve Cancelled for false positives.** Don't use Cancelled to "clean up" a real incident that ended up being minor — that incident still belongs in metrics. Cancelled is for incidents that were never real (duplicates, test fires from monitoring tools). * **Use sub-statuses for workflow gating, not for taxonomy.** If you want to label incidents as "Investigating", "Mitigating", "Verifying", sub-statuses are the right tool. If you want to label incidents as "Customer Impact", "Infrastructure", "Security" — that's [Incident Types](/configuration/incident-types) or [Custom Fields](/configuration/custom-fields). * **Reopen instead of re-declaring when an incident recurs.** Reopening preserves the original timeline, action items, and retrospective context. Re-declaring fragments the history into two records. *** ## Troubleshooting By design — incidents in Triage haven't entered active response yet, so resolving them would produce a zero-duration lifecycle. Move the incident to Started first (even briefly), then to Mitigated and Resolved. If the incident was a false positive that never warranted response, Cancel it instead. Status timestamps must follow `started_at` ≤ `mitigated_at` ≤ `resolved_at` ≤ `closed_at`. If you're backdating Mitigated to be earlier than Started, the system blocks the save. Either adjust Started earlier or move Mitigated forward to match the actual order of events. Closed is an optional terminal status controlled by team configuration. If your team hasn't enabled it, Resolved is the only terminal status available. Ask an admin to enable Closed in team settings if you need a two-step Resolved → Closed flow. Working as designed. **Sub-status-only transitions do not emit the Status Updated trigger.** The trigger fires only when the *parent* status changes (for example, Started → Mitigated). If your incident stays in Started and the sub-status moves from "Investigating" to "Verifying," no Status Updated event is dispatched, and no workflow triggered on Status Updated will run — regardless of what run conditions you add. Run conditions can only *filter* workflows that were already triggered. So an "only run when sub-status is Verifying" condition narrows a Status Updated workflow to just the parent transitions that also happen to land on the Verifying sub-status; it does not create a trigger for later Verifying → some-other-sub-status shifts inside the same parent status. If you need automation on sub-status transitions specifically, the current recommendation is to structure your process so sub-status transitions coincide with meaningful parent-status transitions (making the workflow trigger on the parent change), or to run the automation manually via a Slack command workflow. Reopening to Started overwrites `started_at` to the reopen time. The original `started_at`, `mitigated_at`, and `resolved_at` are preserved in the incident timeline events but not the top-level fields. If you need the original timing for reporting, query the timeline events for the historical status transitions. *** ## Frequently Asked Questions Yes. Terminal statuses (**Resolved**, **Closed**, **Cancelled**) can be reopened to **Started** status. This restarts active response tracking and allows the incident to progress through its lifecycle again. Reopening is useful when: * An incident recurs after resolution * Additional investigation reveals the original resolution was incomplete * A cancelled incident turns out to be a real issue **Resolved** indicates that active incident response has completed and service impact has ended. At this stage, retrospective processes typically begin. **Closed** (when enabled via team configuration) is an optional terminal status used to mark incidents as fully finalized after review. It requires the incident to already be in **Resolved** status and provides a clear distinction between incidents that are resolved but still under review versus incidents that are completely closed. Not all teams use the Closed status. If it's not enabled, **Resolved** serves as the terminal status. Status transitions are validated to preserve logical lifecycle progression. Incidents in **Triage** or **Cancelled** cannot skip directly to **Mitigated**, **Resolved**, or **Closed** because these statuses require the incident to have been actively responded to (in other words, in **Started** status first). To resolve an incident that's in Triage, you must first transition it to **Started**, then proceed through **Mitigated** (optional) to **Resolved**. Rootly validates timestamp relationships to maintain chronological integrity. If you attempt to set `mitigated_at`, `resolved_at`, or `closed_at` to a time before `started_at`, the system will reject the change and display a validation error. Timestamps must follow this order: * `started_at` ≤ `mitigated_at` ≤ `resolved_at` ≤ `closed_at` This ensures incident timelines remain accurate and reportable. Sub-statuses provide granular tracking within parent statuses (like **Started** or **Resolved**) but don't change the fundamental status-based workflow triggers. Workflows that trigger on "Status Updated" will still fire when the parent status changes, regardless of sub-status transitions. However, you can use sub-statuses in workflow **run conditions** to create more specific automation logic. For example, a workflow could run only when an incident is in **Started** status with a specific Active sub-status. Sub-statuses are particularly useful for enforcing sequential workflows within a status. *** ## Related Pages The companion fixed property — controls structural behavior and metrics inclusion. Add custom sub-statuses within Triage, Started, Mitigated, and Resolved. The full lifecycle narrative — detection through retrospective. # Incident Types Source: https://docs.rootly.com/configuration/incident-types Configure custom incident type categories to classify incidents by your own taxonomy — customizable, and available in workflow conditions and metrics. ## Overview **Incident Types** let you classify incidents by a taxonomy that matches how your organization thinks about incident categories — "UI Bug", "API Failure", "Security Event", "Internal Outage", "Customer-Facing", or whatever grouping is meaningful to your team. Types are **fully customizable**: you name them, you pick the colors, you decide how many. Types are frequently confused with the [Kind](/configuration/incident-kind) property. The distinction matters: | Property | Nature | Purpose | | -------- | ------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | | **Kind** | System-defined, immutable, fixed set (Incident, Sub Incident, Test Incident, Backfill, Scheduled Maintenance) | Structural — governs metrics inclusion, status-page eligibility, and workflow trigger behavior | | **Type** | Customer-defined, editable, unbounded | Categorical — supports your organization's incident taxonomy for filtering, reporting, and routing | Think of Kind as answering *"what kind of incident is this structurally?"* and Type as answering *"what category does this incident fall into in our organization's taxonomy?"*. *** ## How Incident Types Are Used Like Severity, Type is a lever that other Rootly features pull on: | Feature | How Type is used | | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **[Workflow conditions](/workflows/conditions)** | Filter workflows so they fire only on specific types. Common patterns: "auto-create a Jira ticket only when Type is 'UI Bug'" or "notify the security team only when Type contains 'Security Event'." | | **Slack channel + alias notifications** | Each Type can be linked to Slack channels and user groups. Workflows use these to auto-invite the right subject-matter experts (for example, invite the frontend team on "UI Bug" types). | | **Notify emails** | Each Type can be linked to email addresses. Useful for stakeholder groups that only care about a specific incident category — for example, a legal team on "Data Privacy" types. | | **Retrospective templates** | Different Types can trigger different retrospective templates via workflow — a "Security Event" retrospective covers regulatory reporting, a "UI Bug" retrospective is lightweight. | | **Metrics + reporting** | Type is a top-level filter in every metrics dashboard. Segmenting MTTR by Type helps you see whether infrastructure issues take longer to resolve than product bugs. | | **API + Liquid references** | Type is available as `{{ incident.types }}` (names) and `{{ incident.type_ids }}` (IDs) in every workflow template, retrospective template, and API payload. | Because Type drives so much automation, the shape of your Type taxonomy directly shapes how well your automation targets the right responders — an overly generic Type ("Bug") lands every notification with everyone, while an overly granular one ("iOS Bug on Login Screen") splinters routing until nothing has enough volume to justify its rule. *** ## Choosing a Type Taxonomy There's no universal Type taxonomy — but there are patterns that work and patterns that don't. Use these to design or audit your team's list. ### How Many Types Most teams land on **five to ten types**. Fewer than five and Type becomes redundant with Severity (which you already have). More than ten and calibration breaks down — responders default to whichever Type is at the top of the picker. If you catch yourself creating a Type that answers "who owns this?" — that's what [Teams](/configuration/teams) or [Services](/configuration/services) are for. If you're creating a Type that answers "how bad is this?" — that's [Severity](/configuration/severities). Type is for **what kind of thing is broken**, not who owns it or how urgently. ### Single-Select vs Multi-Select Type can be configured as **single-select** (one Type per incident) or **multi-select** (multiple Types per incident). Which you choose changes both the picker UX and the workflow conditions available: * **Single-select** is simpler to reason about. Responders pick one Type; workflows filter with `is` / `is one of`. Best when your Types are mutually exclusive (an incident is a UI Bug or an Infrastructure issue, not both). * **Multi-select** captures overlapping taxonomies. Responders can tag both "Security Event" and "Data Privacy" on the same incident; workflows filter with `contains any of` / `contains all of`. Best when Types represent aspects rather than exclusive categories. Most teams start single-select and switch to multi-select only when they hit real overlap. Switching later is fine — historical incidents preserve their existing Type values. ### Common Taxonomies Focus on the technical shape of the incident. | Type | When to use | | --------------------------- | ----------------------------------------------------------------------- | | **Infrastructure** | Underlying services (databases, network, hosting) failed. | | **Application Bug** | A code-level bug — regression, unhandled edge case, logic error. | | **Performance Degradation** | System is up but slow. Not a hard failure. | | **Third-Party Dependency** | External service (Stripe, Twilio, an SSO provider) is failing. | | **Deployment Issue** | Caused by a bad release / rollout. Recovery is usually rollback. | | **Configuration Error** | A settings change (feature flag, config file, DNS) caused the incident. | | **Security Event** | Actual or potential unauthorized access, exposure, or breach. | Focus on how the customer experiences the incident. | Type | When to use | | ------------------------- | ---------------------------------------------------------------------- | | **Customer-Facing** | Users directly notice the issue. | | **Internal-Only** | Employees affected, no customer impact. | | **Partner / Integration** | Impacts a business partner or B2B integration, not end users. | | **Data Integrity** | Data loss, corruption, or exposure — often overrides other taxonomies. | | **Compliance / Legal** | Regulatory or contractual obligations triggered. | Focus on which product area is broken. Best paired with Multi-Select so cross-product incidents can be tagged with all affected areas. | Type | When to use | | ----------------- | ------------------------------------------------------- | | **Web App** | Browser-facing product. | | **Mobile App** | iOS / Android apps. | | **API** | Programmatic surface used by customers or integrations. | | **Admin Console** | Internal admin tools. | | **Data Pipeline** | Batch / streaming data infrastructure. | | **Analytics** | Reporting, dashboards, exports. | *** ## Field Type Configure Type as either **single-select** or **multi-select** in **Configuration → Incident Types**. The setting affects every incident going forward — historical incidents keep their existing values. Liquid syntax differs slightly between the two modes. Single-select uses `{{ incident.types | get: '' }}` for the one value. Multi-select uses `{{ incident.raw_types[index] | get: '' }}` where `index` references a specific Type in the list. The attribute reference below covers both. *** ## Configuring Type Attributes Each Type can be configured with the attributes below. All are available as Liquid variables for use in workflows, retrospective templates, and status page updates. Unique identifier assigned automatically by Rootly on creation. **Not customizable.** Used in Liquid references and API calls. ```liquid theme={null} {{ incident.type_ids }} {{ incident.raw_types | get: 'id' }} {/* single-select */} {{ incident.raw_types[0] | get: 'id' }} {/* multi-select, first Type */} ``` The display name shown throughout the Rootly UI. Fully customizable — pick names that match your team's operational vocabulary. ```liquid theme={null} {{ incident.types }} {{ incident.raw_types | get: 'name' }} {/* single-select */} {{ incident.raw_types[0] | get: 'name' }} {/* multi-select, first Type */} ``` Auto-generated by lower-casing and hyphenating the name. Used in Liquid references and in workflow condition matches. **Slugs regenerate when you rename a Type.** Anything referencing the old slug — workflow conditions, saved metrics dashboards, third-party integrations that filter by slug — needs to be updated after a rename. ```liquid theme={null} {{ incident.type_slugs }} {{ incident.raw_types | get: 'slug' }} {{ incident.raw_types[0] | get: 'slug' }} ``` Additional context shown alongside the Type in the UI. Best used to remind responders what qualifies for each Type — for example, "Any incident affecting customer-facing surfaces (web, mobile, API)." ```liquid theme={null} {{ incident.raw_types | get: 'description' }} {{ incident.raw_types[0] | get: 'description' }} ``` Six-digit hex color code used for Type-tinted UI accents and metrics-graph color coding. Pick colors that are meaningful and consistent — reserving red for security-adjacent Types, for example. ```liquid theme={null} {{ incident.raw_types | get: 'color' }} {{ incident.raw_types[0] | get: 'color' }} ``` Rootly expects six-digit hex codes (for example, `#c4231c`). Use a color picker if you're not sure — [color-hex.com](https://www.color-hex.com/) is a common choice. One or more Slack channels linked to the Type. **Linking alone doesn't post to the channels** — a workflow action (typically "Attached Types Channels") reads this list and performs the notification. ```liquid theme={null} {{ incident.raw_types | get: 'slack_channels' }} {{ incident.raw_types[0] | get: 'slack_channels' }} ``` One or more Slack user groups (aka aliases) linked to the Type. **Linking alone doesn't invite users** — a workflow action (typically "Attached Types Aliases") reads this list and performs the invitation. ```liquid theme={null} {{ incident.raw_types | get: 'slack_aliases' }} {{ incident.raw_types[0] | get: 'slack_aliases' }} ``` One or more email addresses linked to the Type. **Linking alone doesn't send email** — a workflow action reads this list and sends the notification. ```liquid theme={null} {{ incident.raw_types | get: 'notify_emails' }} {{ incident.raw_types[0] | get: 'notify_emails' }} ``` For workflow-driven use, most teams reference the flattened list: ```liquid theme={null} {{ incident.raw_types | map: 'notify_emails' | flatten | join: ',' }} ``` *** ## Best Practices * **Design Types for automation, not documentation.** If a Type doesn't drive at least one workflow condition, alert routing, or metrics filter, it's just a label. Retire it after 90 days if it never gets used. * **Keep Type distinct from Team, Service, and Severity.** Type is *what's broken*; Team is *who owns it*; Service is *which component is affected*; Severity is *how bad it is*. Overlapping Types with those dimensions leads to the same data being encoded four times. * **Start single-select, switch to multi-select when overlap is genuine.** Multi-select is more flexible but harder to filter in workflow conditions (you need `contains any of` instead of `is`). Only take the added complexity when you actually have overlapping taxonomies. * **Colors should be intuitive.** Reserve red for security / data integrity Types. Use warmer colors (orange, yellow) for customer-facing Types and cooler colors (blue, gray) for internal-only Types. Responders read the color before the label. * **Attach Slack channels + aliases per Type, but require workflow actions to actually use them.** Same principle as Severities. Keeps notification behavior explicit and auditable. * **Audit quarterly.** Look at Type usage over the last 90 days. Rare Types (\<5% of incidents) either need a rename to broaden their reach or removal from the picker. Dominant Types (>40%) probably need to be split. *** ## Troubleshooting Confirm the Type is enabled under Configuration → Incident Types. Archived Types remain visible on historical incidents but don't appear as options on new incidents. If it's enabled and still missing, check whether team-level restrictions are in play — some teams scope which Types their responders can select. Two common causes: (1) the workflow's condition uses `is` on a multi-select Type field — switch to `contains any of` (see [Workflow Conditions](/workflows/conditions) for the operator reference); (2) the Type slug was regenerated after a rename and the workflow still references the old slug. Rename-triggered slug changes are automatic; update the workflow condition to match the new slug. Linking Slack channels to a Type doesn't cause auto-invitation on its own — a workflow with an "Attached Types Channels" action is required. Check that a workflow exists, is enabled, and has run conditions that match the Type you're testing. The Type-updated trigger is a good candidate for this workflow. Working as designed. `{{ incident.types }}` returns a joined string; access individual Types via `{{ incident.raw_types[0] | get: 'name' }}` or iterate with `{% for t in incident.raw_types %}...{% endfor %}` when you need per-Type rendering. Metrics query by the Type's `slug`, and slugs regenerate on rename. Saved dashboards or reports that filtered by the pre-rename slug won't match anymore. Update the dashboard filter to the new slug, or plan the rename around a natural retention boundary if that filter can't be updated cleanly. *** ## Frequently Asked Questions Most teams land on 5-10. Fewer and Type becomes redundant with Severity. More and calibration breaks down (responders default to whichever Type is at the top of the picker). See Choosing a Type Taxonomy above for detail. **Kind** is a fixed, system-defined property that controls structural behavior (test vs normal, backfill vs scheduled maintenance, etc.). **Type** is a customer-defined categorical property for your organization's taxonomy. Kind is set once at creation and is immutable; Type can be changed anytime. See [Incident Kind](/configuration/incident-kind) for the full Kind reference. Yes. Type is fully mutable — change it via the incident details page or a workflow action. Changes are logged in the incident timeline. This is different from Kind, which is immutable after declaration. Yes — Types belong to a Team. Each team maintains its own Type list, and the picker on an incident form shows the Types defined for that incident's team. If your workspace uses multiple teams, define the Types each team actually uses; there's no single org-wide Type list. Historical incidents keep the Type value they were created with, even after the Type is deleted from the picker. Only new incidents lose access to the removed Type. For matrix overhauls, archive rather than delete so historical data stays readable. Yes. Type is one of the most common fields used in workflow run conditions. See [Workflow Conditions](/workflows/conditions) for the operator reference — Type is often used with `contains any of` in multi-select mode. No. Test incidents (declared via `/rootly test`) are excluded from production metrics regardless of Type. This is a Kind-level behavior; see [Incident Kind](/configuration/incident-kind) for the full exclusion matrix. *** ## Related Pages The fixed counterpart — governs structural incident behavior. Read this to disambiguate Kind from Type. The other most-used incident property. Type and Severity are the two dimensions most workflows filter on. Use Type in workflow run conditions to route different incident categories to different response processes. # Kubernetes Configuration Source: https://docs.rootly.com/configuration/kubernetes Configure Kubernetes integration to monitor cluster resources and automatically generate pulses from pod, deployment, and service changes. The Kubernetes integration watches events in your clusters — pod crashes, deployment updates, service changes, and more — and records them as [pulses](/configuration/pulses) in Rootly. Pulses give responders infrastructure context directly on the incident timeline, so you can quickly answer the question "what changed?" when investigating an incident. Kubernetes integration can watch different resources and create pulses. ## How It Works Cluster events are captured by [kubewatch](https://github.com/robusta-dev/kubewatch), an open-source Kubernetes watcher that you deploy in your cluster, and forwarded to a unique webhook URL that Rootly generates for your workspace. You choose which resource types kubewatch monitors — deployments, pods, services, nodes, jobs, namespaces, and other resource types are supported. Each event appears as a pulse with a summary in the form `[k8s][{resource kind}] {event text}`, along with labels and refs identifying the resource and namespace. ## Linking Pulses to Services Rootly automatically associates Kubernetes pulses with your [services](/configuration/services) by matching the **Kubernetes Deployment Name** field on the service against the event's resource name. The match is partial, so a service named `api-server` will match events from any deployment containing `api-server` in its name. Set this field on each service you want correlated with cluster events. If pulse volume gets noisy, narrow the resource types enabled in your kubewatch configuration — disabling low-signal resources like secrets and ConfigMaps significantly reduces noise. Ready to configure the Kubernetes integration? See [Kubernetes integration setup](/integrations/kubernetes). ## Related pages * [Kubernetes integration setup](/integrations/kubernetes) — step-by-step installation and troubleshooting * [Pulses](/configuration/pulses) — how change events appear in Rootly * [Services](/configuration/services) — link cluster events to the services they affect *** ## Related Pages Where Kubernetes cluster events appear as change events on incident timelines. Link services to Kubernetes deployment names so pulses correlate with the right incident context. kubewatch installation, resource selection, and troubleshooting. # Incident response playbooks overview Source: https://docs.rootly.com/configuration/playbooks Create and manage response playbooks that automatically attach to incidents based on conditions like severity, service, or team to guide resolution efforts. ## Overview Playbooks are a great way to create a document that can help speed incident resolution. Think of them as a collection of simple instructions to empower someone to resolve a particular incident (even if they have minimal experience). Playbooks are **automatically attached** to incidents when they **match a configured condition** (for example: severity, service, functionality, team impacted). If you have Playbooks or supported documentation hosted internally, you can link to them in the "External URL" field and provide detailed instructions in the content field. On the above example, the **Database outage playbook** will be attached to any incident with the **SEV2 severity or the** **customers-postgresql-db** **microservices.** Please note that this is all OR logic currently, meaning this playbook will be attached to an incident that has just one of those matching conditions, such as SEV2 severity for example. Additionally, at the bottom of the Playbook details page you have the ability to append any relevant tasking that needs to be done during the incident. Playbooks are a great way to prevent a single person from becoming the de facto expert on how to resolve a particular problem. One person shouldn't be the only one who knows how to bring a critical system back online. *** ## Related Pages Walk-through of how playbooks auto-attach based on incident type and other properties. The adjacent automation surface — event-driven actions that can complement playbooks during response. The umbrella page covering incident properties and configuration surface. # Publishing Incidents to Status Pages Source: https://docs.rootly.com/configuration/publishing-incidents Publish incidents to your status pages from Slack or the Rootly web UI to keep customers and internal teams updated as an incident progresses. Publishing an incident to a [status page](/configuration/status-pages) shares its details and progress with stakeholders, keeping affected users informed while you work. Publishing is deliberate, not automatic. An incident attached to a service or functionality on your status page is **not** published on its own — someone on the response team writes and publishes each update, so every message is reviewed before customers see it. ## What Gets Published You can publish incidents to status pages to communicate incident details, timeline updates, and resolution status with your external stakeholders such as customers, partners, or internal teams. When you publish an incident to a status page, it will display: * Incident title * Affected Services, Functionalities & External Services * Timeline of events * Incident resolution status Incident Status Page ## Publishing from Slack In addition to using the web interface for publishing incidents to status pages, you can also accomplish the same thing without leaving Slack. To publish an incident using Slack, do the following: From Slack, navigate to the Slack channel specific to that incident, and type the command: **/rootly statuspage** Publish an incident using Slack A dialog will be presented for you to choose the appropriate status pages where you want the incident published. This will also be your chance to add a useful title and description so your external users can better understand. Add the appropriate information in the title and event fields. Select a status for the incident, and then click **Publish**. ## Publishing from the Web UI To publish an incident on a status page in Rootly's Web UI: On the incident's details page, navigate to the **Status Page** tab. Click **Publish Incident**, and fill out the form to write your incident update. Use any templates provided to help craft and standardize your message. Once you've provided all the details, the incident will be published to the status page. Publish incident form Any Service or [functionality](/configuration/functionalities) attached to the incident that is also a component of that status page will be automatically updated to show that it is currently **Affected** by an incident. Once the status page is updated to indicate that the incident is resolved, the component will be updated to **Operational**. ## Updating a Published Incident As your incident progresses, you'll need to continually communicate progress to your customers and stakeholders via the status page. You can do so from the same tab in your incident's detail page. 1. Click 'Add to status page' and fill out the necessary information. 2. Rootly will pre-fill the title based on the previous update that was published to the status page. ## Resolving a Published Incident Once your incident has been resolved, publish your final update to the status page using the same flow above. Make sure to update the status in this form to 'Resolved' so that your stakeholders know the issue has been resolved, and all impacted components will return to operational. *** ## Related Pages The umbrella concept — where published incidents actually show up. Set up the page before you can publish updates to it. Where published-update events surface inside the incident record. # Pulses Source: https://docs.rootly.com/configuration/pulses Track deploys, config changes, and other operational events as pulses — silent context signals that surface in triage to correlate breaks with changes. ## Overview **Pulses** are lightweight event records that capture *changes* to your systems — deploys, config updates, feature-flag flips, database migrations, CI builds — without paging anyone, creating an incident, or generating a notification. They exist for a single reason: **when an incident happens, responders need to answer "what changed?" as fast as possible.** Pulses give you a searchable, filterable timeline of every change that landed in the recent past, so triage takes minutes instead of digging through Slack, git logs, and deploy dashboards to reconstruct the timeline. Pulses are **passive context**, not alerts. They don't trigger notifications, don't page on-call, and don't create incidents on their own. A [Pulse Workflow](/workflows/pulse-workflows) is what turns a pulse into any of those things — but the pulse itself is inert. *** ## How Pulses Are Used | Feature | How pulses are used | | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Incident triage** | The most common use. When a responder opens an incident, Rootly shows pulses that landed in the recent past — filtered by the incident's services, environments, and time window — so "what changed right before this broke" is a one-glance question. | | **[Pulse Workflows](/workflows/pulse-workflows)** | Trigger a workflow when a pulse arrives that matches specific criteria. Example: auto-post a Slack message when a Production deploy pulse arrives, so the team sees the deploy timeline in-context. | | **API + CLI** | Any system that knows about a change can send a pulse. CI/CD pipelines, feature-flag services, config-management tools, custom scripts — all common sources. | Because pulses cost nothing to send and everything to have during triage, **the right pattern is to send more pulses than you think you need**. Pipe every deploy, every feature-flag flip, every config change — filter and narrow at read time via the pulse UI, not at write time. *** ## Sending Pulses Pulses can be created two ways: through the Rootly API and through the Rootly CLI. Pick whichever matches how your pipeline is already structured — most teams end up using both (API for programmatic sources, CLI for shell scripts and CI). ### API Every pulse is a `POST /v1/pulses` with a summary and optional metadata. Minimal request: ```bash Linux theme={null} curl --header "Content-Type: application/json" \ -H "Authorization: Bearer " \ --data '{"data": {"attributes": {"summary": "Deployed website v2.14.1"}}}' \ -X POST https://api.rootly.com/v1/pulses ``` Richer request with metadata for filtering: ```bash Linux theme={null} curl --header "Content-Type: application/json" \ -H "Authorization: Bearer " \ --data '{ "data": { "attributes": { "summary": "Deployed website v2.14.1", "environments": ["production"], "services": ["checkout-web", "payments-api"], "labels": { "version": "2.14.1", "author": "alice@example.com", "commit": "a1b2c3d" } } } }' \ -X POST https://api.rootly.com/v1/pulses ``` Best used from **CI/CD hooks, feature-flag webhook receivers, and infrastructure-as-code apply hooks**. Wire the pulse creation into your deploy pipeline once and every future deploy is captured automatically. ### CLI The [Rootly CLI](https://github.com/rootlyhq/rootly-cli) exposes two pulse commands — one that creates a pulse from a summary and one that wraps an arbitrary shell command: **Simple pulse:** ```bash Linux theme={null} export ROOTLY_API_TOKEN="your-api-token" rootly pulse create "Deployed website v2.14.1" \ --services=checkout-web,payments-api \ --labels="env=production,version=2.14.1" ``` **Wrap a shell command as a pulse:** ```bash Linux theme={null} rootly pulse run \ --summary="Deploy Website" \ --services=checkout-web \ --labels="env=production,version=2" \ -- sh deploy.sh ``` `pulse run` executes the wrapped command and creates a pulse capturing the command, its exit status, and its runtime. Best for CI job wrappers where you want "this thing ran" as pulse metadata automatically. See the [Rootly CLI docs](/integrations/cli) for the full command reference. ### Pulse Attributes Every pulse supports the following fields. All are searchable and filterable in the pulses UI and in [pulse variables for workflow templates](/liquid/pulse-variables). Human-readable one-line description. This is what appears in the triage timeline. Keep it short and specific — "Deploy website v2.14.1" beats "Deployment" or "Prod push". Which environments the change affects. Matches the [Environments](/configuration/environments) field on incidents, so pulses filter cleanly against incident context. ```bash theme={null} --environments "production" --environments "staging, production" ``` Which [Services](/configuration/services) the change touches. This is the single most important field for triage filtering — a pulse tagged with the affected service surfaces in the right place at the right time. Free-form metadata attached to the pulse. Use for anything that helps at read time — commit hash, deploy author, version, ticket ID, feature-flag name. ```bash theme={null} --labels "version=2.14.1, author=alice, commit=a1b2c3d" ``` In the JSON API, labels is a flat object: `{"version": "2.14.1", "author": "alice"}`. Optional link back to the source of the change — Datadog dashboard, GitHub commit, CircleCI build. Renders as a clickable link in the pulses UI so responders can jump straight to the source. *** ## Common Pulse Sources The single most valuable pulse source. Post a pulse from every deploy job — success and failure both — with the version, commit, and environment as labels. When an incident hits, the responder immediately knows what shipped in the last hour. Common integrations: GitHub Actions, CircleCI, Jenkins, Buildkite, GitLab CI. Add a step to the deploy job that curls the pulses API. Every feature-flag flip is a change. Wire your feature-flag service (LaunchDarkly, Statsig, Unleash, PostHog) to POST a pulse when a flag toggles in production. When a customer reports "it worked yesterday and doesn't today," the pulse timeline shows the exact flag that changed between then and now. Post a pulse on every `terraform apply`, every `kubectl rollout`, every Pulumi update. Include the plan diff (or a link to it) in labels or `external_url` so responders can see what actually changed at the infra level. Every schema migration is a landmine waiting to be stepped on during triage. Post a pulse from your migration runner with the migration name and target database. If an incident happens 3 hours after a migration, the pulse timeline surfaces the migration immediately. Any manual change — restarting a service, applying a config patch, running a maintenance script — deserves a pulse. Use the CLI (`rootly pulse create "Restarted elasticsearch-prod"`) as an operator habit. Future you will thank present you when the change becomes relevant during triage. *** ## Best Practices * **Send more pulses than you think you need.** Filtering out noisy pulses at read time is trivial (label filters, service filters, time-window filters). Reconstructing a change history from scratch during a live incident is not. * **Wire pulses at the automation layer, not by hand.** A pulse that requires an engineer to remember to send it doesn't get sent when it matters most (during a rushed hotfix). Bake pulse creation into deploy jobs, CI hooks, and feature-flag webhooks so it happens automatically. * **Use consistent labels across sources.** If your GitHub deploys use `version`, your Terraform runs use `terraform_version`, and your feature flags use `variant`, filtering at read time gets awkward. Standardize on a small label vocabulary and apply it everywhere. * **Tag `environments` and `services` on every pulse.** Untagged pulses don't surface in incident triage because triage filters by service and environment. A pulse without those tags is a pulse that responders won't see. * **Include an `external_url` when the pulse links to actionable detail.** A pulse that says "Deploy v2.14.1" is useful; a pulse that says "Deploy v2.14.1" + a link to the CircleCI build page is a rollback candidate in one click. * **Don't use pulses for alerts.** Pulses are inert by design. If you want an incident to open when a specific change happens, that's a [Pulse Workflow](/workflows/pulse-workflows) with an Incident Created action — not the pulse itself. *** ## Troubleshooting Two common causes: (1) the pulse's `services` or `environments` don't match the incident's — triage filters by intersection, so a pulse tagged only with `staging` won't appear on a Production incident; (2) the pulse landed outside the triage time window (default is the last few hours before the incident). Widen the window from the triage view's date picker if the pulse is older. The `Authorization: Bearer ` header is missing or the token is invalid. Generate a token in **Account → Manage API keys → Generate New API Key** and confirm it has API access enabled. If you're using a Team API key, confirm the key's team has permission to write pulses. The CLI expects labels as comma-separated `key=value` pairs: `--labels "version=2, attempt=1"`. Common mistakes: quoting individual pairs (`--labels "version=2","attempt=1"`), using colons instead of equals (`--labels "version:2"`), or wrapping values in inner quotes. Check the workflow's run conditions in [Workflows](/workflows/pulse-workflows). Pulse workflows fire on every matching pulse by default — narrow the conditions to filter by `services`, `environments`, or specific label values. The [Workflow Conditions](/workflows/conditions) evaluator lets you test conditions against a sample pulse payload. Some sources (for example, a chatty CI system) generate too many pulses to be useful during triage. Two options: (1) filter noisy pulses out of the triage view via label filters — the pulse data stays available for post-incident review; (2) reduce the source's pulse volume by only sending on meaningful events (for example, successful deploys, not every retry). *** ## Frequently Asked Questions **Pulses** capture changes to your systems (deploys, config updates) and are passive — no notifications, no paging, no incident lifecycle. **Incidents** capture problems requiring response — they trigger workflows, page on-call, and follow the full incident lifecycle. Pulses inform incident triage; they don't become incidents on their own unless a [Pulse Workflow](/workflows/pulse-workflows) turns them into one. Not directly. A pulse itself is inert. To page on-call when a specific pulse arrives, create a [Pulse Workflow](/workflows/pulse-workflows) with matching conditions and an incident-creation or paging action. Pulses are retained indefinitely by default. If your workspace has a data-retention policy, pulses fall under the same retention window as incidents. Contact support if you need a shorter retention window for pulses specifically. Yes. The Pulses page in Rootly Web is a searchable, filterable timeline independent of any specific incident. Filter by service, environment, label, or time window. Pulses use the standard Rootly API rate limits. High-volume pulse sources (for example, a CI system pulsing on every commit) can hit limits — batch or throttle at the source, or use the CLI which handles retries. Yes. See [Pulse Variables](/liquid/pulse-variables) for the reference — `{{ pulse.id }}`, `{{ pulse.short_id }}`, `{{ pulse.source }}`, `{{ pulse.summary }}`, and `{{ pulse.data }}` (the raw pulse payload). Reach into the payload with `{{ pulse.data | get: 'field_name' }}` for anything not exposed as its own top-level variable. `rootly pulse create` creates a pulse from a summary and metadata you provide. `rootly pulse run` wraps an actual shell command — it executes the command, captures its exit status and runtime, and creates a pulse with that metadata attached automatically. Use `pulse run` when the pulse *is* the fact that a specific command ran (deploy scripts, migration jobs, backup jobs). *** ## Related Pages Turn pulses into automation — post to Slack, create tickets, trigger incidents based on pulse content. Liquid reference for `pulse.id`, `pulse.short_id`, `pulse.source`, `pulse.summary`, and `pulse.data`. Full command reference for the Rootly CLI, including `pulse create` and `pulse run`. # Security Best Practices Source: https://docs.rootly.com/configuration/security-best-practices Harden your Rootly tenant — identity and SSO, RBAC and least privilege, API hygiene, audit logging, session controls, and integration hygiene. ## Overview This page walks Rootly administrators through the controls available for hardening a tenant against unauthorized access, lateral movement, and silent configuration drift. It is the recommended checklist when preparing Rootly for an enterprise security review, a SOC 2, or onboarding a new organization. Every recommendation below is grounded in features Rootly ships today — links lead to the relevant configuration page. The order mirrors how most teams roll out hardening: identity first, then permissions, then API surface, then monitoring. SAML SSO plus SCIM provisioning so the IdP is the source of truth for who can log in and what role they hold. Custom roles and on-call seat controls scoped to job function — no blanket admin grants. OAuth 2.0 over long-lived tokens, scoped permissions, and routine credential rotation. Indefinite audit log retention with filterable change history across configuration, integrations, incidents, and workflows. *** ## Centralize Identity The fastest single hardening step for any Rootly tenant is moving authentication behind your IdP. Once SSO is enforced, you control account lifecycle, MFA, and conditional access from one place — Rootly inherits whatever your IdP enforces. Configure SAML 2.0 with your IdP (Okta, Azure AD, Google Workspace, OneLogin, JumpCloud, Auth0, or any SAML 2.0-compatible provider). See [SSO](/integrations/sso) for the service provider details and IdP-specific walkthroughs. MFA is enforced at the IdP layer, not in Rootly directly. Use the IdP's conditional access policies to require MFA, device posture checks, or location restrictions before letting users land in Rootly. Configure SCIM 2.0 so user creation, role assignment, and deactivation are driven by IdP group membership. See [SCIM](/integrations/scim). SCIM is the most important control for deprovisioning: when an employee leaves and the IdP disables their account, SCIM automatically deactivates their Rootly account on the next sync — closing the gap where a manual admin would otherwise need to remember to revoke access. With SSO enforced, prefer SCIM-driven provisioning (or Just-In-Time provisioning from the SAML assertion) over manual invite-by-email. Direct email invites create accounts that won't be auto-deprovisioned when the user leaves the organization. See [SCIM](/integrations/scim) for full lifecycle provisioning and [SSO](/integrations/sso) for the SAML attribute mapping that drives Just-In-Time provisioning. (Rootly also supports manual invites via [Inviting Users via Third-Party Integrations](/managing-users/inviting-users-via-third-party-integrations) for Slack, Opsgenie, PagerDuty, and Splunk On-Call — useful for narrow cases, but not the right primitive for IdP-managed lifecycle.) *** ## Apply Least Privilege Rootly's role model lets you scope what a user can do down to the action level. Use it — broad admin grants are the largest unforced security risk in most tenants. Define purpose-built roles ("Incident Responder", "On-Call Operator", "Auditor") instead of granting full admin. See [User Permissions](/managing-users/user-permissions) for the available permission scopes. Delegate team-scoped configuration to team admins instead of org-wide admins. Team admins can manage their team's schedules, escalation policies, and members without touching org-level settings. See [Configuring Teams](/managing-teams/configuring-teams). On-call paging requires a separate seat type. Grant on-call seats only to users who actually take pages — users without a seat cannot be added to schedules, eliminating accidental paging exposure to non-responders. Compliance and security reviewers should hold an Auditor role with read-only access to the audit log and configuration — never an admin role. Run a quarterly review of admin role assignments. The [Audit Log](/configuration/audit-log) records every role change with before-and-after values, making this a five-minute filter exercise rather than a manual cross-check. *** ## Lock Down API Access Rootly exposes a public API plus OAuth 2.0 provider endpoints. Both deserve deliberate hardening. ### Prefer OAuth 2.0 Over Long-Lived API Tokens For machine-to-machine integrations, use [OAuth 2.0](/api-reference/oauth2) rather than static API tokens. OAuth tokens have explicit scopes, short lifetimes, and can be revoked from a single place. Long-lived API tokens are appropriate only for narrow internal tooling, and should be rotated on a fixed cadence. ### Scope API Tokens Tightly When an API token is necessary, scope it to the minimum permission set the integration needs. A token used by a Datadog → Rootly forwarder should not have the ability to modify escalation policies or user roles. ### Audit Outgoing Webhook Destinations [Outgoing webhooks](/configuration/webhooks) post to URLs you supply. Review the webhook destinations in your tenant on a recurring cadence and remove ones pointing at decommissioned receivers — orphaned destinations accumulate over time and become exfiltration risks once their hosts change ownership. *** ## Turn On Continuous Audit Rootly's [Audit Log](/configuration/audit-log) captures every create, update, and delete across \~60 resource types with full before-and-after field values. It is the compliance evidence layer auditors look for. Walk security and compliance reviewers through **Configuration → Audit Log** so they can self-serve "who changed X, when?" questions without filing tickets to the Rootly admins. The audit log is available via the [audit log JSON:API endpoint](/configuration/audit-log#programmatic-access-via-api) for scheduled export — useful for backing up evidence into long-term storage your auditors already own, or for ad-hoc queries beyond what the UI filters expose. Review these events on a routine cadence: role assignments granting admin, API token creation, webhook destination changes, user deletion, escalation policy changes outside change-control windows. These are the events that precede or are part of most security incidents. *** ## Control Session And Device Posture Configure a default session timeout in your team settings. Shorter timeouts (8 hours or less for high-privilege roles) reduce the scope of impact of a stolen session cookie or unlocked workstation. Use your IdP's conditional access (Okta, Microsoft Entra Conditional Access, Google Context-Aware Access) to gate Rootly access on device posture — managed device, current OS, antivirus running. Rootly inherits the gate; you don't need to re-implement it. *** ## Harden Third-Party Integration Hygiene Each integration you connect is a potential blast-radius vector if its credentials leak. Routine hygiene: * **Rotate integration credentials on a schedule.** Most providers let you regenerate API keys without recreating the integration — schedule a quarterly rotation for high-privilege integrations (PagerDuty, Slack, GitHub, Datadog). * **Disable integrations you no longer use.** A connected-but-unused integration is still attack surface. Review your integrations list each quarter and disable connections to systems your team no longer relies on. The [Audit Log](/configuration/audit-log) captures recent configuration changes to each integration, which helps confirm whether one has been actively maintained. * **Limit Slack workspace access.** When configuring the Slack integration, install it as a specific workspace admin rather than a personal account — that way, the integration outlives any individual user's tenure. * **Review integration scope grants.** When connecting OAuth-based integrations (Google Workspace, Microsoft 365), confirm the requested scopes match what Rootly actually needs for the features you use. *** ## Status Page And Public Surface If you publish status pages, treat the public surface deliberately: * Use [Status Page Authentication Methods](/configuration/status-page-authentication-methods) — password protection or SAML SSO — on any status page that should not be world-readable. * Confirm [Public And Private Status Pages](/configuration/status-pages#public-or-private) classifications match intent — a misclassified private page is a data exposure. * Use a [Custom Domain](/configuration/custom-domain-names-for-status-pages) for branded status pages so DNS and TLS sit under your control. *** ## Compliance Posture Rootly maintains SOC 2 Type II. Auditors and customer security teams typically request the following artifacts during review: | Artifact | Where To Get It | | ------------------------ | --------------------------------------------------------------------------------------- | | SOC 2 Type II report | Contact [support@rootly.com](mailto:support@rootly.com) for the latest report under NDA | | Subprocessor list | Published at [Subprocessors](/configuration/subprocessors) | | Data processing addendum | Available through your account team | For tenant-side compliance evidence (who has access, what changed, when), the [Audit Log](/configuration/audit-log) is the system of record — its filterable change history and JSON:API export are designed to satisfy "demonstrate continuous monitoring" controls. *** ## Frequently Asked Questions MFA is enforced at the identity-provider layer. Once SAML SSO is configured, whatever MFA policy your IdP applies (TOTP, push, FIDO2/WebAuthn, certificate-based) is what controls Rootly login. There is no separate Rootly-native MFA setting — using the IdP's MFA is the recommended pattern because it centralizes policy. Audit log retention is unlimited by default — every create, update, and delete event is retained for the lifetime of your tenant. For long-term archival outside Rootly, use the [audit log JSON:API endpoint](/configuration/audit-log#programmatic-access-via-api) to export events into compliance storage your auditors already own. Create the replacement token first, deploy it to the consuming integration, verify traffic is flowing on the new token (visible in audit log events sourced from "API" with the new token's identifier), then revoke the old one. The overlap window is the safe rotation pattern — never delete a token before its replacement is in use. No. The audit log automatically redacts sensitive fields (passwords, API keys, OAuth tokens, signing secrets) in the UI and API responses. You see that the field changed, but not the value. Create a custom **Auditor** role with read-only access to configuration, the audit log, and (optionally) incident records. Auditors should never hold an admin role — they need to read, not modify. *** ## Next Steps SAML 2.0 setup with Okta, Azure AD, Google Workspace, and other identity providers. Automate user lifecycle from your IdP — the deprovisioning control most worth getting right. Full change history across configuration, integrations, and incidents — filterable in the UI and exportable via the JSON:API. Custom roles, team admins, and the permission scopes available for least-privilege design. *** ## Related Pages The visibility layer — every change to sensitive configuration surfaces here. Route incident, alert, workflow, and status-page events to external systems — periodically review destinations for orphans. The umbrella page covering incident properties and configuration surface. # Services Source: https://docs.rootly.com/configuration/services Configure services to identify impacted components during incidents, manage responders, and integrate with status pages and external tools. ## Overview *Service* allows you to specify the impacted component during an incident. This can help you with identifying which responders to bring in, which on-call to page, which customers to inform, etc. Individual services can be mapped to your status pages. ## Adding Services in Rootly To add a new Service via the Rootly Web UI, navigate to **Configuration > Services** then click **New Service**. Assign your new Service with a descriptive Title and Description to help the rest of your team know what the Service represents. ## Editing Services Services are made up of a number of properties. Each property can be referenced via Liquid syntax and can be set in the Rootly Web UI, [API](/api-reference/services/list-services), or [imported from Opsgenie and PagerDuty](/configuration/services#import-services). This section outlines how to edit the Services in the Rootly Web UI. ## Adding Properties While Services in Rootly comes with built-in properties, additional properties can be added. This allows you to build automations and workflows for your incident response processes using this information: for example, quickly identifying the customer impact of an incident based on the related service. To add custom properties, open **Services**, click **Edit catalog**, and click **Add Property**. You can choose from several property types, including text, boolean, and importantly references to other Catalogs. For each Service, you'll be able to find the values of these properties in the **Custom Properties** tab. ## Basics Configure the basic details of your Service here. This is the unique identifier of the service. This field **cannot be customized**. Rootly will auto assign the *ID* upon creation. It is typically used in Liquid references and API calls. The following Liquid syntax will allow you to list out the service *ID*(s) that are selected for an incident: `{{ incident.services }}` OR `{{ incident.raw_services | get: 'id'}}` for select field type `{{ incident.raw_services[index] | get: 'id' }}` for multi-select field type This is the value that is displayed on the UI for the service. This field is customizable. The following Liquid syntax will allow you to list out the service *name*(s) that are selected for an incident: `{{ incident.services }}` OR `{{ incident.raw_services | get: 'name'}}` for select field type `{{ incident.raw_services[index] | get: 'name' }}` for multi-select field type This value is displayed on the UI to further explain each service. This field is customizable. The following Liquid syntax will allow you to list out the service *description*(s) that are selected for an incident: `{{ incident.raw_services | get: 'description'}}` for select field type `{{ incident.raw_services[index] | get: 'description' }}` for multi-select field type Clear team ownership helps identify service owners and dependencies during incidents. The Owning Team's admins will be able to make changes to the Service. Add any services that may be related or affected by this service. This is for reference only and won't have any actual impact. Each service can be assigned a color, which will be used for color-coding on metrics graphs. Rootly uses **color-hex codes**. For example, #000000 is black, #ffffff is white. Use [color-hex.com](https://www.color-hex.com/) to find the exact hex code for the color you want. The following Liquid syntax will allow you to list out the service *color*(s) that are selected for an incident: `{{ incident.raw_services | get: 'color'}}` for select field type `{{ incident.raw_services[index] | get: 'color' }}` for multi-select field type ## On-Call Configure what happens when this Service is paged in Rootly On-Call. When this Service is paged either manually by a user, or through an Alert Source, the Escalation Policy selected here will fire. ## Channels Configure the Channels section to reference the Service's related Slack properties. These Slack properties (like Slack Channel and User Group) can be used in Rootly's Workflows to build powerful Slack automations off of the Service. Each service can be linked to one or more Slack channels. By default, Rootly does not notify the linked channel(s) when a service is selected for an incident. Notification needs to be explicitly called out as Attached Service Channels in workflow configurations. Systematically, each Slack channel is stored as an object containing an id and name. The following Liquid syntax will allow you to list out the service *Slack Channel*(s) that are selected for an incident: `{{ incident.raw_services | get: 'slack_channels'}}` for select field type `{{ incident.raw_services[index] | get: 'slack_channels' }}` for multi-select field type Each service can be linked to one or more Slack user groups (aka aliases). By default, Rootly does not invite users in the linked user group(s) when a service is selected for an incident. Invitations need to be explicitly called out as Attached Service Aliases in workflow configurations. The following Liquid syntax will allow you to list out the service *Slack Alias*(es) that are selected for an incident: `{{ incident.raw_services | get: 'slack_aliases'}}` for select field type `{{ incident.raw_services[index] | get: 'slack_aliases' }}` for multi-select field type Each service can be linked to one or more emails. By default, Rootly does not send emails to the linked address(es) when a service is selected for an incident. Notification needs to be explicitly called out as `{{ incident.raw_services | map: 'notify_emails' | flatten | join: ',' }}` in workflow configurations. The following Liquid syntax will allow you to list out the service *Notify Email*(s) that are selected for an incident: `{{ incident.raw_services | get: 'notify_emails'}}` for select field type `{{ incident.raw_services[index] | get: 'notify_emails' }}` for multi-select field type You can also set up default broadcast channels for when the service is either paged, or added to an incident on this page. Toggle **Set up a default Alerts Channel** On when you want Rootly to automatically post an update to Slack when the service is paged. Toggle **Set up a default Incidents Channel** when you want to post once the service has been added to an incident. ## Services in Fields *Service* can be customized to be either a **select** or **multi-select** field type. This means you can configure it to allow only one service value to be selected per incident or allow multiple service values to be selected for a single incident. Since the service field can be either a **select** or **multi-select** field type, the Liquid syntax to reference each field type will differ. Select will follow a single-value syntax `{{incident.raw_services | get: ''}}` Multi-select will follow an array syntax. Where i references the specific service object in the list of services. `{{incident.raw_services[index] | get: ''}}` ## Import Services Instead of creating services from scratch, Rootly allows you to import services from **PagerDuty** or **Opsgenie**. Imported services will be automatically kept in sync on a daily basis. The ability to import services will only become available once you have PagerDuty or Opsgenie installed on the [integrations page](https://rootly.com/account/integrations). The following Liquid syntax will allow you to list out the corresponding ids from each of the external paging applications: **PagerDuty** `{{ incident.raw_services | get: 'pagerduty_id' }}` for select field type `{{ incident.raw_services\[0\] | get: 'pagerduty_id' }}` for multi-select field type **Opsgenie** `{{ incident.raw_services | get: 'opsgenie_id' }}` for select field type `{{ incident.raw_services\[0\] | get: 'opsgenie_id' }}` for multi-select field type *** ## Related Pages Group services into higher-level customer-facing capabilities like Login or Checkout. Assign services to owning teams that get paged when the service is impacted. Attach an escalation policy to a service so alerts on it actually page someone. # Severities Source: https://docs.rootly.com/configuration/severities Configure incident severity levels, calibrate a severity matrix for your team, and use severities to drive workflows, escalations, and status pages. ## What Are Incident Severity Levels? **Severity** is the property that expresses how bad an incident is. It's the single number responders reach for first — "is this a SEV0 or a SEV2?" — because so much else in the response process keys off it: who gets paged, how urgently, whether the status page is updated, what the retrospective template looks like, and how the incident is counted in your metrics. Severity is a **fixed, single-select property**. Every incident carries exactly one severity value, and that value is fully customizable — pick the number of levels, their names, colors, and behavior that matches how your team actually calibrates impact. *** ## How Severities Are Used Severity isn't just a label — it's a lever that other Rootly features pull on: | Feature | How severity is used | | ------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | **[Workflow conditions](/workflows/conditions)** | Filter workflows so they fire only on specific severities. The most common pattern is "page on-call on SEV0/SEV1" or "auto-create Jira ticket on SEV2+". | | **Escalation policies** | While escalation policies themselves don't branch on severity directly, workflow-driven paging typically routes different severities to different escalation policies (higher severity = shorter first-step timeout, more responders). | | **Slack channel + alias notifications** | Each severity can be linked to Slack channels and user groups (aliases). Workflows use these to auto-invite the right responders and post to the right announcement channels when a severity is set. | | **Notify emails** | Each severity can be linked to email addresses. Workflows use these to send severity-tiered stakeholder notifications. | | **Status page publication** | Not automatic per severity — status page publication is decided by workflow conditions that check severity. Most teams auto-publish SEV0/SEV1 and manually decide on SEV2. | | **Metrics + reporting** | Severity is a top-level filter in every metrics dashboard. MTTR-by-severity is one of the most-referenced numbers in incident review programs. | | **Retrospective templates** | Different severities can trigger different retrospective templates via workflow — SEV0s get the full multi-section review, SEV3s get a lightweight one. | Because so much automation branches on severity, **the shape of your severity matrix drives the shape of your response process**. That's why the picker below and the matrix-design guidance further down matter as much as the attribute configuration. *** ## Which Severity Should I Pick? Deciding severity under pressure is the hardest part of severity calibration — new responders default to SEV0 out of caution and burn out the team; old hands default to SEV2 out of habit and miss real emergencies. Use the picker below as a starting point when the answer isn't obvious, then refine against your team's specific severity matrix. Your team's severity matrix may weight impact dimensions differently (for example, regulated industries treat data exposure as automatic SEV0; ad-supported businesses may treat revenue-blocking outages as SEV1 even at partial scope). The picker offers a common baseline; the final call belongs to the responder declaring the incident. *** ## Designing Your Severity Matrix There is no universal severity matrix — but there is a small set of patterns that work for most teams. Use these as a starting point, then adjust the wording to match your specific product and customer promises. ### How Many Levels Most teams land on **four to five severity levels**. Fewer than four and you can't distinguish "everything is broken" from "some things are broken." More than five and calibration becomes fuzzy — SEV4 and SEV5 stop being meaningfully different, and responders default to SEV3 for everything below the top tier. | Levels | When it fits | | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | **SEV0–SEV3** (four levels) | Most SaaS teams. Clean top-to-bottom scale with room to distinguish emergency, major, moderate, and minor incidents. | | **SEV1–SEV5** (five levels) | Larger engineering orgs with formal incident review programs. Extra granularity helps segment metrics. | | **SEV0–SEV5** (six levels) | Overkill for most teams. Consider consolidating unless you have a documented reason each level is used regularly. | | **P1–P4** or **Critical/High/Medium/Low** | Named tiers are functionally equivalent to numbered tiers. Match whichever naming convention your team already uses in Jira or your incident channel. | ### Impact Dimensions A well-calibrated matrix considers multiple dimensions of impact — not just "how many users are affected" but also *what* is affected and for how long. Common dimensions: * **User scope** — everyone, a large segment, a small segment, individual users * **Feature scope** — entire product, one workflow, one screen, edge case * **Data integrity** — data loss / corruption / exposure present or not * **Workaround availability** — none, painful, minor friction, invisible * **Duration expectation** — active, transient, self-resolving Not every dimension needs to weight equally. A regulated financial-services company weights data integrity above everything; an ad-supported consumer app weights user scope more heavily. **Explicit weighting is fine and often better than pretending your team treats all dimensions equally.** ### Response Commitments Per Level Severity levels should tie to **concrete response commitments** so calibration isn't just a name — it's a promise. Common commitments to attach per severity: * **Paging urgency** — SEV0 pages all-hands immediately; SEV1 pages the owning team; SEV2 pages during business hours; SEV3 assigns without paging * **Incident Commander required** — SEV0/SEV1 yes, SEV2/SEV3 optional * **First status-page update within** — SEV0: 5 min · SEV1: 15 min · SEV2: 30 min · SEV3: not required * **Retrospective required** — SEV0/SEV1 always, SEV2 if user-visible, SEV3 optional * **Executive notification** — SEV0 immediately, SEV1 within an hour, SEV2/SEV3 in weekly summary Documenting these commitments in a shared runbook — not just in your head — is what turns severity from a label into an operating agreement. ### Example Matrices Common for mid-market SaaS teams with a mix of enterprise and self-serve customers. | Level | Trigger example | First response | | -------- | --------------------------------------------------- | ---------------------------------------------------- | | **SEV0** | Total outage, active data loss, security breach | Page all-hands, IC required, status page in 5 min | | **SEV1** | Major feature down for large segment, no workaround | Page owning team, IC required, status page in 15 min | | **SEV2** | Partial degradation, workaround available | Assign to team, business-hours response | | **SEV3** | Minor bug, cosmetic issue | File a ticket, roadmap-driven fix | Adds a level explicitly for data-integrity events, which typically override user-scope considerations. | Level | Trigger example | First response | | -------- | -------------------------------------------------------------- | --------------------------------------------------------------------------------------------- | | **SEV0** | Total outage or active security breach | All-hands, exec notification, status page in 5 min | | **SEV1** | Data integrity event (loss, corruption, exposure) at any scale | Page privacy + security + owning team, mandatory retrospective, regulator-notification review | | **SEV2** | Major feature broken, large user segment, no workaround | Page owning team, status page in 15 min | | **SEV3** | Partial degradation, workaround available | Business-hours response | | **SEV4** | Minor bug or cosmetic issue | File a ticket | Fewer levels because customer-facing severity nuance doesn't apply the same way. | Level | Trigger example | First response | | -------- | ---------------------------------------------------------- | --------------------------------- | | **SEV1** | Blocking most engineers (CI, deploys, source control down) | Page platform on-call immediately | | **SEV2** | Impacting some workflows (specific integrations broken) | Assign to team, same-day fix | | **SEV3** | Nuisance-level issues | Ticket, next sprint | *** ## Configuring Severity Attributes Configure severities in **Configuration → Severities**. Each severity can be tuned with the following attributes. Every attribute is available in Liquid syntax for use in workflows, retrospective templates, and status page updates. Unique identifier assigned automatically by Rootly on creation. **Not customizable.** Used in Liquid references and API calls. ```liquid theme={null} {{ incident.severity_id }} {{ incident.raw_severity | get: 'id' }} ``` The display name shown throughout the Rootly UI. Fully customizable — most teams use `SEV0`, `SEV1`, `SEV2`, `SEV3` or `P1`, `P2`, `P3`, `P4`. ```liquid theme={null} {{ incident.severity }} {{ incident.raw_severity | get: 'name' }} ``` Auto-generated by lower-casing and hyphenating the name. Used in Liquid references and stable across name changes. ```liquid theme={null} {{ incident.severity_slug }} {{ incident.raw_severity | get: 'slug' }} ``` Additional context shown alongside the severity in the UI. Best used to remind responders what qualifies for each level — for example, "Total outage or active data loss." ```liquid theme={null} {{ incident.raw_severity | get: 'description' }} ``` Hex color code used for severity-tinted UI accents and metrics-graph color coding. Convention: red for the highest severity, orange/yellow for middle tiers, blue/gray for the lowest. ```liquid theme={null} {{ incident.raw_severity | get: 'color' }} ``` Rootly expects six-digit hex codes (for example, `#c4231c` for red, `#ed8f17` for orange). Use a color picker if you're not sure — [color-hex.com](https://www.color-hex.com/) is a common choice. One or more Slack channels linked to the severity. **Linking alone doesn't post to the channels** — a workflow action (typically "Attached Severity Channels" or "Notify Attached Slack Channels") reads this list and performs the notification. ```liquid theme={null} {{ incident.raw_severity | get: 'slack_channels' }} ``` One or more Slack user groups (aka aliases) linked to the severity. **Linking alone doesn't invite users** — a workflow action (typically "Attached Severity Aliases") reads this list and performs the invitation. ```liquid theme={null} {{ incident.raw_severity | get: 'slack_aliases' }} ``` One or more email addresses linked to the severity. **Linking alone doesn't send email** — a workflow action reads this list and sends the notification. ```liquid theme={null} {{ incident.raw_severity | get: 'notify_emails' }} ``` For workflow-driven use, most teams reference the flattened list: ```liquid theme={null} {{ incident.raw_severity | map: 'notify_emails' | flatten | join: ',' }} ``` *** ## Best Practices * **Calibrate quarterly.** Look at the last 90 days of incidents and ask: did we call any of these wrong in retrospect? Adjust the matrix language, not just individual calls. * **Don't add SEV4/SEV5 until SEV3 is used regularly.** Extra levels only work if you actually distinguish between them. If SEV3 is your effective floor, adding SEV4 just creates a level nobody uses. * **Colors should be intuitive.** Red for the top severity, orange/yellow for middle, blue/gray for the lowest. Don't invent custom mappings — responders read the color before the name and calibration takes twice as long if the color contradicts convention. * **Downgrading is fine; upgrading is expected.** Encourage responders to over-page at SEV0 and downgrade within 15 minutes if scope narrows. Under-response at declaration is the failure mode you're trying to avoid, not over-response. * **Keep the picker open during on-call handoffs.** Sharing the picker link (`/configuration/severities#which-severity-should-i-pick`) is one of the fastest ways to onboard new responders to the calibration model. * **Attach Slack channels + aliases per severity, but require workflow actions to actually use them.** This keeps notification behavior explicit and auditable in the workflow list rather than hidden in severity settings. * **Test severity changes in a Test Incident first.** If you rework the matrix or add a new severity, declare a `/rootly test` and walk the workflows through their branches before the next real incident hits the new definitions. *** ## Troubleshooting Confirm the severity is enabled (not archived) under Configuration → Severities. Archived severities remain visible on historical incidents but don't appear as options on new incidents. If it's enabled and still missing, check whether team-level severity restrictions are in play — some teams scope which severities each team can declare. Linking Slack channels or aliases to a severity **does not** cause auto-invitation on its own. You need a workflow with an "Attached Severity Channels" or "Attached Severity Aliases" action, keyed off a Severity Updated trigger or the initial Incident Created trigger. Check that the workflow exists, is enabled, and has run conditions that match the severity you're testing with. Metrics bucket incidents by the severity value at the time of the metric query — so if severity was changed mid-incident, the current severity is what's counted (not the initial one). If you need historical severity data, query the incident timeline events, which record every severity transition with timestamps. Confirm the color is a valid six-digit hex code starting with `#` (for example, `#c4231c`, not `c4231c` or `rgb(196, 35, 28)`). Rootly won't attempt to parse shorthand or non-hex color formats. Two common causes: (1) the description field for each severity is empty or too vague — expand each severity's description to name concrete example scenarios; (2) the picker on this page isn't linked from your on-call runbook — add a link so responders reach for it during triage. Also review the last 30 days of incidents in a calibration meeting and identify which mis-calls the language could have prevented. *** ## Frequently Asked Questions Most teams land on four (SEV0–SEV3) or five (SEV1–SEV5). Fewer than four can't distinguish emergency from major from moderate. More than five and the extra levels stop being meaningfully different in practice — see the Designing Your Severity Matrix section above for detail. Yes, and it's expected. Changing severity logs a timeline event with the transition timestamp, which downstream workflows can trigger off (via the Severity Updated trigger). Most teams see severity change one to two times per incident as scope becomes clearer. In Rootly, severity is the built-in property. Priority (if you use it) is typically a custom field layered on top — often used to distinguish "how urgent is this to fix" from "how bad is this while it's happening." A minor bug with a big customer implication might be SEV3 severity but P1 priority. Rootly doesn't ship priority as a built-in; add it as a [Custom Field](/configuration/custom-fields) if you want it. No. Test incidents (declared via `/rootly test`) are excluded from production metrics regardless of the severity assigned. This is enforced at the Kind level — see [Incident Kind](/configuration/incident-kind) for the full behavior matrix. Yes. Severity is one of the most common fields to filter on in workflow run conditions. The [Workflow Conditions](/workflows/conditions) page has an interactive evaluator you can use to test severity-based conditions against a sample incident before wiring them into a real workflow. Rootly's severity list is org-wide, but teams can restrict which severities their responders declare. If you need genuinely different severity matrices per team (for example, an infra team using P1–P4 and a product team using SEV0–SEV3), the current recommendation is to unify to one matrix and use naming that works for both — running two parallel matrices is confusing at the org level for metrics and executive reporting. Deleting (or archiving) a severity leaves historical incidents referencing it intact — the incident keeps its original severity value even after the severity is removed from the picker. Only new incidents lose access to the removed severity. If you're doing a matrix overhaul, archive old severities rather than deleting, so historical incident data stays readable. *** ## Related Pages Use severity in workflow run conditions to route different severities to different response processes. The other fixed property — governs whether an incident counts in metrics regardless of severity. Add a priority field or other custom taxonomy on top of severity. # Status Page Authentication Methods Source: https://docs.rootly.com/configuration/status-page-authentication-methods Configure authentication for public Rootly status pages to control viewer access using password protection or SAML-based single sign-on. ## Overview Rootly provides multiple authentication methods to secure access to your public status pages. You can choose from no authentication, password protection, or enterprise-grade SAML authentication depending on your security requirements. Authentication is only available for **public status pages**. Private status pages require users to be logged in to Rootly by default. ## Authentication Methods Your status page is publicly accessible to anyone with the URL. This is the default setting and is suitable for: * Public-facing service status pages * External customer communications * Maximum visibility during incidents Protect your status page with a shared password. Anyone with the password can access the page. **Best for:** * Partner or vendor portals * Limited external stakeholder access * Quick setup without SSO infrastructure **How to configure:** 1. Navigate to your status page settings. 2. Go to the **Authentication** tab. 3. Select "Password" as the authentication method. 4. Enter your desired password. 5. Save the changes. Share the password securely with stakeholders who need access. Enterprise-grade single sign-on using SAML 2.0 protocol. Users authenticate through your identity provider (IdP) without needing separate credentials. **Best for:** * Enterprise customers with existing SSO infrastructure * Compliance requirements (SOC 2, ISO 27001) * Centralized access control and audit logs * Multiple status pages with different IdP configurations **Supported features:** * SAML 2.0 authentication flow * Single Logout (SLO) * Per-status-page IdP configuration * X.509 certificate validation * Multiple name identifier formats ## Configuring SAML Authentication ### Prerequisites Before configuring SAML authentication, you'll need: * Access to your Identity Provider (IdP) admin console (for example, Okta, Azure AD, Google Workspace) * Your IdP's SSO Service URL * Your IdP's X.509 certificate * Permissions to create SAML applications in your IdP - Navigate to your status page settings. - Select the **Authentication** tab. - Choose "SAML" as the authentication method. You'll need to create a new SAML application in your IdP with the following information from Rootly. **Service Provider (SP) Details:** | Field | Description | Example | | ---------------------------- | -------------------------------------- | ------------------------------------------ | | **Entity ID / Audience URL** | Unique identifier for your status page | `https://status.company.com/saml/metadata` | | **ACS URL / Callback URL** | Where SAML responses are sent | `https://status.company.com/saml/consume` | | **Metadata URL** | Complete SP metadata (optional) | `https://status.company.com/saml/metadata` | These URLs are automatically generated after you save your status page and will be displayed in the Authentication tab for easy copying. Enter the following information from your Identity Provider: The SAML authentication endpoint provided by your IdP. **Example:** `https://your-company.okta.com/app/abc123/sso/saml` The X.509 certificate from your IdP for validating SAML responses. Paste the full certificate including the BEGIN/END lines. ```text theme={null} -----BEGIN CERTIFICATE----- MIIDpDCCAoygAwIBAgIGAXoTpGkZMA0GCSqGSIb3DQEBCwUAMIGSMQswCQYDVQQG ... -----END CERTIFICATE----- ``` The format for user identification in SAML assertions. **Options:** * Email Address (default) * Unspecified * Persistent * Transient Optional endpoint for SAML Single Logout functionality. **Example:** `https://your-company.okta.com/app/abc123/slo/saml` * Save your SAML configuration. * Open your status page URL in a private/incognito browser window. * Click the sign-in option. * You should be redirected to your IdP for authentication. * After successful authentication, you'll be redirected back to the status page. ## Common Identity Provider Guides Configure SAML with Okta using the Entity ID, ACS URL, and download the certificate from your Okta application settings. Use Azure AD Enterprise Applications to create a custom SAML app. Copy the Login URL and certificate from the SAML Signing Certificate section. Configure a custom SAML app in the Google Admin console. Use the SSO URL and download the IDP certificate. Create a SAML application in OneLogin and configure the ACS URL. Download the X.509 certificate from the SSO tab. ## Security Considerations **Certificate Management:** SAML certificates have expiration dates. Monitor your certificate expiration and update it in Rootly before it expires to prevent authentication failures. Rootly's SAML implementation includes: * **X.509 Certificate Validation** - All SAML responses are verified using your IdP's certificate * **Signature Verification** - Protects against tampering and man-in-the-middle attacks * **Replay Attack Protection** - SAML assertions are validated for freshness * **Audit Logging** - All authentication attempts are logged for compliance * **Secure Session Management** - Encrypted cookies with automatic expiration ## Troubleshooting ### "Invalid SAML Response" Error * Verify your IdP certificate is correctly formatted with BEGIN/END lines * Check that the certificate hasn't expired * Ensure the ACS URL in your IdP matches exactly (including https\://) ### "Authentication Failed" Error * Confirm the SSO Service URL is correct * Check that the SAML application is assigned to the correct users in your IdP * Verify the Name Identifier Format matches your IdP configuration ### Users Cannot Access After Authentication * Ensure the status page authentication method is set to "SAML" * Check that your IdP is sending the SAML response to the correct ACS URL * Verify there are no network/firewall restrictions blocking the SAML flow ### Certificate Expiration If your SAML certificate expires: Download the new certificate from your IdP. Navigate to your status page Authentication settings. Update the IdP Certificate field with the new certificate. Save the changes. Set a calendar reminder 30 days before your certificate expiration date to ensure uninterrupted access. ## Switching Authentication Methods You can change authentication methods at any time: Navigate to your status page settings. Go to the **Authentication** tab. Select a different authentication method. Configure any required fields. Save your changes. Changing from SAML or Password to "No Authentication" will make your status page publicly accessible immediately. ## API Configuration Authentication methods can also be configured via the Rootly API: ```json theme={null} PATCH /v1/status_pages/:id { "authentication_method": "saml", "saml_idp_sso_service_url": "https://your-idp.com/sso/saml", "saml_idp_cert": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----", "saml_name_identifier_format": "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress" } ``` See the [Rootly API documentation](/api-reference/overview) for complete details. ## Related Resources Learn about the differences between public and private status pages Get started with creating and managing status pages *** ## Related Pages Set up the status page you'll add auth to — auth options only apply to public pages. Point your own domain at the status page users authenticate against. The umbrella concept — public vs private, and which auth options apply where. # Status Page Public API Source: https://docs.rootly.com/configuration/status-page-public-api Access status and incident information programmatically through public JSON API endpoints exposed on your status page custom domain. ## Overview Rootly exposes a public JSON API on your status page's custom domain, allowing you to programmatically retrieve current status and incident data. These endpoints are available at your custom domain (for example, `status.example.com`) and respect your status page's existing authentication settings — password-protected and SAML-protected pages are not exposed. These endpoints are only available on status pages with a [custom domain](/configuration/custom-domain-names-for-status-pages) configured. ## Endpoints ### Get Current Status Returns the overall status of your services along with any active incidents. ```http theme={null} GET /api/v1/status.json ``` #### Get Current Status Response ```json theme={null} { "page": { "name": "Acme Status", "url": "https://status.example.com", "time_zone": "America/Los_Angeles", "updated_at": "2026-03-19T12:00:00Z" }, "status": { "indicator": "none", "description": "All Systems Operational" }, "incidents": [] } ``` The `status.indicator` field can be one of: | Indicator | Description | | ------------- | ------------------------------------------------ | | `none` | All systems operational | | `minor` | Minor service outage or degraded performance | | `major` | Major service outage or critical incident active | | `maintenance` | Scheduled maintenance in progress | ### List Incidents Returns a paginated list of active incidents, ordered by most recent first. ```http theme={null} GET /api/v1/incidents.json ``` #### Query Parameters | Parameter | Type | Default | Description | | ---------- | ------- | ------- | -------------------------------------- | | `page` | integer | 1 | Page number | | `per_page` | integer | 25 | Number of incidents per page (max 100) | #### List Incidents Response ```json theme={null} { "page": { "name": "Acme Status", "url": "https://status.example.com", "time_zone": "America/Los_Angeles", "updated_at": "2026-03-19T12:00:00Z" }, "incidents": [ { "name": "API Degradation", "status": "started", "impact": "minor", "started_at": "2026-03-19T10:30:00Z", "resolved_at": null, "url": "https://status.example.com/incidents/abc123", "incident_updates": [ { "body": "We are investigating reports of elevated API latency.", "status": "investigating", "created_at": "2026-03-19T10:35:00Z" } ] } ], "pagination": { "current_page": 1, "per_page": 25, "total_pages": 1, "total_count": 1 } } ``` ## Incident Impact Levels The `impact` field on each incident maps from the incident's severity: | Severity | Impact | | -------- | ---------- | | Critical | `critical` | | High | `major` | | Medium | `minor` | | Low | `minor` | | None | `none` | ## Authentication These API endpoints respect the same authentication settings as your status page: * **Public status pages**: Endpoints are accessible without authentication * **Password-protected pages**: Endpoints require the same password * **SAML-protected pages**: Endpoints require SAML authentication ## Example Usage ```bash theme={null} # Get current status curl https://status.example.com/api/v1/status.json # List incidents with pagination curl "https://status.example.com/api/v1/incidents.json?page=1&per_page=10" ``` *** ## Related Pages The umbrella concept — the public and private pages this API is the JSON surface of. How updates land on a status page — this API is the read side of the same data. The API sits on the same domain — auth mirrors the page's auth mode. # Status pages for internal and customer updates Source: https://docs.rootly.com/configuration/status-pages Create and manage status pages to communicate service health and incident information to internal stakeholders and external customers in real-time. ## What's a Status Page? Status pages allow you to quickly communicate information about the health of your services and applications to internal stakeholders and external customers. This helps save time for team members who might be actively involved in responding to an incident, or customer support staff who need to direct end users to a centralized place for live updates about your organization. Example Rootly status page displaying incident status and component health It only takes about a minute to set up a status page, so set one up soon after you've [signed up](/quick-start-guide). ## Public or Private? This is the first choice you make, and it shapes everything after it. The page type sets who can reach the page at all; [authentication](/configuration/status-page-authentication-methods) and a [custom domain](/configuration/custom-domain-names-for-status-pages) are options you layer on top of a public page afterwards. Rootly has two types of status pages available: public status pages and private status pages. Both can be used to communicate relevant information about ongoing or past incidents and the status of incidents and services. Rootly status page settings with public and private page options By default, you will have a public and private status page to customize and configure. You can add additional pages from the Status Page section in Rootly. Private status pages can only be accessed by Rootly users. These are great for communicating important incidents and service statuses to your internal teams. Users must be logged in to Rootly to access this page. Public status pages can be accessed by anyone who has access to the status page's URL. These are the perfect option to communicate incident updates and service statuses to your external stakeholders, like customers or partners. *** ## Related Pages Set up a status page after picking a type. Push incident updates to a status page from Web or Slack. Point your own domain at a status page with CNAME + CAA records. # Subprocessors Source: https://docs.rootly.com/configuration/subprocessors The third-party subprocessors Rootly uses to deliver its services, what each one is used for, and the categories of customer data each one processes. ## Overview A **subprocessor** is a third party Rootly engages to process customer personal data in the course of delivering the Rootly platform. This page lists those subprocessors, grouped by the function they serve. This list covers processing performed by Rootly. It does not cover integrations you connect yourself — see [Customer-enabled integrations](#customer-enabled-integrations) below for that distinction. All subprocessors listed here are bound by data processing agreements. Data sent to subprocessors is used solely to provide Rootly services and is not used for model training. *** ## Infrastructure Core infrastructure that Rootly runs on, including hosting, networking, and data transit. | Subprocessor | Purpose | Data processed | | ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | | [Amazon Web Services](https://aws.amazon.com) | Primary cloud infrastructure — compute, application databases, object storage, queuing, and event routing. Rootly runs entirely on AWS. | All customer data stored in Rootly, encrypted at rest | | [Cloudflare](https://cloudflare.com) | Content delivery, edge networking, and web application firewall | HTTP request data and tenant identifiers | | [ClickHouse Cloud](https://clickhouse.com/cloud) | Columnar analytics database for AI evaluation and product analytics | AI evaluation datasets and product usage metrics | | [QuotaGuard](https://www.quotaguard.com) | Static IP proxy for outbound integration traffic | HTTP request payloads transiting to customer-connected integrations | *** ## AI Features Applies to Rootly AI features. See [Data Privacy for AI](/ai/data-privacy-for-ai) for the full safeguards, retention terms, and bring-your-own-key options. | Subprocessor | Purpose | Data processed | | ---------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- | | [OpenAI](https://openai.com) | LLM inference for AI-powered summarization, catchup, and generative features | Incident content submitted for AI processing | | [Anthropic](https://anthropic.com) | LLM inference for AI-powered summarization, catchup, and generative features | Incident content submitted for AI processing | | [Amazon Bedrock](https://aws.amazon.com/bedrock/) | Hosted model inference for AI-powered summarization, catchup, and generative features | Incident content submitted for AI processing | | [Braintrust](https://braintrust.dev) | AI gateway and observability — LLM request routing, tracing, and evaluation | Incident content and other data submitted for AI processing | | [Recall.ai](https://recall.ai) | Meeting orchestration, recording capture, and platform connectivity for [AI Meeting Scribe](/ai/meeting-scribe) | Meeting audio/video streams, bot lifecycle events | | [AssemblyAI](https://assemblyai.com) (via Recall.ai) | Speech-to-text transcription, summarization, PII redaction, and speaker identification | Meeting audio for transcription | *** ## Notifications and alerting How Rootly reaches responders when they are paged. | Subprocessor | Purpose | Data processed | | -------------------------------------------------------------------------------- | -------------------------------------------------------------------------- | --------------------------------------------- | | [Twilio](https://twilio.com) | SMS and voice call delivery for on-call paging and live call routing | Phone numbers, alert and notification content | | [SendGrid](https://sendgrid.com) | Transactional and notification email delivery | Email addresses, notification content | | [Mailgun](https://mailgun.com) (Sinch AB) | Transactional email delivery | Email addresses, notification content | | [Firebase Cloud Messaging](https://firebase.google.com/products/cloud-messaging) | Push notification delivery to Android devices | Device push tokens, notification content | | [Apple Push Notification service](https://developer.apple.com/notifications/) | Push notification delivery to iOS devices | Device push tokens, notification content | | [Pushy](https://pushy.me) | Push notification delivery for devices in regions where FCM is unavailable | Device push tokens, notification content | *** ## Platform Operations Tooling Rootly uses to keep the service running and reliable. These process operational telemetry, which can incidentally contain user identifiers. | Subprocessor | Purpose | Data processed | | ------------------------------------------------------ | ----------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | | [Datadog](https://datadoghq.com) | Application performance monitoring, logging, and infrastructure observability | Application logs and telemetry, which may include user and team identifiers | | [Sentry](https://sentry.io) | Application error and exception tracking | Error traces and request context, which may include user and team identifiers | | [pganalyze](https://pganalyze.com) (Duboce Labs, Inc.) | Database performance monitoring and query analytics | Database query patterns and telemetry, which may include user and team identifiers | | [LaunchDarkly](https://launchdarkly.com) | Feature flag evaluation and progressive rollout targeting | Team and user identifiers used as targeting keys | | [Short.io](https://short.io) | URL shortening for incident and retrospective links (root.ly domain) | Incident and retrospective URLs | *** ## Business Operations and Analytics Internal tooling Rootly personnel use to support accounts, troubleshoot issues, and analyze product usage. | Subprocessor | Purpose | Data processed | | ---------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | | [Google Workspace](https://workspace.google.com) (Alphabet Inc.) | Corporate email, document storage, and productivity tools used by Rootly personnel | Employee and customer communication content, shared documents | | [Segment](https://segment.com) | Customer data platform for product analytics event routing | User profile data, product usage events | | [PostHog](https://posthog.com) | Product analytics and user behavior tracking | User and team identifiers, product usage events | | [HubSpot](https://hubspot.com) | CRM for account management and customer communication | User profile data and account metadata | | [Salesforce](https://salesforce.com) | CRM for account management and customer communication | User profile data and account metadata | | [Pylon](https://usepylon.com) | Customer support platform | User profile data, support ticket content | | [Linear](https://linear.app) (Linear Orbit, Inc.) | Internal support ticket tracking | User profile data, support ticket content | | [Oliv.ai](https://oliv.ai) | Product and customer analytics | User profile data and product usage metrics | | [Metabase](https://metabase.com) | Business intelligence. Rootly personnel run read-only queries against production application data to support customer accounts, troubleshoot issues, and analyze product usage. | User profile data (names, email addresses, phone numbers), incident and alert records, and associated metadata | | [Snowflake](https://snowflake.com) | Data warehouse for aggregated product usage and account health analytics | Product usage metrics and account metadata | | [Stripe](https://stripe.com) | Subscription billing and payment processing | Billing contact details and payment metadata | *** ## Communication and support How Rootly personnel communicate internally and with customers. | Subprocessor | Purpose | Data processed | | ---------------------------------------------------- | ----------------------------------------------------- | ----------------------------------------------- | | [Slack](https://slack.com) (Slack Technologies, LLC) | Internal team communication and incident coordination | User identifiers, message content | | [Intercom](https://intercom.com) (Intercom, Inc.) | In-app live chat and customer support | User profile data, support conversation content | *** ## Customer-Enabled Integrations Rootly connects to a wide range of third-party tools — Microsoft Teams, Jira, PagerDuty, GitHub, Datadog as an alert source, and [many others](/integrations/overview). These are **not** Rootly subprocessors. You enable them, you control the credentials, and data flows to them at your direction under your own agreement with that vendor. Rootly acts on your instruction to send data to a destination you chose. The distinction matters for your own DPA: the vendors listed above process your data because Rootly engaged them. Integration vendors process your data because you did. *** ## Changes to this list Rootly maintains a data processing agreement covering the processors listed here. To request the current DPA, or to ask about notification of changes to this list, contact your account team or [security@rootly.com](mailto:security@rootly.com). Additional compliance artifacts — SOC 2 Type II report, penetration test results, and security policies — are available through the [Rootly Trust Center](https://security.rootly.com). # Teams Source: https://docs.rootly.com/configuration/teams Configure team attributes in Rootly including Slack channels, user groups, escalation policies, on-call schedules, and imports from PagerDuty or Opsgenie. ## Overview Teams in Rootly let you organize your on-call and incident response processes around your organization's teams. Teams can be paged, assigned to an incident, and be used to build powerful workflow automations. This section outlines how Teams can be used as an attribute in your incident response processes. Learn more about [building and managing Teams](/managing-teams/managing-teams) in the Rootly Admin. ## Field Type **Teams** can be customized to be either a **select** or **multi-select** field type. This means you can configure it to allow only one team value to be selected per incident or allow multiple team values to be selected for a single incident. ## Attributes **Teams** can be configured with the following attributes. Each team attribute can be referenced via Liquid syntax. *Team* originally was called *group*. Hence all data values you see reference groups. Due to the risk of changing data values, Rootly kept referencing teams as groups from a data point of view. From a UI display point of view, you will see the term "*teams*" being used. Since the *team* field can be either a **select** or **multi-select** field type, the Liquid syntax to reference each field type will differ. Select will follow a single-value syntax `{{incident.raw_groups | get: ''}}` Multi-select will follow an array syntax. Where i references the specific team object in the list of teams. `{{incident.raw_groups[index] | get: ''}}` ### ID This is the unique identifier of the team. This field **cannot be customized**. Rootly will automatically assign the *ID* upon creation. It is typically used in Liquid references and API calls. The following Liquid syntax will allow you to list out the team *ID*(s) that are selected for an incident: `{{ incident.group_ids }}` **OR** * `{{ incident.raw_groups | get: 'id'}}` for select field type * `{{ incident.raw_groups[index] | get: 'id' }}` for multi-select field type ### Name This is the value that is displayed on the UI for the team. This field is customizable. The following Liquid syntax will allow you to list out the team *name*(s) that are selected for an incident: `{{ incident.groups }}` **OR** * `{{ incident.raw_groups | get: 'name'}}` for select field type * `{{ incident.raw_groups[index] | get: 'name' }}` for multi-select field type ### Slug This is the string that is used to reference the team in Liquid references. This field is automatically generated by lower-casing and hyphenating the team *name*. The following Liquid syntax will allow you to list out the team *slug*(s) that are selected for an incident: `{{ incident.group_slugs }}` **OR** * `{{ incident.raw_groups | get: 'slug'}}` for select field type * `{{ incident.raw_groups[index] | get: 'slug' }}` for multi-select field type ### Description This value is displayed on the UI to further explain each team. This field is customizable. The following Liquid syntax will allow you to list out the team *description*(s) that are selected for an incident: * `{{ incident.raw_groups | get: 'description'}}` for select field type * `{{ incident.raw_groups[index] | get: 'description' }}` for multi-select field type ### Color Each team can be assigned a color, which will be used for color-coding on metrics graphs. Rootly uses **color-hex codes**. For example, #000000 is black, #ffffff is white. Use [color-hex.com](https://www.color-hex.com/) to find the exact hex code for the color you want. The following Liquid syntax will allow you to list out the team *color*(s) that are selected for an incident: * `{{ incident.raw_groups | get: 'color'}}` for select field type * `{{ incident.raw_groups[index] | get: 'color' }}` for multi-select field type ### Slack Channels Each team can be linked to one or more Slack channels. By default, Rootly does not notify the linked channel(s) when a team is selected for an incident. Notification needs to be explicitly called out as Attached Teams Channels in workflow configurations. Systematically, each Slack channel is stored as an object containing an ID and name. The following Liquid syntax will allow you to list out the team *Slack Channel*(s) that are selected for an incident: * `{{ incident.raw_groups | get: 'slack_channels'}}` for select field type * `{{ incident.raw_groups[index] | get: 'slack_channels' }}` for multi-select field type ### Slack Aliases Each team can be linked to one or more Slack user groups (aka aliases). By default, Rootly does not invite users in the linked user group(s) when a team is selected for an incident. Invitations need to be explicitly called out as Attached Teams Aliases in workflow configurations. The following Liquid syntax will allow you to list out the team *Slack Alias*(es) that are selected for an incident: * `{{ incident.raw_groups | get: 'slack_aliases'}}` for select field type * `{{ incident.raw_groups[index] | get: 'slack_aliases' }}` for multi-select field type ### Notify Emails Each team can be linked to one or more emails. By default, Rootly does not send emails to the linked address(es) when a team is selected for an incident. Notification needs to be explicitly called out as `{{ incident.raw_groups | map: 'notify_emails' | flatten | join: ',' }}` in workflow configurations. The following Liquid syntax will allow you to list out the team *Notify Email*(s) that are selected for an incident: * `{{ incident.raw_groups | get: 'notify_emails'}}` for select field type * `{{ incident.raw_groups[index] | get: 'notify_emails' }}` for multi-select field type ## Import Teams Instead of creating teams from scratch, Rootly allows you to import teams from **PagerDuty**, **Opsgenie**, **VictorOps**, or **PagerTree**. Imported teams will be automatically kept in sync on a daily basis. The ability to import teams will only become available once you have PagerDuty, Opsgenie, VictorOps, or PagerTree installed on the [integrations page](https://rootly.com/account/integrations). The following Liquid syntax will allow you to list out the corresponding IDs from each of the external paging applications: **PagerDuty** * `{{ incident.raw_groups | get: 'pagerduty_id' }}` for select field type * `{{ incident.raw_groups\[0\] | get: 'pagerduty_id' }}` for multi-select field type **Opsgenie** * `{{ incident.raw_groups | get: 'opsgenie_id' }}` for select field type * `{{ incident.raw_groups\[0\] | get: 'opsgenie_id' }}` for multi-select field type **VictorOps** * `{{ incident.raw_groups | get: 'victor_ops_id' }}` for select field type * `{{ incident.raw_groups\[0\] | get: 'victor_ops_id' }}` for multi-select field type **PagerTree** * `{{ incident.raw_groups | get: 'pagertree_id' }}` for select field type * `{{ incident.raw_groups\[0\] | get: 'pagertree_id' }}` for multi-select field type *** ## Related Pages Where teams are created, edited, and organized — this page covers Teams as an incident attribute. Services are typically owned by teams — the link that drives service ownership and paging. Higher-level customer-facing capabilities that teams own alongside their services. # Outgoing Webhooks Source: https://docs.rootly.com/configuration/webhooks Send real-time event notifications from Rootly to any external HTTP endpoint as incidents, alerts, pulses, and workflows progress through their lifecycles. ## Overview Outgoing webhooks let you push Rootly events to any system that accepts HTTP POST requests — a custom internal tool, a data pipeline, an audit log, or a third-party service that does not have a native Rootly integration. Each webhook endpoint you configure receives a JSON payload for the event types you subscribe it to. Rootly signs every delivery so your server can verify the payload came from Rootly. ## Create a Webhook Endpoint Go to **Settings → Webhooks** and click **New Webhook**. Give the endpoint a descriptive name and enter the destination URL. The URL must be publicly reachable and accept HTTPS POST requests. A label for this endpoint, unique within your team. The HTTPS endpoint that will receive event payloads. Choose which events this endpoint should receive. If you leave the event types list empty, the endpoint will receive **all** events. See [Event Types](#event-types) below for the full list. Click **Save**. Rootly generates a signing secret for this endpoint automatically. Copy it now — it is only shown once. You will use it to verify incoming payloads on your server. The signing secret cannot be retrieved after you leave this page. If you lose it, you can regenerate it from the endpoint's edit form, which will invalidate the old secret immediately. *** ## Event Types Subscribe an endpoint to one or more event types. An empty subscription list means the endpoint receives all events. ### Incidents | Event | When it fires | | -------------------- | ---------------------------------- | | `incident.created` | A new incident is opened | | `incident.updated` | Any field on the incident changes | | `incident.in_triage` | Incident moves to In Triage status | | `incident.mitigated` | Incident is marked as mitigated | | `incident.resolved` | Incident is resolved | | `incident.cancelled` | Incident is cancelled | | `incident.deleted` | Incident is deleted | ### Scheduled Incidents | Event | When it fires | | -------------------------------- | ----------------------------------- | | `incident.scheduled.created` | A scheduled incident is created | | `incident.scheduled.updated` | A scheduled incident is updated | | `incident.scheduled.in_progress` | A scheduled incident becomes active | | `incident.scheduled.completed` | A scheduled incident completes | | `incident.scheduled.deleted` | A scheduled incident is deleted | ### Retrospectives | Event | When it fires | | -------------------------------- | ---------------------------- | | `incident_post_mortem.created` | A retrospective is created | | `incident_post_mortem.updated` | A retrospective is updated | | `incident_post_mortem.published` | A retrospective is published | | `incident_post_mortem.deleted` | A retrospective is deleted | ### Status Page Events | Event | When it fires | | ------------------------------------ | ------------------------------ | | `incident_status_page_event.created` | A status page event is created | | `incident_status_page_event.updated` | A status page event is updated | | `incident_status_page_event.deleted` | A status page event is deleted | ### Timeline Events | Event | When it fires | | ------------------------ | ---------------------------------------- | | `incident_event.created` | A timeline event is added to an incident | | `incident_event.updated` | A timeline event is updated | | `incident_event.deleted` | A timeline event is deleted | ### Alerts and Pulses | Event | When it fires | | --------------- | ----------------------------------------------------------------------------------- | | `alert.created` | An alert is created in Rootly | | `alert.updated` | An alert changes or a timeline event is added, including manual ownership transfers | | `pulse.created` | A pulse is created | ### Workflows | Event | When it fires | | ------------------------------- | ------------------------------------- | | `genius_workflow_run.queued` | A workflow run is queued | | `genius_workflow_run.started` | A workflow run begins executing | | `genius_workflow_run.completed` | A workflow run completes successfully | | `genius_workflow_run.failed` | A workflow run fails | | `genius_workflow_run.canceled` | A workflow run is cancelled | For payload examples for the most common event types, see [Event Payloads](/configuration/event-payloads). *** ## Delivery and Retries Each event triggers a separate HTTP POST to every matching enabled endpoint. Rootly expects a `2xx` response within **10 seconds**. If the delivery fails or times out, Rootly retries automatically on the following schedule: | Attempt | Delay after previous failure | | --------- | ---------------------------- | | 1st retry | 15 seconds | | 2nd retry | 1 minute | | 3rd retry | 5 minutes | After three failed retries the delivery is abandoned. You can inspect delivery history — including response status codes and response bodies — from the endpoint detail page in **Settings → Webhooks**. Retries use the same payload as the original attempt. If your endpoint processed the event before returning an error, implement idempotency using the event ID in the payload to avoid duplicate processing. *** ## Verifying Webhook Signatures Every delivery includes an `X-Rootly-Signature` header containing a timestamp and an HMAC-SHA256 signature. Use this to confirm the payload originated from Rootly. ```txt theme={null} X-Rootly-Signature: t=1492774588,v1=6657a869e8ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd ``` To verify: Extract the timestamp (`t=`) and signature (`v1=`) from the header. Concatenate the timestamp with the raw request body. Compute an HMAC-SHA256 digest of that string using your endpoint's signing secret. Compare the result to the `v1` value. If they match, the payload is authentic. ```ruby Ruby theme={null} require 'openssl' require 'rack' header = request.headers['X-Rootly-Signature'] parts = header.split(',') timestamp = parts[0].split('t=').last signature = parts[1].split('v1=').last secret = 'your_webhook_secret' expected = OpenSSL::HMAC.hexdigest('SHA256', secret, timestamp + request.body.read) is_valid = Rack::Utils.secure_compare(expected, signature) ``` ```python Python theme={null} import hmac import hashlib header = request.headers['X-Rootly-Signature'] parts = header.split(',') timestamp = parts[0].split('t=')[1] signature = parts[1].split('v1=')[1] secret = "your_webhook_secret" expected = hmac.new( key=secret.encode(), msg=(timestamp + request.data.decode()).encode(), digestmod=hashlib.sha256 ).hexdigest() is_valid = hmac.compare_digest(expected, signature) ``` ```javascript Node.js theme={null} const crypto = require('crypto'); const header = request.headers['x-rootly-signature']; const parts = header.split(','); const timestamp = parts[0].split('t=')[1]; const signature = parts[1].split('v1=')[1]; const secret = "your_webhook_secret"; // Use the raw request body, not the parsed body. // In Express, configure express.raw({ type: 'application/json' }) and use req.body directly, // or capture the raw body via a middleware before any JSON parsing. const rawBody = request.rawBody; // string or Buffer const expected = Buffer.from( crypto.createHmac('sha256', secret) .update(timestamp + rawBody) .digest('hex') ); const received = Buffer.from(signature); const isValid = expected.length === received.length && crypto.timingSafeEqual(expected, received); ``` To prevent replay attacks, also check that the timestamp in the header is within a few minutes of the current time before accepting the payload. *** ## Manage Endpoints From **Settings → Webhooks** you can: * **Enable or disable** an endpoint without deleting it — disabled endpoints receive no deliveries. * **Edit** the name, URL, or event subscriptions at any time. * **View delivery history** for each endpoint, including the HTTP status code and response body for each attempt. * **Delete** an endpoint to permanently stop deliveries to that URL. *** ## Troubleshooting Check that the endpoint is **enabled** in **Settings → Webhooks**. Also verify that the event types you expect are included in the endpoint's subscription, or that the subscription list is empty (which receives all events). If the URL requires authentication headers or is behind an IP allowlist, those must be handled at the receiving server — Rootly sends only the `X-Rootly-Signature` header alongside the standard `Content-Type: application/json` header. Rootly waits up to 10 seconds for a response. If your endpoint takes longer to process, return a `200` immediately and handle the payload asynchronously. Rootly will retry failed deliveries up to three times before abandoning the delivery. You can regenerate the signing secret from the endpoint's edit form in **Settings → Webhooks**. Regenerating immediately invalidates the old secret, so update your server-side verification logic before regenerating. Use a tool like [ngrok](https://ngrok.com) or [localtunnel](https://theboroer.github.io/localtunnel-www/) to expose a local port over a public HTTPS URL, then register that URL as a webhook endpoint in Rootly. Trigger a test event by creating or updating an incident, and inspect the delivery in the endpoint detail view. *** ## Related Pages Payload structure reference for every webhook event type Rootly emits. HMAC signature verification is one part of a broader tenant-hardening checklist. The umbrella page covering incident properties and configuration surface. # Contacting Support Source: https://docs.rootly.com/contacting-support How to reach Rootly support: email and status page, what to include in your report, and how to grab a device dump from the mobile app. Have a question, or something not working? Here's how to reach Rootly support, and what to send so they can help on the first reply. ## How to reach us * Email [**support@rootly.com**](mailto:support@rootly.com) (in the mobile app, this is **Settings → Email support**). ## What to include Helpful details to include: * A **device dump** from the app (see below). It captures the app version, device model, OS, and push provider. * The **specific alert** that misbehaved: the link (`rootly.com/account/alerts/…`) or the date and time you expected a page. * **What you saw vs. expected**, for example "the page arrived silently," "the call didn't ring," or "stuck on the login screen." * For **login issues:** your sign-in method (Okta, Google, Slack, email) and whether signing in at rootly.com in a desktop browser works. * **What you already tried** from the troubleshooting guide. * If you can, a **screen recording** of a failed test alert (**Settings → Troubleshooting → Send a test alert**). ## How to grab a device dump The app can copy a full diagnostic to your clipboard in three taps: In the Rootly app, open **Settings** and tap **About**. Tap the **Version** (for example, `v2.14.0`) five times quickly. A **Device Info** panel appears. Tap **Copy device info**, then paste it into your email to support. Check the Rootly [status page](https://status.rootly.com/) for platform status and ongoing incidents. # Rootly Edge Connector for on-premises systems Source: https://docs.rootly.com/edge-connectors Securely integrate Rootly with internal systems that cannot accept inbound internet connections using outbound-only polling through the Edge Connector. ## Overview The Rootly Edge Connector is a lightweight agent that enables secure, bidirectional integration between Rootly and internal or on-premises systems that cannot accept inbound internet connections. It uses an outbound-only polling model to listen for events from Rootly and execute local actions in response. Edge Connectors are ideal for organizations with strict security requirements where opening inbound firewall ports is not permitted or desirable. ## Key Benefits * **Enhanced Security**: No inbound firewall rules required - only outbound HTTPS connections * **Flexibility**: Execute any script or automation in response to Rootly events * **Auditability**: Full Git-based configuration and comprehensive execution logs * **Reliability**: Event queueing with retry logic ensures no missed actions * **Seamless Integration**: Bridge cloud-based Rootly with on-premises systems ## How It Works Edge Connector Architecture ```mermaid theme={null} graph TD A[Rootly Cloud
rec.rootly.com] -->|HTTPS Outbound Only
Poll every N seconds| B[Corporate Firewall
No inbound ports required] B --> C[Rootly Edge Connector] C -->|Polls for events| A C -->|Executes local scripts| D[Internal Systems] C -->|Reports results back| A subgraph "Internal Network / On-Premises" C D[Internal Systems
• Monitoring tools
• ITSM platforms
• Automation scripts] end style A fill:#8b5cf6,stroke:#7c3aed,stroke-width:2px,color:#fff style B fill:#f3f4f6,stroke:#9ca3af,stroke-width:2px style C fill:#10b981,stroke:#059669,stroke-width:2px,color:#fff style D fill:#3b82f6,stroke:#2563eb,stroke-width:2px,color:#fff ``` ### Communication Flow 1. **Polling**: The Edge Connector polls Rootly's API at regular intervals for new events 2. **Event Processing**: When events are received, the connector maps them to configured actions 3. **Execution**: Allowlisted scripts are executed with event context as parameters 4. **Reporting**: Results and logs are sent back to Rootly for visibility and audit ## Security Model ### Why Outbound-Only is More Secure **Traditional Webhook Approach** (Inbound): * Requires exposing an endpoint to the internet * Must configure and maintain TLS termination * Attack surface for scanning, probing, and DDoS * Firewall changes and security reviews required **Edge Connector Approach** (Outbound): * Only outbound HTTPS (same as normal web browsing) * No exposed endpoints for attackers to discover * No firewall changes needed * Cannot be directly targeted from the internet ### Additional Security Features * **API Key Scoping**: Create Edge Connector-specific API keys with minimal permissions * **Script Whitelisting**: Only approved, version-controlled scripts can execute * **Team-based Authorization**: Map Rootly teams to allowed local actions * **Audit Trail**: Every action logged with full context (who, what, when) * **Network Isolation**: Run the connector on a dedicated, isolated host ## Getting Started ### Prerequisites * Rootly team with Edge Connector feature enabled * Ability to run a service in your internal network * API key with Edge Connector permissions ### Request Access Edge Connector is an enterprise feature that requires enablement by Rootly administrators. To request access: 1. Navigate to **Settings** → **Edge Connectors** in Rootly 2. Click **Request Access** 3. Your team administrators will be notified 4. Contact [sales@rootly.com](mailto:sales@rootly.com) for feature enablement ### Setup Overview 1. **Create an Edge Connector in Rootly** * Navigate to Settings → Edge Connectors * Click "Create Edge Connector" * Configure name and event subscriptions * Generate an API key 2. **Install the Edge Connector Agent** * See the [Installation & Deployment](/edge-connectors-installation) guide for detailed setup instructions 3. **Configure Actions** * See the [Action Configuration](/edge-connectors-actions) guide to define your automations 4. **Monitor and Maintain** * View connector status in Rootly dashboard * Review execution logs * Update scripts as needed **Quick Links:** * [Installation & Deployment](/edge-connectors-installation) - Install and run the Edge Connector * [Action Configuration](/edge-connectors-actions) - Define script and HTTP actions * [Template Syntax](/edge-connectors-templates) - Use dynamic values in actions * [Event Examples](/edge-connectors-event-examples) - See example event payloads ## Action Types Edge Connector actions fall into two categories: ### Automatic Actions These run automatically in response to system events, without user interaction. Configured in the `on:` section of `actions.yml`. **Examples:** Auto-restart services when alerts fire, send notifications when incidents are created, collect diagnostics automatically. ### Callable Actions These are triggered manually by users from the Rootly UI with interactive buttons and forms. Configured in the `callable:` section of `actions.yml`. **Examples:** Manual service restart, deploy hotfix, scale infrastructure, clear cache on demand. For a detailed comparison including UI behavior, registration process, and configuration differences, see the [Action Configuration Guide](/edge-connectors-actions#automatic-vs-callable-actions). ## Supported Event Types Edge Connectors support two categories of events: ### Automatic Event Types These events are triggered automatically by system events and can be subscribed to when configuring your Edge Connector: **Alert Events:** * `alert.created` - New alert from monitoring system * `alert.updated` - Alert properties changed * `alert.acknowledged` - Alert acknowledged by a user * `alert.resolved` - Alert marked as resolved * `alert.deleted` - Alert removed **Incident Events:** * `incident.created` - New incident started * `incident.updated` - Incident properties changed * `incident.in_triage` - Incident moved to triage status * `incident.mitigated` - Incident mitigated * `incident.resolved` - Incident marked resolved * `incident.cancelled` - Incident cancelled * `incident.deleted` - Incident deleted ### Manual Trigger Event Types These events are triggered by user actions and are configured per action: * `action.triggered` - Standalone action triggered by a user * `alert.action_triggered` - Action triggered from an alert context * `incident.action_triggered` - Action triggered from an incident context You can configure which automatic events your Edge Connector subscribes to when creating or editing it in the Rootly UI. Manual trigger events are configured in your action definitions. For detailed payload examples and templating patterns, see the [Event Examples](/edge-connectors-event-examples) page. ## Use Cases ### Automated Remediation Automatically restart services or run diagnostic scripts when critical alerts are detected. Perfect for known issues that have established remediation procedures. ### Internal System Integration Create tickets in internal ITSM systems that aren't accessible from the internet. Bridge Rootly with on-premises Jira, ServiceNow, or custom ticketing systems. ### Hybrid Cloud Orchestration Run Ansible playbooks or other automation tools in response to incident lifecycle events. Trigger infrastructure changes, scaling operations, or deployment rollbacks. ### Diagnostic Collection Automatically collect logs, metrics, and diagnostics when incidents occur. Gather context automatically to speed up incident investigation. See the [Action Configuration](/edge-connectors-actions) guide for detailed examples of these use cases with complete action definitions. ## Managing Edge Connectors ### Viewing Connector Status In the Rootly dashboard, you can monitor: * **Online Status**: Whether the connector is actively polling * **Last Poll Time**: When the connector last checked for events * **Events Pending**: Number of events waiting to be processed * **Recent Executions**: Logs of recently executed actions ### API Key Management Each Edge Connector requires an API key: 1. Navigate to **Settings** → **API Keys** 2. Create a new key with type **Edge Connector** 3. Associate it with your Edge Connector 4. Store the key securely on your connector host API keys should be rotated regularly and stored securely. Never commit API keys to version control. ## Documentation * **[Installation & Deployment](/edge-connectors-installation)** - Install and configure the Edge Connector in your environment * **[Action Configuration](/edge-connectors-actions)** - Define script and HTTP actions to automate responses * **[Template Syntax](/edge-connectors-templates)** - Use Liquid templates for dynamic values in actions * **[Event Examples](/edge-connectors-event-examples)** - Reference for event payload structures and fields ## Best Practices **Security:** * Run the Edge Connector on a dedicated, isolated host * Store secrets in environment variables, never in configuration files * Version control all scripts and review through pull requests * Rotate API keys periodically **Reliability:** * Configure appropriate polling intervals (typically 10-30 seconds) * Set reasonable script timeouts based on expected execution time * Implement retry logic in your scripts for transient failures * Monitor connector health and set up downtime alerts **Configuration:** * Use descriptive names for connectors and actions * Document script requirements and dependencies * Test actions thoroughly before production deployment * Keep the connector software updated For detailed troubleshooting, see the [Installation & Deployment](/edge-connectors-installation#troubleshooting) guide. # Action Configuration Source: https://docs.rootly.com/edge-connectors-actions Configure script and HTTP actions for Rootly Edge Connectors to automate responses to events from internal systems behind your firewall using outbound polling. ## Overview Actions define what your Edge Connector executes in response to events. Each action specifies: * **Type**: Script or HTTP request * **Source Type**: Local scripts or Git-based scripts * **Trigger**: Which events activate this action * **Parameters**: User-configurable inputs (for manual triggers) * **Execution details**: Scripts to run or HTTP requests to make ## Automatic vs Callable Actions Edge Connector actions fall into two categories with different behaviors: ### Automatic Actions (`on:` section) **What they are:** * Execute automatically in response to Rootly system events * Run without user interaction * Configured in the `on:` section where the event type is the key **When to use:** * Auto-remediation (restart services when alerts fire) * Notifications (send webhooks when incidents are created) * Data collection (gather logs when alerts trigger) * Monitoring integration (sync status to external systems) **Configuration:** ```yaml theme={null} on: alert.created: # Event type is the key script: /opt/scripts/handle-alert.sh parameters: alert_id: "{{ id }}" severity: "{{ labels.severity }}" timeout: 60 ``` **Characteristics:** * ✅ No `parameter_definitions` needed (no user input) * ✅ Execute immediately when events occur * ✅ Registered with backend for visibility/audit * ✅ Appear in Rootly UI as read-only badges (visible but not clickable) * ✅ Users can see what automations are configured **How they appear in Rootly UI:** * Badge: "🔄 Script: alert.created" or "🌐 HTTP: incident.created" * Read-only display showing what's automated * No interaction possible (run automatically only) ### Callable Actions (`callable:` section) **What they are:** * Triggered manually by users from the Rootly UI * Require user input via parameter forms * Configured in the `callable:` section where the action slug is the key **When to use:** * Manual remediation (restart specific services on demand) * User-initiated operations (deploy hotfixes, scale infrastructure) * Diagnostic tools (collect logs, run health checks) * Administrative tasks (clear caches, trigger backups) **Configuration:** ```yaml theme={null} callable: restart_service: # Action slug is the key name: "Restart Service" # Display name in UI (required) description: "Restart a production service with graceful shutdown" trigger: alert.action_triggered # Shows on alerts script: /opt/scripts/restart.sh parameter_definitions: # Creates UI form - name: service_name type: string required: true description: "Service to restart" timeout: 120 ``` **Characteristics:** * ✅ Require `parameter_definitions` to create UI forms * ✅ Users provide input values before execution * ✅ Registered with backend to generate UI buttons * ✅ Appear in Rootly UI as interactive buttons * ✅ Can be triggered from alerts, incidents, or standalone **How they appear in Rootly UI:** * Button: "Restart Service" with form dialog * Users click → fill out form → submit → action executes * Real-time execution status and results shown ### Comparison Table | Feature | Automatic Actions (`on:`) | Callable Actions (`callable:`) | | -------------------------- | ----------------------------------------------------- | ------------------------------------------- | | **Trigger** | System events (alert.created, incident.created, etc.) | User clicks button in Rootly UI | | **User Input** | None - uses event data only | Yes - users fill out parameter forms | | **Config Section** | `on:` (event type is key) | `callable:` (action slug is key) | | **parameter\_definitions** | Not needed | Required to create UI forms | | **name** | Optional | Required for UI display | | **UI Appearance** | Read-only badge (visible, not clickable) | Interactive button (clickable with form) | | **Registration** | Registered for visibility | Registered to generate UI | | **Execution** | Immediate when event occurs | On-demand when user triggers | | **Use Cases** | Auto-remediation, notifications, monitoring | Manual operations, diagnostics, admin tasks | ### Registration Behavior **Both automatic and callable actions are registered with the Rootly backend on connector startup:** 1. **Connector Startup:** * Reads `actions.yml` configuration * Sends all actions to `POST /rec/v1/actions` endpoint * Backend syncs actions for this connector 2. **Backend Processing:** * **Automatic actions** (no `parameter_definitions`): * Stored for visibility and audit * Displayed as read-only badges in UI * Users can see what automations exist * **Callable actions** (with `parameter_definitions`): * UI forms generated from parameter definitions * Displayed as interactive buttons * Users can click and provide inputs 3. **Sync Behavior:** * Backend matches actions by slug * Creates new actions not seen before * Updates existing actions with new configuration * Removes actions no longer in config **What gets sent to backend:** * Action slug, name, description (for UI display) * Action type (script or HTTP) and timeout * Trigger event types * Parameter definitions (for callable actions only) **What stays on connector:** * Script paths and execution details * HTTP URLs, headers, and body templates * Security settings and environment variables The presence of `parameter_definitions` is what tells the backend whether an action is automatic (read-only) or callable (interactive). ## Action File Structure Actions are defined in an `actions.yml` file with three main sections: ```yaml theme={null} # Global defaults (optional) defaults: timeout: 30 source_type: local env: ENVIRONMENT: production # Automatic actions - triggered by system events on: alert.created: script: /path/to/script.sh # ... # Manual actions - triggered by users from UI callable: restart_service: name: "Restart Service" # ... ``` ## Action Types ### Script Actions Execute scripts from local filesystem or Git repositories. #### Local Scripts Execute scripts stored on the Edge Connector host: ```yaml theme={null} callable: restart_service: name: "Restart Production Service" description: | Restarts the specified service with graceful shutdown. Use when service becomes unresponsive. trigger: alert.action_triggered script: /opt/scripts/restart-service.sh parameter_definitions: - name: service_name type: string required: true description: "Service to restart" - name: environment type: string required: false default: "production" options: ["development", "staging", "production"] timeout: 300 ``` **Key Fields:** * `script`: Absolute path to the script to execute * `timeout`: Maximum execution time in seconds * `parameter_definitions`: User inputs when triggered manually * `trigger`: Specifies the event type (`alert.action_triggered`, `incident.action_triggered`, or defaults to `action.triggered`) * `source_type`: `local` (default) or `git` #### Git-Based Scripts Execute scripts from a Git repository that the Edge Connector syncs automatically: ```yaml theme={null} callable: run_playbook: name: "Run Incident Playbook" description: "Execute Ansible playbook from Git repository" trigger: incident.action_triggered source_type: git script: playbooks/incident-response.yml git_options: url: "https://github.com/your-org/runbooks.git" branch: main poll_interval_sec: 300 parameter_definitions: - name: playbook type: list options: [database, network, application] required: true description: "Which playbook to run" parameters: incident_id: "{{ entity_id }}" severity: "{{ severity.slug }}" timeout: 600 ``` **Git Options:** * `url`: Git repository URL (HTTPS or SSH) * `branch`: Branch to checkout (default: `main`) * `poll_interval_sec`: How often to pull updates (default: 300) Git-based scripts allow you to version control your automation scripts and update them without redeploying the Edge Connector. ### HTTP Actions Make HTTP/HTTPS requests to external APIs or webhooks. ```yaml theme={null} on: alert.created: http: url: "https://example.com/webhook" method: POST headers: Content-Type: "application/json" Authorization: "Bearer {{ env.API_TOKEN }}" params: source: "rootly" body: | { "alert_id": "{{ id }}", "summary": "{{ summary }}", "severity": "{{ labels.severity }}", "services": "{{ services | map: 'name' | join: ', ' }}" } timeout: 30 ``` **HTTP Configuration:** * `url`: Target endpoint (supports templates) * `method`: GET, POST, PUT, PATCH, DELETE * `headers`: HTTP headers (supports templates) * `params`: Query parameters * `body`: Request body (supports templates for JSON/text) ## Action Triggers ### Automatic Event Triggers These actions run automatically when system events occur. They are defined in the `on:` section where the event type is the key. **Alert Events:** ```yaml theme={null} on: alert.created: # Action configuration here script: /path/to/handle-alert.sh ``` **Incident Events:** ```yaml theme={null} on: incident.mitigated: # Action configuration here script: /path/to/handle-mitigation.sh ``` **Available Automatic Triggers:** * `alert.created`, `alert.updated`, `alert.acknowledged`, `alert.resolved`, `alert.deleted` * `incident.created`, `incident.updated`, `incident.in_triage`, `incident.mitigated`, `incident.resolved`, `incident.cancelled`, `incident.deleted` Automatic triggers do not require `parameter_definitions` - they execute automatically with event data. ### Manual Trigger Events These actions are triggered manually by users from the Rootly UI. They require `parameter_definitions` to create input forms. **Action on Alert:** ```yaml theme={null} callable: restart_affected_service: name: "Restart Affected Service" trigger: alert.action_triggered script: /opt/scripts/restart.sh parameter_definitions: - name: service_name type: string required: true - name: force_restart type: boolean default: false ``` **Action on Incident:** ```yaml theme={null} callable: scale_infrastructure: name: "Scale Infrastructure" trigger: incident.action_triggered script: /opt/scripts/scale.sh parameter_definitions: - name: target_capacity type: number required: true ``` **Standalone Action:** ```yaml theme={null} callable: clear_cache: name: "Clear Global Cache" # trigger defaults to: action.triggered http: url: "https://api.example.com/cache/clear" method: POST parameter_definitions: - name: cache_type type: string required: true options: ["redis", "memcached", "all"] ``` ## Parameter Definitions Parameters create user input forms for manually triggered actions. ### Parameter Types **String:** ```yaml theme={null} - name: service_name type: string required: true description: "Name of the service" ``` **Number:** ```yaml theme={null} - name: capacity type: number required: true description: "Target capacity percentage" ``` **Boolean:** ```yaml theme={null} - name: force_restart type: boolean default: false description: "Force restart without graceful shutdown" ``` **List (Dropdown):** ```yaml theme={null} - name: cache_type type: list options: [redis, memcached, all] default: redis required: true description: "Which cache to clear" ``` Use `type: list` with `options` array for dropdown selections. This is preferred over `type: string` with `options` for clarity. ### Parameter Fields * `name`: Parameter identifier (used in templates as `{{ parameters.name }}`) * `type`: Data type (string, number, boolean) * `required`: Whether input is mandatory * `default`: Default value if not provided * `options`: List of allowed values (creates dropdown) * `description`: Help text shown in UI ## Using Templates in Actions Actions support Liquid templates for dynamic values. See the [Template Syntax](/edge-connectors-templates) guide for detailed documentation. ### Event Data Templates Access event data in your action configuration: ```yaml theme={null} parameters: alert_id: "{{ id }}" summary: "{{ summary }}" severity: "{{ labels.severity }}" service: "{{ services.first.name }}" ``` ### User Parameter Templates Access user inputs in manually triggered actions: ```yaml theme={null} parameters: service: "{{ parameters.service_name }}" env: "{{ parameters.environment }}" force: "{{ parameters.force_restart }}" ``` ### Environment Variables Access environment variables securely: ```yaml theme={null} headers: Authorization: "Bearer {{ env.API_TOKEN }}" X-API-Key: "{{ env.SECRET_KEY }}" ``` ## Complete Examples ### Example 1: Automatic Alert Response Automatically restart a service when critical alerts are detected: ```yaml theme={null} on: alert.created: script: /opt/scripts/restart-service.sh parameters: service: "{{ services.first.slug }}" environment: "{{ environments.first.slug }}" alert_id: "{{ id }}" severity: "{{ labels.severity }}" timeout: 120 ``` ### Example 2: Manual Service Scaling Allow users to manually scale services from incidents: ```yaml theme={null} callable: scale_service: name: "Scale Service Capacity" description: | Manually scale service capacity. Use during incidents to increase capacity. trigger: incident.action_triggered script: /opt/scripts/scale-service.sh parameter_definitions: - name: target_capacity type: number required: true description: "Target capacity (50-200%)" - name: scaling_speed type: string required: false default: "normal" options: ["slow", "normal", "fast"] description: "Scaling speed" parameters: # User inputs: target_capacity and scaling_speed # are auto-available as {{ parameters.target_capacity }}, etc. # Add extra context here: incident_id: "{{ entity_id }}" triggered_by: "{{ triggered_by.email }}" timeout: 300 ``` ### Example 3: Webhook Notification Send HTTP notification when incidents are mitigated: ```yaml theme={null} on: incident.mitigated: http: url: "{{ env.SLACK_WEBHOOK_URL }}" method: POST headers: Content-Type: "application/json" body: | { "text": "Incident Mitigated", "attachments": [{ "color": "good", "fields": [ {"title": "Incident", "value": "{{ title }}", "short": false}, {"title": "Severity", "value": "{{ severity.name }}", "short": true}, {"title": "Services", "value": "{{ services | map: 'name' | join: ', ' }}", "short": true}, {"title": "Duration", "value": "{{ mitigated_at | date: '%Y-%m-%d %H:%M' }}", "short": true} ] }] } timeout: 10 ``` ### Example 4: PagerDuty Integration Create PagerDuty incidents for high-severity Rootly incidents: ```yaml theme={null} on: incident.created: http: url: "https://api.pagerduty.com/incidents" method: POST headers: Authorization: "Token token={{ env.PAGERDUTY_TOKEN }}" Content-Type: "application/json" From: "{{ env.PAGERDUTY_FROM_EMAIL }}" body: | { "incident": { "type": "incident", "title": "[{{ severity.name }}] {{ title }}", "service": { "id": "{{ env.PAGERDUTY_SERVICE_ID }}", "type": "service_reference" }, "urgency": "high", "body": { "type": "incident_body", "details": "{{ summary }}\n\nAffected services: {{ services | map: 'name' | join: ', ' }}" } } } timeout: 15 ``` ## Best Practices ### Security * **Store secrets in environment variables**, never in action configuration * **Use absolute paths** for scripts to prevent path traversal * **Validate user inputs** in your scripts * **Limit script permissions** - run with minimal privileges * **Audit action execution logs** regularly ### Reliability * **Set appropriate timeouts** based on expected execution time * **Implement retry logic** in your scripts for transient failures * **Handle errors gracefully** and return meaningful error messages * **Test actions thoroughly** before deploying to production * **Monitor action execution** via Rootly dashboard ### Configuration * **Use descriptive IDs** (snake\_case: `restart_production_db`) * **Provide clear names** for UI display * **Write helpful descriptions** explaining when to use the action * **Add parameter descriptions** to guide users * **Use options** for parameters with limited valid values ### Templates * **Use `default` filter** for optional fields: `{{ field | default: "N/A" }}` * **Test templates** with sample event data before deploying * **Keep templates simple** - complex logic belongs in scripts * **Document template variables** in action descriptions ## Action Configuration File Actions are defined in an `actions.yml` file with three main sections: ```yaml theme={null} # Global defaults (optional) - applied to all actions defaults: timeout: 30 # Default timeout for all actions source_type: local # Default source: local or git env: # Environment variables for all actions ENVIRONMENT: production LOG_LEVEL: info # Automatic actions - triggered by system events # Event type is the KEY on: alert.created: script: /path/to/handle-alert.sh parameters: alert_id: "{{ id }}" severity: "{{ labels.severity }}" timeout: 60 incident.created: http: url: "{{ env.SLACK_WEBHOOK_URL }}" method: POST body: | {"text": "Incident: {{ title }}"} # Manual actions - triggered by users from UI # Action slug is the KEY callable: restart_service: name: "Restart Service" description: "Restart a production service" trigger: alert.action_triggered # Shows on alerts only script: /path/to/restart.sh parameter_definitions: - name: service_name type: string required: true parameters: # User inputs are auto-available as {{ parameters.service_name }} # This section adds EXTRA context beyond user inputs: alert_id: "{{ entity_id }}" triggered_by: "{{ triggered_by.email }}" timeout: 120 clear_cache: name: "Clear Cache" description: "Clear application cache" # trigger defaults to: action.triggered (standalone action) script: /path/to/clear-cache.sh parameter_definitions: - name: cache_type type: list options: [redis, memcached, all] run_from_git: name: "Run Git-based Script" source_type: git # Override default source_type script: scripts/automation.sh git_options: url: "https://github.com/org/repo.git" branch: main poll_interval_sec: 300 ``` The Edge Connector reads this file on startup and registers all actions with Rootly. **Key Concepts:** * `defaults:` section: Global settings applied to all actions unless overridden * `on:` section: Automatic actions where event type is the **key** * `callable:` section: Manual actions where action slug is the **key** * `source_type`: `local` for filesystem scripts, `git` for repository-based scripts * `parameter_definitions`: Create user input forms; auto-accessible as `{{ parameters.X }}` * `parameters:` section: Adds **extra** parameters beyond user inputs * Scripts receive all parameters as `REC_PARAM_*` environment variables ## Next Steps * See [Event Examples](/edge-connectors-event-examples) for sample event payloads * Learn [Template Syntax](/edge-connectors-templates) for dynamic values * Review the main [Edge Connectors](/edge-connectors) documentation # Event Examples Source: https://docs.rootly.com/edge-connectors-event-examples Real-world examples of event payloads received from Rootly Edge Connectors, showing JSON structures for testing actions, scripts, and Liquid template logic. ## Overview This page provides real-world examples of event payloads that Edge Connectors receive when polling the Rootly API. These examples show the structure and data available for templating in your action configurations. ## Event Types Edge Connector events are divided into two categories based on how actions are triggered: **Understanding Action Types:** Automatic events trigger actions automatically (configured in `on:` section), while manual trigger events are user-initiated actions (configured in `callable:` section). See the [Automatic vs Callable Actions](/edge-connectors-actions#automatic-vs-callable-actions) guide for detailed comparison. ### Automatic Event Types These events are triggered automatically by system events and can be subscribed to by connectors for monitoring and notifications: **Alert Events:** * `alert.created` - New alert from monitoring system * `alert.updated` - Alert properties changed * `alert.acknowledged` - Alert acknowledged by a user * `alert.resolved` - Alert marked as resolved * `alert.deleted` - Alert removed **Incident Events:** * `incident.created` - New incident started * `incident.updated` - Incident properties changed * `incident.in_triage` - Incident moved to triage status * `incident.mitigated` - Incident mitigated * `incident.resolved` - Incident marked resolved * `incident.cancelled` - Incident cancelled * `incident.deleted` - Incident deleted ### Manual Trigger Event Types These events are triggered by user actions and are managed by actions' `event_types_trigger` field, not connector subscriptions: * `action.triggered` - Standalone action triggered by a user * `alert.action_triggered` - Action triggered from an alert context * `incident.action_triggered` - Action triggered from an incident context Automatic events can be subscribed to when configuring your Edge Connector. Manual trigger events are configured per action and execute when users trigger them from the UI. ## Event Payload Examples Below are detailed examples of event payloads for each event type. ### alert.created - Production Database Alert ```json theme={null} { "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "event_id": "a3bb189e-8bf9-3888-9912-ace4e6543002", "event_type": "alert.created", "timestamp": "2025-10-26T21:30:00Z", "data": { "id": "6aeb35ae-ca31-4bcf-91bd-c4ecce44dedc", "source": "datadog", "summary": "High database latency detected", "status": "open", "labels": { "severity": "critical", "component": "database", "region": "us-west-2" }, "data": { "host": "prod-db-01.example.com", "latency_ms": 1500, "threshold_ms": 500, "query_count": 342 }, "started_at": "2025-10-26T21:29:45Z", "ended_at": null, "created_at": "2025-10-26T21:29:50Z", "updated_at": "2025-10-26T21:29:50Z", "services": [ { "id": "8e3f9c2a-1d5b-4e8f-9a3c-7b2d4e6f8a1c", "name": "DB - Production Database", "slug": "db-production" } ], "environments": [ { "id": "2c4e6a8b-3f5d-4a7c-8b9e-1f3a5c7d9e2b", "name": "Production", "slug": "production", "color": "#E74C3C" } ] } } ``` ### Template Usage ```yaml theme={null} parameters: alert_id: "{{ id }}" alert_summary: "{{ summary }}" severity: "{{ labels.severity }}" host: "{{ data.host }}" latency: "{{ data.latency_ms }}" service_name: "{{ services.0.name }}" # First service environment: "{{ environments.0.slug }}" # First environment ``` ## alert.created - PagerDuty Integration ```json theme={null} { "id": "9d4e2f1c-7a8b-4c3d-9e5f-6a7b8c9d0e1f", "event_id": "5c6d7e8f-9a0b-4c5d-8e9f-0a1b2c3d4e5f", "event_type": "alert.created", "timestamp": "2025-10-26T21:35:00Z", "data": { "id": "b8c9d0e1-f2a3-4b5c-6d7e-8f9a0b1c2d3e", "source": "pagerduty", "summary": "API service is down", "status": "open", "labels": { "severity": "high", "urgency": "high", "impact": "critical" }, "data": { "incident_key": "PD-12345", "incident_url": "https://example.pagerduty.com/incidents/12345", "triggered_by": "monitoring_service", "escalation_policy": "Engineering On-Call" }, "started_at": "2025-10-26T21:34:30Z", "ended_at": null, "created_at": "2025-10-26T21:34:35Z", "updated_at": "2025-10-26T21:34:35Z", "services": [ { "id": "3f4e5d6c-7b8a-4c9d-0e1f-2a3b4c5d6e7f", "name": "API Gateway", "slug": "api-gateway" }, { "id": "8a9b0c1d-2e3f-4a5b-6c7d-8e9f0a1b2c3d", "name": "Authentication Service", "slug": "auth-service" } ], "environments": [ { "id": "1e2f3a4b-5c6d-7e8f-9a0b-1c2d3e4f5a6b", "name": "Production", "slug": "production", "color": "#E74C3C" } ] } } ``` ### Template Usage ```yaml theme={null} parameters: pagerduty_key: "{{ data.incident_key }}" pagerduty_url: "{{ data.incident_url }}" urgency: "{{ labels.urgency }}" all_services: "{{ services | join:', ' }}" # "API Gateway, Authentication Service" ``` ## alert.updated - Status Change ```json theme={null} { "id": "4d5e6f7a-8b9c-0d1e-2f3a-4b5c6d7e8f9a", "event_id": "7e8f9a0b-1c2d-3e4f-5a6b-7c8d9e0f1a2b", "event_type": "alert.updated", "timestamp": "2025-10-26T22:00:00Z", "data": { "id": "6aeb35ae-ca31-4bcf-91bd-c4ecce44dedc", "source": "datadog", "summary": "High database latency detected", "status": "resolved", "labels": { "severity": "critical", "component": "database" }, "data": { "host": "prod-db-01.example.com", "latency_ms": 150, "resolution": "auto-scaled database pool" }, "started_at": "2025-10-26T21:29:45Z", "ended_at": "2025-10-26T21:59:30Z", "created_at": "2025-10-26T21:29:50Z", "updated_at": "2025-10-26T22:00:00Z", "services": [ { "id": "8e3f9c2a-1d5b-4e8f-9a3c-7b2d4e6f8a1c", "name": "DB - Production Database", "slug": "db-production" } ], "environments": [ { "id": "2c4e6a8b-3f5d-4a7c-8b9e-1f3a5c7d9e2b", "name": "Production", "slug": "production", "color": "#E74C3C" } ] } } ``` ## incident.created - Full Example Based on `EdgeConnectors::IncidentSerializer`: ```json theme={null} { "id": "c1d2e3f4-a5b6-7c8d-9e0f-1a2b3c4d5e6f", "event_id": "2b3c4d5e-6f7a-8b9c-0d1e-2f3a4b5c6d7e", "event_type": "incident.created", "timestamp": "2025-10-26T23:00:00Z", "data": { "id": "9f8e7d6c-5b4a-3210-fedc-ba9876543210", "sequential_id": 42, "title": "Production API Gateway Outage", "slug": "production-api-gateway-outage", "summary": "Complete outage affecting all customers", "status": "started", "kind": "normal", "private": false, "detected_at": "2025-10-26T22:58:00Z", "acknowledged_at": null, "started_at": "2025-10-26T22:58:00Z", "mitigated_at": null, "resolved_at": null, "cancelled_at": null, "created_at": "2025-10-26T22:59:00Z", "updated_at": "2025-10-26T23:00:00Z", "services": [ { "id": "3f4e5d6c-7b8a-4c9d-0e1f-2a3b4c5d6e7f", "name": "API Gateway", "slug": "api-gateway" } ], "environments": [ { "id": "1e2f3a4b-5c6d-7e8f-9a0b-1c2d3e4f5a6b", "name": "Production", "slug": "production", "color": "#E74C3C" } ], "functionalities": [ { "id": "a1b2c3d4-e5f6-7a8b-9c0d-1e2f3a4b5c6d", "name": "API Requests", "slug": "api-requests" } ], "severity": { "id": "5e4d3c2b-1a09-8f7e-6d5c-4b3a2910fedc", "name": "SEV1", "slug": "sev1", "color": "#FF0000" } } } ``` ## alert.action\_triggered - User-Initiated Restart on Alert ```json theme={null} { "id": "e6f7a8b9-c0d1-2e3f-4a5b-6c7d8e9f0a1b", "event_id": "d5e6f7a8-b9c0-1d2e-3f4a-5b6c7d8e9f0a", "event_type": "alert.action_triggered", "timestamp": "2025-10-26T23:15:00Z", "action": { "id": "7a8b9c0d-1e2f-3a4b-5c6d-7e8f9a0b1c2d", "name": "Restart Test Service", "slug": "restart_test_service" }, "data": { "entity_id": "f0a1b2c3-d4e5-6f7a-8b9c-0d1e2f3a4b5c", "parameters": { "service_name": "api-gateway", "environment": "production", "force_restart": true, "drain_timeout": 30 }, "triggered_by": { "id": 50, "name": "Quentin Rousseau", "email": "quentin@rootly.com" } } } ``` ### Template Usage in Actions ```yaml theme={null} # Script action for alert actions - name: restart_test_service type: script script: /opt/scripts/restart-service.sh trigger: event_type: "alert.action_triggered" parameters: # Action metadata (from top-level action object) action_display_name: "{{ action.name }}" # "Restart Test Service" action_slug: "{{ action.slug }}" # "restart_test_service" # User inputs (from UI) service_name: "{{ parameters.service_name }}" environment: "{{ parameters.environment }}" force: "{{ parameters.force_restart }}" # Context data entity_id: "{{ entity_id }}" triggered_by_email: "{{ triggered_by.email }}" # Hardcoded region: "us-west-2" timeout: "60" ``` ## incident.action\_triggered - Escalation on Incident ```json theme={null} { "id": "b9c0d1e2-f3a4-5b6c-7d8e-9f0a1b2c3d4e", "event_id": "a8b9c0d1-e2f3-4a5b-6c7d-8e9f0a1b2c3d", "event_type": "incident.action_triggered", "timestamp": "2025-10-26T23:20:00Z", "action": { "id": "6c7d8e9f-0a1b-2c3d-4e5f-6a7b8c9d0e1f", "name": "Scale Infrastructure", "slug": "scale_infrastructure" }, "data": { "entity_id": "d4e5f6a7-b8c9-0d1e-2f3a-4b5c6d7e8f9a", "parameters": { "target_capacity": 200, "scaling_policy": "aggressive" }, "triggered_by": { "id": 42, "name": "Sarah Johnson", "email": "sarah@example.com" } } } ``` ## action.triggered - Standalone Action ```json theme={null} { "id": "c3d4e5f6-a7b8-9c0d-1e2f-3a4b5c6d7e8f", "event_id": "b2c3d4e5-f6a7-8b9c-0d1e-2f3a4b5c6d7e", "event_type": "action.triggered", "timestamp": "2025-10-26T23:25:00Z", "action": { "id": "5f6a7b8c-9d0e-1f2a-3b4c-5d6e7f8a9b0c", "name": "Clear Global Cache", "slug": "clear_global_cache" }, "data": { "parameters": { "cache_type": "redis", "scope": "global" }, "triggered_by": { "id": 50, "name": "Quentin Rousseau", "email": "quentin@rootly.com" } // No entity_id - this is a standalone action } } ``` ## Edge Cases ### Alert with No Services ```json theme={null} { "event_type": "alert.created", "data": { "id": "e9f0a1b2-c3d4-5e6f-7a8b-9c0d1e2f3a4b", "summary": "Orphaned alert", "status": "open", "services": [], // ← Empty array "environments": [] // ← Empty array } } ``` ### Alert with Custom Data (Datadog) ```json theme={null} { "event_type": "alert.created", "data": { "id": "d8e9f0a1-b2c3-4d5e-6f7a-8b9c0d1e2f3a", "source": "datadog", "summary": "CPU usage above 90%", "status": "open", "data": { "tags": ["env:production", "service:api", "host:prod-01"], "metric": "system.cpu.usage", "value": 94.2, "threshold": 90.0, "monitor_id": "12345678", "monitor_name": "High CPU Usage" } } } ``` ### Standalone Action with No Parameters ```json theme={null} { "event_type": "action.triggered", "action": { "id": "c7d8e9f0-a1b2-3c4d-5e6f-7a8b9c0d1e2f", "name": "Clear Cache", "slug": "clear_cache" }, "data": { "parameters": {}, // ← No user inputs required "triggered_by": { "id": 50, "name": "Quentin Rousseau", "email": "quentin@rootly.com" } // No entity_id - standalone action } } ``` ## HTTP Action Examples ### alert.created → Slack Notification ```yaml theme={null} - name: notify_slack_alert type: http trigger: event_type: "alert.created" http: url: "{{ env.SLACK_WEBHOOK_URL }}" method: POST headers: Content-Type: "application/json" body: | { "text": ":warning: New Alert", "attachments": [{ "color": "danger", "fields": [ {"title": "Summary", "value": "{{ summary }}", "short": false}, {"title": "Source", "value": "{{ source }}", "short": true}, {"title": "Severity", "value": "{{ labels.severity }}", "short": true}, {"title": "Host", "value": "{{ data.host }}", "short": true}, {"title": "Environment", "value": "{{ environments.0.name }}", "short": true} ] }] } timeout: 10 ``` ### incident.created → PagerDuty Integration ```yaml theme={null} - name: create_pagerduty_incident type: http trigger: event_type: "incident.created" http: url: "https://api.pagerduty.com/incidents" method: POST headers: Authorization: "Token token={{ env.PAGERDUTY_TOKEN }}" Content-Type: "application/json" From: "{{ env.PAGERDUTY_FROM_EMAIL }}" body: | { "incident": { "type": "incident", "title": "[{{ severity.name }}] {{ title }}", "service": { "id": "{{ env.PAGERDUTY_SERVICE_ID }}", "type": "service_reference" }, "urgency": "high", "body": { "type": "incident_body", "details": "{{ summary }}\n\nAffected services: {{ services.0.name }}" } } } timeout: 15 ``` ### alert.action\_triggered → Restart Service API ```yaml theme={null} - name: restart_service_api type: http trigger: event_type: "alert.action_triggered" action_name: "restart_service_api" parameter_definitions: - name: service_name type: string required: true - name: force_restart type: boolean default: false http: url: "https://api.example.com/v1/services/{{ parameters.service_name }}/restart" method: POST headers: Authorization: "Bearer {{ env.API_TOKEN }}" Content-Type: "application/json" X-Triggered-By: "{{ triggered_by.email }}" body: | { "force": {{ parameters.force_restart }}, "reason": "Manual restart via Rootly", "alert_id": "{{ entity_id }}" } timeout: 60 ``` ### action.triggered → Clear Global Cache ```yaml theme={null} - name: clear_cache_http type: http trigger: event_type: "action.triggered" action_name: "clear_cache_http" parameter_definitions: - name: cache_type type: string options: ["redis", "memcached", "all"] required: true http: url: "https://cache-api.example.com/v1/clear" method: POST headers: X-API-Key: "{{ env.CACHE_API_KEY }}" params: type: "{{ parameters.cache_type }}" body: | { "triggered_by": "{{ triggered_by.email }}", "scope": "global" } timeout: 30 ``` **HTTP Action Behavior:** * Exit code = HTTP status code (200, 404, 500, etc.) * Stdout = Response body + status message * Stderr = Error message (if request fails) * Success = 2xx status codes * Failure = 4xx, 5xx status codes ## Template Access Patterns ### Simple Fields ```yaml theme={null} alert_id: "{{ id }}" status: "{{ status }}" summary: "{{ summary }}" ``` ### Nested Objects ```yaml theme={null} severity: "{{ labels.severity }}" host: "{{ data.host }}" metric_value: "{{ data.value }}" ``` ### Arrays (First Element) ```yaml theme={null} service_name: "{{ services.0.name }}" service_slug: "{{ services.0.slug }}" environment: "{{ environments.0.slug }}" ``` ### Environment Variables ```yaml theme={null} api_key: "{{ env.DATADOG_API_KEY }}" region: "{{ env.AWS_REGION }}" ``` ### Mixed ```yaml theme={null} message: "[{{ labels.severity }}] {{ summary }} on {{ data.host }} in {{ environments.0.name }}" # Result: "[critical] High database latency detected on prod-db-01.example.com in Production" ``` ## Testing Locally Create a test event payload file: ```bash theme={null} # test-alert.json { "events": [{ "id": "b6c7d8e9-f0a1-2b3c-4d5e-6f7a8b9c0d1e", "event_id": "a5b6c7d8-e9f0-1a2b-3c4d-5e6f7a8b9c0d", "event_type": "alert.created", "timestamp": "2025-10-26T23:00:00Z", "data": { "id": "9e0f1a2b-3c4d-5e6f-7a8b-9c0d1e2f3a4b", "source": "test", "summary": "Test alert for local development", "status": "open", "labels": {"severity": "critical"}, "data": {"host": "localhost"}, "services": [{"id": "8d9e0f1a-2b3c-4d5e-6f7a-8b9c0d1e2f3a", "name": "Test Service", "slug": "test"}], "environments": [{"id": "7c8d9e0f-1a2b-3c4d-5e6f-7a8b9c0d1e2f", "name": "Development", "slug": "dev"}] } }] } ``` Then post to your local mock server to trigger actions. # Installation & Deployment Source: https://docs.rootly.com/edge-connectors-installation Install and deploy the Rootly Edge Connector in your environment using Docker or supported orchestrators to securely poll Rootly without inbound connections. ## Overview The Rootly Edge Connector is a lightweight agent that runs in your infrastructure to securely integrate with internal systems. This guide covers installation, configuration, and deployment for production environments. ## Prerequisites Before installing the Edge Connector, ensure you have: * **Operating System**: Linux (systemd-based distributions recommended) * **Network Access**: Outbound HTTPS to `rec.rootly.com` (port 443) * **API Key**: Edge Connector API key from Rootly (see [Getting Started](/edge-connectors#getting-started)) * **Permissions**: Root or sudo access for system installation The Edge Connector only requires **outbound** network access. No inbound firewall rules are needed. ## Installation Methods Choose one of the following installation methods based on your environment: ### Option 1: Homebrew (Recommended for macOS/Linux) ```bash theme={null} # Add Rootly tap brew tap rootlyhq/tap # Install Edge Connector brew install rootly-edge-connector # Verify installation rootly-edge-connector --version ``` ### Option 2: Go Install If you have Go 1.24+ installed: ```bash theme={null} # Install latest version go install github.com/rootlyhq/rootly-edge-connector/cmd/rec@latest # The binary will be installed to $GOPATH/bin/rec ``` ### Option 3: Build from Source ```bash theme={null} # Clone repository git clone https://github.com/rootlyhq/rootly-edge-connector.git cd rootly-edge-connector # Build and install make build make install # Verify installation rootly-edge-connector --version ``` ### Option 4: Pre-built Binaries For enterprise customers with access to private releases: Contact [support@rootly.com](mailto:support@rootly.com) for access to pre-built binaries and download credentials. ## Quick Start (Development) For testing and development, run the Edge Connector directly: ### 1. Create Configuration Files **config.yml:** ```yaml theme={null} app: name: "rootly-edge-connector" rootly: api_url: "https://rec.rootly.com" api_path: "/v1" api_key: "YOUR_REC_API_KEY" poller: polling_wait_interval_ms: 5000 visibility_timeout_sec: 30 logging: level: "info" format: "json" metrics: enabled: true port: 9090 ``` **actions.yml:** ```yaml theme={null} defaults: timeout: 30 on: alert.created: script: /path/to/test-script.sh parameters: alert_id: "{{ id }}" severity: "{{ labels.severity }}" timeout: 60 ``` ### 2. Set API Key ```bash theme={null} export REC_API_KEY="your-api-key-here" ``` ### 3. Run the Connector ```bash theme={null} ./rootly-edge-connector \ -config config.yml \ -actions actions.yml ``` You should see output indicating the connector is polling: ```text theme={null} INFO Starting Rootly Edge Connector INFO Registered actions with backend action_count=1 INFO Polling for events poll_interval=10s ``` ## Production Installation (Linux/systemd) For production deployments, install the Edge Connector as a systemd service. ### Step 1: Create System User Create a dedicated user for the Edge Connector: ```bash theme={null} sudo groupadd -r rootly sudo useradd -r -g rootly -s /bin/false -d /opt/rootly-edge-connector rootly ``` ### Step 2: Create Directories Set up the directory structure: ```bash theme={null} sudo mkdir -p /opt/rootly-edge-connector/bin sudo mkdir -p /opt/rootly-edge-connector/scripts sudo mkdir -p /etc/rootly-edge-connector sudo mkdir -p /var/log/rootly-edge-connector ``` ### Step 3: Install Binary Copy the binary to the installation directory. The binary location depends on your installation method: ```bash theme={null} # If you built from source or downloaded a binary directly: sudo cp rootly-edge-connector /opt/rootly-edge-connector/bin/ # If you used Homebrew: sudo cp $(which rootly-edge-connector) /opt/rootly-edge-connector/bin/ # If you used Go install: sudo cp $GOPATH/bin/rec /opt/rootly-edge-connector/bin/rootly-edge-connector # Set permissions sudo chmod +x /opt/rootly-edge-connector/bin/rootly-edge-connector ``` ### Step 4: Create Configuration Create your configuration files in `/etc/rootly-edge-connector/`: **`/etc/rootly-edge-connector/config.yml`:** ```yaml theme={null} app: name: "rootly-edge-connector" rootly: api_url: "https://rec.rootly.com" api_path: "/v1" api_key: "YOUR_REC_API_KEY" poller: polling_wait_interval_ms: 10000 visibility_timeout_sec: 30 max_number_of_messages: 10 security: script_timeout: 300 allowed_script_paths: - /opt/rootly-edge-connector/scripts logging: level: "info" format: "json" output: "stdout" metrics: enabled: true port: 9090 path: "/metrics" ``` **`/etc/rootly-edge-connector/actions.yml`:** ```yaml theme={null} # Automatic action - runs when incidents are created on: incident.created: http: url: "{{ env.WEBHOOK_URL }}" method: POST headers: Content-Type: "application/json" body: | { "incident_id": "{{ id }}", "title": "{{ title }}", "severity": "{{ severity.name }}" } timeout: 30 # Manual action - triggered by users from Rootly UI callable: restart_service: name: "Restart Service" trigger: alert.action_triggered script: /opt/rootly-edge-connector/scripts/restart.sh parameter_definitions: - name: service_name type: string required: true timeout: 120 ``` ### Step 5: Create Environment File Store the API key and sensitive values securely: ```bash theme={null} sudo tee /etc/rootly-edge-connector/environment > /dev/null < connector-logs.txt ``` ### Checking Metrics If metrics are enabled (default port 9090): ```bash theme={null} # View Prometheus metrics curl http://localhost:9090/metrics # Common metrics: # - rec_events_polled_total: Total events polled # - rec_actions_executed_total: Total actions executed # - rec_action_duration_seconds: Action execution duration # - rec_poll_errors_total: Polling errors ``` ## Updating ### Update Binary ```bash theme={null} # Stop the service sudo systemctl stop rootly-edge-connector # Backup current binary sudo cp /opt/rootly-edge-connector/bin/rootly-edge-connector \ /opt/rootly-edge-connector/bin/rootly-edge-connector.backup # Install new binary sudo cp new-rootly-edge-connector /opt/rootly-edge-connector/bin/rootly-edge-connector sudo chmod +x /opt/rootly-edge-connector/bin/rootly-edge-connector sudo chown rootly:rootly /opt/rootly-edge-connector/bin/rootly-edge-connector # Start the service sudo systemctl start rootly-edge-connector # Verify sudo systemctl status rootly-edge-connector ``` ### Update Configuration ```bash theme={null} # Edit configuration files sudo vim /etc/rootly-edge-connector/config.yml sudo vim /etc/rootly-edge-connector/actions.yml # Validate configuration (optional) sudo -u rootly /opt/rootly-edge-connector/bin/rootly-edge-connector \ -config /etc/rootly-edge-connector/config.yml \ -actions /etc/rootly-edge-connector/actions.yml \ -validate # Restart service to apply changes sudo systemctl restart rootly-edge-connector ``` ## Docker Deployment For containerized environments: **Dockerfile:** ```dockerfile theme={null} FROM ubuntu:22.04 RUN apt-get update && apt-get install -y ca-certificates && rm -rf /var/lib/apt/lists/* COPY rootly-edge-connector /usr/local/bin/ RUN chmod +x /usr/local/bin/rootly-edge-connector USER 1000:1000 ENTRYPOINT ["/usr/local/bin/rootly-edge-connector"] CMD ["-config", "/etc/rootly/config.yml", "-actions", "/etc/rootly/actions.yml"] ``` **docker-compose.yml:** ```yaml theme={null} version: '3.8' services: edge-connector: image: rootly-edge-connector:latest container_name: rootly-edge-connector restart: always environment: - REC_API_KEY=${REC_API_KEY} volumes: - ./config.yml:/etc/rootly/config.yml:ro - ./actions.yml:/etc/rootly/actions.yml:ro - ./scripts:/opt/scripts:ro ports: - "9090:9090" # Metrics port ``` **Run with Docker:** ```bash theme={null} # Build image docker build -t rootly-edge-connector:latest . # Run container docker run -d \ --name rootly-edge-connector \ --restart always \ -e REC_API_KEY="your-api-key" \ -v $(pwd)/config.yml:/etc/rootly/config.yml:ro \ -v $(pwd)/actions.yml:/etc/rootly/actions.yml:ro \ -v $(pwd)/scripts:/opt/scripts:ro \ -p 9090:9090 \ rootly-edge-connector:latest # View logs docker logs -f rootly-edge-connector ``` ## Troubleshooting ### Connector Won't Start **Check configuration syntax:** ```bash theme={null} sudo -u rootly /opt/rootly-edge-connector/bin/rootly-edge-connector \ -config /etc/rootly-edge-connector/config.yml \ -actions /etc/rootly-edge-connector/actions.yml \ -validate ``` **Check permissions:** ```bash theme={null} ls -la /opt/rootly-edge-connector/bin/ ls -la /etc/rootly-edge-connector/ ``` **View detailed logs:** ```bash theme={null} sudo journalctl -u rootly-edge-connector -n 50 --no-pager ``` ### API Connection Issues **Test network connectivity:** ```bash theme={null} curl -v https://rec.rootly.com/health ``` **Verify API key:** ```bash theme={null} # Check environment file sudo cat /etc/rootly-edge-connector/environment # Test with API key curl -H "Authorization: Bearer YOUR_API_KEY" \ https://rec.rootly.com/rec/v1/health ``` ### Actions Not Executing **Check action registration:** ```bash theme={null} # Look for registration success in logs sudo journalctl -u rootly-edge-connector | grep "Registered actions" ``` **Verify script permissions:** ```bash theme={null} # Scripts must be executable sudo chmod +x /opt/rootly-edge-connector/scripts/*.sh # Check script ownership ls -la /opt/rootly-edge-connector/scripts/ ``` **Test script manually:** ```bash theme={null} sudo -u rootly /opt/rootly-edge-connector/scripts/your-script.sh arg1 arg2 ``` ### High Memory/CPU Usage **Check poll interval:** * Increase `poller.polling_wait_interval_ms` in config.yml (for example, from 5000 to 30000) **Review action timeouts:** * Ensure actions complete within their timeout values * Check for hung processes **Monitor metrics:** ```bash theme={null} curl http://localhost:9090/metrics | grep rec_ ``` ## Security Best Practices ### 1. Run as Dedicated User Always run the Edge Connector as a non-root user with minimal privileges. ### 2. Protect Sensitive Files ```bash theme={null} # Environment file should be 600 (owner read/write only) sudo chmod 600 /etc/rootly-edge-connector/environment # Config files should be 640 (owner read/write, group read) sudo chmod 640 /etc/rootly-edge-connector/*.yml ``` ### 3. Network Isolation * Run on a dedicated or isolated host * Restrict outbound connections to rec.rootly.com only (if using firewall) * Do not expose metrics port publicly ### 4. Audit Scripts * Review all scripts before adding to actions.yml * Use version control for scripts * Implement pull request approval process ### 5. Rotate API Keys * Rotate API keys periodically (for example, quarterly) * Use different keys for dev/staging/production * Revoke old keys after rotation ### 6. Monitor Logs * Set up log aggregation (for example, to ELK, Splunk) * Alert on errors and failures * Review execution logs regularly ## Next Steps * Configure [Actions](/edge-connectors-actions) for your use cases * Learn [Template Syntax](/edge-connectors-templates) for dynamic values * Review [Event Examples](/edge-connectors-event-examples) for payload structures * See the main [Edge Connectors](/edge-connectors) documentation for architecture details # Template Syntax Source: https://docs.rootly.com/edge-connectors-templates Use Liquid templates in Rootly Edge Connectors to dynamically insert event data, parameters, and secrets into HTTP and script actions during execution. ## Overview Edge Connectors use **Liquid templates** to dynamically substitute values from events, user parameters, and environment variables into your action configurations. Templates allow you to: * Access event data (alerts, incidents, etc.) * Use user-provided parameters from manual triggers * Reference environment variables securely * Transform data with filters Edge Connectors use the [osteele/liquid](https://github.com/osteele/liquid) library, a Go implementation of Shopify's Liquid template language. ## Basic Syntax ### Simple Fields Access top-level fields directly: ```yaml theme={null} {{ id }} # Event ID {{ summary }} # Alert/incident summary {{ status }} # Current status {{ title }} # Incident title ``` ### Nested Fields Use dot notation for nested objects: ```yaml theme={null} {{ labels.severity }} # Alert severity label {{ data.host }} # Custom monitoring data {{ severity.name }} # Incident severity object {{ triggered_by.email }} # User who triggered action ``` ### Array Access Access array elements by index or using helpers: ```yaml theme={null} {{ services[0].name }} # First service (by index) {{ services.first.name }} # First service (helper) {{ services.last.slug }} # Last service (helper) {{ environments[0].slug }} # First environment ``` ### Environment Variables Securely access environment variables: ```yaml theme={null} {{ env.API_KEY }} # From REC_API_KEY or API_KEY {{ env.AWS_REGION }} # From REC_AWS_REGION or AWS_REGION {{ env.WEBHOOK_URL }} # From REC_WEBHOOK_URL or WEBHOOK_URL ``` Store sensitive values like API keys and tokens in environment variables, never in action configuration files. ## Event Data Access ### Alert Events Common fields available in alert events: ```yaml theme={null} {{ id }} # Alert UUID {{ summary }} # Alert summary text {{ status }} # open, acknowledged, resolved {{ source }} # datadog, pagerduty, etc. {{ labels.severity }} # Severity from monitoring system {{ data.host }} # Custom monitoring data {{ services[0].name }} # Affected service {{ environments[0].slug }} # Environment (production, etc.) {{ started_at }} # When alert started ``` ### Incident Events Common fields available in incident events: ```yaml theme={null} {{ id }} # Incident UUID {{ sequential_id }} # Incident number (42, 43, etc.) {{ title }} # Incident title {{ summary }} # Incident summary {{ status }} # started, mitigated, resolved {{ severity.name }} # SEV1, SEV2, etc. {{ severity.slug }} # sev1, sev2, etc. {{ services | map: 'name' }} # All affected services {{ environments[0].name }} # Environment name {{ detected_at }} # When detected {{ mitigated_at }} # When mitigated {{ resolved_at }} # When resolved ``` ### Action Trigger Events Fields available when users manually trigger actions: ```yaml theme={null} {{ entity_id }} # Alert or incident ID {{ action.name }} # Action display name {{ action.slug }} # Action identifier {{ parameters.service_name }} # User input parameter {{ parameters.environment }} # User input parameter {{ triggered_by.id }} # User ID {{ triggered_by.name }} # User name {{ triggered_by.email }} # User email ``` ## Filters Filters transform values using the pipe (`|`) operator. ### Array Filters **map** - Extract property from objects: ```yaml theme={null} {{ services | map: "name" }} # [{name: "DB"}, {name: "API"}] → ["DB", "API"] ``` **join** - Combine array elements: ```yaml theme={null} {{ services | map: "name" | join: ", " }} # ["DB", "API", "Cache"] → "DB, API, Cache" ``` **first** - Get first element: ```yaml theme={null} {{ services | first }} # Returns first service object ``` **last** - Get last element: ```yaml theme={null} {{ services | last }} # Returns last service object ``` **sort** - Sort alphabetically: ```yaml theme={null} {{ names | sort }} # ["charlie", "alice", "bob"] → ["alice", "bob", "charlie"] ``` **uniq** - Remove duplicates: ```yaml theme={null} {{ items | uniq }} # [1, 2, 2, 3, 1] → [1, 2, 3] ``` **compact** - Remove nil values: ```yaml theme={null} {{ items | compact }} # [1, nil, 2, nil, 3] → [1, 2, 3] ``` **reverse** - Reverse order: ```yaml theme={null} {{ items | reverse }} # [1, 2, 3] → [3, 2, 1] ``` ### String Filters **upcase** - Convert to uppercase: ```yaml theme={null} {{ status | upcase }} # "open" → "OPEN" ``` **downcase** - Convert to lowercase: ```yaml theme={null} {{ severity | downcase }} # "CRITICAL" → "critical" ``` **capitalize** - Capitalize first letter: ```yaml theme={null} {{ name | capitalize }} # "john doe" → "John doe" ``` **default** - Provide fallback value: ```yaml theme={null} {{ field | default: "N/A" }} # If field is empty → "N/A" ``` **truncate** - Shorten text: ```yaml theme={null} {{ summary | truncate: 50 }} # "Very long summary text..." → "Very long summary text..." ``` **replace** - Replace all occurrences: ```yaml theme={null} {{ text | replace: "foo", "bar" }} # "foo foo" → "bar bar" ``` **remove** - Remove all occurrences: ```yaml theme={null} {{ severity | remove: "SEV" }} # "SEV1" → "1" ``` **strip** - Remove whitespace: ```yaml theme={null} {{ text | strip }} # " hello " → "hello" ``` **append** - Add to end: ```yaml theme={null} {{ name | append: ".txt" }} # "file" → "file.txt" ``` **prepend** - Add to beginning: ```yaml theme={null} {{ name | prepend: "prefix-" }} # "name" → "prefix-name" ``` **split** - Split into array: ```yaml theme={null} {{ "a,b,c" | split: "," }} # "a,b,c" → ["a", "b", "c"] ``` ### Number Filters **plus** - Add: ```yaml theme={null} {{ count | plus: 1 }} # 5 → 6 ``` **minus** - Subtract: ```yaml theme={null} {{ count | minus: 2 }} # 5 → 3 ``` **times** - Multiply: ```yaml theme={null} {{ value | times: 10 }} # 5 → 50 ``` **divided\_by** - Divide: ```yaml theme={null} {{ value | divided_by: 2 }} # 10 → 5 ``` **modulo** - Remainder: ```yaml theme={null} {{ value | modulo: 3 }} # 10 → 1 ``` **abs** - Absolute value: ```yaml theme={null} {{ value | abs }} # -5 → 5 ``` **round** - Round number: ```yaml theme={null} {{ value | round: 2 }} # 3.14159 → 3.14 ``` **ceil** - Round up: ```yaml theme={null} {{ value | ceil }} # 3.2 → 4 ``` **floor** - Round down: ```yaml theme={null} {{ value | floor }} # 3.8 → 3 ``` ### Date Filters **date** - Format timestamp: ```yaml theme={null} {{ started_at | date: "%Y-%m-%d %H:%M:%S" }} # "2025-10-26T21:30:00Z" → "2025-10-26 21:30:00" {{ started_at | date: "%B %d, %Y" }} # "2025-10-26T21:30:00Z" → "October 26, 2025" ``` Common date format codes: * `%Y` - Year (2025) * `%m` - Month (01-12) * `%d` - Day (01-31) * `%H` - Hour 24h (00-23) * `%M` - Minute (00-59) * `%S` - Second (00-59) * `%B` - Full month name (January) * `%b` - Short month name (Jan) ## Real-World Examples ### Example 1: Alert Notification Format a Slack message with alert details: ```yaml theme={null} body: | { "text": ":warning: New Alert", "attachments": [{ "color": "danger", "fields": [ {"title": "Summary", "value": "{{ summary }}", "short": false}, {"title": "Severity", "value": "{{ labels.severity | upcase }}", "short": true}, {"title": "Host", "value": "{{ data.host | default: 'unknown' }}", "short": true}, {"title": "Services", "value": "{{ services | map: 'name' | join: ', ' }}", "short": false}, {"title": "Environment", "value": "{{ environments.first.name }}", "short": true}, {"title": "Time", "value": "{{ started_at | date: '%Y-%m-%d %H:%M' }}", "short": true} ] }] } ``` ### Example 2: Incident Summary Create a concise incident summary: ```yaml theme={null} message: "[{{ severity.name }}] {{ title }} - {{ services | map: 'name' | join: ', ' }} ({{ environments.first.slug }})" # Result: "[SEV1] API Gateway Outage - API Gateway, Auth Service (production)" ``` ### Example 3: Script Parameters Pass structured data to a script: ```yaml theme={null} parameters: incident_id: "{{ id }}" incident_number: "{{ sequential_id }}" severity: "{{ severity.slug }}" services: "{{ services | map: 'slug' | join: ',' }}" environment: "{{ environments.first.slug }}" triggered_by: "{{ triggered_by.email | default: 'system' }}" timestamp: "{{ started_at | date: '%Y-%m-%d %H:%M:%S' }}" ``` ### Example 4: Conditional Values Use defaults for optional fields: ```yaml theme={null} parameters: reason: "{{ parameters.reason | default: 'Manual action triggered' }}" environment: "{{ parameters.environment | default: 'production' }}" force: "{{ parameters.force_restart | default: false }}" host: "{{ data.host | default: 'localhost' }}" ``` ### Example 5: Complex Transformation Chain multiple filters: ```yaml theme={null} # Extract, sort, and format service names services_list: "{{ services | map: 'name' | sort | join: ' | ' | upcase }}" # Result: "API GATEWAY | AUTH SERVICE | DATABASE" # Format severity without prefix severity_number: "{{ severity.name | remove: 'SEV' }}" # "SEV1" → "1" ``` ## Advanced Patterns ### Chaining Filters Combine multiple filters in sequence: ```yaml theme={null} {{ services | map: "name" | sort | uniq | join: ", " | upcase }} # Extract names → sort → remove duplicates → join → uppercase ``` ### Nested Array Access Access deeply nested data: ```yaml theme={null} {{ services[0].tags[0] }} # First service's first tag {{ data.metrics.values[5] }} # Sixth metric value {{ environments.first.config.region }} # Environment config ``` ### Safe Navigation Liquid handles missing values gracefully: ```yaml theme={null} {{ missing.field }} # Returns empty string "" {{ array[999].name }} # Returns "" (out of bounds) {{ undefined | default: "N/A" }} # Returns "N/A" ``` ## Common Patterns ### Service List ```yaml theme={null} services: "{{ services | map: 'name' | join: ', ' }}" # "Database, API Gateway, Cache" ``` ### Environment Detection ```yaml theme={null} env: "{{ environments.first.slug | default: 'unknown' }}" # "production" ``` ### Severity Formatting ```yaml theme={null} severity: "{{ labels.severity | upcase | default: 'UNKNOWN' }}" # "CRITICAL" ``` ### User Context ```yaml theme={null} user: "{{ triggered_by.name }} ({{ triggered_by.email }})" # "John Doe (john@example.com)" ``` ### Timestamp Formatting ```yaml theme={null} time: "{{ started_at | date: '%Y-%m-%d %H:%M:%S UTC' }}" # "2025-10-26 21:30:00 UTC" ``` ## Limitations To keep templates simple and secure, the following Liquid features are **not** supported: * **No logic tags**: `{% if %}`, `{% unless %}`, `{% case %}` not supported * **No loops**: `{% for %}` not supported - use filters like `map` and `join` instead * **No custom tags**: Only `{{ }}` output tags are supported * **No assignments**: `{% assign %}` not supported Use filters and the `default` filter for conditional logic: ```yaml theme={null} # Instead of {% if field %}{{ field }}{% else %}N/A{% endif %} # Use: {{ field | default: "N/A" }} ``` ## Tips & Best Practices ### 1. Use Default Filter Always provide fallback values for optional fields: ```yaml theme={null} {{ data.host | default: "unknown" }} {{ parameters.timeout | default: 30 }} ``` ### 2. Extract Then Join For arrays of objects, use `map` + `join`: ```yaml theme={null} {{ services | map: "name" | join: ", " }} ``` ### 3. Test Templates Test with sample event data before deploying: * Use the [Event Examples](/edge-connectors-event-examples) for reference payloads * Verify templates produce expected output * Handle edge cases (empty arrays, missing fields) ### 4. Keep It Simple Complex logic belongs in scripts, not templates: ```yaml theme={null} # Good: Simple data extraction service: "{{ services.first.name }}" # Bad: Complex transformation (do this in a script instead) # Avoid overly complex filter chains ``` ### 5. Environment Variables for Secrets Never hardcode secrets in templates: ```yaml theme={null} # Good Authorization: "Bearer {{ env.API_TOKEN }}" # Bad Authorization: "Bearer sk-1234567890abcdef" ``` ### 6. Format for Readability Use multiline strings for JSON/YAML bodies: ```yaml theme={null} body: | { "field1": "{{ value1 }}", "field2": "{{ value2 }}" } ``` ## Troubleshooting ### Template Returns Empty String * Check field name spelling * Verify field exists in event payload (see [Event Examples](/edge-connectors-event-examples)) * Use `default` filter: `{{ field | default: "missing" }}` ### Array Access Fails * Verify array is not empty * Use `.first` or `.last` helpers for safety * Check array index is in bounds ### Filter Not Working * Verify filter name is correct * Check filter arguments (some require arguments: `{{ value | round: 2 }}`) * Ensure input type matches filter (can't `upcase` a number) ### Environment Variable Not Found * Verify variable is set in environment * Check variable name (case-sensitive) * Edge Connector supports both `REC_` prefix and plain names ## Next Steps * See [Action Configuration](/edge-connectors-actions) to use templates in actions * Review [Event Examples](/edge-connectors-event-examples) for available fields * Read the main [Edge Connectors](/edge-connectors) documentation # Frequently Asked Questions Source: https://docs.rootly.com/faq Answers to common questions about Rootly incident management: creating incidents from Slack, on-call schedules, alert deduplication, workflows, and Rootly AI. This page answers the questions teams ask most often when adopting Rootly for incident management, on-call, and alerting. Each answer links to the full documentation page where you can go deeper. ## Incidents ### How do I create an incident from Slack? Type `/rootly new` in any Slack channel to open the New Incident form, or hover over an existing message, click **More actions** (three dots), and select **Create an incident** to declare an incident from a message, alert, or customer report. You can also mention `@Rootly` and ask the AI agent to create the incident for you in plain language. Slack-based creation supports customizable fields, required-field validation, private incidents, and automatic incident channel creation. Learn more: [Creating Incidents via Slack](/incidents/creating-incidents/creating-incidents-via-slack). ### What's the difference between severity and priority in Rootly? Severity is Rootly's built-in property describing how bad an incident is while it's happening; priority is typically a custom field layered on top to capture how urgent it is to fix. For example, a minor bug affecting a major customer might be SEV3 severity but P1 priority. Rootly doesn't ship priority as a built-in — add it as a custom field if you need it. Learn more: [Severities](/configuration/severities). ### What's the difference between the Resolved and Closed statuses? **Resolved** means active incident response has completed and service impact has ended — this is typically when retrospective work begins. **Closed** is an optional terminal status (enabled via team configuration) that marks an incident as fully finalized after review; it requires the incident to already be Resolved. If your team hasn't enabled Closed, Resolved serves as the terminal status. Learn more: [Incident Status](/configuration/incident-status). ### What are private incidents and who can see them? Private incidents restrict sensitive operational, customer, or security-related information to a limited group of responders, adding a second layer of access control on top of workspace-wide RBAC. Users can access a private incident either through a role that grants private incident read access, or by being explicitly invited through the **Manage Access** dialog in the web UI or Slack. Learn more: [Private Incidents](/incidents/private-incidents/private-incidents). ### Can I split a large incident into sub-incidents? Yes. A sub-incident is a normal incident linked to a parent via `parent_incident_id`, letting a team investigate and coordinate their scope independently while keeping shared context with the parent. Each parent incident can have multiple sub-incidents, which is useful for large, cross-functional incidents. Learn more: [Creating Sub-Incidents](/incidents/incident-operations/creating-sub-incident). ## Alerts & Noise Reduction ### How does alert deduplication work? Alert Deduplication collapses repeat events from the same monitor onto a single open Rootly alert, so responders see a rising event count instead of getting paged again. Rootly provides two layers: configurable per–Alert Source deduplication using a stable unique identifier (extracted via JSONPath from the payload or from an alert field, optionally normalized with a regex), plus payload-based exact-body suppression as a backstop. Learn more: [Alert Deduplication](/alerts/alert-deduplication). ### What's the difference between alert deduplication and alert grouping? Use deduplication when the *same* monitor keeps re-firing while an issue is unresolved; use grouping when *different* monitors all fire on the same underlying problem (for example latency, error rate, and DB health alerts at once). Alert Grouping consolidates related alerts into a single leader alert with member alerts — responders are paged for the leader, and matching alerts join the group silently. You can enable both together. Learn more: [Alert Grouping](/alerts/alert-grouping). ### How does alert routing decide who gets notified? Alert Routes define when, how, and to whom Rootly sends incoming alerts, evaluating conditions against Alert Sources, normalized Alert Fields, and raw payload values via JSONPath. Matching alerts are routed to teams, services, or escalation policies, giving you one centralized routing layer that works consistently across all your monitoring tools. Learn more: [Alert Routing](/alerts/alert-routing). ### What does alert urgency control? Alert Urgency controls how quickly responders must act on an alert — how aggressively Rootly pages on-call responders, whether notifications are audible or quiet, and which escalation paths apply during or outside working hours. Rootly ships with High, Medium, and Low urgency levels by default, and you can add, rename, and reorder urgencies. Learn more: [Alert Urgency](/alerts/alert-urgency). ### How do I monitor cron jobs and background workers with Rootly? Use Heartbeats: they require your systems to "check in" on a regular cadence, and if a heartbeat misses its expected interval, Rootly automatically triggers an alert and notifies the appropriate on-call responders. Each heartbeat cycles through waiting, active, and expired statuses, making it easy to catch silent failures in cron jobs, schedulers, and background workers. Learn more: [Heartbeats](/on-call/heartbeats). ## On-Call & Paging ### How do I set up an on-call schedule? Navigate to **On-Call → Schedules**, click **+ New Schedule**, name it, and define rotations that determine who is on call and when responsibility hands over. Note that schedules alone don't trigger paging — they must be linked to an Escalation Policy to become part of the alerting process. Creating or editing schedules requires the On-Call Admin or On-Call User role. Learn more: [On-Call Schedules](/on-call/schedules). ### How do escalation policies work? Escalation Policies define who is notified first when an alert fires, what happens if no one acknowledges it, and how long Rootly keeps escalating before stopping. Policies are assigned to a Team or Service, and each new policy automatically includes a Default Escalation Path with audible notifications that acts as a fallback. Learn more: [Escalation Policies](/on-call/escalation-policies). ### How do I page someone manually? Manual paging lets you page a specific user, team, service, functionality, or escalation policy directly from Rootly Web, Slack, or the mobile app — useful for escalating to another team or looping in a subject matter expert. Paging a team or service runs the same escalation policy as a programmatic alert, so the behavior is identical to automated paging. Learn more: [Manual Paging](/alerts/manual-paging). ### How do I cover an on-call shift when someone is unavailable? Create an override: it temporarily assigns a specific shift to a different user while leaving the underlying rotation unchanged, making it the safest way to handle short-term coverage changes. Overrides always apply to individual users, take precedence over rotation-based shifts, and Rootly validates them to prevent overlaps or paging conflicts. Learn more: [Editing Schedules & Overrides](/on-call/edit-schedules). ### Can Rootly route phone calls to on-call engineers? Yes. Live Call Routing gives you dedicated phone numbers that either connect callers live to the current on-call team member or route to a voicemail where the message is logged and the team is alerted. It also supports IVR calling trees for directing callers to the right team. Learn more: [Live Call Routing](/on-call/live-call-routing). ## Workflows & Automation ### What can I automate with Rootly workflows? Workflows are Rootly's automation engine: they combine trigger events, run conditions, and actions to remove repetitive coordination work during incident response. Common patterns include creating incident channels in Slack or Microsoft Teams, posting periodic status reminders, notifying legal or support teams on high-impact incidents, creating Jira or Linear tickets, and spinning up Zoom or Google Meet bridges for high-severity incidents. Learn more: [Workflows Overview](/workflows/workflows). ### Can I run a workflow manually? Yes. Beyond automatic trigger-based execution, workflows can be run on demand via a Slack command, an interactive Slack modal, or directly from an incident in the web UI. Manual runs still respect permissions — if you can't trigger workflows for a given incident, Rootly blocks the action. Learn more: [Manually Running Workflows](/workflows/manually-running-workflows). ### Can workflows keep Jira tickets in sync with incident action items? Yes. Action item workflows trigger whenever action items are created, updated, assigned, or completed, so you can automatically create or update Jira (or other ticketing) issues, assign tickets based on the Rootly assignee, and notify owners when work is assigned or overdue. They trigger on action item events but can still use incident properties like severity or team as run conditions. Learn more: [Action Item Workflows](/workflows/action-item-workflows). ## Rootly AI ### What is Rootly AI in Slack? Rootly AI is an AI agent that works inside your Slack incident channels, the Slack assistant pane, and DMs — type `@Rootly` to catch up on an incident, update severity, draft customer comms, or page another team without leaving Slack. It reads from your Rootly data, channel messages, and bridge call transcripts (when available), and it can only take actions that you as a user have permission to perform. Learn more: [Rootly AI in Slack](/ai/rootly-in-slack/overview). ### What data does Rootly AI access? Rootly AI reads only the incident and conversation context for the request in front of it — never your broader Rootly data or message history. In Slack it does not crawl historical messages, browse channels it hasn't been invited to, or call Slack's `conversations.history` API; in the web and mobile apps it sees only the incident you're viewing and your conversation with it. Learn more: [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai). ### Is my data used to train AI models? No. Customer data is processed in-context for each request and is not used to fine-tune base models. Rootly AI uses Claude Sonnet 4.6 from Anthropic as the default model with OpenAI's GPT-5 as a fallback, both accessed through a managed gateway. Learn more: [Data Privacy for Rootly AI](/ai/data-privacy-for-rootly-ai). ## Integrations, Retrospectives & Administration ### Does Rootly integrate with tools like Datadog, PagerDuty, and Jira? Yes. Rootly integrates with a wide range of tools across communication and collaboration, alerting and on-call, observability and monitoring, issue tracking, video conferencing, and automation and AI — including PagerDuty, Jira, Zoom, Kubernetes, GitHub, and Datadog. Each integration section documents setup, workflow actions, and configuration. Learn more: [Integrations Overview](/integrations/overview). ### How do I set up a status page? Creating a status page takes about a minute: go to **Configuration → Status Pages**, click **Add New Status Page**, and give it a name and description. Rootly recommends configuring at least one service first so you have something to display, and you can then customize branding, components, and visibility for internal stakeholders or external customers. Learn more: [Creating a Status Page](/configuration/creating-a-status-page). ### How do retrospectives work in Rootly? Rootly lets you define multiple retrospective processes and right-size follow-up work based on severity, incident type, or team, with a default process as a fallback when no custom process matches. Each process contains ordered steps — gathering data, writing the retrospective document, hosting a review meeting, creating action items — that can include due dates, assignees, and reminders. Learn more: [Retrospectives Overview](/retrospectives/retrospectives). ### How are user permissions managed in Rootly? Permissions are managed through team-scoped roles: each team membership assigns a user two roles, an Incident Response role (governing incident creation, management, configuration, and analytics) and an On-Call role (governing alerting, paging, schedules, and escalation policies). A user can hold different access levels across different teams in the same workspace, and default roles include Owner, Admin, User, Observer, and No Access. Learn more: [User Permissions](/managing-users/user-permissions). # Incident Management Glossary Source: https://docs.rootly.com/glossary Plain-English definitions of incident management terms — incident commander, escalation policy, alert fatigue, MTTR, SEV levels, runbooks, and more. Clear definitions for the terms you'll meet across Rootly and in incident management generally. Entries link to the Rootly docs page where you can put the concept to work — and the most-asked-about terms have full deep-dive entries with formulas, tables, and worked examples. ## Action item An action item is a concrete follow-up task that comes out of an incident or retrospective — fix the bug, add the missing alert, update the runbook. Tracking them to completion is how incidents actually make systems better. Learn more: [Action Items & Tasks](/incidents/action-items/action-items). ## Alert An alert is a signal from a monitoring or observability tool that something may be wrong. Alerts feed into routing, grouping, and escalation so the right responder is notified. Not every alert becomes an incident. Learn more: [Alerts](/alerts/alerts). ## Alert deduplication Alert deduplication collapses repeated notifications for the same underlying problem into a single alert, so responders see one actionable signal instead of a flood. Learn more: [Alert Deduplication](/alerts/alert-deduplication). ## Alert fatigue Alert fatigue is the desensitization responders develop when they receive too many noisy, low-value, or false-positive alerts — leading to slower responses and missed real incidents. Deduplication, grouping, routing, and urgency tuning are the main defenses. Learn more: [Alert Deduplication](/alerts/alert-deduplication) and [Alert Urgency](/alerts/alert-urgency). Deep dive: [What is alert fatigue?](/glossary/alert-fatigue). ## Alert grouping Alert grouping bundles related alerts — same service, same time window, similar payloads — into one group so they can be triaged and resolved together. Learn more: [Alert Grouping](/alerts/alert-grouping). ## Alert routing Alert routing evaluates incoming alerts against rules and sends each one to the right team, service, or escalation path the first time. Routing rules typically match on alert source, payload fields, and urgency. Learn more: [Alert Routing](/alerts/alert-routing). ## Error budget An error budget is the amount of unreliability an SLO allows — the gap between your target and 100%. It's SRE's tool for balancing reliability work against shipping speed. Full entry: [What is an error budget?](/glossary/error-budget). ## Escalation policy An escalation policy is the ordered chain of people or teams to notify when an alert isn't acknowledged in time — for example, page the on-call engineer, then their backup, then the team lead. It guarantees nothing falls through the cracks. Learn more: [Escalation Policies](/on-call/escalation-policies). ## Heartbeat monitoring A heartbeat is an expected periodic signal from a system ("I'm alive"). When the signal stops arriving, an alert fires — catching silent failures that produce no error at all. Learn more: [Heartbeats](/on-call/heartbeats). ## Incident An incident is any unplanned disruption or degradation of a service that requires a response — from a full outage to elevated error rates or a security event. In Rootly, an incident is a structured record with a severity, status, timeline, roles, and follow-ups. Learn more: [Incident Management](/incidents/incidents). ## Incident channel (war room) An incident channel — commonly called a war room — is the dedicated space, physical or virtual, where responders coordinate during a major incident. Rootly favors the calmer "incident channel" over the militaristic framing. Full entry: [What is an incident channel?](/glossary/war-room). ## Incident commander The incident commander (IC) is the single person accountable for driving an incident to resolution: coordinating responders, making decisions, and keeping communication flowing. The IC directs the response but doesn't have to fix the issue personally. Rootly assigns incident roles like IC automatically when an incident starts. Learn more: [Incident Roles](/incidents/incident-roles/incident-roles). ## Incident management Incident management is the end-to-end discipline of detecting, responding to, resolving, and learning from incidents — the processes, roles, and tooling that keep services reliable. Full entry: [What is incident management?](/glossary/incident-management). ## Incident response Incident response is the hands-on work of an incident: triaging, mitigating, communicating, and resolving. It's the "doing" inside the broader incident management discipline. Full entry: [What is incident response?](/glossary/incident-response). ## Incident roles Incident roles are the named responsibilities in a response — incident commander, communications lead, scribe, operations lead — so everyone knows who is doing what. Rootly assigns and tracks roles per incident. Learn more: [Incident Roles](/incidents/incident-roles/incident-roles). ## Incident severity (SEV levels) Severity expresses how much impact an incident has, usually on a scale from SEV1 (critical, all-hands) down to SEV4/SEV5 (minor). Severity drives who gets paged, how fast, and what gets communicated. Rootly lets you define your own severity levels and tie automation to them. Learn more: [Severities](/configuration/severities). Deep dive: [SEV levels explained](/glossary/sev-levels) and [severity vs priority](/glossary/severity-vs-priority). ## Incident timeline The incident timeline is the chronological record of everything that happened during an incident — status changes, key decisions, messages, and events — captured automatically so the retrospective starts from facts instead of memory. Learn more: [Incident Timeline](/incidents/incident-timeline/incident-timeline). ## Incident triage Triage is the first-pass assessment of an incoming incident or alert: how bad is it, who does it affect, and how urgently does it need a response. Full entry: [What is incident triage?](/glossary/incident-triage). ## Live call routing Live call routing gives your customers or internal users a phone number that rings the current on-call responder directly, following your schedules and escalation policies. Learn more: [Live Call Routing](/on-call/live-call-routing). ## MTBF (mean time between failures) MTBF measures the average time a system runs between failures — a reliability indicator that pairs with MTTR to express availability. Full entry: [MTBF explained](/glossary/mtbf). ## MTTA (mean time to acknowledge) MTTA measures the average time between an alert firing and a responder acknowledging it. It's the primary signal of how quickly your paging and escalation setup actually reaches humans. Learn more: [On-Call Metrics](/on-call/on-call-metrics). Deep dive: [MTTA explained](/glossary/mtta) and [MTTA vs MTTR](/glossary/mtta-vs-mttr). ## MTTR (mean time to resolution) MTTR measures the average time from incident start to resolution. It's the most common top-level indicator of incident response health, and shrinking it is the goal of most process and tooling investments. Learn more: [Analytics & Dashboards](/metrics/default-metrics). Deep dive: [MTTR explained](/glossary/mttr) and [MTBF](/glossary/mtbf). ## On-call schedule An on-call schedule defines who is responsible for responding to alerts at any given time, rotating responsibility across a team in shifts. Good schedules balance coverage with responder health. Rootly supports rotations, overrides, and shift swaps. Learn more: [On-Call Schedules](/on-call/schedules). ## Paging Paging is the act of actively notifying an on-call responder — by push notification, SMS, or phone call — that they're needed now. A "page" cuts through normal notification channels. Learn more: [Manual Paging in Rootly](/alerts/manual-paging). ## Problem management (incident vs problem) In ITIL terms, an incident is the disruption; a problem is its underlying cause. Problem management hunts root causes across incidents. Full entry: [Incident vs problem](/glossary/incident-vs-problem). ## Retrospective (postmortem) A retrospective (also called a postmortem) is the structured review after an incident: what happened, why, how the response went, and what will prevent recurrence. Blameless retrospectives focus on systems rather than individuals. Learn more: [Retrospectives](/retrospectives/retrospectives). Deep dive: [retrospective vs postmortem](/glossary/retrospective-vs-postmortem) and [how to run a retrospective](/concepts/incident-retrospective). ## Runbook / playbook A runbook (or playbook) is a predefined set of steps for handling a specific scenario — what to check, who to involve, and how to mitigate. Rootly playbooks attach those steps directly to incidents so responders don't work from memory. Learn more: [Playbooks](/configuration/playbooks). Deep dive: [What is a runbook?](/glossary/runbook) and [runbook vs playbook](/glossary/runbook-vs-playbook). ## Service catalog A service catalog is the inventory of your services and their metadata: owners, teams, dependencies, and tooling. Incident response uses it to answer "what is affected and who owns it?" instantly. Learn more: [Catalog](/catalogs). ## SLA / SLO / SLI An SLI measures service behavior, an SLO is your internal target for that measurement, and an SLA is the external contract with consequences. Full entry: [SLA vs SLO vs SLI](/glossary/sla-vs-slo-vs-sli). ## Status page A status page communicates service health and incident updates to customers or internal stakeholders. Public status pages reduce support load during incidents; private ones keep internal teams aligned. Learn more: [Status Pages](/configuration/status-pages). ## Sub-statuses Sub-statuses add organization-specific stages to the incident lifecycle (for example "investigating — vendor engaged") beyond the standard started/mitigated/resolved flow, so reporting reflects how your team actually works. Learn more: [Statuses & Sub-Statuses](/incidents/incident-lifecycle). ## Workflow In Rootly, a workflow is an automation rule: when conditions match (an incident is created, a severity changes, an alert fires), Rootly performs actions — creating Slack channels, notifying stakeholders, filing Jira tickets, or updating status pages — the same way every time. Learn more: [Workflows](/workflows/workflows). # What Is Alert Fatigue? Source: https://docs.rootly.com/glossary/alert-fatigue Alert fatigue is the desensitization that sets in when responders receive too many alerts, causing real problems to be missed. Learn the causes and the fixes. **Alert fatigue** is the desensitization that sets in when responders receive so many alerts—especially noisy, low-value, or false ones—that they begin to ignore, mute, or slow-walk them. It is dangerous because it degrades exactly the behavior alerting exists to create: fast, attentive response. A team suffering from alert fatigue will eventually sleep through the one page that actually mattered. ## What causes alert fatigue? Alert fatigue is rarely caused by one bad alert. It accumulates from systemic problems: * **Noise.** Alerts that fire for conditions nobody needs to act on—a CPU spike that self-resolves, a threshold set years ago and never revisited. * **False positives.** Alerts that cry wolf. Each one teaches responders that pages can be safely ignored, and that lesson is hard to unteach. * **Duplication.** One underlying failure triggering twenty alerts from different monitors, each paging separately. * **Over-paging.** Routing everything to a human pager regardless of urgency, so a full disk on a staging server interrupts dinner the same way a production outage does. * **Wrong recipients.** Alerts sent to people who can't act on them, who then either ignore them or spend effort re-routing them by hand. The common thread is a broken signal-to-noise ratio: when most alerts don't require action, responders rationally stop treating any alert as if it does. ## What are the consequences of alert fatigue? The costs show up in two places—systems and people: * **Missed or delayed incidents.** The real SEV1 arrives looking exactly like the fifty ignorable pages before it. Detection-to-response time stretches, and outages run longer. * **On-call burnout.** Interrupted sleep and constant context-switching are among the most-cited reasons engineers leave on-call rotations, and sometimes teams entirely. * **Eroded trust in monitoring.** Once engineers believe the alerting system is noise, they stop improving it, which makes it noisier—a self-reinforcing spiral. * **Alert-handling theater.** Teams start bulk-acknowledging pages without reading them, which looks fine on dashboards while providing zero actual coverage. A realistic example: a platform team's disk-usage alert fires nightly at 3 a.m. because a log-rotation job briefly crosses 85%. After three weeks, the on-call engineer creates a mental rule—"the 3 a.m. page is always the log thing"—and starts acknowledging it from bed without looking. On night 24, the 3 a.m. page is a genuine database disk exhaustion. It gets acknowledged and ignored, and the outage is discovered by customers four hours later. ## How do you fix alert fatigue? The fixes attack noise at different points in the pipeline: * **Deduplication.** Collapse repeated firings of the same alert into one incident-worthy notification instead of a page-storm. Rootly supports this via [alert deduplication](/alerts/alert-deduplication). * **Grouping.** Bundle related alerts—same service, same failure window—so responders see one coherent event, not twenty fragments. See [alert grouping](/alerts/alert-grouping). * **Routing.** Send each alert to the team that owns the affected service, so alerts land with people who can act. See [alert routing](/alerts/alert-routing). * **Urgency tuning.** Not every alert deserves a phone call. Map alerts to urgency levels—page immediately, notify during business hours, or just log—so interruptions are reserved for problems that need a human now. See [alert urgency](/alerts/alert-urgency). * **Ruthless pruning.** Regularly review which alerts fired, which were actionable, and delete or fix the rest. An alert that has never led to action is a candidate for removal, not a keepsake. ## How do you know if your team has alert fatigue? Watch for these signals: pages routinely acknowledged in under ten seconds (nobody reads that fast), recurring alerts with no linked follow-up work, on-call handoff notes that say "you can ignore X," and engineers negotiating to avoid rotations. A useful metric is the actionable-alert rate—the fraction of pages that led to real action. Healthy teams push this well above half; fatigued teams often sit below one in ten. ## Related terms * [What Is Incident Triage?](/glossary/incident-triage) * [What Is MTTR?](/glossary/mttr) * [What Is Incident Management?](/glossary/incident-management) Browse all definitions in the [incident management glossary](/glossary). # What Is an Error Budget? Source: https://docs.rootly.com/glossary/error-budget An error budget is the amount of unreliability an SLO allows — 100% minus the SLO target. How to calculate it, track burn rate, and set error budget policies. An error budget is the amount of unreliability a service is allowed before it violates its service level objective (SLO). It equals 100% minus the SLO target: a service with a 99.9% availability SLO has a 0.1% error budget. The budget can be "spent" on incidents, risky deploys, and planned maintenance — and when it runs out, the team shifts focus from shipping features to restoring reliability. ## How do you calculate an error budget? ```text theme={null} Error budget = 100% − SLO target ``` Applied to a time window, the percentage converts into concrete minutes of allowed downtime (or a count of allowed bad requests, for request-based SLOs). ### Worked example A service has a 99.9% availability SLO measured over a 30-day window. * Error budget = 100% − 99.9% = 0.1% * Minutes in 30 days = 30 × 24 × 60 = 43,200 * Budget in minutes = 43,200 × 0.001 = **43.2 minutes** (about 43 minutes 12 seconds per month; often rounded to \~43.8 minutes when quoted per average calendar month of 30.44 days) If the service has already had a 20-minute outage this window, roughly 23 minutes of budget remain. A second incident of similar size would nearly exhaust it. For a request-based SLO the same logic applies to counts: at 99.9% success over 10 million monthly requests, the budget is 10,000 failed requests. ## What is burn rate? Burn rate measures how fast you are consuming the budget relative to the pace that would exactly exhaust it at the end of the window: ```text theme={null} Burn rate = Actual error rate / Allowed error rate ``` A burn rate of 1 means you will land exactly on budget. A burn rate of 14.4 against a 30-day, 99.9% SLO means the entire month's budget will be gone in about 50 hours. Burn rate is the basis for modern SLO alerting. Instead of paging on raw error percentages, teams page on fast burn (for example, a high burn rate sustained for an hour — something is actively wrong) and ticket on slow burn (a modest burn rate sustained for days — reliability is quietly eroding). This keeps pages tied to real budget impact rather than momentary blips. ## What is an error budget policy? An error budget policy is a pre-agreed document that says what happens as the budget depletes. Deciding this in advance — before anyone is angry — is the whole point. A typical policy might look like: | Budget remaining | Action | | ---------------- | ----------------------------------------------------------------------------------------------- | | > 50% | Ship normally; budget may be spent on risky launches and experiments | | 10–50% | Heightened review for risky changes; prioritize reliability action items | | Exhausted | Feature freeze on the service; engineering effort goes to reliability until the budget recovers | The policy is a contract between product and engineering. Product gets a guarantee that reliability work won't be invoked arbitrarily to block launches; engineering gets an objective trigger for prioritizing stability that doesn't depend on winning an argument. ## How do error budgets relate to SLOs? An error budget is simply an SLO viewed from the other side. The SLO states the reliability floor ("99.9% of requests succeed"); the error budget states the failure allowance that floor implies ("0.1% may fail"). This reframing does two useful things: 1. **It makes reliability spendable.** Instead of treating every incident as a moral failure, teams treat downtime as a resource: spend it on velocity when the budget is healthy, conserve it when it isn't. 2. **It acknowledges that 100% is the wrong target.** Users cannot tell the difference between 99.999% and 100%, but the engineering cost of chasing the last fraction is enormous. The budget makes that trade-off explicit. Error budgets only work when the underlying SLO is measured from a well-chosen SLI and set at a level users actually need — see [SLA vs SLO vs SLI](/glossary/sla-vs-slo-vs-sli) for how the three fit together. Rootly's incident data feeds budget tracking naturally: incident duration and severity metrics (see [default metrics](/metrics/default-metrics)) show exactly which incidents consumed the budget and where reliability effort should go next. ## Related terms * [SLA vs SLO vs SLI](/glossary/sla-vs-slo-vs-sli) * [MTBF (mean time between failures)](/glossary/mtbf) * [MTTR (mean time to resolution)](/glossary/mttr) Browse the full [incident management glossary](/glossary). # What Is Incident Management? Source: https://docs.rootly.com/glossary/incident-management Incident management is the practice of detecting, responding to, resolving, and learning from unplanned service disruptions. Lifecycle, roles, and tooling. **Incident management** is the end-to-end practice of detecting, responding to, resolving, and learning from unplanned disruptions to a service. It covers everything from the alert that wakes an engineer up to the retrospective that prevents the same failure from happening again. The goal is not to eliminate incidents—complex systems will always fail—but to make each failure shorter, less damaging, and more instructive than the last. ## What counts as an incident? An incident is any unplanned event that degrades a service or puts it at risk. That includes obvious outages, but also partial failures that only some users notice: * A checkout API returning errors for 5% of requests * A background job queue silently backing up for hours * A certificate expiring on an internal service * A security event, such as leaked credentials If customers are affected—or could be soon—it's an incident. Teams that only declare incidents for full outages tend to under-count, which hides real reliability problems from leadership and from their own metrics. ## What are the stages of the incident lifecycle? Most incidents move through the same broad stages, even when the details differ: 1. **Detection.** Monitoring fires an alert, or a customer reports a problem. Faster detection means everything downstream starts sooner. 2. **Declaration and triage.** Someone confirms the problem is real, declares an incident, and assigns a severity so the response is proportional to the impact. 3. **Response.** Responders assemble, investigate, and communicate. Roles are assigned, hypotheses are tested, and stakeholders get regular updates. 4. **Mitigation and resolution.** The team stops the bleeding first—often with a rollback or failover—then restores full service. 5. **Learning.** A retrospective (or postmortem) examines what happened, why, and what should change. Action items are tracked to completion. The lifecycle is a loop, not a line: what a team learns in stage five should improve detection, triage, and response for the next incident. ## Why does incident management matter? Downtime has a direct cost—lost revenue, missed SLAs, churned customers—but the indirect costs are often larger. Engineers pulled into a chaotic, unstructured scramble lose focus for days. Repeated incidents with no follow-through erode trust between teams and burn out on-call staff. Consider a mid-size SaaS company whose payments service fails at 2 a.m. Without a process, the on-call engineer spends 40 minutes figuring out who owns the database, another 20 finding someone with production access, and nobody updates customers until support tickets pile up in the morning. With a working incident management practice, the same failure pages the right person immediately, a severity is assigned within minutes, a status page update goes out, and the retrospective the next week produces a fix for the connection-pool bug that caused it. The failure is identical; the outcome is not. ## What are the key roles in incident management? Structured teams assign explicit roles during an incident rather than letting everyone do everything: * **Incident commander** — owns the response process, coordinates people, and drives decisions * **Technical lead (or ops lead)** — leads the hands-on investigation and mitigation * **Communications lead** — keeps stakeholders and customers informed so engineers can focus * **Scribe** — records the timeline, decisions, and actions for the retrospective On small teams one person may wear several hats, but naming the roles still matters: it makes handoffs and gaps visible. Rootly lets you define and assign these as [incident roles](/incidents/incident-roles/incident-roles) when an incident is declared. ## What tooling does incident management involve? No single tool covers the whole lifecycle. A typical stack includes: * **Monitoring and observability** — metrics, logs, and traces that detect problems * **Alerting and on-call** — paging, escalation policies, and schedules that reach the right human * **Incident response platforms** — tooling that declares incidents, spins up channels, assigns roles, and tracks timelines * **Status pages** — external and internal communication during an incident * **Retrospective and action-item tracking** — turning incidents into lasting improvements The connective tissue matters as much as any single layer: an alert that never becomes a declared incident, or a retrospective action item that never ships, is where most incident management programs quietly fail. ## Related terms * [What Is Incident Response?](/glossary/incident-response) * [What Are SEV Levels?](/glossary/sev-levels) * [What Is MTTR?](/glossary/mttr) Browse all definitions in the [incident management glossary](/glossary). # What Is Incident Response? Source: https://docs.rootly.com/glossary/incident-response Incident response is the active work of handling an incident as it happens—mobilizing responders, investigating, mitigating, and communicating until resolved. **Incident response** is the active, real-time work of handling an incident while it is happening: assembling the right people, diagnosing the problem, mitigating the impact, and communicating with stakeholders until service is restored. Where incident management describes the whole discipline—including prevention, tooling, and learning—incident response is the part that happens under pressure, between the moment an incident is declared and the moment it is resolved. ## How is incident response different from incident management? The two terms are often used interchangeably, but the distinction is useful: * **Incident response** is the *doing*: the live effort during an incident. It starts when an incident is declared and ends when it is resolved. * **Incident management** is the *whole discipline*: the processes, roles, tooling, metrics, and learning loops that surround response. It includes what happens before an incident (on-call schedules, runbooks, severity definitions) and after (retrospectives, action items, trend analysis). A team can have excellent responders and still have weak incident management—heroic, reactive response with no follow-through. The reverse is also possible: beautiful process documents that fall apart the first time something actually breaks. Strong organizations invest in both. ## What are the phases of incident response? Once an incident is declared, response typically moves through four phases: 1. **Mobilize.** Page the right responders, open a dedicated channel, and assign roles. The first few minutes set the tone—an [incident commander](/concepts/incident-commander) taking charge early prevents the "everyone watching, nobody driving" failure mode. 2. **Assess.** Establish what is broken, who is affected, and how badly. Assign or confirm a severity. Resist the urge to jump straight to fixes before anyone understands the scope of impact. 3. **Mitigate.** Stop the customer impact first, even if the fix is temporary—roll back the deploy, fail over to a replica, disable the feature flag. Root-cause analysis can wait; bleeding cannot. 4. **Resolve and hand off.** Restore full service, confirm with monitoring (not just a hopeful "looks fine"), communicate the all-clear, and capture the timeline for the retrospective. ## What does good incident response look like in practice? Imagine a deploy at 4:50 p.m. on a Friday starts returning 500s on the login endpoint. Within two minutes, an alert pages the on-call engineer, who declares an incident. A channel is created automatically, the incident commander role is claimed, and a second responder joins to check the deploy history. By minute ten, the team has rolled back and error rates return to baseline. A communications update goes out at minute twelve, and the incident is resolved with a full timeline already recorded. Nothing about this requires genius—only preparation: alerting that works, a clear declaration path, and roles people already understand. ## What are incident response best practices? Patterns that consistently separate calm responses from chaotic ones: * **Declare early and often.** A false alarm costs minutes; a late declaration costs hours. Make declaring an incident cheap and blameless. * **Assign a single incident commander.** One person owns the process so everyone else can investigate. * **Mitigate before you diagnose.** Prefer the fastest safe path to reducing impact, then investigate at leisure. * **Communicate on a cadence.** Post updates at predictable intervals—even "no new information" beats silence for stakeholders. * **Keep the timeline as you go.** Reconstructing events after the fact is lossy; capturing decisions in the moment makes the retrospective honest. * **Separate the fix from the follow-up.** Ship the mitigation now; file the durable fix as a tracked action item. ## Who is involved in incident response? The core responders are usually the on-call engineer for the affected service plus anyone they escalate to. Around them sit the structured roles—commander, communications lead, scribe—and, for severe incidents, stakeholders such as support leads or executives who consume updates but stay out of the technical channel. The response team should be as small as possible while still covering the needed expertise: every extra person in the room adds coordination cost. ## Related terms * [What Is Incident Management?](/glossary/incident-management) * [What Is Incident Triage?](/glossary/incident-triage) * [What Is a Runbook?](/glossary/runbook) Browse all definitions in the [incident management glossary](/glossary). # What Is Incident Triage? Source: https://docs.rootly.com/glossary/incident-triage Incident triage is the rapid assessment of a new incident—its impact, urgency, and scope—to assign a severity and get the right response started fast. **Incident triage** is the rapid initial assessment of a newly reported problem: how bad is it, how urgent is it, and how wide does it reach? The output of triage is a severity assignment and a decision about who responds and how fast. Done well, it takes minutes and ensures a proportional response—major failures get immediate mobilization, minor ones don't wake anyone up. ## Where does the term come from? Triage is borrowed from emergency medicine, where clinicians sort incoming patients by urgency rather than arrival order—treating the critical case first even if someone else has been waiting longer. The insight transfers directly to operations: response capacity is finite, and the order in which you spend it matters more than raw speed. A team that handles alerts strictly first-in-first-out will inevitably burn its best responders on trivia while something serious waits in the queue. ## What questions does triage answer? Effective triage runs through a short, consistent set of questions: * **Impact: what is actually broken?** Is functionality degraded or fully down? Is data at risk? Is revenue affected? Distinguish "the dashboard looks weird" from "customers cannot pay us." * **Urgency: is it getting worse?** A slow memory leak and a cascading failure both matter, but on very different clocks. Urgency determines whether the response starts now or at 9 a.m. * **Scope: who is affected?** All customers or one? A single region or every region? Internal tooling or customer-facing paths? Scope is the difference between a SEV3 and a SEV1 for the same symptom. * **Certainty: what do we actually know?** Is this confirmed by monitoring, or a single unverified report? Triage with low certainty should err toward investigating quickly rather than mobilizing everyone. The questions deliberately avoid *why is it broken*—root cause is a response activity, not a triage one. Trying to diagnose during triage delays the mobilization the diagnosis needs. ## How does severity assignment work? Triage concludes by mapping the answers onto the organization's severity scale—typically SEV1 (critical) through SEV4 or SEV5 (minor). The severity then drives everything mechanical: who gets paged, whether a dedicated incident channel opens, how often stakeholders get updates, and whether a retrospective is required. This is why severity definitions need to be written down and unambiguous; triage under pressure is exactly the wrong time to debate what "major impact" means. Rootly lets you define these levels—with descriptions and notification behavior—under [severities](/configuration/severities), so the person triaging picks from a shared menu instead of inventing a judgment call. Two rules keep severity assignment healthy: * **When unsure, round up.** Downgrading an over-called SEV2 costs a few apologetic messages; upgrading an under-called one costs response time you never get back. * **Severity is provisional.** Re-triage as facts arrive. An incident that looked contained at declaration can and should be upgraded the moment scope grows. ## Who does the triage? In most organizations, the first responder triages—usually the on-call engineer who received the alert, since waiting for a designated triager adds latency exactly where it hurts most. Larger organizations sometimes add a dedicated first-line rotation that triages everything and escalates to service owners. Whoever does it needs two things: authority to assign a severity without asking permission, and written severity definitions so their 3 a.m. judgment matches the team's daytime intent. ## What does triage look like in practice? An on-call engineer is paged at 22:40: elevated error rates on the file-upload service. In four minutes she establishes: uploads are failing for roughly 30% of requests (impact: partial degradation of one feature), the rate has been flat for 20 minutes (urgency: not cascading), it affects all regions but only the upload path (scope: broad but narrow), and it's confirmed by two independent monitors (certainty: high). She assigns SEV2—significant customer impact, not a full outage—which pages the storage team's on-call and opens an incident channel, but doesn't trigger the executive-notification workflow a SEV1 would. Total time from page to proportional response: about five minutes, and nobody was over- or under-mobilized. ## Related terms * [What Are SEV Levels?](/glossary/sev-levels) * [Severity vs Priority](/glossary/severity-vs-priority) * [What Is Alert Fatigue?](/glossary/alert-fatigue) Browse all definitions in the [incident management glossary](/glossary). # Incident vs Problem: What's the Difference? Source: https://docs.rootly.com/glossary/incident-vs-problem An incident is an unplanned disruption you fix now; a problem is the underlying cause you investigate to stop recurrence. ITIL treats them separately. An incident is an unplanned interruption or degradation of a service — something is broken for users right now, and the goal is to restore service fast. A problem is the underlying cause (or potential cause) of one or more incidents — the goal is to diagnose it and prevent recurrence. In ITIL terms, incident management optimizes for speed of restoration; problem management optimizes for permanent elimination. One incident can surface a problem, and one problem can spawn many incidents. ## Comparison at a glance | Dimension | Incident | Problem | | -------------- | ------------------------------------------------ | ----------------------------------------- | | Definition | Unplanned service interruption or degradation | Underlying cause of one or more incidents | | Goal | Restore service as fast as possible | Find root cause and prevent recurrence | | Time horizon | Minutes to hours | Days to weeks | | Acceptable fix | Workaround is fine (restart, rollback, failover) | Permanent fix or documented known error | | Success metric | MTTR, user impact minimized | Incident recurrence eliminated or reduced | | Typical owner | On-call responder / incident commander | Service owner / problem manager | ## What is incident management? Incident management is the reactive discipline: detect the disruption, mobilize responders, mitigate impact, and restore normal service. Speed dominates every decision — a restart that buys stability is a perfectly good incident resolution even if nobody yet knows why the service crashed. Incidents are closed when users are no longer affected, not when the cause is understood. ## What is problem management? Problem management is the investigative discipline that picks up where incidents leave off. It asks why the disruption happened and what will stop it happening again. Its outputs are root cause analyses, permanent fixes, and **known error records** — documented causes with proven workarounds that make the *next* incident faster to resolve even before the permanent fix ships. Problem management can also be proactive: analyzing incident trends or vendor advisories to remove causes before they ever produce an incident. ## Can an incident exist without a problem? Yes. A one-off disruption with a fully understood, already-remediated cause — say, a bad config push that was rolled back and now has a validation check preventing recurrence — needs no separate problem record. Problems earn their overhead when the cause is unknown, the fix is nontrivial, or the incident keeps coming back. Likewise, a problem can exist without any incident: if a vendor discloses a defect in a library you run, you can open a problem and fix it proactively before it bites. ## Worked example Over three weeks, a team logs four incidents: the checkout service runs out of memory and restarts, each time causing 5–10 minutes of failed payments. Each incident is resolved the same way — the on-call engineer restarts the pods and confirms recovery. MTTR is good; users barely notice. But the fourth recurrence makes the pattern undeniable, so the team opens a problem record. The problem investigation takes eight days: a heap analysis reveals a slow memory leak in a session-caching library introduced in a March upgrade. The team documents the known error ("leak in cache library ≥ v4.2; workaround: rolling restart") so any future incident resolves in two minutes instead of ten, then ships the permanent fix — pinning the patched library version and adding a memory-growth alert. The four incidents were each resolved in minutes; the problem took over a week — and eliminated the entire incident class. ## Why keep them as separate processes? Because their incentives conflict. Incident response rewards the fastest path to restoration, which is usually a workaround; root-causing during an outage prolongs user pain. Problem investigation rewards depth and patience, which you can't have at 3 a.m. with revenue burning. Merging them either slows your incident response ("don't close it until we know the root cause") or guts your investigations ("it's back up, move on"). Link them instead: incidents reference the problems they revealed, and problems track the incidents they caused. ## How this works in Rootly Rootly tracks each incident as a structured record with a timeline, severity, and linked follow-up actions, so recurring incidents and their underlying causes stay connected. See [Incident Management](/incidents/incidents). ## Related terms * [Retrospective vs Postmortem](/glossary/retrospective-vs-postmortem) * [Incident Severity vs Priority](/glossary/severity-vs-priority) * [Runbook vs Playbook](/glossary/runbook-vs-playbook) * Browse the full [Incident Management Glossary](/glossary) # What Is MTBF? Mean Time Between Failures Explained Source: https://docs.rootly.com/glossary/mtbf MTBF (mean time between failures) is the average operating time between failures. Formula, examples, and how it relates to MTTR and availability. MTBF stands for mean time between failures: the average operating time a system runs between one failure and the next. It is calculated by dividing total uptime by the number of failures over a period. Where MTTR measures how fast you recover from incidents, MTBF measures how often they happen — together they determine a system's availability. ## How do you calculate MTBF? ```text theme={null} MTBF = Total operating (up) time / Number of failures ``` Only count time the system was actually running: downtime spent repairing a failure belongs to MTTR, not MTBF. The metric originated in hardware reliability engineering, where it described physical components; in software operations it is usually applied per service, counting incidents or outages as "failures." ### Worked example A service is observed for a 30-day month (43,200 minutes) and fails three times, with outages of 60, 30, and 90 minutes. Total downtime = 60 + 30 + 90 = 180 minutes. Total uptime = 43,200 − 180 = 43,020 minutes. MTBF = 43,020 / 3 = **14,340 minutes**, or roughly 9.96 days between failures. For the same period, MTTR = 180 / 3 = 60 minutes. ## What is the difference between MTBF and MTTR? MTBF and [MTTR](/glossary/mttr) answer complementary questions: * **MTBF: how often do we break?** Improving it means preventing failures — better testing, safer deploys, redundancy, capacity planning, and fixing the root causes surfaced in retrospectives. * **MTTR: how fast do we fix it?** Improving it means recovering faster — better detection, paging, runbooks, and rollback. A high MTBF with a terrible MTTR describes a system that rarely fails but is catastrophic when it does. A low MTBF with an excellent MTTR describes a system that fails constantly but self-heals quickly. Neither number alone tells you whether users are having a good time — for that you combine them. Modern reliability thinking (popularized by the DORA research and the SRE community) tends to prioritize reducing MTTR over maximizing MTBF: failures are inevitable in complex systems, and teams that recover in minutes can ship faster than teams that try to prevent every failure. But MTBF still matters — if the same service fails every week, no amount of fast recovery makes that acceptable. ## How do MTBF and MTTR determine availability? Availability is the fraction of time a system is up, and it falls directly out of the two metrics: ```text theme={null} Availability = MTBF / (MTBF + MTTR) ``` Intuitively: each failure cycle consists of MTBF minutes of uptime followed by MTTR minutes of repair, so availability is uptime's share of the whole cycle. Using the worked example above: | Metric | Value | | ------------ | ----------------------------------------------------- | | MTBF | 14,340 minutes | | MTTR | 60 minutes | | Availability | 14,340 / (14,340 + 60) = 14,340 / 14,400 = **99.58%** | The formula also shows two routes to any availability target. To reach 99.9%, you can make failures rarer (raise MTBF) or make recovery faster (cut MTTR). Halving MTTR from 60 to 30 minutes in the example lifts availability to 99.79% — the same effect as roughly doubling MTBF, and often far cheaper to achieve. ## How should you use MTBF in practice? * **Segment by service and severity.** A fleet-wide MTBF blends critical and trivial services into a meaningless average. * **Watch the trend, not the absolute.** A declining MTBF for a specific service is an early warning of accumulating tech debt or scaling limits. * **Pair it with an [error budget](/glossary/error-budget).** MTBF and MTTR describe past reliability; an error budget turns an availability target into a forward-looking spending allowance. * **Feed it back into planning.** Services with the worst MTBF are the strongest candidates for reliability investment in the next quarter. Rootly derives failure frequency and duration metrics automatically from your incident data — see [default metrics](/metrics/default-metrics) for the available measures and groupings. ## Related terms * [MTTR (mean time to resolution)](/glossary/mttr) * [Error budget](/glossary/error-budget) * [SLA vs SLO vs SLI](/glossary/sla-vs-slo-vs-sli) Browse the full [incident management glossary](/glossary). # What Is MTTA? Mean Time to Acknowledge Explained Source: https://docs.rootly.com/glossary/mtta MTTA (mean time to acknowledge) is the average time between an alert firing and a responder acknowledging it. Formula, examples, and how to improve it. MTTA stands for mean time to acknowledge: the average time between an alert being created and a responder acknowledging that they are handling it. It is calculated by dividing the total time-to-acknowledgment across a set of alerts or incidents by their count. MTTA measures how quickly a team reacts to problems, making it the standard health check for paging, on-call, and escalation systems. ## How do you calculate MTTA? ```text theme={null} MTTA = Total time from alert to acknowledgment / Number of alerts ``` The clock starts when the alert or incident is created and stops when a human acknowledges it — typically by tapping "acknowledge" in a paging app, claiming the incident in Slack, or otherwise signaling "I've got this." Acknowledgment is not resolution; it just means someone is on it. ### Worked example An on-call team receives five pages in a week: * Alert 1: acknowledged after 2 minutes * Alert 2: acknowledged after 4 minutes * Alert 3: acknowledged after 1 minute * Alert 4: acknowledged after 15 minutes (escalated to a secondary responder) * Alert 5: acknowledged after 3 minutes Total = 2 + 4 + 1 + 15 + 3 = 25 minutes. MTTA = 25 / 5 = **5 minutes**. Notice how one missed page (alert 4) doubles the average. That sensitivity is a feature: MTTA surfaces escalation problems that a median would smooth over. Tracking both, plus the count of alerts that escalated past the primary on-call, gives the fullest picture. ## Why does MTTA matter? MTTA is a direct read on the health of your paging and escalation setup. Everything it measures happens before anyone has debugged anything, so a bad MTTA almost always points to a process or tooling problem rather than a hard technical one: * **Notification rules.** Are pages reaching people on channels they actually notice, with sensible retry behavior? * **Escalation policies.** When the primary doesn't respond, how quickly does the page move to the next person? Long escalation timeouts inflate MTTA on every missed page. * **Alert quality.** Teams drowning in noisy, non-actionable alerts start ignoring pages. A creeping MTTA is often the first measurable symptom of alert fatigue. * **Schedule coverage.** Gaps or misconfigured handoffs in on-call schedules show up as outlier acknowledgment times at specific hours. MTTA is also the first segment of [MTTR](/glossary/mttr): every minute an alert sits unacknowledged is a minute added to total resolution time before diagnosis even begins. ## What is a good MTTA? For urgent, page-worthy alerts, most teams aim for acknowledgment within a few minutes — fast enough that escalation to a backup responder rarely triggers. But the right target depends on alert urgency (a low-priority ticket queue doesn't need a 5-minute acknowledgment), business hours versus overnight coverage, and whether your escalation timeouts are 5 minutes or 30. Set targets per urgency level, and judge yourself against your own trend rather than someone else's benchmark. ## How do you improve MTTA? | Lever | What it fixes | | ---------------------------------------- | ---------------------------------------------------- | | Multi-channel notifications with retries | Pages that go unseen | | Tighter escalation timeouts | Long waits before a backup is paged | | Alert deduplication and grouping | Noise that trains responders to ignore pages | | Urgency-based routing | Waking people for non-urgent issues (and vice versa) | | Fair, well-staffed rotations | Burned-out responders who respond slowly | Start by cutting noise: acknowledgment speed improves almost automatically when every page is real and actionable. Then tune escalation timeouts so a missed page costs minutes, not half an hour. Finally, review outliers — the handful of slowest acknowledgments each month usually share a root cause, like a schedule gap or a responder whose phone silences notifications overnight. Rootly tracks MTTA per alert, per service, and per on-call shift out of the box — see [on-call metrics](/on-call/on-call-metrics) for the available breakdowns. ## Related terms * [MTTA vs MTTR](/glossary/mtta-vs-mttr) * [MTTR (mean time to resolution)](/glossary/mttr) * [Error budget](/glossary/error-budget) Browse the full [incident management glossary](/glossary). # MTTA vs MTTR: What's the Difference? Source: https://docs.rootly.com/glossary/mtta-vs-mttr MTTA measures how fast a responder acknowledges an alert; MTTR measures how fast the team restores service. Learn the formulas and how they work together. MTTA (mean time to acknowledge) measures how long it takes a responder to acknowledge an alert after it fires. MTTR (mean time to resolve) measures how long it takes to fully restore service after an incident begins. MTTA captures the speed of your paging and on-call process; MTTR captures the effectiveness of your entire response, from detection through fix. Both are averages calculated across incidents over a period. ## Comparison at a glance | Dimension | MTTA | MTTR | | ---------------- | ------------------------------------------------------- | ----------------------------------------------- | | Full form | Mean time to acknowledge | Mean time to resolve (also repair or recovery) | | What it measures | Alert fired → responder acknowledges | Incident start → service restored | | What it reflects | On-call health: paging, escalation, alert quality | End-to-end response: diagnosis, mitigation, fix | | Typical scale | Minutes | Minutes to hours | | Formula | Total time to acknowledge ÷ number of alerts | Total time to resolve ÷ number of incidents | | Improved by | Better routing, escalation policies, less alert fatigue | Runbooks, better tooling, architecture changes | ## What is MTTA? MTTA is the average time between an alert firing and a human acknowledging it. The formula: **MTTA = (sum of time-to-acknowledge across all alerts) ÷ (number of alerts)** If your team acknowledged 40 alerts this month and the acknowledgment times sum to 120 minutes, MTTA is 3 minutes. A rising MTTA usually points to problems upstream of the actual fix: alerts routed to the wrong team, escalation policies with gaps, notification channels people ignore, or plain alert fatigue from too many low-value pages. MTTA is the clearest single signal of whether your on-call setup is working. ## What is MTTR? MTTR is the average time from the start of an incident to full resolution: **MTTR = (sum of time-to-resolve across all incidents) ÷ (number of incidents)** If you had 5 incidents this quarter totaling 10 hours of downtime, MTTR is 2 hours. MTTR spans everything: detection, acknowledgment, triage, diagnosis, mitigation, and verification. That breadth makes it a useful executive-level indicator of reliability, but a blunt diagnostic tool — a bad MTTR tells you something is slow without telling you what. ## What does the R in MTTR actually stand for? MTTR's "full form" is genuinely ambiguous, and the ambiguity matters when comparing numbers across teams: * **Mean time to resolve** — through full resolution, including any follow-up work. The most common meaning in incident management. * **Mean time to recovery (or restore)** — until service is back for users, even if a permanent fix comes later. Used by DORA metrics ("time to restore service"). * **Mean time to repair** — a hardware and manufacturing term for the time to physically fix a failed component. Before you benchmark against another team's MTTR or set a target, agree on which definition your clock stops at. A team measuring "recovery" (mitigation) will always look faster than a team measuring "resolution" (permanent fix), even with identical performance. ## When should you track MTTA vs MTTR? Track both — they answer different questions. Use MTTA to tune the front of your pipeline: if MTTA is high, fix routing, escalation, and alert noise before touching anything else, because nobody can resolve an incident they haven't seen. Use MTTR to evaluate the whole response system and to spot trends after process changes, such as adopting runbooks or adding automation. If MTTA is low but MTTR is high, your paging works and your bottleneck is diagnosis or remediation. ## Worked example A payment API starts throwing errors at 14:00. The monitor fires at 14:02, and the on-call engineer acknowledges the page at 14:06. She identifies a bad deploy, rolls it back, and the service is confirmed healthy at 14:50. * Time to acknowledge: 14:02 → 14:06 = **4 minutes** (contributes to MTTA) * Time to resolve: 14:02 → 14:50 = **48 minutes** (contributes to MTTR) If the previous month's incidents averaged 6 minutes to acknowledge and 70 minutes to resolve, this incident improves both averages. Notice that only 4 of the 48 minutes were acknowledgment — here, shaving MTTA further buys little, while faster rollback tooling would cut MTTR meaningfully. ## How this works in Rootly Rootly calculates MTTA and MTTR automatically from alert and incident timestamps, with a pre-built dashboard you can slice by team, service, and severity. See [On-Call Metrics](/on-call/on-call-metrics). ## Related terms * [SLA vs SLO vs SLI](/glossary/sla-vs-slo-vs-sli) * [Incident Severity vs Priority](/glossary/severity-vs-priority) * [Runbook vs Playbook](/glossary/runbook-vs-playbook) * Browse the full [Incident Management Glossary](/glossary) # What Is MTTR? Mean Time to Resolution Explained Source: https://docs.rootly.com/glossary/mttr MTTR (mean time to resolution) is the average time from when an incident starts to when it is fully resolved. Formula, examples, and how to improve it. MTTR stands for mean time to resolution: the average time it takes to fully resolve an incident, measured from the moment the incident begins to the moment service is restored and the fix is complete. It is calculated by dividing total resolution time across a set of incidents by the number of incidents. MTTR is the most widely used measure of how quickly a team recovers from failure. ## What does MTTR stand for? The "R" in MTTR is ambiguous, and the four common expansions measure genuinely different things. When someone quotes an MTTR number, always confirm which definition they mean — comparing "time to respond" against "time to resolution" makes a team look either heroic or terrible for no reason. | Expansion | What it measures | Clock stops when... | | --------------------------- | ------------------------------ | ------------------------------------------------------ | | Mean time to **resolution** | Full incident lifecycle | The incident is fully resolved, including any cleanup | | Mean time to **repair** | Fixing the failed component | The repair itself is complete | | Mean time to **recovery** | Restoring service to users | Users can use the service again, even via a workaround | | Mean time to **respond** | Reaction speed after detection | A responder begins actively working the incident | Mean time to recovery and mean time to repair often differ: rolling back a bad deploy restores service in minutes (recovery) even if the underlying bug takes days to fix (repair). Mean time to respond is closer to [MTTA](/glossary/mtta) territory — it measures the front end of the incident, not the fix. ## How do you calculate MTTR? ```text theme={null} MTTR = Total resolution time across incidents / Number of incidents ``` Resolution time for each incident runs from the incident's start time (or detection time, depending on your convention — pick one and apply it consistently) to its resolved timestamp. ### Worked example A team handles four incidents in a month: * Incident 1: resolved in 45 minutes * Incident 2: resolved in 2 hours (120 minutes) * Incident 3: resolved in 30 minutes * Incident 4: resolved in 3 hours 25 minutes (205 minutes) Total resolution time = 45 + 120 + 30 + 205 = 400 minutes. MTTR = 400 / 4 = **100 minutes**, or 1 hour 40 minutes. Because it is a mean, one long-running incident can drag the number dramatically. Many teams track the median and the 90th percentile alongside MTTR, and segment by severity, so a single messy SEV1 doesn't hide steady improvement everywhere else. ## What is a good MTTR? There is no universal benchmark, and be skeptical of anyone selling one. A "good" MTTR depends on: * **Severity.** A SEV1 outage and a SEV4 cosmetic bug should never share a target. Most teams set per-severity goals. * **Industry and risk profile.** A payments platform tolerates far less downtime than an internal analytics tool. * **Architecture.** Systems designed for fast rollback and graceful degradation recover faster by construction. * **Definition.** Resolution, repair, recovery, and respond produce very different numbers for the same incidents. The most useful comparison is your own trend line: is MTTR for each severity level going down quarter over quarter? ## How do you reduce MTTR? MTTR compresses when you shorten each phase of the incident: 1. **Detect faster.** Better alerting and monitoring coverage means the clock starts closer to the actual failure. 2. **Acknowledge and mobilize faster.** Clear on-call schedules and escalation policies reduce the gap between alert and action — this is what [MTTA](/glossary/mtta) measures. 3. **Diagnose faster.** Runbooks, service catalogs, and searchable history of past incidents cut investigation time. 4. **Fix faster.** Practiced rollback procedures, feature flags, and automation beat improvising under pressure. 5. **Learn.** Retrospectives that produce completed action items prevent repeat incidents and make the next one shorter. Rootly computes MTTR automatically from incident timestamps, segmented by severity, service, and team — see [default metrics](/metrics/default-metrics) for how each duration is derived. ## Related terms * [MTTA vs MTTR](/glossary/mtta-vs-mttr) * [MTTA (mean time to acknowledge)](/glossary/mtta) * [MTBF (mean time between failures)](/glossary/mtbf) Browse the full [incident management glossary](/glossary). # Retrospective vs Postmortem: What's the Difference? Source: https://docs.rootly.com/glossary/retrospective-vs-postmortem A postmortem analyzes a specific incident after it ends; a retrospective reviews how a team works over time. In incident management the terms overlap. A postmortem is a structured analysis of a single incident after it's resolved: what happened, why, and what will prevent recurrence. A retrospective is traditionally a recurring team ritual — borrowed from agile — that reviews how the team worked over a period, incident or not. In incident management the two words now largely describe the same artifact, with "retrospective" increasingly preferred because "postmortem" implies death and blame, while the process should be about learning. ## Comparison at a glance | Dimension | Postmortem | Retrospective | | ------------------------- | --------------------------------------------- | --------------------------------------------- | | Origin | Medicine — examination after death | Agile — recurring sprint review | | Trigger | A specific incident ends | A cadence (sprint, month) or an incident | | Scope | One incident: timeline, causes, actions | Team practices, process, and outcomes broadly | | Tone risk | Can sound like an autopsy of a failure | Framed around continuous improvement | | Typical output | Written report + action items | Discussion notes + process changes | | In incident tooling today | Often used interchangeably with retrospective | Often used interchangeably with postmortem | ## What is an incident postmortem? A postmortem is the written record and review meeting produced after a significant incident. A complete one includes a timeline (detection through resolution), user and business impact, contributing causes, what went well and what didn't in the response itself, and concrete action items with owners and due dates. The gold standard is the **blameless postmortem**: the analysis assumes people acted reasonably given what they knew, and asks why the system made the failure possible — because responders who fear blame stop reporting honestly, and the organization stops learning. ## What is a retrospective? In its original agile sense, a retrospective is a recurring meeting where a team reflects on a recent period of work — what to keep, drop, and try — regardless of whether anything broke. In incident management, the term has been adopted for post-incident review specifically, as a deliberate rebranding: same timeline, same causal analysis, same action items, but a name that signals learning rather than autopsy. Some teams also run genuine periodic incident retrospectives — a monthly review of all incidents in aggregate to spot patterns no single postmortem reveals, like a rising share of deploy-triggered incidents. ## Does the name actually matter? More than you'd expect. The document is identical either way, but words set the tone of the meeting. "Postmortem" primes participants to explain a death; "retrospective" primes them to improve a process. Teams that struggle with defensive, finger-pointing reviews often find the rename a cheap, effective nudge — especially paired with explicit blameless ground rules. If your culture is already healthy, keep whichever term your team uses consistently; a shared vocabulary beats a fashionable one. ## Worked example A SEV2 takes checkout down for 38 minutes on Tuesday. On Thursday the team holds its incident review — call it a retrospective or a postmortem, the agenda is the same: 1. **Timeline:** alert at 09:14, acknowledged 09:17, root cause (expired TLS certificate on an internal service) identified 09:35, new cert deployed 09:52. 2. **Impact:** \~4,100 failed checkout attempts, roughly \$18,000 in delayed orders. 3. **Contributing causes:** certificate expiry monitoring covered public endpoints only; the renewal runbook referenced a decommissioned tool. 4. **What went well:** paging worked, the right responder was engaged within 3 minutes. 5. **Action items:** add internal endpoints to cert monitoring (owner: platform, due in 2 weeks); update the renewal runbook; automate renewal for internal certs (due next quarter). Then, at the end of the month, the team's periodic retrospective reviews all six incidents from the month and notices three involved expired credentials of some kind — elevating "credential lifecycle automation" from a one-off action item to a roadmap priority. The single-incident review and the periodic review answered different questions; healthy teams run both. ## When should you write one? Not every incident deserves a full review — a blanket rule produces rushed, low-value documents. A common policy: mandatory for SEV1 and SEV2, optional for lower severities unless the incident was novel, customer-visible, or surprising. The trigger worth honoring above all: whenever a responder says "that was weird," schedule the review. ## How this works in Rootly Rootly generates retrospectives from the incident's actual timeline and supports configurable, step-based retrospective processes per incident type. See [Retrospectives](/retrospectives/retrospectives). ## Related terms * [Incident vs Problem](/glossary/incident-vs-problem) * [Runbook vs Playbook](/glossary/runbook-vs-playbook) * [MTTA vs MTTR](/glossary/mtta-vs-mttr) * Browse the full [Incident Management Glossary](/glossary) # What Is a Runbook? Source: https://docs.rootly.com/glossary/runbook A runbook is a step-by-step operational guide for handling a specific task or failure scenario, written so any qualified responder can follow it under pressure. A **runbook** is a step-by-step operational guide for handling a specific task or failure scenario—restarting a service, failing over a database, rotating a certificate. It is written so that any qualified responder can execute it correctly under pressure, without needing the tribal knowledge of the person who wrote it. Good runbooks turn 3 a.m. panic into a checklist. ## What does a good runbook contain? A runbook is only as useful as it is followable at the worst possible moment. The strong ones share a structure: * **Trigger conditions.** When to use this runbook—the alert names, symptoms, or dashboards that point here. * **Preconditions and access.** What permissions, tools, or credentials the responder needs before starting, so step 4 isn't where they discover they lack production access. * **Numbered steps with exact commands.** Copy-pasteable commands, real hostnames or clear placeholders, and the expected output of each step so responders know whether it worked. * **Verification.** How to confirm the fix took—which metric should recover, which endpoint should return 200. * **Rollback and escalation.** What to do if a step fails, and who to page when the runbook runs out. * **Ownership and last-reviewed date.** A runbook nobody has touched in two years is a liability wearing the costume of an asset. The test is simple: could a competent engineer who has never touched this system follow it end to end? If a step says "restart the service the usual way," it fails the test. ## How is a runbook different from documentation? Documentation explains how a system works; a runbook tells you what to do right now. Architecture docs, API references, and design documents are optimized for understanding—they reward slow, careful reading. Runbooks are optimized for execution—they reward scanning, and they assume the reader is stressed, possibly half-asleep, and not in a mood to learn. A page that starts with three paragraphs of background on the caching layer is documentation; a page that starts with "Step 1: check whether the cache hit rate on this dashboard is below 60%" is a runbook. Teams need both, but mixing them produces something that serves neither purpose well. Closely related is the playbook—a broader response plan that may reference several runbooks. In Rootly, [playbooks](/configuration/playbooks) attach step-by-step guidance directly to matching incidents. The distinction is covered in [runbook vs playbook](/glossary/runbook-vs-playbook). ## What is the runbook automation spectrum? Runbooks evolve along a spectrum from human-executed to fully automated: 1. **Manual.** A human reads each step and performs it by hand. This is where every runbook starts, and it's where you learn whether the steps are actually correct. 2. **Semi-automated.** The tedious or error-prone steps become scripts or one-click actions, but a human still decides when to run them and reviews the results. Most operational runbooks should live here for a while—automation with human judgment at the decision points. 3. **Fully automated.** The system detects the condition and executes the remediation with no human in the loop—auto-scaling, automatic failover, self-healing restarts. At this point the runbook has effectively graduated into software, and it needs the same testing and review as any other production code. The spectrum is a maturity path, not a ranking: some procedures (say, anything involving irreversible data operations) should deliberately stay manual or semi-automated. The rule of thumb: automate a step only after it has been executed manually enough times that you trust it completely, and keep the human at every step where judgment beats speed. ## What does a runbook look like in practice? Consider a "primary database failover" runbook. It names the triggering alerts (`db-primary-unreachable`), lists required access (production SSH plus the `dba` role), then walks through: confirm the primary is truly down (with the exact health-check command and expected failure output), verify replica lag is under 10 seconds, run the promotion script, update the connection string, and watch the error-rate dashboard recover. It ends with an escalation line—"if replica lag exceeds 10 seconds, stop and page the DBA on-call"—that saves a responder from turning an outage into data loss. ## Related terms * [Runbook vs Playbook](/glossary/runbook-vs-playbook) * [What Is Incident Response?](/glossary/incident-response) * [What Is Alert Fatigue?](/glossary/alert-fatigue) Browse all definitions in the [incident management glossary](/glossary). # Runbook vs Playbook: What's the Difference? Source: https://docs.rootly.com/glossary/runbook-vs-playbook A runbook is a step-by-step procedure for one specific technical task; a playbook is a broader strategy for handling a whole class of situations. A runbook is a precise, step-by-step procedure for completing one specific technical task — restart this service, rotate this certificate, fail over this database. A playbook is a higher-level guide for navigating an entire class of situations — how to run a SEV1 response, how to handle a security incident — including roles, decision points, and communication. Runbooks tell you exactly what to type; playbooks tell you how to think and coordinate. ## Comparison at a glance | Dimension | Runbook | Playbook | | -------------------- | --------------------------------------------------- | ------------------------------------------------- | | Scope | One specific task or failure mode | A whole scenario or incident class | | Content | Ordered commands, checks, expected outputs | Roles, phases, decision trees, comms plans | | Level of judgment | Minimal — follow the steps | Significant — adapt to the situation | | Primary user | The engineer at the keyboard | The incident commander and responders | | Automation potential | High — often fully scriptable | Low — coordination resists automation | | Example | "Recover the payments queue after a poison message" | "Responding to a customer-data security incident" | ## What is a runbook? A runbook documents the exact procedure for a known task so that any qualified on-call engineer can execute it correctly under pressure, ideally without waking the one person who understands the system. A good runbook includes preconditions ("confirm replication lag is under 10 s before failing over"), numbered steps with exact commands, expected output at each step, and a clear abort path if something looks wrong. Because runbooks are deterministic, the best ones eventually become automation — a script or workflow — with the document remaining as the fallback and the explanation. ## What is a playbook? A playbook operates one level up. It doesn't assume you know what's broken; it guides you through a category of event. An incident response playbook typically covers who takes which role (commander, communications lead, scribe), what the phases are (detect, triage, mitigate, resolve, review), when to escalate, what to tell customers and when, and which decisions need which approvals. Playbooks contain branch points — "if customer data may be exposed, engage legal and switch to the security playbook" — because the situations they cover are too varied for a single linear script. ## Which one do you need? Both, at different layers. The playbook is the skeleton of your response; runbooks are the tools it reaches for. During an incident, the playbook tells the commander to assign a responder to mitigate database load — and the responder then opens the "enable read-replica overflow" runbook to actually do it. Teams that only write playbooks have great coordination and slow hands-on fixes; teams that only write runbooks execute known fixes fast but flail when the failure is novel or the incident spans teams. ## Worked example At 03:10 a checkout-latency alert fires and pages the on-call engineer. She acknowledges and, seeing sustained impact, declares a SEV2. The **SEV2 playbook** kicks in: it assigns her as interim incident commander, opens a dedicated channel, sets a 30-minute status-update cadence, and lists the first triage questions. Triage points to Redis memory exhaustion. She opens the **"Redis memory pressure" runbook**: step 1, confirm `used_memory` above 90%; step 2, identify the top key patterns; step 3, flush the sessions cache with the provided command; step 4, verify latency recovers within 5 minutes. Fix confirmed at 03:41. The playbook then directs the close-out: downgrade severity, post the final update, and schedule the retrospective. One incident, one playbook, one runbook — each doing a job the other couldn't. ## How do you keep them from going stale? Stale runbooks are worse than none, because responders trust them at the exact moment they can't verify them. Treat both documents as code: review them after every incident where they were used (the retrospective is the natural checkpoint), date-stamp them, assign an owner, and test runbooks during game days rather than discovering the commands changed during a real outage. ## How this works in Rootly Rootly playbooks attach task lists and procedures directly to incidents based on conditions like severity or affected service, so the right guidance surfaces automatically when an incident starts. See [Playbooks](/configuration/playbooks). ## Related terms * [Retrospective vs Postmortem](/glossary/retrospective-vs-postmortem) * [Incident Severity vs Priority](/glossary/severity-vs-priority) * [Incident vs Problem](/glossary/incident-vs-problem) * Browse the full [Incident Management Glossary](/glossary) # What Are SEV Levels? SEV1, SEV2, SEV3 Explained Source: https://docs.rootly.com/glossary/sev-levels SEV levels (SEV1, SEV2, SEV3...) classify incidents by severity of impact, driving who responds, how fast, and how the incident is communicated. **SEV levels** are a numbered scale for classifying incidents by the severity of their impact, with SEV1 conventionally the most critical and higher numbers progressively less serious. Assigning a SEV level at declaration sets the response in motion proportionally: it determines who gets paged, how quickly, whether leadership is notified, and how often updates go out. "SEV" is simply shorthand for "severity." ## Why do SEV levels exist? Without a shared scale, every incident starts with a negotiation: is this bad? Whom should I bother? SEV levels replace that negotiation with a lookup. Once an incident is labeled SEV1, nobody debates whether it deserves a dedicated incident channel or an executive update—the label carries the playbook with it. The scale also makes reporting possible: "we had three SEV1s this quarter, down from seven" is a meaningful sentence only if SEV1 means the same thing every time. The numbering convention runs opposite to intuition for newcomers: **lower number = worse incident**. A SEV1 is an emergency; a SEV5 is a note. ## What does a typical SEV scale look like? There is no universal standard—every organization tunes definitions, and many use only three or four levels. The following five-level scheme is a common starting point: | Level | Typical meaning | Example | Response expectation | | -------- | ------------------------------------------------------------------------------------ | ------------------------------------- | ---------------------------------------------------------------------------------------------------------- | | **SEV1** | Critical: full outage, data loss, or security breach affecting most or all customers | Payment processing down for all users | Immediate page, all-hands response, dedicated incident channel, exec notification, frequent public updates | | **SEV2** | Major: significant degradation or a core feature broken for many customers | Search failing for \~30% of requests | Immediate page to owning team, incident channel, regular stakeholder updates | | **SEV3** | Moderate: minor feature impaired, or a workaround exists; limited customer impact | Export-to-CSV broken; API works | Response during business hours, owned by one team, tracked to resolution | | **SEV4** | Low: cosmetic issues or negligible customer impact | Misaligned dashboard widget | Ticketed and prioritized in normal work; no paging | | **SEV5** | Informational: no impact, but worth recording | Near-miss caught by a canary deploy | Logged for trend analysis and learning | Two design choices matter more than the exact wording. First, definitions should be observable—"affects more than X% of customers," not "really bad"—so two responders reach the same answer. Second, each level must map to concrete response behavior; a severity that changes nothing about the response is just decoration. In Rootly, severity levels and their notification behavior are configured under [severities](/configuration/severities). ## How are SEV levels used during an incident? The initial SEV is assigned during triage, in the first minutes, using whatever is known at the time—and it is explicitly provisional. Teams should upgrade or downgrade freely as facts emerge, since scope frequently looks different twenty minutes in. Best practice when uncertain: round up. Over-calling a SEV2 costs some interrupted evenings; under-calling one costs response time during real customer impact. A realistic sequence: at 14:02 an engineer sees checkout errors in one region and declares a SEV2. At 14:15, monitoring shows the failure spreading to a second region and the error rate doubling—the commander upgrades to SEV1, which automatically pages additional responders and notifies leadership. At 14:40 a rollback contains the issue and impact drops to a single degraded feature; the incident is downgraded back to SEV2 for the remainder of the response. Each change re-tunes the machinery without anyone renegotiating from scratch. ## How do SEV levels differ from P-levels? Many teams also use P-levels (P1, P2, P3...), and the two scales are easy to conflate. Strictly speaking, **severity measures impact—how bad it is—while priority measures order—what gets worked on first.** They usually correlate but can diverge: a SEV3 bug with a contractual deadline might be P1 work, while a technically severe issue in a deprecated system might be deliberately low priority. In practice, plenty of organizations use "P1" and "SEV1" interchangeably for incidents; what matters is picking one scale for incident classification and defining it precisely. The distinction is unpacked further in [severity vs priority](/glossary/severity-vs-priority). ## Related terms * [Severity vs Priority](/glossary/severity-vs-priority) * [What Is Incident Triage?](/glossary/incident-triage) * [What Is Incident Management?](/glossary/incident-management) Browse all definitions in the [incident management glossary](/glossary). # Incident Severity vs Priority: What's the Difference? Source: https://docs.rootly.com/glossary/severity-vs-priority Severity measures how bad an incident's impact is; priority determines how urgently your team responds. They usually align — but not always. Severity describes the impact of an incident — how badly it degrades service and how many users it affects. Priority describes the urgency of the response — how quickly your team should act relative to everything else in flight. Severity is an assessment of the world; priority is a decision about your resources. They correlate strongly, but a low-severity issue can still be high priority, and vice versa. ## Comparison at a glance | Dimension | Severity | Priority | | ------------ | ---------------------------------------------------- | ------------------------------------------- | | Answers | "How bad is the impact?" | "How urgently do we act?" | | Based on | Scope of degradation, users affected, data risk | Business context, deadlines, who's affected | | Common scale | SEV1–SEV4 (or SEV0–SEV3) | P1–P4 | | Set by | Responder assessing the incident | Responder or leadership weighing trade-offs | | Drives | Escalation, paging, exec notification, comms cadence | Ordering of work and resource allocation | | Changes when | Impact grows or shrinks | Business context shifts | ## What is incident severity? Severity classifies impact on a fixed scale so everyone responds consistently. A typical scheme: * **SEV1** — critical: full outage or data loss risk; most users affected. * **SEV2** — major: significant degradation or a core feature down for many users. * **SEV3** — minor: partial degradation, workaround exists, limited user impact. * **SEV4** — low: cosmetic issues or minor bugs with negligible impact. Severity should be defined by observable criteria ("checkout error rate above 5%") rather than gut feel, because it triggers concrete machinery: who gets paged, whether executives are notified, how often status updates go out, and whether a retrospective is required. ## What is incident priority? Priority ranks the response against everything else your team could be doing. It folds in context that severity deliberately ignores: contractual deadlines, which customer is affected, regulatory exposure, upcoming launches, and what else is on fire. Two incidents of identical severity can carry different priorities — one affects a trial user on a Sunday night, the other affects your largest customer during their peak sales event. ## Can a low-severity incident be high priority? Yes, and this is exactly why the two dimensions exist separately. A typo in your pricing page is SEV4 by any impact rubric — nothing is down, no errors, no data at risk. But if it displays the wrong price and creates legal exposure, fixing it may be P1: drop other work and ship the correction now. Conversely, a SEV2 degradation in an internal batch system at 2 a.m. might be P3 — real impact, but nothing gained by waking anyone when it can be fixed at 9 a.m. ## Worked example Two incidents open on the same afternoon: 1. **Incident A:** search indexing lags 45 minutes behind. Impact is broad but shallow — every user sees slightly stale results. The team classifies it **SEV3**. No SLA covers search freshness and no revenue path is blocked, so it's **P3**: fix within the sprint. 2. **Incident B:** a single enterprise customer can't export compliance reports. Only one tenant is affected, so it's **SEV3** by the impact rubric. But that customer's regulatory filing is due in 48 hours and the contract includes support commitments — the team sets **P1** and assigns an engineer immediately. Same severity, opposite priorities. If the team had only one field to express both, they'd either inflate B's severity (breaking their paging and reporting rules) or under-respond to it. ## Should you track both fields? Smaller teams often start with severity alone and treat it as an implicit priority — for a five-person startup where every SEV1 is all-hands anyway, that's fine. Add a separate priority field once you regularly have multiple concurrent incidents, customer-specific commitments, or a support queue feeding engineering. The test: if you find yourself arguing "it's technically SEV3 but we should treat it like a SEV1," you need a priority field. ## How this works in Rootly Rootly ships with configurable severity levels that can drive escalations, notifications, and workflows automatically, and you can add a separate priority as a custom field. See [Severities](/configuration/severities). ## Related terms * [MTTA vs MTTR](/glossary/mtta-vs-mttr) * [SLA vs SLO vs SLI](/glossary/sla-vs-slo-vs-sli) * [Incident vs Problem](/glossary/incident-vs-problem) * Browse the full [Incident Management Glossary](/glossary) # SLA vs SLO vs SLI: What's the Difference? Source: https://docs.rootly.com/glossary/sla-vs-slo-vs-sli An SLI is a measurement, an SLO is your internal target for that measurement, and an SLA is the external contract with consequences. Here's how they stack. An SLI (service level indicator) is a measurement of service behavior, such as the percentage of requests served successfully. An SLO (service level objective) is the internal target you set for that measurement, such as 99.9% success over 30 days. An SLA (service level agreement) is the external contract that promises customers a level of service, with penalties if you miss it. SLIs feed SLOs, and SLOs are set stricter than SLAs. ## Comparison at a glance | Dimension | SLI | SLO | SLA | | ---------------------- | ---------------------------- | ----------------------------------------- | --------------------------------------- | | What it is | A measurement | An internal target | A customer contract | | Example | 99.92% of requests succeeded | ≥ 99.9% success over 30 days | 99.5% monthly uptime or service credits | | Audience | Engineers | Engineering and product teams | Customers and legal | | Consequence of missing | None — it's just data | Slow feature work, prioritize reliability | Refunds, credits, contractual penalties | | Who defines it | SRE / platform teams | Engineering with product | Sales, legal, and leadership | | Changes | Rarely (it's a definition) | Tuned as the service matures | Only via contract renegotiation | ## What is an SLI? An SLI is a quantitative measure of some aspect of service level — nothing more. Common SLIs include availability (successful requests ÷ total requests), latency (proportion of requests faster than a threshold), and freshness or durability for data systems. A good SLI is expressed as a ratio of good events to total events, because that maps directly to user experience. "CPU utilization" is a metric; "percentage of checkout requests completing under 500 ms" is an SLI. ## What is an SLO? An SLO attaches a target and a window to an SLI: "99.9% of checkout requests complete successfully, measured over a rolling 30 days." SLOs are internal commitments. Their real power is the **error budget** they imply — at 99.9% over 30 days, you can "spend" about 43 minutes of full downtime before breaching. While budget remains, teams ship freely; when it's exhausted, reliability work takes priority. That trade-off is the core mechanism SRE teams use to balance velocity against stability. ## What is an SLA? An SLA is a business agreement with customers, typically written by legal and sales rather than engineers. It specifies a service level (often looser than your SLO) and what happens when you miss it: service credits, refunds, or termination rights. Because breaching an SLA costs real money and trust, teams deliberately keep SLOs tighter than SLAs — the SLO acts as an early-warning line you cross internally before customers are affected contractually. ## Why should your SLO be stricter than your SLA? The gap between them is your safety margin. If your SLA promises 99.5% monthly uptime and your SLO targets 99.9%, an SLO breach triggers internal escalation while you still have roughly 3.2 hours of budget before the contractual line. Setting SLO equal to SLA means every internal miss is instantly a customer-facing breach, with no room to react. ## Worked example A B2B API team defines the stack like this: * **SLI:** proportion of API requests returning a non-5xx response within 300 ms. * **SLO:** 99.9% over a rolling 30-day window — an error budget of about 43 minutes. * **SLA:** 99.5% monthly, with a 10% service credit for any month below it. Mid-month, a bad migration causes 25 minutes of elevated errors. The SLI dips, consuming more than half the error budget. The SLO isn't breached yet, but the team freezes risky deploys for the rest of the window and prioritizes the migration fix. The SLA (which allows roughly 3.6 hours of downtime per month) is never in danger — which is exactly the point. The SLO absorbed the incident so the SLA didn't have to. ## Do you need all three? You always need SLIs and SLOs if you want to manage reliability deliberately — they cost nothing contractually and give teams a shared target. SLAs only make sense when customers demand contractual guarantees, which is common for paid B2B products and rare for internal services. Internal platform teams often run SLIs and SLOs alone, sometimes informally calling the SLO an "internal SLA." ## Related terms * [MTTA vs MTTR](/glossary/mtta-vs-mttr) * [Incident Severity vs Priority](/glossary/severity-vs-priority) * Browse the full [Incident Management Glossary](/glossary) In Rootly, incidents affecting SLO-backed services can be tracked against severity and service impact from creation onward. See [Incident Management](/incidents/incidents). # What Is an Incident Channel (aka War Room)? Source: https://docs.rootly.com/glossary/war-room An incident channel—often called a war room—is the dedicated space where responders coordinate a major incident, keeping the investigation in one place. An **incident channel**—widely known as a **war room**—is a dedicated space, physical or virtual, where responders coordinate during a major incident. It concentrates the people, context, and decisions in one place so the investigation moves as a single effort rather than a scatter of side conversations. Today it is almost always virtual: a dedicated chat channel plus a bridge call, spun up the moment a serious incident is declared. Rootly prefers **incident channel** or **coordination space** over "war room." The work is focused coordination, not combat—and the calmer name sets the tone teams want in the room. This entry uses "war room" because it's the term most people search for, but the plainer language appears throughout Rootly's product and docs. ## Why do teams use a dedicated incident channel? Major incidents fail in predictable ways without a focal point: three people debug the same hypothesis in different DMs, a critical finding gets posted where half the team never sees it, and nobody can answer "what's the current status?" without interviewing four people. A dedicated channel fixes this by making one place authoritative. Everything important—findings, decisions, status—flows through it, which means the timeline reconstructs itself and new responders get up to speed by reading backward instead of interrupting everyone. The physical version—engineers around a table with laptops and a whiteboard—still exists, but distributed teams have made the virtual channel the default. The principle is identical either way: one room, one conversation, one source of truth. ## When should you open one? Not every incident needs one. A single-responder SEV3 handled in twenty minutes gains nothing from ceremony. A dedicated channel earns its overhead when: * The incident is severe (typically SEV1 or SEV2) or customer-facing * More than two or three responders are involved, or multiple teams need to coordinate * The investigation is likely to run longer than an hour * Executives or support teams need a place to get status without interrupting responders Many teams remove the judgment call entirely: declaring a SEV1 automatically creates the channel, starts the bridge, and pages the roster. Automation matters here because the minutes after declaration are precisely when nobody has spare attention for logistics. In Rootly, [declaring an incident](/incidents/incidents) can create the dedicated Slack channel and assemble responders automatically. ## Who belongs in the channel? Small enough to move fast, complete enough to act: * **Incident commander** — runs the room, tracks the effort, and makes the calls * **Technical responders** — the engineers actively investigating, usually the service owners * **Communications lead** — translates the room's progress into stakeholder and customer updates * **Scribe** — captures the timeline, decisions, and action items as they happen * **Subject-matter experts** — pulled in for specific questions, released when answered Everyone else—curious engineers, anxious executives—should follow along from outside, via status updates or a read-only view. A channel with thirty spectators stops being a working space; the commander should feel free to ask observers to leave. ## What makes a virtual incident channel work? Virtual coordination has its own craft: * **One dedicated channel per incident.** Never reuse a general channel; the incident's history should live in one scrollable place, uncontaminated by other traffic. * **A bridge call for high-bandwidth moments.** Voice or video is faster for debate and decisions; the channel is better for commands, links, and the record. Decisions made on the call must be written back into the channel—if it isn't written down, half the responders never heard it. * **Pinned status.** Keep a regularly updated summary (impact, current hypothesis, next steps, owner) pinned so joiners self-serve context. * **Threads for side investigations.** Parallel workstreams get threads; conclusions get promoted to the main channel. * **An explicit end.** When the incident resolves, the commander closes the room with a final summary. The channel is then archived intact as input for the retrospective. ## What does this look like in practice? A payments provider takes a SEV1 at 09:14 when transaction success rates fall to 60%. Declaration auto-creates `#inc-2091-payments-degraded` and a bridge link. By 09:20 the commander has pinned a status, two engineers are on the bridge comparing deploy timelines, and a third posts in-channel that a partner API's latency tripled at 09:10. The commander declares the working hypothesis in the channel, the communications lead posts a status-page update, and when the partner confirms their fix at 09:58, the resolution and full timeline are already sitting in one place—ready for the retrospective. ## Related terms * [What Is Incident Response?](/glossary/incident-response) * [What Are SEV Levels?](/glossary/sev-levels) * [What Is Incident Management?](/glossary/incident-management) Browse all definitions in the [incident management glossary](/glossary). # Welcome to Rootly help and documentation Source: https://docs.rootly.com/help-and-documentation Rootly documentation: set up on-call and alerting, run incidents, publish status pages, and learn from retrospectives, with AI throughout every step.
Welcome to Rootly help and documentation.

The all-in-one AI platform for on-call, incident response, status pages, and post-incident learning.

Start with a task


Browse by product area

On-Call On-call that's built for simplifying paging, scheduling, requesting coverage, and more—so you can stay focused on fixing. Incident Response Incident management with built-in AI to automate your workflows for faster resolutions—directly in Slack, Google Chat, and Teams. Rootly AI AI that works for you across the incident lifecycle—triage, root cause analysis, response, comms, and retros. Alerts Alerts from every tool you run, ingested, deduplicated, grouped, and routed to the right responder the first time. Automation & Workflows Automation that runs your response: channels created, stakeholders updated, tickets filed, retros started, the same way every time. Integrations Connect all your existing tools—Slack, Jira, Zoom—and extend further with the Terraform provider, API, or MCP server.


Build with Rootly

# Incident Response Setup Checklist Source: https://docs.rootly.com/incident-response-setup-checklist Work through the configuration that makes incident response automatic: declaration forms, the incident channel, roles and runbooks, and closing the loop. Work top to bottom. You'll configure how incidents get **declared**, how the **incident channel** becomes a command center, how **roles, tasks, and runbooks** kick in automatically, and how you **close the loop** with status pages, follow-ups, and retrospectives. Check items off as you go. ## How the pieces fit together | 1 · Declare & organize | 2 · Respond & communicate | 3 · Learn & improve | | :-------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------- | | **How an incident starts.** Forms, severities, roles, and runbooks that kick in the moment it's declared. | **What happens while it's live.** The command center, AI assistance, paging, and stakeholder updates. | **What happens after.** Follow-ups, retrospectives, and the data that makes the next incident faster. | 📌 **Note:** Rootly is highly customizable — forms, fields, severities, and automations are all configured per organization, so what your team sees may look different from any demo or default setup. The incident form is designed to guide responders through what they need to fill out regardless of configuration. *** ## 1. Configure incident declaration Decide how an incident gets started, and what the form asks for. 1. **Set up the New Incident form** — Most fields are customizable in [Configuration → Forms](https://rootly.com/account/forms). Decide what's required (title, summary, severity, type) before responders ever see it. ([Creating incidents via Slack](/incidents/creating-incidents/creating-incidents-via-slack)) 2. **Align your forms across channels** — You can create different forms per channel, but Rootly recommends keeping them in sync so responders have a consistent experience no matter where an incident originates. 1. Clean Shot 2026 07 31 At 15 52 10@2x 3. **Configure your severities** — [Severity](https://rootly.com/account/severities) isn't just a label — it's what triggers automations and workflows behind the scenes, so map out what each severity level should kick off before you go live. ([Incident lifecycle](/incidents/incidents)) 4. **Decide on Triage vs. Started** — Choose whether incidents can be declared directly into Started, or must pass through an In Triage state first. ([Incidents](/incidents/incidents)) 5. **Set up private incidents** — For security, legal, or customer-sensitive situations. Rootly's AI features (catchup, summaries) still work inside private incidents, so teams don't have to trade confidentiality for speed. ([Managing private incident access](/incidents/private-incidents/manage-via-web)) 6. **Learn every command** — `/rootly help` in Slack surfaces every available command, so responders never need to memorize the list. ## 2. Set up the incident channel & command center Make sure the auto-created Slack channel gives responders everything they need at a glance. 1. **Confirm automatic channel creation** — Rootly should spin up a dedicated channel per incident, with the severity in the name and a link out to the web view. 2. **Link your team's own tools** — Add links to your bridge, ticketing system, and any other tools your responders reach for mid-incident. 3. **Customize the command center block** — This is the pinned message at the top of the channel — walk through what buttons and links show up for your org by configuring your [Integration settings](https://rootly.com/account/integrations) (e.g. conferencing tool, Jira, runbooks, etc.). 4. **Add the bridge transcript / recording** — Enable Meeting Scribe so incident bridge calls (Zoom, Meet, Webex, Teams, GoToMeeting) get recorded, transcribed, and summarized automatically ([Meeting Scribe](/ai/meeting-scribe)). You can do this from the settings of your bridge integration. 1. Clean Shot 2026 07 31 At 15 55 43@2x ## 3. Configure incident roles & tasks Make sure the right responsibilities — and the right follow-up work — get assigned automatically. 1. **Define your [Incident Roles](https://rootly.com/account/incident-roles)** — e.g. Incident Commander, Comms Lead, Scribe. Configure these in advance so people aren't assigned ad hoc mid-incident. ([Incident roles](/managing-teams/incident-roles)) 2. **Attach Default Tasks to each role** — When a role is assigned, its default tasks are automatically created for that person — no one has to remember the checklist. 3. **Use roles as a training tool** — Once roles are assigned, anyone joining the incident can immediately see who's doing what, which doubles as on-the-job training for newer responders. 4. **Test it** — Create a test incident, attach a team, and confirm role assignment and task creation behave the way you configured them. ## 4. Enable AI catch-up & summaries Let responders get up to speed instantly, without scrolling the whole channel. 1. **Turn on Incident Summarization** — Generates a concise, single-paragraph summary of the incident using metadata, alerts, timeline events, and communications. ([AI Summaries](/ai/ai-summaries)) 2. **Use the catchup command** — `/rootly catchup` uses the same summarization technology, aimed at helping a late joiner understand a long-running incident without reading the full history. 3. **Feed it good context** — Summary quality depends on what's in the incident: timeline events, action items, alerts, and Slack communication all improve it. Encourage responders to keep the timeline updated as they go. 4. **Know the private-incident caveat** — For private incidents, confirm Slack channel message visibility settings allow AI access, or summarization won't have enough to work with. ## 5. Connect playbooks to your services Make sure the right checklist shows up the moment an incident touches a given service. 1. **Build out your [Catalog](https://rootly.com/account/catalogs)** — [Services](https://rootly.com/account/services), and [teams](https://rootly.com/account/teams) live in the Catalog, and it's what powers automatic playbook attachment. ([Catalogs](/catalogs)) 2. **Attach [playbooks](https://rootly.com/account/playbooks) to services and incident types** — When a service or type (e.g. "Security") is added to an incident, its associated playbook — and the tasks in it — attach automatically. ([Example usage with incidents](/configuration/example-usage-with-incidents)) 1. Clean Shot 2026 07 31 At 16 01 55@2x 3. **Verify the auto-attach behavior** — Add a service to a test incident and confirm the runbook's tasks appear without anyone manually adding them. ## 6. Set up emoji reactions & the timeline Turn a Slack reaction into a task, a follow-up, or a retrospective note — automatically. 1. **Configure your event emoji** — Choose which emoji create timeline events, tasks, or follow-ups when reacted to a message. Emoji lists for each purpose are separate and can't overlap. ([Adding events to timeline via Slack](/incidents/incident-timeline/adding-events-to-timeline-via-slack)) 2. **Set your "pin to retrospective" emoji** — This is the most important one to get right: pinned messages build your retrospective as you go, and can always be edited or pruned later. 3. **Set your "task" and "follow-up" emoji** — So a reaction like ⭐ can create a task, and 📝 can create a follow-up, without anyone leaving the conversation. ## 7. Set up paging & escalation Make sure responders never have to leave the incident channel to bring in the right people. 1. **Confirm the paging paths all work** — Responders should be able to page via natural-language AI request, `/rootly page`, or the Escalate button in the command center — all three should reach the same on-call rotations. 2. **Tie escalation policies to schedules** — Paging only works end-to-end if your On-Call schedules and escalation policies are already configured. ([Escalation policies](/on-call/escalation-policies)) 3. **Confirm the leadership channel gets notified** — Severity changes (e.g. escalating to Sev 2) should automatically post an update to your leadership channel — verify this workflow is wired up. ## 8. Connect status pages Keep external stakeholders informed without pulling responders out of the incident. 1. **Create your [status page(s)](https://rootly.com/account/status-pages)** — Public for customers, private for internal stakeholders, each with its own components. ([Creating a status page](/configuration/creating-a-status-page)) 2. **Know it's not automatic** — Status pages are not 1:1 with incident status by default; someone needs to publish each update. Decide who owns that during an incident. ([Incident status pages](/configuration/publishing-incidents)) 3. **Consider a workflow to prompt updates** — e.g. remind the channel to publish a status page update every 30 minutes during a live Sev 1/Sev 2. ## 9. Set up follow-ups & ticketing sync Make sure action items land somewhere engineers already work. 1. **Connect Jira, Linear, or Asana** — Follow-ups created in Rootly can auto-create tickets in your team's actual backlog instead of getting lost in a doc. ([Jira integration](/integrations/jira/jira)) 2. **Confirm two-way sync** — When a ticket status changes in Jira, the corresponding Rootly follow-up should update automatically, and vice versa. 3. **Map custom fields** — If your Jira project uses custom fields, map them so incident data lands in the right place instead of a generic description box. ## 10. Configure retrospectives Decide what "done" looks like after an incident resolves. 1. **Set your retrospective [process](https://rootly.com/account/retrospective-processes?tab=process) & [template](https://rootly.com/account/retrospective-processes)** — Define the steps, required fields, and Liquid-templated content responders will see. One template can be marked default. ([Retrospectives](/retrospectives/retrospectives)) 2. **Decide when a retrospective is required vs. optional vs. skipped** — Not every incident needs a full retro; set thresholds (severity, service, commander discretion) so the process scales. 3. **Set up retrospective-specific workflows** — Trigger actions when a retrospective is created or updated, separate from your incident-level workflows. 4. **Confirm the resolution AI assistance is on** — The resolution form includes AI-suggested resolution summaries — verify this is enabled so responders aren't writing from scratch. ## 11. Build supporting workflows Automate the repetitive parts once the manual process is proven with [Workflows](https://rootly.com/account/workflows). 1. **Map out triggers → conditions → actions** for your top 2–3 repeated manual steps (e.g. leadership notifications, status page reminders, Jira creation). ([Workflows](/workflows/workflows)) 2. **Start narrow, then expand** — A single reliable workflow (e.g. "post to leadership channel when severity ≥ Sev 2") beats a dozen half-configured ones. 3. **Review workflows periodically** — As services, teams, and tools change, workflows can silently stop matching conditions correctly — put a recurring check on the calendar. *** Congratulations! You've successfully configured your Incident Response process in Rootly. Next up, when things go wrong, learn how Rootly pulls it all together to help you respond in an incident: review the Incident Responder Checklist. # Custom Fields on Action Items Source: https://docs.rootly.com/incidents/action-items/action-item-custom-fields Add custom fields to tasks and follow-ups to capture organization-specific metadata, drive reporting, power workflow automation, and enrich ticketing exports. ## Overview Custom fields let you attach organization-specific metadata—like product area, business unit, cluster, or infrastructure provider—to the tasks and follow-ups created from your incidents. That metadata then flows everywhere action items go: the web UI, Slack, workflows, ticketing exports, dashboards, the API, and webhooks. Use custom fields on action items to: * **Categorize action item work** by the dimensions your organization cares about (owning business unit, product area, affected cluster, etc.) * **Report on follow-through** — filter and group action items by field values in lists and dashboards * **Automate with workflows** — trigger on field changes, branch on field values, and write values into Jira, Linear, GitHub, and other ticketing tools * **Keep exports complete** — include required metadata when action items are exported to external project management tools Custom fields apply to both kinds of action item: **tasks** (lightweight, in-incident work) and **follow-ups** (post-incident work). Each kind has its own form, so you can surface different fields on tasks than on follow-ups. Only custom fields can be added to these forms—an action item's standard fields (title, description, assignee, priority, status, due date) are always present. Custom fields for action items are rolling out progressively. If you don't see the **Incident Follow Up** or **Incident Task** forms under **Configuration → Forms**, reach out to your Rootly customer success manager or **[support@rootly.com](mailto:support@rootly.com)** to have it enabled. *** ## How It Works Action items use the same custom field library as incidents. A single field definition—say, *Business Unit Owner*—can be placed on your incident forms, your action item forms, or both, so your reporting categories stay consistent: one name, one slug, one set of options. Each action item stores its **own value** for the field—seeded from the parent incident at creation where fields are shared, but fully independent after that (see [Pre-Filled from the Parent Incident](#pre-filled-from-the-parent-incident)). There are three moving parts: 1. **Fields** — created and managed under **Configuration → Fields**, exactly like [custom incident fields](/configuration/custom-fields). All custom field types are supported: text, textarea, rich text, number, checkbox, date, datetime, select, and multiple select—including select fields backed by Teams, Users, Services, Functionalities, Environments, Causes, Incident Types, or [Catalogs](/catalogs). 2. **The action item forms** — the **Incident Follow Up** and **Incident Task** forms, both under **Configuration → Forms**, control which custom fields appear on follow-ups and tasks respectively. Each has separate **Web** and **Slack** versions you can configure independently. 3. **Values** — set by responders in the web UI or Slack, pre-filled from the parent incident where fields are shared, or written automatically by workflows and the API. *** ## Configuring the Task and Follow-Up Forms Go to **Configuration → Fields** and create the fields you need, or reuse fields that already exist for your incidents. See [Custom Fields](/configuration/custom-fields) for field types, options, and best practices. Go to **Configuration → Forms** and select **Configure** on the **Incident Follow Up** form (shown whenever a follow-up is added or edited) or the **Incident Task** form (shown whenever a task is added or edited). Click **Add Fields** and select the custom fields to display. Drag and drop to reorder them. Use the tabs to configure the **Web** and **Slack** versions of the form separately. To keep data consistent, Rootly recommends keeping the Web and Slack versions of a form in sync. A field placed only on the Web form won't appear in Slack dialogs (and vice versa). Edit each field on the form to control whether it is **required**, and whether it is displayed or required **conditionally** based on the value of another field above it—the same conditional logic available on [built-in forms](/configuration/built-in-forms). The **Incident Task** and **Incident Follow Up** forms are independent, and the Task form starts **empty**—placing a field on the follow-up form does not add it to tasks (or vice versa). Add fields to each form explicitly. Only custom fields can be placed on these forms; an action item's standard fields (title, description, assignee, priority, status, due date) are always present, and built-in incident fields (severity, services, etc.) belong to the incident itself. If you use [Dynamic Forms](/configuration/dynamic-forms), the action item forms respect your form sets, so different incident types or conditions can present different fields. *** ## Filling In Custom Field Values ## In the Web UI When creating or editing an action item on an incident, the form displays every custom field placed on the Web version of the matching form (**Incident Task** or **Incident Follow Up**). Values can be added at creation or filled in later by editing the action item. The global **Follow-ups** view under Post-Incident also exposes follow-up custom fields. ## In Slack Slack action item dialogs display the custom fields placed on the Slack version of the matching form. Required and conditional rules are enforced in the dialog just as on the web. * **Tasks** — created with `/rootly task` (or `/rootly add action item`); view and manage yours with `/rootly todo` or `/rootly tasks`. * **Follow-ups** — created with `/rootly followup` (or `/rootly add action item`); manage via `/rootly action items` or the message **More actions** menu. Follow-ups created instantly from emoji reactions skip the dialog, so their custom fields start empty—fill them in afterward by editing the follow-up from `/rootly action items` or the web UI. Fields shared with the incident are still pre-filled automatically (see below). Slack notifications sent when a follow-up is assigned also display its custom field values (up to 10 fields) beneath the summary, so assignees get full context without leaving Slack. ## Pre-Filled from the Parent Incident When a new action item is created, any custom field that is both **placed on the matching action item form** and **already set on the parent incident** is pre-filled with the incident's value. You can edit or clear the pre-filled value before saving. Pre-filling applies to both tasks and follow-ups, however the action item is created—web, Slack, API, or workflows. Pre-filling is a one-time convenience, not a sync. Once the action item is saved, its field values are fully independent of the incident's—changing one never changes the other. ## Converting Between Tasks and Follow-Ups Tasks and follow-ups can carry different custom fields, since each has its own form. When you convert an action item from one kind to the other, any field that is on the **source** form but **not** on the **destination** form is hidden—its value is **preserved, not deleted**, and reappears if you convert back. Fields present on both forms stay visible and keep their values. Rootly warns you before converting (in both web and Slack) and lists the fields that will be hidden, but only when the conversion would actually hide something. *** ## Filtering, Columns, and Reporting **Follow-ups list.** The global Follow-ups view supports follow-up custom fields as table columns and filters: * Use **Configure View** to add custom field columns to the table. Fields with **Display this field in the incident details** turned off are hidden from the column picker. * Filter follow-ups by custom field values—including select, user, team, service, functionality, and catalog-backed fields. * Custom field values are searchable, so follow-ups can be found by the values set on them. This view lists follow-ups only; task custom fields don't appear here. Use Dashboards for reporting across tasks. **Dashboards.** [Dashboard](/metrics/customized-dashboards) panels built on action item data can group and filter by custom field values from **both** the task and follow-up forms, letting you chart action item volume and completion by product area, business unit, or any other dimension you track. *** ## Automating with Workflows [Action item workflows](/workflows/action-item-workflows) get full custom field support for both tasks and follow-ups: * **Triggers** — each custom field adds a `[CustomField] Updated` trigger, so a workflow can fire the moment a field value is set or changed on an action item. * **Conditions** — workflows can branch on an action item's custom field values (is, is not, is one of, is set, is unset, plus contains any / all / none of for multi-value fields). * **Actions** — the **Update Action Item** action can set custom field values, including with Liquid templating (for example, populating a field from `{{ incident.severity }}`). * **Ticketing exports** — ticketing actions (Jira, Linear, GitHub, Asana, and more) support custom field mappings, so you can write an action item's field values into the external ticket using [Liquid variables](/liquid/action-item-variables). Example: keep a Jira ticket's *Business Unit* field in sync with the action item. **Trigger** * `[CustomField] Business Unit Owner Updated` **Action** * **Update Jira Issue**, with a custom field mapping that sets the Jira field to `{{ action_item.custom_fields_by_slug.business-unit-owner }}` *** ## Referencing Values in Liquid Action item custom field values are available in Liquid wherever action item variables are supported: ```liquid theme={null} # Simplest access — by field slug (multi-value fields return an array) {{ action_item.custom_fields_by_slug.your-field-slug }} {{ action_item.custom_fields_by_slug.your-multi-select-slug | join: ', ' }} ``` See [Action Item Variables](/liquid/action-item-variables#custom-fields) for the full structure, including the `action_item.custom_fields` array for advanced use. *** ## API and Webhooks The [incident action items API](/api-reference/incidentactionitems/creates-an-incident-action-item) accepts custom field values through the `form_field_selections` attribute and returns them as `custom_field_selections`: * **Create/update** — pass a `form_field_selections` array under `data.attributes`, with each entry containing a `form_field_id` and either a `value` (text-like fields) or the relevant `selected_*_ids` (option, user, group, service, functionality, catalog entity, environment, cause, or incident type fields). * **Read** — responses include the `custom_field_selections` relationship; use `?include=custom_field_selections` to embed full values. * **Webhooks** — incident [webhook](/configuration/webhooks) event payloads (such as `incident.updated`) embed the incident's action items in an `action_items` array; each embedded action item includes a `custom_field_selections` array with its field values. See [Event Payloads](/configuration/event-payloads) for the payload structure. *** ## Frequently Asked Questions Yes. Custom fields apply to both tasks and follow-ups. Place the fields you want on tasks on the **Incident Task** form under **Configuration → Forms**—it's separate from the Incident Follow Up form and starts empty, so add fields to it explicitly. No. Shared fields are **pre-filled** from the incident when the action item is created, but after that the values are independent. This is intentional—an action item's business unit, for example, may legitimately differ from the incident's. Yes. Each action item form (Incident Follow Up and Incident Task) has separate Web and Slack versions. That flexibility can cause confusion (an item created in Slack may show different fields when edited on web), so Rootly recommends keeping them in sync unless you have a specific reason not to. Yes. Each field placed on a form can be required always or conditionally, based on the values of fields above it. Required rules are enforced in both the web form and Slack dialogs. Check that: (1) the feature is enabled for your organization, (2) the fields are **enabled** under Configuration → Fields, (3) the fields are placed on the correct form (Incident Task vs. Incident Follow Up) and the correct version (Web vs. Slack), and (4) any conditional display rules on the placement are met. API support is available today via the form field placements endpoints. Terraform provider support for placing fields on the action item forms is rolling out—check the Rootly Terraform provider docs for the latest. *** ## Related Pages The parent concept — tasks and follow-ups these custom fields attach to. The organization-wide custom fields system these action-item fields are part of. Trigger workflows off custom field changes and map fields into ticket exports. # Action Items Source: https://docs.rootly.com/incidents/action-items/action-items Understand how action items—including tasks and follow-ups—help teams drive effective incident response and long-term reliability improvements. ## How Action Items Work Action items are structured pieces of work created during or after an incident. They help teams capture urgent tasks, assign ownership, track accountability, and ensure important follow-up work is completed. Action items live alongside the incident timeline, Slack workflows, retrospectives, and analytics—providing full visibility into what was done during an incident and what still needs to be done. This page introduces how action items work, why they matter, and where they fit into the incident lifecycle. *** ## Why Action Items Matter During fast-moving incidents, it’s easy for important work to be forgotten. Action items help by: * Capturing tasks needed to investigate or mitigate the issue * Tracking follow-up work after the incident to prevent recurrence * Assigning clear ownership so nothing is lost * Providing structure for retrospectives and improvement planning * Enabling automation through workflows and integrations * Improving accountability and long-term system reliability Common examples include: * **Task** – “Restart service X on cluster Y.” * **Task** – “Verify the hotfix on canary pods.” * **Follow-up** – “Add alerting for cache saturation.” * **Follow-up** – “Update the API runbook with new mitigation steps.” Action items are fully customizable and can be created from the Web UI, Slack, API, Workflows, or even tied to specific Incident Roles. *** ## Types of Action Items Action items come in two forms, each serving a different purpose in the response lifecycle. ### **Tasks — Work During the Incident** Tasks represent operational or investigative work that helps move the incident toward mitigation or resolution. Tasks typically include: * **Title** (required) * Description (Markdown supported) * **Assignee** (user or group) * Priority (High, Medium, Low) * Status (Open, In Progress, Done, Cancelled) * Optional reminder (5–180 minutes) ### **Follow-Ups — Work After the Incident** Follow-ups help teams improve reliability after the incident is over. They are usually completed post-resolution. Follow-ups include: * **Title** (required) * Description (Markdown supported) * Priority * **Assignee** (user or group) * **Due date** * Status * **Custom fields** — organization-specific metadata like product area or business unit (see [Custom Fields on Action Items](/incidents/action-items/action-item-custom-fields)) Follow-ups are often reviewed and assigned during retrospectives, making them a critical part of continuous improvement. *** ## Where Action Items Live in Rootly ### **On the Incident Timeline (Web UI)** Every task or follow-up appears directly on the timeline, keeping work tied to the context of the incident. Responders can: * Create or edit items * Assign or reassign owners * Update status or priority * Open linked JIRA / Linear / GitHub issues (if integrated) ### **In Slack** If Slack is integrated, responders can create and manage action items without leaving the incident channel: * `/rootly task` * `/rootly followup` * `/rootly add action item` * `/rootly action items` (manage existing items) Slack modals support assignment, priority, reminders, and descriptions. ### **In the Web Interface** Each incident has an **Action Items** section where teams can: * Filter by priority, type, or status * Bulk-review outstanding work * Export action items to CSV, JSON, or XML * Manage all items across all incidents from a global dashboard ### **In Workflows** Workflows can create tasks or follow-ups automatically based on: * Severity * Impacted services * Incident type * Sub-status changes * Timeline events * Role assignments * Custom logic Automation ensures important tasks are created consistently and early. ### **Through the API** Developers can programmatically create or update items: ```http theme={null} POST /api/v1/teams/:team_id/incidents/:incident_id/action_items ``` The API supports full lifecycle management, including due dates, priority, and linking external issue IDs. *** ## How Action Items Support the Response Process Action items help orchestrate the human work that happens around incidents: * Timeline entries show when items were created, updated, or completed * Slack channel summaries update dynamically as items change * Workflow triggers can depend on action item status or presence * Retrospectives include a full list of tasks and follow-ups for review * Analytics dashboards help track overdue items, recurrence, and team performance * Permissions determine who can create, edit, or complete action items When paired with roles and workflows, action items create a structured, predictable response process across teams. *** ## Where to Go Next These pages will help you manage action items across all interfaces: * **Add via Slack** – Create tasks or follow-ups using Slack commands * **Add via Web Interface** – Add items directly from the incident page * **Add via API** – Programmatically create items from external systems * **Add via Email** – Append email-based action items when responding to incident emails * **Custom Fields** – Capture organization-specific metadata on tasks and follow-ups * **Incident Roles** – Automatically create action items based on role responsibilities * **Workflows** – Generate tasks and follow-ups automatically based on incident conditions *** ## Best Practices * **Create tasks early**\ Capture investigative work as soon as it emerges. * **Use follow-ups for durable improvements**\ These often prevent recurrence. * **Assign owners immediately**\ Unassigned tasks often go stale. * **Set due dates for follow-ups**\ This increases accountability and helps with retrospective follow-through. * **Use priorities intentionally**\ High-priority follow-ups should be reviewed in retrospectives or weekly ops meetings. * **Automate repetitive items**\ Workflow-generated tasks ensure consistent coverage. * **Review open follow-ups regularly**\ Keeps your reliability improvement backlog healthy. *** ## Frequently Asked Questions No. Smaller or operationally simple incidents may not require tasks or follow-ups. One user may own the item, but **multiple groups** can also be assigned for shared accountability. Yes. Descriptions fully support Markdown for links, formatting, and structured notes. Yes — both **tasks** and **follow-ups** support custom fields for organization-specific metadata like product area or business unit. Fields are configured on the Incident Task and Incident Follow Up forms and flow through workflows, exports, dashboards, and the API. See [Custom Fields on Action Items](/incidents/action-items/action-item-custom-fields). Yes. This is one of the most powerful features of Rootly’s workflows for predictable processes. Yes. All tasks and follow-ups associated with an incident appear in the retrospective for review. Yes. Action items support external issue linking for teams who track work in external systems. Tasks may be completed, and remaining work typically becomes follow-ups. Some orgs disable new task creation after resolution. *** ## Related Pages Automatic due dates and violation tracking for follow-ups. Organization-specific metadata for tasks and follow-ups. Where follow-ups live after resolution — retros are the natural home for long-running work. # Creating Action Items via Automation & API Source: https://docs.rootly.com/incidents/action-items/adding-action-items-via-api Automate action item creation through workflows, incident roles, and direct API integration for scalable incident response processes. ## How Automation Creates Action Items Action items—tasks and follow-ups—can be generated automatically through **Workflows**, **Incident Roles**, or the **Rootly API**. Automation ensures teams never miss a critical task, follow-up, or improvement opportunity during or after an incident. Automation is especially powerful for: * Enforcing consistent response processes * Creating tasks or follow-ups automatically based on incident conditions * Routing work to the correct owners * Producing reliable audit trails * Integrating with tools such as Jira, GitHub, and Slack Automation reduces operational overhead and ensures every incident produces actionable, trackable work. *** ## Action Items and Workflows Workflows can both **create** and **react to** action items using a variety of triggers and conditions. ### Supported Workflow Triggers (Action Item Category) Rootly supports the following action-item–related triggers: * `incident_updated` * `action_item_created` * `action_item_updated` * `assigned_user_updated` * `summary_updated` * `description_updated` * `status_updated` * `priority_updated` * `due_date_updated` * `teams_updated` * `slack_command` ### Workflow Conditions Workflows can filter based on: * Action item type (Task / Follow-up) * Status * Priority * Incident severity * Visibility * Incident kind * Incident roles * Other incident attributes (teams, services, etc.) Conditions and triggers map directly to code-backed enums and workflow schemas, ensuring strict validation and predictable automation. *** ### Example: Workflow **creates** a task when the Security team is added **Trigger** * Teams added **Conditions** * Kind → Incident * Team → is one of → Security **Action** * Create a task to alert the Legal team *** ### Example: Workflow **reacts to** a new action item **Trigger** * Action item created **Conditions** * Type → Task * Priority → High **Action** * Create an external ticket (for example, Jira, GitHub, GitLab, Linear) Workflow tasks are grouped by integration. Jira actions, for example, appear under the Jira task group and require the Jira integration to be enabled. *** ## Action Items and Incident Roles Incident Roles can include predefined tasks that are automatically converted into incident action items when an incident is created. These role-based tasks carry: * Summary * Priority * Role assignment metadata * Ordering/position To configure: Go to **Configuration → Roles**. Select the role you want to add tasks to. Open the **Tasks** tab. Add or reorder tasks as needed. Role-based action items give each incident a predictable starting checklist and ensure operational discipline. Learn more about [Incident Roles](/configuration/incident-roles). *** ## Action Items and the API The Rootly API allows programmatic creation, management, and retrieval of action items. ### Endpoints * **List incident action items**\ [/api-reference/incidentactionitems/list-incident-action-items](/api-reference/incidentactionitems/list-incident-action-items) * **Create an incident action item**\ [/api-reference/incidentactionitems/creates-an-incident-action-item](/api-reference/incidentactionitems/creates-an-incident-action-item) * **Retrieve an incident action item**\ [/api-reference/incidentactionitems/retrieves-an-incident-action-item](/api-reference/incidentactionitems/retrieves-an-incident-action-item) * **Update an incident action item**\ [/api-reference/incidentactionitems/update-an-incident-action-item](/api-reference/incidentactionitems/update-an-incident-action-item) * **Delete an incident action item**\ [/api-reference/incidentactionitems/delete-an-incident-action-item](/api-reference/incidentactionitems/delete-an-incident-action-item) * **List all action items for an organization**\ [/api-reference/incidentactionitems/list-all-action-items-for-an-organization](/api-reference/incidentactionitems/list-all-action-items-for-an-organization) ## Supported API Fields (Create/Update) * `kind` (`task` or `follow_up`) * `summary` (required) * `description` (Markdown supported) * `assigned_to_user_id` * `assigned_to_group_ids` * `priority` (`high`, `medium`, `low`) * `status` (`open`, `in_progress`, `done`, `cancelled`) * `due_date` (ISO 8601) * `form_field_selections` ([custom field](/incidents/action-items/action-item-custom-fields) values — each entry takes a `form_field_id` plus a `value` or the relevant `selected_*_ids`) * **Jira fields:** * `jira_issue_id` * `jira_issue_key` * `jira_issue_url` ## Response Fields Include * Kind, priority, status * Due date * Assigned user & groups * Custom field values via the `custom_field_selections` relationship (use `?include=custom_field_selections` to embed them) * Integration URLs: * `jira_issue_url` * `github_issue_url` * `gitlab_issue_url` * `linear_issue_url` * `url` and `short_url` * Timestamps and metadata The API follows the JSON:API spec and enforces the same validations as the Web UI and Slack. *** ## Best Practices * **Automate common tasks** to reduce manual work * **Use role-based tasks** for consistent incident startup actions * **Assign owners early** to prevent drift * **Use priorities intentionally** to structure follow-up workflows * **Integrate external systems** (Jira, GitHub, etc.) for centralized tracking * **Review overdue follow-ups regularly** for reliability improvements *** ## Troubleshooting Confirm the trigger conditions matched the incident and that the user/action had permission to create action items. Ensure the role is enabled and the role tasks themselves are active. Disabled tasks are not copied over. Make sure summary is present and enum fields (priority, status, kind) match allowed values. Check Jira fields if provided. Some organizations disable task/follow-up creation after an incident is resolved, cancelled, or closed. Slack notifications fire only when:
• The team has a Slack integration\
• The incident has a slack\_summary\_timestamp\
• Notifications aren’t suppressed
These notifications are not workflow-dependent.
# Creating Action Items in Slack Source: https://docs.rootly.com/incidents/action-items/adding-action-items-via-slack Create tasks and follow-ups in Slack using slash commands, emoji reactions, or message menus to convert incident discussions into actionable items. ## How Action Item Creation Works in Slack Slack is where most real-time incident collaboration occurs, which makes it the perfect place to quickly capture tasks and follow-ups as they emerge. Rootly lets you turn conversations directly into structured action items so nothing is missed. You can create action items using: * **Slash commands** * **Emoji reactions** * **Slack’s More Actions message menu** All of these features require that you are inside a **Rootly incident channel** and have permission to create or manage action items.\ For private incidents, you must also have access to the incident itself. *** ## Slash Commands Slash commands are the fastest and most flexible way to create or update action items. Run these commands **inside an incident channel**: ### Create New Items **`/rootly task`**\ Creates a new task for the current incident. **`/rootly followup`**\ Creates a new follow-up item intended for post-incident improvement work. Slash-command creation opens a Slack modal, allowing you to set priority, assignee, description, reminders, and more before submitting. Task and follow-up modals also display any [custom fields](/incidents/action-items/action-item-custom-fields) placed on the matching Slack form (Incident Task or Incident Follow Up). ### Manage or review items **`/rootly action`**\ Opens the action-item management menu, allowing you to: * View all action items for the incident * Create a new task or follow-up * Change the status * Assign or reassign a user or group * Edit descriptions or details * Delete action items * Convert between task ↔ follow-up **`/rootly todo`**\ Displays tasks assigned **specifically to you**, making personal follow-up easy. The `/rootly todo` command is especially helpful for engineers rotating through on-call — it ensures no assigned work is forgotten after the incident. *** ## Emoji Reactions Emoji reactions turn Slack messages directly into action items with minimal interruption to the conversation. When enabled under **Configuration → Integrations → Slack**, reacting to a message triggers auto-creation: ### Task Creation React with a ⭐️ **star emoji** to turn the message into a task. The star emoji reaction generates a task. ### Follow-Up Creation React with a 🔧 **wrench emoji** to convert the message into a follow-up. The wrench emoji creates a follow-up Rootly will add a **white check mark emoji** on success. Emoji used for tasks and follow-ups must not overlap with emojis configured for:\ **timeline events**, **incident follow-ups**, or **task creation**.\ Rootly enforces this to ensure each emoji has a single clear purpose. *** ## Slack “More Actions” Menu You can also create action items using Slack’s built-in message menu: Hover over any message in the incident channel. Click **More actions** (•••). Select **Add Action Item**. A modal opens with the message text pre-filled as the summary. This option is ideal when turning longer discussions, decisions, or troubleshooting notes into structured work without retyping. *** ## What Happens When an Action Item Is Created Action items created from Slack: * Appear immediately on the **incident timeline** * Include the original Slack message text when created from a message * Support Markdown formatting in descriptions * May trigger workflows (for example, create Jira tickets, notify owners) * Sync with retrospectives and analytics * Can be assigned to users or groups Some organizations restrict task creation after incidents are resolved or closed.\ Follow-ups, however, typically remain available for use in post-incident improvement. *** ## Best Practices * **Capture tasks early**\ Adding tasks in real time prevents important work from getting lost in conversation. * **Assign owners immediately**\ Tasks without owners are often forgotten — assignment drives accountability. * **Use follow-ups for long-term improvements**\ These items support durable reliability gains after the incident. * **Use priorities intentionally**\ High-priority items should be reviewed in retrospectives, weekly ops syncs, or technical leadership meetings. * **Keep emoji intuitive**\ Choose emojis your team naturally reaches for during conversations. * **Use `/rootly todo`**\ Helps responders keep track of what’s on their plate throughout and after the incident. * **Automate recurring work**\ Use workflows to auto-create tasks like “Prepare retrospective document” or “Notify customer support.” The strongest incident programs treat action items as part of a continuous improvement loop — not just a list of things to do. *** ## Troubleshooting Check the following: * You reacted **inside an incident channel** * The emoji is configured in the Slack integration settings * Emoji aren’t conflicting with other trigger types * Emoji ingestion is enabled for your Slack workspace This usually means: * You don’t have permission to create or modify action items * The incident is in a state where new tasks are restricted * You're not inside a valid incident channel * Confirm you created it in the **correct** incident channel * Ensure the Slack message wasn’t deleted * Verify the Rootly Slack app has permission to read and react to messages Often caused by: * Slack integration not fully installed * You're not in an incident channel * Your Slack role/user permissions limit access to message actions The checkmark is Rootly’s confirmation reaction, letting you know your task or follow-up was created successfully. This depends on your workspace settings. Some organizations disable new task creation after resolution to preserve process discipline, but follow-ups remain available. # Creating Action Items in Web Interface Source: https://docs.rootly.com/incidents/action-items/adding-action-items-via-web-ui Add tasks and follow-ups to incidents through the web interface, with options for exporting to external tools and manual tracking. ## How Web-Based Action Items Work From the incident page in the Rootly web app, you can create and manage **tasks** (work done during the incident) and **follow-ups** (work done after the incident to prevent recurrence). Tasks and follow-ups live in dedicated tabs on the incident and are also reflected in retrospectives, exports, and integrations with external tools. Use the web interface when you want a complete view of all action items for an incident, need richer editing controls, or want to export items to ticketing/project management tools. *** ## Creating Tasks and Follow-Ups from an Incident Add a task or follow-up directly from the incident page. Open the incident in the Rootly web app from your incidents list or a direct link. Under the incident title, click either the **Tasks** tab (for work done during the incident) or the **Follow-ups** tab (for post-incident work). Click **+ New Task** or **+ New Followup**. A form will appear where you can enter details such as: * **Title** (required) * Description * Assignee (person and/or team) * Priority * Status * Due date (especially for follow-ups) * Optional links to external systems (for example, Jira issue URL) * Custom fields — pre-filled from the incident where fields are shared Click **Save** to create the item. The task or follow-up will appear in the list on the tab and be associated with the incident timeline for future reference and retrospectives. Depending on your workspace configuration, you may see slightly different fields (for example, required teams, custom fields, or external ticket links). Your admin controls these under **Configuration**. *** ## Using Markdown in Action Item Descriptions Action item descriptions support [Markdown](https://www.markdownguide.org/ "Markdown") so you can structure notes and instructions clearly. You can use Markdown to: * Add **bold** or *italic* emphasis * Create bullet lists or numbered steps * Insert links to dashboards, runbooks, or logs * Highlight command snippets Markdown makes it easier for assignees to understand exactly what needs to be done—especially for complex or multi-step work. *** ## Exporting Action Items Automatically (Smart Defaults) With **Smart Defaults**, you can configure Rootly to automatically export tasks to external tools for tracking—so responders don’t need to create tickets manually. These settings live under integration pages such as Jira, Asana, Motion, or Linear. Examples: * Automatically create a Jira issue whenever a new follow-up is created * Push all high-priority follow-ups to Linear as issues * Create Asana tasks for follow-ups tied to specific services Use Smart Defaults when you want **every** action item (or a filtered subset) to end up in your external tracker without manual effort. *** ## Exporting Action Items Manually from an Incident If you prefer more control, you can export action items manually from the **Tasks** and **Follow-ups** tabs. Open the incident in the web app. Go to the **Tasks** or **Follow-ups** tab. Click the **Export to ticketing** button to send selected items to your configured tool (Jira, Linear, Asana, Trello, Zendesk, etc.). During export, you may need to select: * Which integration to use * Project, board, team, or workspace * Issue type or workflow state * Whether to create a **subtask/sub-issue** when an incident already has a linked parent ticket Manual export is perfect when only some action items should be tracked externally. The **Export to ticketing** modal does not support [Liquid variables](/liquid/liquid). Anything you type into the description field is sent as literal text — `{{ incident.url }}` will not be interpolated. To enrich exported tickets with incident context (URL, severity, services, etc.), use the workflow pattern in the next section. *** ## Linking Exported Tasks Back to the Incident When you export an action item via **Export to ticketing**, the resulting Jira (or Linear, Asana, ClickUp, etc.) ticket lands in your tracker without any incident context — no Rootly link, no severity, no service. That's a frequent gap: the assignee sees the ticket later, can't tell which incident it came from, and has to dig. You can close the gap with a small **[Action Item Workflow](/workflows/action-item-workflows)** that enriches the ticket automatically the moment it's created. Pressing **Export to ticketing** stores the external ticket reference on the action item, which fires the `Action Item Updated` trigger — so a workflow can react in real time and write incident fields into the just-created ticket. In Jira, add a **custom URL or text field** on the issue type used for exports — name it something like *"Source Incident"*. The custom-field path is what the Update Jira Issue action's field mapping targets and is also JQL-searchable later. Adding entries to the Jira issue's **Links** panel (Jira "remote links" / web links) is a separate REST endpoint that the Update Jira Issue field mapping doesn't drive. If you specifically want a Links-panel entry rather than a custom field value, that's outside this walkthrough — keep the link in a custom field, or open the Jira issue manually and add a remote link. In Rootly, go to **Workflows → Create Workflow** and pick **Action Item** as the type. Configure: * **Trigger:** `Action Item Updated`. This fires when **Export to ticketing** writes the external ticket reference back to the action item. It also fires on every other action-item update — see the safety guard in the Action step below. * **Action:** add the **Update Jira Issue** action (see the [Jira Workflows](/integrations/jira/jira#workflows) reference). Use `{{ action_item.jira_issue_id }}` in the **Jira Issue to Update** field. The action requires a valid Jira issue ID — if the action item doesn't have one yet (the export hasn't happened, or another kind of update fired the trigger), the action fails cleanly rather than running against the wrong issue. Enable **Skip on Failure** on the action so unrelated updates silently no-op instead of halting the workflow. Open the **Advanced** tab on the Update Jira Issue action. Add a [custom field mapping](/integrations/jira/jira#field-type-mappings) that sets the custom field you created in Step 1 to a [Liquid expression](/liquid/incident-variables) like `{{ incident.url }}`. Common payloads: | Goal | Liquid value | | -------------------- | --------------------------------------------------------------------- | | Just the Rootly link | `{{ incident.url }}` | | Title plus link | `{{ incident.title }} — {{ incident.url }}` | | Severity-aware label | `[{{ incident.severity }}] {{ incident.title }} ({{ incident.url }})` | Save the workflow. Future Export to Ticketing presses on action items will write the incident link into the custom Jira field automatically, in addition to whatever the export modal recorded. The same shape of pattern is available for other ticketing tools that have action-item-workflow Update actions — **Linear**, **Asana**, **ClickUp**, **Shortcut**, **Zendesk**, **GitHub**, **GitLab**, and **Trello** all expose an "Update \[Tool] Issue/Task" action that can be invoked from an Action Item Workflow. The exact field-mapping mechanism and supported field types differ per tool — open the [integration page](/integrations/overview) for the tool you use and check its workflows or functionalities reference to see the action's available fields and how custom-field mapping works for that tool, then mirror the pattern above. *** ## Best Practices * **Create tasks early** — capture investigation steps while context is fresh. * **Use follow-ups for long-term improvements** — reliability work, runbook updates, etc. * **Assign owners immediately** — unassigned items go stale. * **Set due dates** — especially for follow-ups tied to retrospectives. * **Use Markdown for clarity** — links and structured notes help assignees move faster. * **Export to ticketing systems when appropriate** — keep work aligned with your team’s backlog. * **Review open follow-ups regularly** — ensures continuous improvement. *** ## Troubleshooting Your workspace or role may have restricted access, or you may not have permission to manage action items for this incident. Check with your Rootly admin. Some organizations disable new action items after certain incident lifecycle stages (for example, after resolution or close). If the creation buttons are missing, your configuration may enforce these rules. Exporting requires at least one ticketing integration (Jira, Linear, Asana, etc.) to be configured. Check **Configuration** → **Integrations**. The external tool may have missing required fields or permission restrictions. Verify: * Project/workspace is valid * Issue type and fields are allowed * The integration user has permission to create tickets # SLA Policies for Follow-Ups Source: https://docs.rootly.com/incidents/action-items/sla-policies Use SLA policies to set assignment and completion deadlines on follow-up action items, get notified before deadlines pass, and track violations. ## Overview SLA policies let you define time-based expectations for follow-up action items. When a matching follow-up is created, Rootly automatically calculates its assignment and completion deadlines, sends notifications as those deadlines approach, and records a violation if the deadline is missed. SLA policies apply exclusively to **follow-ups** — not to tasks. They are configured per team and evaluated against every follow-up that team creates. SLA policies are managed under **Configuration → SLA Policies** in the web app. *** ## Create an SLA Policy Go to **Configuration → SLA Policies** and click **+ New SLA Policy**. Give the policy a clear, descriptive name. Names must be unique within your team. Optionally add a description to explain when this policy applies or what it enforces. The manager is the person responsible for ensuring follow-ups covered by this policy are completed on time. Choose one of: The policy is managed by whoever holds a specific role on the incident (for example, the Incident Commander or the assigned engineer). This is the recommended option for most teams since it adapts dynamically to each incident. A named user is always the manager, regardless of who holds any particular role on the incident. You must set either a manager role or a specific user — not both. Configure the two deadlines Rootly tracks for each follow-up: How many days after a given incident status the follow-up must be assigned to someone. How many days after a given incident status the follow-up must be completed. When a policy applies, Rootly writes this computed date into the follow-up's **Due date** field — the same field you see when creating a follow-up manually. If a policy is applied, the Due date reflects the SLA deadline rather than a manually entered value. For each deadline, choose: The incident status that starts the deadline clock. Options: `In Triage`, `Started`, `Mitigated`, `Resolved`, `Closed`, `Cancelled`. 1, 2, 3, 4, 5, 6, 7, 14, 21, or 30 days. If your team uses custom lifecycle sub-statuses, you can anchor deadlines to a specific sub-status instead of a top-level status. By default, a policy applies to every follow-up the team creates. Add conditions to scope it to a subset. Conditions can be built on: * **Built-in incident fields** — severity, environment, service, functionality, incident type, team, cause, status, incident role, visibility, and timestamps * **Custom fields** — any select or multi-select custom field configured for your team Most conditions support the operators **is one of**, **is not one of**, **is set**, and **is not set**. Timestamp fields (such as `started_at` or `resolved_at`) only support **is set** and **is not set**, since specific datetime values cannot be selected from a list. Use the **Match** toggle to control whether the policy triggers when **Any** condition matches or when **All** conditions match. A policy can have up to 20 conditions. Add up to 5 notification rules that control when the policy's manager is notified about upcoming or overdue deadlines. Notifications are sent to the manager only — either the user in the configured incident role or the specific user assigned to the policy. Each rule fires independently for **both** the assignment deadline and the completion deadline. For example, a "1 day before due" rule will send one notification before the assignment deadline and another before the completion deadline. Send a notification X days before the deadline. Requires a minimum deadline of at least 2 days. Send a notification on the day the deadline falls. Send a notification X days after the deadline has passed (1–99 days). Use this to escalate violations that have not been resolved. Click **Save**. The policy will immediately start applying to new follow-ups that match its conditions. Existing follow-ups are not retroactively affected. *** ## How Deadlines Are Calculated When a follow-up is created, Rootly scans all active SLA policies for the team and applies the first matching policy. The deadline clock starts when the incident reaches the configured trigger status. For example, if a policy sets a **7-day completion deadline from Resolved** and the incident resolves on Tuesday the 1st, the follow-up completion deadline is Tuesday the 8th. Deadlines are calculated once when the trigger status is reached. If the incident moves back through statuses (for example, from Resolved back to Started), the deadline is not recalculated. *** ## Violations A **violation** is recorded when a deadline passes without the required action being taken. Rootly tracks two violation types: * **Assignment overdue** — the follow-up had no assignee when the assignment deadline passed * **Completion overdue** — the follow-up was not marked done when the completion deadline passed Violations remain open until the follow-up is assigned or completed. Once resolved, the violation is marked as resolved with a timestamp. You can view open violations and historical SLA data on the SLA Policies page under **Configuration**. *** ## Best Practices * **Set completion deadlines relative to Resolved** for most follow-ups — this aligns accountability with the natural end of the incident lifecycle. * **Use assignment deadlines** to catch follow-ups that get created but never picked up, especially across team handoffs. * **Use conditions to differentiate by severity** — a P1 incident may warrant a 2-day completion SLA while a P3 can tolerate 14 days. * **Add a before-due notification** so managers have time to act, not just receive a violation notice after the fact. * **Keep policies simple** — one or two policies per team covering the most common cases is easier to maintain than a complex matrix. *** ## Frequently Asked Questions Only follow-ups. Tasks are intended for work done during an incident and do not have SLA enforcement. The first matching policy (in the order they appear in the SLA Policies list) is applied. Only one policy is applied per follow-up. No. SLA policies are evaluated at follow-up creation time. Existing follow-ups are not affected when a new policy is created or an existing one is updated. Notifications are sent only to the policy's configured manager — either the user currently holding the specified incident role on the incident, or the specific user assigned to the policy. No other users are notified. Yes. Create separate SLA policies with conditions scoped to each severity level, each with different deadline values. In Triage, Started, Mitigated, Resolved, Closed, and Cancelled. If your team uses custom sub-statuses, you can also anchor to a specific sub-status. *** ## Related Pages The parent concept — SLA policies apply to follow-ups. Automate reminders, ticket creation, and reassignment when SLA milestones are hit. Where follow-ups typically get planned and tracked over time. # Converting Existing Slack Channels to Incidents Source: https://docs.rootly.com/incidents/creating-incidents/converting-existing-slack-channels-to-incidents A step-by-step guide to converting an existing Slack channel into a Rootly incident channel without losing message history, members, or context. ## Overview If your team begins investigating an issue in Slack before formally declaring an incident, you can convert that existing conversation into a Rootly incident channel.\ This ensures: * No message history is lost * All responders stay in the same channel * Automated timelines, workflows, and notifications still run * The incident is created with full context from the existing discussion The `/incident convert` command transforms any standard Slack channel into a full Rootly incident channel. *** ## Convert an Existing Slack Channel In the Slack channel you want to convert, type: ```text theme={null} /incident convert ``` Then press **Enter**. This opens the **Convert to Incident** modal. You must run the command inside the channel you want to convert — it cannot be used from other channels or DMs. The modal includes the same configurable fields you see when creating a new incident: * **Title** * **Summary** * **Severity** * **Incident Type** * **Private Incident (optional)** * Any custom fields your workspace has configured *** ## What Happens After Conversion Once submitted, Rootly will: * Create a new incident in the Rootly platform * Link the Slack channel to the incident * Preserve **all** prior messages in the channel * Generate initial timeline entries * Trigger any incident-creation workflows * Assign default roles or responders (if configured) * Enable Slack commands such as `/rootly status`, `/rootly resolve`, etc. From here, the channel behaves like any other incident channel created through Slack or the Web UI. Conversion never deletes or archives the channel — all previous activity remains intact. *** ## When to Use Conversion Use `/incident convert` when: * Responders start troubleshooting informally in Slack * An issue escalates from a conversation into a true incident * You want to preserve all investigative context without creating a new channel * You want workflows, timelines, and notifications to begin after discussion has already started *** ## Troubleshooting Ensure: * You ran `/incident convert` **inside the Slack channel** to be converted * The Rootly Slack app has permission to access that channel * You are a user with permission to create incidents Your workspace may enforce creation requirements.\ Open **Configuration → Forms** to confirm what fields must be included. Confirm Slack channel conversions are enabled in your Rootly Slack Integration settings. *** ## Best Practices * Convert as soon as a conversation becomes operational or time-sensitive * Provide a clear incident title and summary to help responders ramp quickly * Use severity to trigger correct workflows and escalation * Avoid converting channels that contain unrelated historical content * Use private incidents when the discussion involves sensitive data # Creating Incidents via API Source: https://docs.rootly.com/incidents/creating-incidents/creating-incidents-via-api Create incidents programmatically using the Rootly API with supported fields, custom fields, sub-incidents, severity levels, and error handling. ## Overview The Rootly API allows you to create incidents automatically from monitoring tools, CI/CD pipelines, internal services, or any external automation system. This is the preferred method when you need: * Deterministic and repeatable incident creation * Automated declarations from alerting or detection systems * Consistent metadata applied across incidents * The ability to create sub-incidents within orchestrated workflows * Fully headless incident creation with no human intervention API-based creation ensures incidents follow the same lifecycle rules, validations, and workflows as incidents created through Slack or the Web UI. More details are available in the [API documentation](/api-reference/overview). *** ## Before You Begin Before creating incidents via API, ensure you have: * **A Rootly API token** with permissions to create incidents * Knowledge of any **required fields** (severity, type, environments, etc.) * IDs for any contextual fields you intend to populate: * Services * Functionalities * Environments * Groups * Incident types * Custom form fields * The **Create Incident** endpoint reference: `POST /api/v1/incidents` To avoid validation failures, review which fields are required under **Configuration → Forms** and **Configuration → Required Fields.** *** ## Creating an Incident via API Requests must include: ```http theme={null} POST /api/v1/incidents Authorization: Bearer Content-Type: application/json ``` Any HTTP client or automation system (Python, curl, Terraform, GitHub Actions, etc.) will work. Below are the commonly used fields. **Core fields** * `title` * `summary` * `severity_id` * `incident_type_ids` * `private` (boolean) * `notify_emails` (array — used by workflows, not auto-emailed by default) **Contextual fields** * `service_ids` * `functionality_ids` * `environment_ids` * `group_ids` **Custom form fields** Use `form_field_selections` to populate custom data. Supports all field types: text, dropdowns, multi-select, relations, user selectors, catalog entities, etc. **Optional advanced fields** * `parent_incident_id` — creates a **sub-incident** * `create_test_incident` — only works if the **Test Incidents** feature is enabled * `mitigation_message`, `resolution_message`, `cancellation_message` * Lifecycle timestamps (advanced): * `in_triage_at`, `started_at`, `mitigated_at`, `resolved_at`, `closed_at` To create sub-incidents programmatically, provide `parent_incident_id`. Rootly automatically links the child to the parent. A successful response includes: * The incident ID * Lifecycle status * Timestamps * A URL to open the incident in the web app * Slack channel details (if Slack is integrated + auto-create enabled) You can use these details to perform follow-up actions like: * Posting timeline entries * Updating lifecycle status * Attaching alerts * Triggering or monitoring workflows *** ## Example Request Payloads ### Basic Example ```json theme={null} { "title": "API-declared service outage", "summary": "Automated alert from internal monitoring.", "severity_id": 1, "incident_type_ids": [3], "private": false } ``` ### With Custom Fields ```json theme={null} { "title": "Database latency above threshold", "summary": "DB p95 latency exceeded SLO for 10 minutes.", "severity_id": 0, "service_ids": [12], "environment_ids": [4], "form_field_selections": [ { "form_field_id": 45, "value": "us-east-1" }, { "form_field_id": 46, "selected_option_ids": [102] } ] } ``` ### Creating a Sub-Incident ```json theme={null} { "title": "Sub-incident: Cache layer investigation", "summary": "Investigating cache cluster behavior.", "severity_id": 2, "parent_incident_id": 1234, "service_ids": [18] } ``` *** ## Validation & Error Handling Rootly returns standard error responses for debugging and automation safety. ### 401 Unauthorized ```json theme={null} { "error": "unauthorized", "message": "Invalid or missing API token." } ``` ### 403 Forbidden ```json theme={null} { "error": "forbidden", "message": "You do not have permission to create incidents." } ``` ### 422 Validation Errors ```json theme={null} { "error": "unprocessable_entity", "message": "Validation failed.", "details": { "severity_id": ["can't be blank"], "title": ["can't be blank"] } } ``` ### Idempotency (Recommended) To prevent duplicate incidents during retries: ```text theme={null} Idempotency-Key: ``` *** ## Troubleshooting Ensure required fields in **Forms** or **Required Fields** are included. Check that workflow conditions (severity, type, service, etc.) match the payload. Verify: * Slack is connected * Auto-create channels is enabled * Incident is not private (depending on settings) Make sure `parent_incident_id` is passed correctly. *** ## Best Practices * Pre-fill key metadata to streamline response * Use structured fields (services, environments, types) for better analytics * Use private incidents for security-sensitive or customer-specific events * Follow consistent naming conventions across automated incidents * Use idempotency keys to prevent duplication * Automate creation of sub-incidents for multi-team or multi-domain issues * Avoid manually setting lifecycle timestamps unless necessary # Creating Incidents via PagerDuty Integration Source: https://docs.rootly.com/incidents/creating-incidents/creating-incidents-via-pagerduty Create Rootly incidents from PagerDuty alerts with automatic service mapping, resolution sync, severity translation, and troubleshooting tips. ## Overview Rootly can ingest alerts from PagerDuty to power a complete, end-to-end incident lifecycle. PagerDuty remains responsible for **alerting and escalation**, while Rootly handles **incident coordination, communication, workflows, timelines, and retrospectives**. Use this integration when: * Your alerts originate in PagerDuty * You want Rootly to manage the lifecycle, collaboration, and post-incident processes * You need Slack channels, workflows, automations, and retrospectives built off PD alerts Rootly supports: * Ingesting alerts directly from PagerDuty * Creating Rootly incidents from PagerDuty alerts * Linking Rootly incidents to PagerDuty incidents * Syncing resolution back to PagerDuty when the Rootly incident is resolved Resolving an incident in Rootly automatically resolves the linked PagerDuty incident and all associated PagerDuty alerts. Resolving directly in PagerDuty does *not* resolve the corresponding Rootly incident. *** ## Before You Begin Before creating incidents from PagerDuty, ensure: * You have installed and authorized the Rootly ↔ PagerDuty integration * Your PagerDuty services are mapped to Rootly services * On-call coverage exists for the PagerDuty service (PagerDuty won’t trigger incidents without coverage) * Your Rootly team is ready to ingest alerts under **Configuration → Alerts** Correct service mapping (via `pagerduty_id`) ensures alerts land in the right Rootly service. If mapping is missing or incorrect, incidents may not route as expected. *** ## Creating an Incident from PagerDuty You can use any method you normally use in PagerDuty: **Option 1 — Create an incident manually** 1. Open PagerDuty and navigate to the New Incident flow by selecting the **New Incident** button from the top navigation. 2. In the Create New Incident dialog, select the **Impacted Service**, which should be one of the services you integrated earlier with Rootly. Add a descriptive Title, and fill in any other fields as needed. 3. Click *Create Incident*. PagerDuty will create the incident and redirect you to its detail page, where you can view the incident’s status, responders, and associated alerts. After creating the incident in PagerDuty, log in to Rootly and navigate to: **Configuration → Alerts** Here, you’ll see: * All incoming alerts ingested from PagerDuty * Alerts routed to the Rootly services you previously mapped * A clear option to create a Rootly incident from any alert This view is your starting point for turning PagerDuty alerts into fully managed Rootly incidents. Locate the PagerDuty alert you want to escalate and click: **Create Incident** This opens Rootly’s standard incident creation workflow, where you can: * Set severity * Provide an incident summary * Choose the incident type * Mark the incident as private (if needed) * Trigger any relevant workflows When you submit the form, Rootly will: * Create the new incident * Generate initial timeline entries * Create and link a Slack incident channel (if configured) * Run any incident-creation workflows you have enabled * Attach and link the Rootly incident to the originating PagerDuty alert Once created, the Rootly incident becomes the **source of truth** for lifecycle status, workflows, communication, timelines, and retrospectives. *** ## How Resolution Works Resolution behavior between Rootly and PagerDuty is intentionally **one-directional**. This ensures that Rootly remains the authoritative system for lifecycle status, workflows, timelines, and retrospectives. ### Rootly → PagerDuty (Supported) Resolving the incident in Rootly will: * Mark the linked PagerDuty incident as **Resolved** * Resolve all associated PagerDuty alerts linked to that incident ### PagerDuty → Rootly (Not Supported) Resolving the incident directly in PagerDuty will **not** update or resolve the corresponding incident in Rootly. This directional behavior ensures: * Rootly timelines remain accurate and complete * Required fields and lifecycle rules are enforced * Retrospective and follow-up processes function properly Always resolve incidents in Rootly to maintain consistent lifecycle data, ensure workflows run correctly, and preserve accurate analytics. *** ## Additional Details & Behaviors ### Service Mapping PagerDuty alerts are routed into Rootly based on the `pagerduty_id` configured on each Rootly Service (and sometimes Teams). Correct mapping ensures: * Alerts appear under the correct Rootly service * Workflows trigger for the right teams * Rootly knows which PagerDuty incidents to update upon resolution If you recently migrated or reorganized services, re-run the Rootly PagerDuty import to refresh all mappings. ### On-Call Requirements (PagerDuty Behavior) PagerDuty only triggers incidents if **someone is on call** for the escalation policy tied to that service. If a PagerDuty alert appears in Rootly but PD did not create an incident, verify that the correct on-call schedule was in place. ### Temporary Migration Flags (Advanced) For complex migrations, Rootly can temporarily allow overlapping PagerDuty IDs using: * `disable_service_pagerduty_id_unique_validation` * `disable_group_pagerduty_id_unique_validation` These are advanced, temporary options—duplicate IDs can cause ambiguous routing. *** ## Troubleshooting Rootly does not auto-create incidents from PD alerts unless you configure an Alert Workflow.\ To proceed: * Click **Create Incident** manually, or * Enable an Alert Workflow to auto-create incidents for selected conditions Check that the Rootly incident is linked to a mapped PD service.\ Resolution syncing only works when a valid mapping exists. Verify and correct the `pagerduty_id` mapping under: **Services → Edit Service** Your workspace may have temporarily disabled unique ID validation.\ Re-enable uniqueness once the transition is complete. *** ## Best Practices * Treat Rootly as the **source of truth** for lifecycle, communication, timelines, and analytics * Use PagerDuty for **alerting and escalation only** * Keep service mapping clean and up to date * Automate incident creation via Alert Workflows for critical services * Always resolve incidents in Rootly * Avoid resolving directly from PagerDuty unless the alert is non-critical or PD-local # Creating Incidents via Slack Interface Source: https://docs.rootly.com/incidents/creating-incidents/creating-incidents-via-slack Create incidents from Slack using slash commands or message actions with customizable fields, validation, severity, and channel auto-creation. ## Overview Slack is one of the fastest and most natural places to declare an incident. Whether a responder notices an issue in conversation, spots a customer report, or sees a monitoring message posted into a channel, Rootly’s Slack integration lets you create an incident instantly — directly from where your team already works. Use Slack when you need **speed**, **context**, and **collaboration without switching tools**. Slack-based creation supports: * Customizable incident fields * Required-field validation * Private incident creation * Automated Slack channel creation * Full integration with workflows and lifecycle updates Need help installing the Rootly Slack app? See the **Slack Integration Guide**. *** ## Create a New Incident in Slack **Method 1 — Use a Slash Command** 1. Type: ```text theme={null} /rootly new ``` in any Slack channel. 2. Press **Enter** to open the New Incident form. This is the fastest way to start a new incident manually. **Method 2 — Create an Incident From a Slack Message** Use this when the trigger is a message, alert, screenshot, or customer report already posted in Slack. 1. Hover over the message 2. Click **More actions** (three dots) 3. Select **Create an incident** The New Incident form will open **pre-filled with a link to the original message**, giving responders immediate context. Message-based creation provides the clearest starting point for responders and is ideal for customer complaints, noisy alerts, or discussions that evolve into incidents. The New Incident form appears as a Slack modal and includes the essential fields needed to start coordinated response. Most fields are customizable in **Configuration → Forms**. New incident form in Slack. **Default Fields** | Field | Description | | :------------------ | :------------------------------------------------------------------- | | **Title** | Title of the incident; also used to name the Slack incident channel. | | **Summary** | A concise description of the issue. | | **Severity** | Default levels SEV3 → SEV0. | | **Type** | Default categories: Cloud, Security, Customer-Facing, Default. | | **Mark as Private** | Restricts visibility to permitted users. | **Additional Notes** * Required fields are marked with a **\*** * Leaving **Title** blank triggers the **Automatic Incident Title Generator** * Only privileged users can create or access **Private** incidents * Private mode is ideal for sensitive or security-related issues If your team uses **Mark as In Triage**, selecting it will start the incident in **Triage** instead of **Started**. See *Incident Lifecycle* for details. Click **Create**. Rootly will immediately: * Create a **dedicated Slack incident channel** * Post the initial system message * Log the creation event in the Timeline * Trigger any configured workflows * Role assignment * Stakeholder notifications * Ticket creation * Checklists * Channel topic updates Most teams automate channel setup, role assignments, and initial communication, so responders can focus on investigation — not coordination. *** ## After the Incident Is Created The Slack incident channel becomes your command center. From here you can: * Update lifecycle status with `/rootly status` * Resolve or cancel with `/rootly resolve` or `/rootly cancel` * Add timeline events * Modify fields using `/rootly edit` * Run workflows using `/rootly workflow` * Generate an AI summary using `/rootly summary` * Invite responders and collaborate in real time All changes sync automatically with the Rootly Web UI and appear in the Timeline. *** ## Customizing the Slack Incident Form Your Slack form can be fully tailored to match your Web UI form. **To customize:** 1. Go to **Configuration → Forms** 2. Under **Default Forms**, click **Configure** on *New Incident* 3. Select the **Slack** tab 4. (Optional) Click **Copy fields from Web form** The editor shows: * Left side → the form structure * Right side → real-time preview Edit new incident form for Slack. **You can customize:** * Field order * Field visibility * Required fields * Custom field types (dropdowns, multi-selects, relations, etc.) **Controls:** * Drag handle → reorder * Pencil icon → edit * Minus icon → remove * **Add Fields** → add new fields Changes save automatically. Rootly recommends keeping Slack and Web forms aligned. This ensures responders have a consistent experience no matter where incidents originate. *** ## Troubleshooting Make sure you’re inside a **Rootly incident channel**, not a normal channel. You need the correct permissions (owner/admin/private-incident access). Your workspace likely uses **sub-statuses**, which disable the mitigate command.\ Use `/rootly status` instead. Your workspace may enforce: * Required fields * Conditional fields * Required lifecycle metadata Check for missing fields marked with **\***. Check: * Slack integration is connected * Auto-create channels is enabled * Private incident behavior matches workspace rules *** ## Best Practices * Prefer **message-based creation** for rich context * Keep fields minimal but meaningful * Use Private mode for sensitive incidents * Train responders to use `/rootly status` for lifecycle updates * Align Slack + Web forms for consistency * Automate repetitive tasks (channel setup, assignments, notifications) High-quality incident creation through Slack accelerates response, reduces confusion, and keeps everyone aligned from the very first minute. # Creating Incidents via Web Interface Source: https://docs.rootly.com/incidents/creating-incidents/creating-incidents-via-web-ui Create incidents through the Rootly web interface with customizable form fields, severity selection, validation rules, and post-creation automation triggers. ## Overview The Rootly web interface provides the most complete and structured way to create an incident. It supports rich field configuration, required-field validation, access controls, and the full power of automations and workflows. Use the web interface when you need clarity, accuracy, and full control over the incident creation experience. The Web UI is the most reliable way to create high-quality incidents. It enforces all required fields, validations, and permissions set by your workspace. *** ## Create a New Incident in the Web App You can initiate a new incident from several locations: * **Dashboard → Create Incident** (top-right) * **Incidents → Create Incident** (top-right) * **Global Action Menu → Create Incident** (bottom-left) This opens the full New Incident form. The New Incident form captures all core information needed to begin coordinated response and trigger automation. Most fields are customizable under **Configuration → Forms**. **Default fields include:** | Field | Description | | :------------------ | :------------------------------------------------------------------ | | **Title** | Name of the incident; also used to generate the Slack channel name. | | **Summary** | Short description of what’s happening. | | **Severity** | Defaults from SEV3 → SEV0. | | **Type** | Defaults: Cloud, Security, Customer-Facing, Default. | | **Mark as Private** | Restricts visibility to permitted users. | **Additional Notes** * Required fields are marked with a **\*** * Leaving **Title** blank activates the **Automatic Incident Title Generator** * Only owners, admins, or privileged users can create/view private incidents * Private incidents are recommended for security-, privacy-, or customer-sensitive issues If your team uses **Mark as In Triage**, selecting this checkbox starts the incident in **Triage** instead of **Started**. See the *Incident Lifecycle* page for details on how these statuses differ. Your workspace may enforce: * Required fields on incident **creation** * Required fields for **specific lifecycle transitions** * Required fields based on **severity**, **incident type**, or **team** If you miss a required field, the Web UI will block submission and highlight the missing values. Completing required metadata during creation prevents blockers later when moving the incident from Started → Mitigated → Resolved. Depending on how your team configures the form, you may see optional sections such as: * Services * Functionalities * Environments * Groups * Incident Types * Labels * Notify Emails * Custom form fields * Test Incident checkbox (if enabled) Adding contextual metadata improves: * Automated routing * Workflow execution * Analytics and dashboards * Retrospective quality Click **Create Incident**. Upon creation, Rootly will automatically: * Create the incident record * Capture lifecycle timestamps (for example, started\_at) * Trigger your incident-creation workflows * Create a Slack incident channel (if enabled) * Assign default responders or roles * Add initial timeline entries * Redirect you to the newly created incident page Most teams automate channel creation, role assignment, and stakeholder notifications to reduce manual overhead and speed up initial response. *** ## After the Incident Is Created Once the incident is open, you can: * Update lifecycle status (Triage → Started → Mitigated → Resolved → Closed) * Assign roles and add responders * Add timeline entries * Attach or review alerts * Trigger or monitor workflows * Publish stakeholder updates * Track action items and tasks * Join the Slack channel associated with the incident All changes are tracked automatically and appear in the Timeline for retrospective analysis. *** ## Customizing the New Incident Form Navigate to: **Configuration → Forms → New Incident → Configure** Then select the **Web** tab. You can optionally copy the structure from the Slack form using: **Copy fields from Slack form** * Left panel: current form structure * Right panel: real-time preview You can customize: * Field order * Field visibility * Required fields * Custom field types (dropdowns, multi-selects, relations, etc.) Use: * **Drag handle (six dots)** → reorder fields * **Pencil icon** → edit a field * **Minus icon** → remove a field * **Add Fields** → add new fields Changes save automatically. Rootly recommends keeping Slack and Web forms aligned so responders have a consistent experience regardless of where incidents are created. *** ## Troubleshooting Check for: * Missing required fields * Missing permissions * Private incident restrictions Confirm that workflow conditions match: * Severity * Type * Services * Environments * Groups Required-fields enforcement or conditional visibility rules may be preventing submission. Verify: * Slack integration is enabled * Auto-channel creation is turned on * The incident wasn’t created as private (depending on workspace rules) *** ## Best Practices * Use structured fields (Severity, Services, Environments) for clarity & analytics * Keep required fields minimal but meaningful * Use Private mode for security or privacy-sensitive incidents * Align Slack and Web forms for consistency * Automate repetitive creation steps with workflows * Provide descriptive titles and actionable summaries High-quality incident creation dramatically accelerates response and improves clarity for everyone involved. # Incident Title Generator Source: https://docs.rootly.com/incidents/creating-incidents/incident-title-generator Learn how Rootly automatically generates unique incident titles using random adjective–noun combinations while allowing full customization and manual editing. ## How the Incident Title Generator Works Rootly can automatically generate a unique title for an incident when you leave the **Title** field blank. The generator creates a memorable two-word phrase by combining: * An adjective * A noun Both words come from your organization’s **configurable word banks**. This ensures that every incident—manual or automated—has a distinct title, even if responders forget to provide one. Users may edit the title at any time during the incident lifecycle. If a user does not enter a title, Rootly automatically assigns one using the team’s configured adjective and noun lists. *** ## Title Generation Logic When Rootly generates a title: 1. It collects adjectives and nouns used in incident titles **within the last year**. 2. These recently used words are added to an exclusion list to reduce repeats. 3. Rootly selects a random adjective and noun from your team’s configured word banks. 4. The result is **titleized** (for example, `"sleepy server"` → `"Sleepy Server"`). 5. The incident is marked with `title_autogenerated = true`. This logic applies to: * Incidents created in the Web UI * Incidents created via Slack * Incidents created via the API API-created incidents also auto-generate titles if the payload omits the `title`.\ The API response includes `title_autogenerated` so automation can detect system-generated titles. *** ## Configuring the Word Banks Admins may customize the adjective and noun lists used for generation. You can update these from: **Organization Settings → Show Advanced Settings → Incident Title Generator** Configuration options include: List of allowed adjectives. List of allowed nouns. Exclusion logic is automatic (based on 1 year of past incidents). Customizing your word banks allows incident names to better reflect your organization’s culture, domains, and terminology. *** ## Optional: AI-Generated Titles With [Rootly AI](/ai/ai-settings) opted in, responders can replace a generated title with an AI-written one: run `/rootly update` in the incident channel and click **Generate with AI**. Rootly AI reads the incident's summary, alerts, and early timeline to produce the title. See [AI Summaries](/ai/ai-summaries#generated-titles). *** ## Titles in External Integrations When exporting incidents to tools like PagerDuty or Opsgenie: * If the title was auto-generated, Rootly may prefer using the **summary** as the outbound title. * Rootly prepends the **severity** to outbound titles when appropriate. Example: \[SEV2] Database Latency Degradation This ensures external systems receive clear, actionable titles. *** ## Best Practices * **Let Rootly auto-generate titles** when responders are busy—clean-up can happen later. * **Customize your adjective/noun lists** to improve clarity and team culture. * **Use AI generation** for complex or ambiguous incidents. * **Edit titles manually** once the incident scope is understood. * **Avoid relying solely on the title** for operational details—pair it with a strong summary. *** ## Frequently Asked Questions Yes. Titles can be edited at any point during the incident lifecycle. Rootly excludes adjectives and nouns used in the past year to reduce duplication. Yes. If `title` is omitted, Rootly generates one automatically and marks it as auto-generated (`title_autogenerated: true`). Not currently. Titles always follow the adjective + noun format unless manually edited or overwritten by AI. External integrations may use the summary instead when the title is autogenerated. Severity may also be prefixed automatically. *** ## Related Pages Where auto-generated titles fit in the incident creation flow. The umbrella page covering how incidents work end-to-end. Regenerate or override titles later in the incident lifecycle via workflow actions. # Incident Lifecycle Source: https://docs.rootly.com/incidents/incident-lifecycle How Rootly models an incident from triage through closure — every status, the timestamps each one records, and how transitions actually happen. Every incident in Rootly moves through a sequence of **statuses** that mirror how teams actually respond: contain uncertainty, coordinate a response, contain impact, fix the underlying issue, and wrap up the follow-up work. Each transition records a timestamp, which powers MTTx analytics, retrospectives, and workflow automation. ## Overview Rootly's incident status model has six primary statuses and two optional timestamps. A status change is made from the web UI, from Slack (`/rootly mitigate`, `/rootly resolve`, `/rootly cancel`), or via workflow automation — and Rootly records the corresponding timestamp automatically. | Status | Data Value | Timestamp | Notes | | :-------- | :---------- | :------------- | :--------------------------------------------------- | | Triage | `in_triage` | `in_triage_at` | Only recorded if the incident actually enters Triage | | Started | `started` | `started_at` | Set when coordinated response begins | | Mitigated | `mitigated` | `mitigated_at` | Impact contained; work continues | | Resolved | `resolved` | `resolved_at` | Underlying issue fixed | | Closed | `closed` | `closed_at` | All follow-up work complete | | Cancelled | `cancelled` | `cancelled_at` | False positive or duplicate; Triage-only | Two additional timestamps — `detected_at` and `acknowledged_at` — are separate fields, not statuses. They power MTTD and MTTA metrics without changing the incident's primary status. *** ## Triage Incidents often begin with ambiguous signals. **Triage** is designed for the early moment when something *might* be wrong, but responders aren't yet certain. Notifications are limited so teams can investigate without alarming broader stakeholders. **Enter Triage by:** * Selecting **Mark as In Triage** when creating the incident * Updating the status from the incident page or `/rootly status` in Slack Triage contains scope of impact. Use it when the signal is real but unconfirmed — you can always promote to Started once you're sure. *** ## Started Once responders confirm the issue is real, the incident moves to **Started**. This is the point of coordinated response: roles get assigned, communication channels open, and early hypotheses form. **Enter Started by:** * Leaving **Mark as In Triage** *unchecked* at creation — Rootly sets Started directly * Moving from Triage → Started from the incident page or Slack Skipping Triage during creation is common for confirmed incidents. Rootly sets the incident straight to Started with no intermediate Triage timestamp. *** ## Mitigated **Mitigated** means the immediate impact has been contained. Users may still be affected, but the incident is no longer actively getting worse. This is common when a failover, temporary fix, or emergency control has been applied while the underlying issue is still being investigated. **Enter Mitigated by:** * Clicking **Mitigate** on the incident page * Running `/rootly mitigate` in Slack If an incident moves straight to Resolved without passing through Mitigated, Rootly sets `mitigated_at` equal to `resolved_at` so time-to-mitigate analytics stay accurate. *** ## Resolved An incident is **Resolved** when the underlying issue has been fixed and service impact is no longer present. This is the moment that typically triggers stakeholder updates and kicks off the retrospective process. **Enter Resolved by:** * Clicking **Resolve** on the incident page * Running `/rootly resolve` in Slack Many teams configure a workflow to automatically generate a retrospective when an incident reaches Resolved. See [Configuring Templates](/retrospectives/configuring-templates). *** ## Closed **Resolved** means the system is fixed. **Closed** means all follow-up work is complete — retrospectives published, action items verified, and communications wrapped up. Closed is optional but recommended: it separates technical completion from process completion, so dashboards can distinguish "fixed" from "fully done". Closed status is controlled per-team via **Configuration → Teams → Enable Closed Status**. When disabled, incidents transition directly from Resolved to their final state without a separate Closed step. *** ## Cancelled A **Cancelled** incident is a false positive or a duplicate. Cancelling prevents wasted responder effort and keeps analytics clean by excluding non-actionable events from your incident metrics. **Enter Cancelled by:** * Clicking **Cancel Incident** on the incident page * Running `/rootly cancel` in Slack Cancel is only available while the incident is in Triage. Once an incident is Started, it must go through the normal Resolved path — even if it turns out to be non-impactful. *** ## Optional Timestamps Two timestamps sit alongside the primary statuses to support detection and acknowledgement metrics: When the issue was first *noticed* — often earlier than when response formally began. Powers MTTD (Mean Time To Detect). When a specific responder took ownership of the incident. Pauses paging escalations and clarifies responsibility. Powers MTTA (Mean Time To Acknowledge). Neither field changes the incident's primary status. Both can be set from the incident page, updated via API, or backfilled with **Update Timestamps** — see [Updating Incident Timestamps](/incidents/managing-incidents/updating-incident-timestamps). *** ## Planned Maintenance Rootly models scheduled operational work with its own lifecycle values, distinct from unplanned incidents: | Status | Data Value | What It Means | | :---------- | :------------ | :------------------------------------------------------------------ | | Planning | `planning` | Scope and impact being defined | | Scheduled | `scheduled` | Approved for a specific window (`scheduled_for`, `scheduled_until`) | | In Progress | `in_progress` | Work is underway | | Completed | `completed` | Work is finished | | Verifying | `verifying` | Final checks in progress | Planned maintenance uses the same automation, timeline, and retrospective machinery as normal incidents. See [Scheduling a Maintenance Incident](/incidents/incident-operations/scheduling-a-maintenance-incident). *** ## Incident Timeline Every incident has a **Timeline** that captures status changes, role assignments, workflow actions, Slack updates, alert events, and manual entries in one chronological view. It's the source of truth for retrospectives and stakeholder recaps. Timeline entries can be added from Slack, the web UI, email-to-incident, or automations. See [Incident Timeline](/incidents/incident-timeline/incident-timeline). *** ## Troubleshooting Cancel is only available while the incident is in Triage. If the incident has already moved to Started, resolve it as normal — cancellation isn't possible from later stages. If the incident went straight from Started to Resolved without a Mitigate action, Rootly sets `mitigated_at` equal to `resolved_at`. To backfill a true mitigation timestamp, use **Update Timestamps** on the incident page. Closed is controlled per-team. Ask an admin to check **Configuration → Teams → Enable Closed Status**. When disabled, incidents finalize at Resolved. Common causes: * The incident is already Resolved, Closed, or Cancelled — check the channel header before running the command. * Your team has **Sub-Statuses** enabled, which disables `/rootly mitigate` by design. Use `/rootly status` and pick the appropriate sub-status instead. See [Managing Incident Status via Slack](/incidents/managing-incidents/managing-incident-status-via-slack) for the full sub-status flow. *** ## Frequently Asked Questions Use **Triage**. It limits notifications and keeps early investigation to a small responder group. Promote to **Started** once you're confident the issue is real. Yes. Leave **Mark as In Triage** unchecked at creation and Rootly sets the incident directly to Started. No `in_triage_at` timestamp is recorded. No. Mitigated is optional but recommended. If you go straight to Resolved, Rootly sets `mitigated_at = resolved_at` automatically so MTTM analytics still work. **Resolved** means the technical issue is fixed and impact is gone. **Closed** means all follow-up work — retrospective, action items, comms — is complete. Many teams resolve within hours but close days later. They're timestamp fields, not statuses. `detected_at` and `acknowledged_at` power MTTD and MTTA metrics but the incident's primary status keeps moving through the main lifecycle (Triage → Started → Mitigated → Resolved). You can add **sub-statuses** underneath the primary statuses to model your team's more granular process (for example, "Investigating" or "Awaiting Vendor" beneath Started). See [Incident Sub-Statuses](/configuration/incident-status). In [Action Items](/incidents/action-items/action-items). Once every action item is closed and the retrospective is published, move the incident to Closed. *** ## Related Pages The umbrella page covering how incidents work end-to-end. Transition rules, timestamp validation, and sub-statuses beneath the primary lifecycle stages. Where lifecycle-relevant properties like severity and status are configured. # Creating Sub-Incidents Source: https://docs.rootly.com/incidents/incident-operations/creating-sub-incident Learn how to split large incidents into sub-incidents for better organization across multiple teams, with workflow automation support. ## Overview For larger or cross-functional incidents, you may want to break work into **sub-incidents**.\ A sub-incident allows a team to investigate, coordinate, and track their scope independently—while maintaining shared context with the parent incident. Each parent incident can have **multiple sub-incidents**. *** ## What Is a Sub-Incident? A sub-incident is a normal incident that is linked to a parent using `parent_incident_id`.\ Rootly automatically assigns the sub-incident a kind based on its parent: * `normal_sub` * `test_sub` * `scheduled_sub` Sub-incidents are **not** the same as duplicate incidents.\ Duplicates link via `duplicate_incident_id` and do *not* form a hierarchy. *** ## Restrictions * Sub-incidents **cannot be split further** (no nested sub-incidents). * A sub-incident **must have** a parent incident. * You cannot create a sub-incident **from an existing sub-incident**. * Some UI options (like “Attach to Parent Incident”) only appear when: * The incident is not already a sub-incident * It has no existing sub-incidents * You have permission to create incidents *** ## Creating Sub-Incidents Rootly supports creating sub-incidents through two interfaces: 1. **Slack** – Use commands such as `/rootly sub`, `/rootly split`, `/rootly fork`, or `/rootly swimlane`\ → [**See the Slack guide →**](/incidents/incident-operations/slack-creating-a-sub-incident) 2. **Web** – Use **Create Sub-Incident** or **Attach to Parent Incident** from the incident menu\ → [**See the Web guide →**](/incidents/incident-operations/web-creating-a-sub-incident) *** Use any of the following commands in the **parent incident’s Slack channel**: ```text theme={null} /rootly split /rootly sub /rootly fork /rootly swimlane ``` This opens the **Create Sub-Incident** modal, already linked to the parent. Slack enforces: * You must be in an incident channel * The parent cannot itself be a sub-incident * You must have permission to create incidents Slack-created sub-incidents use the same logic as Web-created sub-incidents, including workflow triggers and automatic Slack-channel creation (when enabled). From the parent incident: * Click **…** → **Create Sub-Incident**, or * Use **Attach to Parent Incident** to convert an existing incident into a sub-incident When attaching an existing incident, Rootly updates its kind and sets its parent relationship. *** ## What Gets Inherited? Depending on your configuration, sub-incidents may inherit: * Severity * Status * Privacy settings * Incident types * Attached services, functionalities, environments * Teams / groups * Jira epic or Google Drive folder links * Slack channel creation settings *** ## Configuring Workflows for Sub-Incidents Sub-incidents are fully compatible with Rootly Workflows. To target sub-incidents, set a workflow condition such as: ```text theme={null} Kind → is one of → normal_sub, test_sub, scheduled_sub ``` Use cases include: * Creating role assignments for sub-incident teams * Syncing updates to the parent incident * Auto-generating investigative tasks * Auto-creating a Slack channel for each sub-incident *** ## Best Practices * **Use sub-incidents to delegate ownership** to teams like SRE, Security, or Networking. * **Keep the parent incident customer-facing**, using sub-incidents to track internal workstreams. * **Use workflows to create structure**, such as templated tasks, roles, or Slack-channel creation. * Use the `Create a sub incident` Workflow Action to automatically create a sub-incident for specific scenarios, like being able to coordinate with stakeholders outside of your engineering response teams. [See this in action here](https://www.loom.com/share/e6f038a78d8e4dec8a51c06e557e4298). * **Avoid unnecessary splitting**—small tasks can often stay in the parent incident. * **Name sub-incidents cleanly and consistently**, reflecting the scope of work. *** ## Troubleshooting This occurs when: * The incident is **already a sub-incident** * It has its **own sub-incidents** * You do not have **permission to create incidents** Slack prevents splitting when: * You are not in an incident channel * The incident is a **sub-incident** * You lack required permissions Inheritance depends on: * Workflows that override defaults * Creation method (Slack vs Web) * Privacy restrictions This happens when: * The incident is already a sub-incident * It has existing sub-incidents * It is a scheduled maintenance incident * Permissions prevent linking Sub-incidents group parallel workstreams of one active event, and [marking as duplicate](/incidents/incident-operations/marking-as-duplicate) links two records of the same event. For a failure that keeps coming back across separate incidents, tag the incidents instead: 1. Pick a marker: an incident **Type**, a **Cause**, or a [custom field](/configuration/custom-fields), or a combination. 2. Set it on each incident during the response or in the retrospective. 3. Filter the incidents list by that marker to see the full set of matching incidents in one view. 4. To analyze the set — recurrence, severity, time to resolve — add a [custom dashboard panel](/metrics/customized-dashboards) with a panel-level filter on the same marker. Dashboard-level filters cover date range, period, team, and service; Type, Cause, and custom fields are configured per panel. You can also pull the tagged set through the API to analyze recurring themes externally. *** ## Related Pages The adjacent operation — consolidate related incidents instead of splitting into sub-incidents. The umbrella page covering how incidents work end-to-end. The status and timestamp model sub-incidents move through, same as parent incidents. # Marking Incidents as Duplicate Source: https://docs.rootly.com/incidents/incident-operations/marking-as-duplicate Mark incidents as duplicates in Rootly to consolidate response efforts via the web UI, Slack, or API, with auto-cancellation support and parent linking. ## How Duplicate Incidents Work During fast-moving operational issues, teams may accidentally create multiple incidents describing the same underlying problem. Rootly allows you to **mark one incident as the duplicate of another**, ensuring responders align around a single source of truth. When an incident is marked as a duplicate: * The *duplicate* incident is linked to a *canonical* (primary) incident * The duplicate’s timeline records the change * Workflows, alerts, and Slack channels can consolidate under the primary incident * Optionally, the duplicate incident can be automatically **cancelled** This helps reduce fragmentation, avoid duplicate work, and maintain accurate historical records. Duplicate incidents use a dedicated field (`duplicate_incident_id`) and are **not** the same as sub-incidents, which use `parent_incident_id`. *** ## Why Mark Incidents as Duplicate Teams benefit from merging duplicates because it: * Ensures responders focus on the correct incident * Reduces conflicting updates or duplicated communication * Clarifies ownership and priority * Simplifies retrospectives and reporting * Maintains a clean incident list without losing context Typical scenarios include: * Multiple teams declare the same outage simultaneously * Monitoring tools trigger multiple detection paths * Slack responders create overlapping incidents during triage *** ## What Happens When You Mark an Incident as Duplicate When you mark Incident A as a duplicate of Incident B: * Incident A becomes linked to Incident B * A timeline entry is added to Incident A * Slack responders receive a confirmation message * (Optional) Incident A is automatically **cancelled** and any attached alerts are resolved * The “Duplicate of …” banner appears in the duplicate incident UI This ensures full transparency on how and why incidents were consolidated. Auto-cancellation is enabled by default when marking a duplicate but can be turned off during the action. *** ## Where You Can Manage Duplicates ### **In the Web Interface** From an incident, open the action menu and select **Mark as Duplicate**.\ You can then: * Search for the canonical incident * Choose whether to auto-cancel the duplicate * Add a cancellation reason for context A redirect takes you to the canonical incident after completion. [Learn how to mark duplicates via Web →](/incidents/incident-operations/web-marking-as-duplicate) *** ### **In Slack** Use one of the supported commands: * **`/rootly dup`** * **`/rootly duplicate`** This opens a modal where you can: * Select the canonical incident * Provide a cancellation reason * Enable/disable auto-cancel Slack posts a confirmation message to the duplicate’s channel when completed. Duplicate marking is not available for scheduled maintenance incidents. [Learn how to mark duplicates via Slack →](/incidents/incident-operations/slack-marking-as-duplicate) *** ## API Support You can also mark incidents as duplicates programmatically using: ```http theme={null} POST /api/v1/incidents/:id/duplicate ``` Supported attributes: The canonical incident this incident is a duplicate of. When true, the duplicate is automatically cancelled after linking. Enabled by default — matches the Web and Slack flows. Free-text context recorded on the cancellation — helpful for retrospectives and audit trails. Rootly updates the relationship and adds a timeline entry automatically. API duplicate linking does not automatically resolve attached alerts—this behavior is only available via Slack or Web. *** ## Best Practices * **Always consolidate early**\ Merge duplicate incidents as soon as duplication is detected to reduce confusion. * **Use auto-cancel thoughtfully**\ Cancelling duplicates keeps your incident list clean, but you may leave them open temporarily during complex triage. * **Write clear cancellation reasons**\ Adds helpful context for retrospectives and audit history. * **Educate responders on Slack commands**\ Many duplicates are resolved faster when responders use `/rootly dup`. * **Review duplicate patterns**\ Repeated duplicates may highlight monitoring or workflow tuning opportunities. *** ## Frequently Asked Questions Duplicate incidents refer to the **same problem**, while sub-incidents represent **related but distinct workstreams**. Yes. Edit the incident to remove the duplicate relationship and update the status. Yes, but only if you have permission to view the target incident. Any responder with **update** permission on the incident (including private-incident permissions when relevant). No. Timelines remain separate, but all future response activity should occur in the canonical incident. *** ## Related Pages The adjacent operation — split into sub-incidents instead of consolidating. The umbrella page covering how incidents work end-to-end. What happens to lifecycle state when an incident is marked as a duplicate. # Scheduling Maintenance Incidents Source: https://docs.rootly.com/incidents/incident-operations/scheduling-a-maintenance-incident Learn how to schedule and manage maintenance incidents for planned service interruptions, including Slack channel creation and status page integration.