Try Live
Add Docs
Rankings
Pricing
Enterprise
Docs
Install
Theme
Install
Docs
Pricing
Enterprise
More...
More...
Try Live
Rankings
Create API Key
Add Docs
Incident.io Terraform Provider
https://github.com/incident-io/terraform-provider-incident
Admin
The official Terraform provider for incident.io, enabling management of incident severities, roles,
...
Tokens:
83,512
Snippets:
951
Trust Score:
8.1
Update:
3 days ago
Context
Skills
Chat
Benchmark
69.9
Suggestions
Latest
Show doc for...
Code
Info
Show Results
Context Summary (auto-generated)
Raw
Copy
Link
# terraform-provider-incident ## Introduction The `terraform-provider-incident` is the official Terraform provider for [incident.io](https://incident.io), an incident management platform. It enables teams to manage their entire incident.io configuration as code — including on-call schedules, escalation paths, alert routing, custom fields, catalog types, workflows, severities, and incident roles. By codifying this configuration in Terraform, teams gain reproducibility, version control, and consistency across environments. The provider is published to the [Terraform Registry](https://registry.terraform.io/providers/incident-io/incident/latest) and supports Terraform's standard import workflow, making it easy to bring existing incident.io configuration under Terraform management. The provider wraps the incident.io public API and is implemented in Go using the `hashicorp/terraform-plugin-framework`. The latest stable version is **v5.35.0**, with a linear release history tracked in `CHANGELOG.md`. The entire codebase is a flat, unversioned structure — all resources, data sources, documentation, and examples represent the current latest version of the provider. Authentication is handled via an API key, supplied directly in the provider configuration or via the `INCIDENT_API_KEY` environment variable. --- ## Provider Configuration Configure the provider by supplying an API key. Get one at https://app.incident.io/settings/api-keys. ```terraform terraform { required_providers { incident = { source = "incident-io/incident" version = "~> 5.35" } } } provider "incident" { api_key = var.incident_api_key # or set INCIDENT_API_KEY env var # endpoint = "https://api.incident.io" # optional, override API URL } ``` **Schema:** - `api_key` (String, Sensitive, Optional) — Sourced from `INCIDENT_API_KEY` environment variable if not set inline. - `endpoint` (String, Optional) — Override the incident.io API base URL. --- ## Resources ### `incident_severity` Manage incident severities. Each incident has a severity, used to communicate urgency/impact and for filtering and workflow triggers. ```terraform resource "incident_severity" "critical" { name = "Critical" description = "Major customer-facing outage requiring immediate response." rank = 1 # lower numbers = less severe; use rank to order } resource "incident_severity" "trivial" { name = "Trivial" description = "Issues causing no impact. No immediate response required." } ``` **Schema:** - `name` (String, Required) — Human readable name. - `description` (String, Required) — Description of the severity. - `rank` (Number, Optional) — Sort order (lower = less severe). - `id` (String, Read-Only) — Unique identifier. **Import:** ```shell terraform import incident_severity.example 01ABC123DEF456GHI789JKL ``` --- ### `incident_incident_role` Manage incident roles. Roles are assigned to responders during an incident. Every organization has a special `lead` role (incident commander) that cannot be deleted. ```terraform resource "incident_incident_role" "comms" { name = "Communications Lead" description = "Responsible for communications on behalf of the response team." instructions = "Manage internal and external communications on behalf of the response team." shortform = "comms" } ``` **Schema:** - `name` (String, Required) — Human readable name. - `description` (String, Required) — Purpose of the role. - `instructions` (String, Required) — Provided to whoever is nominated (empty for `reporter` role). - `shortform` (String, Required) — Short name for Slack (empty for `reporter` role). - `id` (String, Read-Only) — Unique identifier. **Import:** ```shell terraform import incident_incident_role.example 01ABC123DEF456GHI789JKL ``` --- ### `incident_custom_field` Manage custom fields that attach metadata to incidents. Custom fields appear in the dashboard, in workflows, and in announcement rules. **Supported field types:** `single_select`, `multi_select`, `text`, `link`, `numeric` ```terraform # Multi-select field for affected teams resource "incident_custom_field" "affected_teams" { name = "Affected Teams" description = "The teams that are affected by this incident." field_type = "multi_select" } # Text field for a customer ID resource "incident_custom_field" "customer_id" { name = "Customer ID" description = "The ID of the affected customer." field_type = "text" } # Numeric field resource "incident_custom_field" "customers_affected" { name = "Customers Affected" description = "How many customers are impacted." field_type = "numeric" } ``` **Schema:** - `name` (String, Required) — Human readable name. - `description` (String, Required) — Description of the field. - `field_type` (String, Required) — One of: `single_select`, `multi_select`, `text`, `link`, `numeric`. - `catalog_type_id` (String, Optional) — For catalog-backed fields, the ID of the catalog type. - `filter_by` (Attributes, Optional) — Filter options based on another custom field's value. - `catalog_attribute_id` (String, Required) - `custom_field_id` (String, Required) - `group_by_catalog_attribute_id` (String, Optional) — Group catalog entries by this attribute. - `helptext_catalog_attribute_id` (String, Optional) — Attribute providing help text for options. - `id` (String, Read-Only) — Unique identifier. **Import:** ```shell terraform import incident_custom_field.example 01ABC123DEF456GHI789JKL ``` --- ### `incident_custom_field_option` Manage options for `single_select` or `multi_select` custom fields. ```terraform resource "incident_custom_field" "affected_teams" { name = "Affected Teams" description = "The teams that are affected by this incident." field_type = "multi_select" } # Use for_each to create multiple options at once resource "incident_custom_field_option" "teams" { for_each = toset(["Payments", "Dashboard", "API", "Platform"]) custom_field_id = incident_custom_field.affected_teams.id value = each.value sort_key = 10 # optional; controls display order } ``` **Schema:** - `custom_field_id` (String, Required) — ID of the parent custom field. - `value` (String, Required) — The text value of this option. - `sort_key` (Number, Optional) — Controls display order of options. - `id` (String, Read-Only) — Unique identifier. **Import:** ```shell terraform import incident_custom_field_option.example 01ABC123DEF456GHI789JKL ``` --- ### `incident_catalog_type` Create and manage catalog types — categories of things in your organization (services, teams, product features, etc.). Each type becomes a schema for catalog entries. ```terraform resource "incident_catalog_type" "service_tier" { name = "ServiceTier" type_name = "Custom[\"ServiceTier\"]" description = "How critical is this service (tier 1 = highest, tier 3 = lowest)." categories = ["service"] source_repo_url = "https://github.com/mycompany/infrastructure" } resource "incident_catalog_type" "service" { name = "Service" description = "All services that we run across our product" categories = ["service"] source_repo_url = "https://github.com/mycompany/services-catalog" } ``` **Schema:** - `name` (String, Required) — Human readable name. - `description` (String, Required) — Human readable description. - `source_repo_url` (String, Required) — URL to external repo managing this type; makes it read-only in the UI. - `type_name` (String, Optional, Immutable) — Type name for use in attribute definitions. Must follow `Custom["SomeName"]` pattern. - `categories` (List of String, Optional) — One or more of: `customer`, `issue-tracker`, `product-feature`, `service`, `on-call`, `team`, `user`. - `use_name_as_identifier` (Boolean, Optional) — Allow lookup by name in addition to ID. - `id` (String, Read-Only) — Unique identifier. **Import:** ```shell terraform import incident_catalog_type.example 01ABC123DEF456GHI789JKL ``` --- ### `incident_catalog_type_attribute` Define attributes (fields) on a catalog type. Attributes can be primitive types (`Text`, `String`, `Number`, `Boolean`) or references to other catalog types. ```terraform resource "incident_catalog_type_attribute" "service_description" { catalog_type_id = incident_catalog_type.service.id name = "Description" type = "Text" } resource "incident_catalog_type_attribute" "service_tags" { catalog_type_id = incident_catalog_type.service.id name = "Tags" type = "String" array = true # multi-value attribute } # Cross-reference another catalog type resource "incident_catalog_type_attribute" "service_tier_ref" { catalog_type_id = incident_catalog_type.service.id name = "Tier" type = incident_catalog_type.service_tier.type_name } # Backlink: Service Tier -> Services (reverse of service.tier) resource "incident_catalog_type_attribute" "service_tier_services" { catalog_type_id = incident_catalog_type.service_tier.id name = "Services" type = incident_catalog_type.service.type_name backlink_attribute = incident_catalog_type_attribute.service_tier_ref.id } ``` **Schema:** - `catalog_type_id` (String, Required) — ID of the catalog type this attribute belongs to. - `name` (String, Required) — Attribute name. - `type` (String, Required) — Attribute type (e.g., `Text`, `String`, `Number`, `Boolean`, or another catalog type's `type_name`). - `array` (Boolean, Optional) — Whether this is a multi-value attribute. - `backlink_attribute` (String, Optional) — For backlinks, the ID of the forward-link attribute. - `path` (List of String, Optional) — For path attributes, the navigation path. - `schema_only` (Boolean, Optional) — If true, Terraform only manages the schema; values can be edited in the UI. - `id` (String, Read-Only). **Import:** ```shell terraform import incident_catalog_type_attribute.example 01CATALOGTYPE:01ATTRIBUTEID ``` --- ### `incident_catalog_entry` Manage a single catalog entry. Best for small numbers of entries (<100) or when you don't want Terraform to be authoritative (i.e., it won't delete entries it doesn't manage). ```terraform locals { service_tiers = [ { name = "tier_1", description = "Critical customer-facing services", external_id = "service-tier-1" }, { name = "tier_2", description = "Either customers or internal processes are impacted", external_id = "service-tier-2" }, { name = "tier_3", description = "Non-essential services", external_id = "service-tier-3" }, ] } resource "incident_catalog_entry" "service_tier" { for_each = { for tier in local.service_tiers : tier.name => tier } catalog_type_id = incident_catalog_type.service_tier.id name = each.value.name external_id = each.value.external_id aliases = [each.value.name] # optional alternative identifiers attribute_values = [ { attribute = incident_catalog_type_attribute.service_tier_description.id value = each.value.description }, ] } ``` **Schema:** - `catalog_type_id` (String, Required) - `name` (String, Required) - `attribute_values` (Attributes Set, Required) — Set of `{ attribute, value, array_value }`. - `external_id` (String, Optional) — Stable ID from the upstream system. - `aliases` (List of String, Optional) — Alternative reference identifiers. - `managed_attributes` (Set of String, Optional) — Only manage specific attributes (useful for partially-managed entries like Schedules). - `rank` (Number, Optional) — For ranked catalog types. - `id` (String, Read-Only). **Import:** ```shell terraform import incident_catalog_entry.example 01ABC123DEF456GHI789JKL ``` --- ### `incident_catalog_entries` Authoritative bulk management of all entries for a catalog type. Use when loading many (>100) entries or when you want Terraform to be the single source of truth (it will delete any unmanaged entries). ```terraform # Load entries from a JSON file (e.g., exported from Backstage) locals { catalog = { for entry in jsondecode(file("catalog.json")) : entry["uid"] => entry } } resource "incident_catalog_type" "service" { name = "Service" description = "All services that we run at Example Org" } resource "incident_catalog_type_attribute" "service_owner" { catalog_type_id = incident_catalog_type.service.id name = "Owner" type = "String" } resource "incident_catalog_entries" "services" { id = incident_catalog_type.service.id entries = { for external_id, entry in local.catalog : external_id => { name = entry["metadata"]["name"] aliases = [entry["metadata"]["name"]] attribute_values = { for attribute, binding in { (incident_catalog_type_attribute.service_owner.id) = { value = try(entry["spec"]["owner"], null) }, } : attribute => binding if try(binding.value, binding.array_value) != null } } } } ``` **Schema:** - `id` (String, Required) — The catalog type ID. - `entries` (Attributes Map, Required) — Map from external ID to entry definition. - Each entry: `name` (Required), `attribute_values` (Attributes Map, Required), `aliases` (List, Optional), `rank` (Number, Optional). - `managed_attributes` (Set of String, Optional) — Restrict which attributes are managed. **Import:** ```shell terraform import incident_catalog_entries.example 01ABC123DEF456GHI789JKL ``` --- ### `incident_alert_attribute` Manage alert attributes — structured fields parsed from incoming alerts to label and route them. ```terraform # Catalog-backed attribute pointing to a GitHub user entry resource "incident_alert_attribute" "github_user" { name = "Github user" type = "CatalogEntry[\"Github User\"]" array = false required = true } # Simple string attribute with an emoji indicator resource "incident_alert_attribute" "severity" { name = "Severity" type = "String" array = false required = false emoji = "warning" } # Array attribute for multiple teams resource "incident_alert_attribute" "teams" { name = "Teams" type = "CatalogEntry[\"Team\"]" array = true required = false } ``` **Schema:** - `name` (String, Required) — Unique name. - `type` (String, Required) — Engine resource name (e.g., `String`, `Number`, `CatalogEntry["TypeName"]`). - `array` (Boolean, Required) — Whether the attribute accepts multiple values. - `required` (Boolean, Optional) — If not set, existing setting is preserved. - `emoji` (String, Optional) — Emoji shown in chat messages (without colons). - `id` (String, Read-Only). **Import:** ```shell terraform import incident_alert_attribute.example 01ABC123DEF456GHI789JKL ``` --- ### `incident_alert_source` Configure alert sources — the external systems that send alerts to incident.io. Supports webhooks, email, CloudWatch, Jira, heartbeats, and more. ```terraform resource "incident_alert_source" "cloudwatch" { name = "CloudWatch Alerts" source_type = "cloudwatch" template = { title = { literal = jsonencode({ content = [{ content = [{ attrs = { label = "Payload → Title", missing = false, name = "title" }, type = "varSpec" }], type = "paragraph" }] type = "doc" }) } description = { literal = jsonencode({ content = [{ content = [{ attrs = { label = "Payload → Description", missing = false, name = "description" }, type = "varSpec" }], type = "paragraph" }] type = "doc" }) } attributes = [ { alert_attribute_id = incident_alert_attribute.teams.id binding = { value = { reference = "expressions[\"cloudwatch-team\"]" } merge_strategy = "first_wins" } } ] expressions = [ { label = "Team" reference = "cloudwatch-team" root_reference = "payload" operations = [{ operation_type = "parse" parse = { returns = { array = false, type = "CatalogEntry[\"CatalogEntryID\"]" } source = "$['query_params']['team']" } }] } ] } } # Wire up an AWS SNS subscription resource "aws_sns_topic_subscription" "incidentio" { endpoint = "https://api.incident.io/v2/alert_events/cloudwatch/${incident_alert_source.cloudwatch.id}" endpoint_auto_confirms = true protocol = "https" topic_arn = aws_sns_topic.alerts.arn } ``` **Schema:** - `name` (String, Required) - `source_type` (String, Required) — Type of source (e.g., `cloudwatch`, `http`, `email`, `jira`, `heartbeat`). - `template` (Attributes, Required) — Defines how to parse `title`, `description`, `attributes`, `expressions`. - `auto_resolve_timeout_minutes` (Number, Optional) — Auto-resolve alerts after N minutes. - `auto_resolve_incident_alerts` (Boolean, Optional) — Auto-resolve incident alerts on alert resolution. - `heartbeat_options` (Attributes, Optional) — `interval_seconds`, `failure_threshold`, `grace_period_seconds`. - `http_custom_options` (Attributes, Optional) — `deduplication_key_path`, `transform_expression` (ES5 JS). - `jira_options` (Attributes, Optional) — `project_ids`. - `owning_team_ids` (Set of String, Optional). - `alert_events_url` (String, Read-Only) — Webhook URL for this source. - `secret_token` (String, Read-Only) — Authentication token for the source. - `id` (String, Read-Only). **Import:** ```shell terraform import incident_alert_source.example 01ABC123DEF456GHI789JKL ``` --- ### `incident_alert_route` Configure alert routes — rules that define how alerts from sources are processed, grouped, and dispatched to teams. It is recommended to build alert routes in the [web dashboard](https://app.incident.io/~/alerts/configuration) using the Export flow, then manage them in Terraform. ```terraform resource "incident_alert_route" "service_alerts" { name = "Service Alerts" enabled = true is_private = false alert_sources = [{ alert_source_id = incident_alert_source.cloudwatch.id condition_groups = [{ conditions = [{ subject = "alert.title" operation = "is_set" param_bindings = [] }] }] }] condition_groups = [{ conditions = [{ subject = "alert.title" operation = "is_set" param_bindings = [] }] }] expressions = [] # Notify a Slack channel for critical alerts channel_config = [{ condition_groups = [{ conditions = [{ subject = "alert.title" operation = "contains" param_bindings = [{ value = { literal = "critical" } }] }] }] slack_targets = { binding = { array_value = [{ literal = "C01234567" }] } channel_visibility = "public" } }] escalation_config = { auto_cancel_escalations = true escalation_targets = [ # Dynamic path from alert attribute { escalation_paths = { array_value = [{ reference = "alert.attributes.escalation_path" }] } }, # Static escalation path ID { escalation_paths = { array_value = [{ literal = "01JPQNFD3RWAAY2V83QQ80D1ZV" }] } }, # Specific user { users = { array_value = [{ literal = "01GX3C1TK13RQSEGP59XZ3MYP0" }] } } ] } incident_config = { auto_decline_enabled = false enabled = true condition_groups = [] defer_time_seconds = 300 grouping_window_seconds = 600 grouping_keys = [] } incident_template = { name = { autogenerated = true, value = { literal = jsonencode({ content = [{ content = [{ attrs = { label = "Alert → Title", missing = false, name = "alert.title" }, type = "varSpec" }], type = "paragraph" }], type = "doc" }) } } summary = { autogenerated = true, value = { literal = jsonencode({ content = [{ content = [{ attrs = { label = "Alert → Description", missing = false, name = "alert.description" }, type = "varSpec" }], type = "paragraph" }], type = "doc" }) } } severity = { merge_strategy = "first-wins" } start_in_triage = { value = { literal = "true" } } } } ``` **Key Schema Fields:** - `name` (String, Required) - `enabled` (Boolean, Required) - `is_private` (Boolean, Required) — If true, only creates private incidents. - `alert_sources` (Attributes Set, Required) — Which sources to match, with per-source conditions. - `condition_groups` (Attributes List, Required) — Route-wide conditions. - `escalation_config` (Attributes, Required) — Escalation targets and auto-cancel behavior. - `incident_config` (Attributes, Required) — Incident creation settings, grouping, defer time. - `incident_template` (Attributes, Required) — Template for name, summary, severity, custom fields. - `expressions` (Attributes Set, Required) — Expressions for dynamic value computation. - `channel_config` (Attributes Set, Optional) — Slack/MS Teams channel notifications. - `message_template` (Attributes, Optional) — Custom message template ID. - `owning_team_ids` (Set of String, Optional). - `id` (String, Read-Only). **Import:** ```shell terraform import incident_alert_route.example 01ABC123DEF456GHI789JKL ``` --- ### `incident_schedule` Manage on-call schedules with rotation configurations. Schedules support multiple rotations, versioned rotation configs (for phased changes), working interval restrictions, and public holiday overlays. It is recommended to build schedules in the [web dashboard](https://app.incident.io/~/on-call/schedules) using the Export flow. ```terraform data "incident_user" "martha" { slack_user_id = "U01HJ1J2Z6Z" } data "incident_user" "rory" { email = "rory@incident.io" } resource "incident_schedule" "primary_on_call" { name = "Primary On-call" timezone = "Europe/London" # IANA tz database name rotations = [{ id = "primary-rotation" name = "Primary Rotation" versions = [ # Initial version (no effective_from = applies from the start) { handover_start_at = "2024-05-01T12:54:13Z" users = [data.incident_user.martha.id] layers = [{ id = "primary", name = "Primary" }] handovers = [{ interval_type = "daily", interval = 1 }] }, # Updated version (takes effect on effective_from date) { effective_from = "2024-05-14T12:54:13Z" handover_start_at = "2024-05-01T12:54:13Z" users = [data.incident_user.martha.id, data.incident_user.rory.id] layers = [{ id = "primary", name = "Primary" }] handovers = [{ interval_type = "weekly", interval = 1 }] # Optional: restrict to business hours only working_intervals = [ { weekday = "monday", start_time = "09:00", end_time = "17:00" }, { weekday = "tuesday", start_time = "09:00", end_time = "17:00" }, { weekday = "wednesday", start_time = "09:00", end_time = "17:00" }, { weekday = "thursday", start_time = "09:00", end_time = "17:00" }, { weekday = "friday", start_time = "09:00", end_time = "17:00" }, ] }, ] }] # Show public holidays on the schedule calendar holidays_public_config = { country_codes = ["GB", "FR"] } team_ids = [] # optional team ownership } ``` **Schema:** - `name` (String, Required) - `timezone` (String, Required) — IANA tz database timezone. - `rotations` (Attributes Set, Required) — Set of rotations, each with: - `id` (String, Required) — User-provided stable ID for the rotation. - `name` (String, Required) - `versions` (Attributes Set, Required) — One or more versioned configs: - `handover_start_at` (String, Required) — RFC3339 datetime for next handover trigger. - `users` (List of String, Required) — incident.io user IDs. - `layers` (Attributes List, Required) — `[{ id, name }]` — concurrent on-call slots. - `handovers` (Attributes List, Required) — `[{ interval_type, interval }]` — `interval_type` is `hourly`, `daily`, or `weekly`. - `effective_from` (String, Optional) — When this version takes effect (RFC3339). - `working_intervals` (Attributes List, Optional) — `[{ weekday, start_time, end_time }]`. - `holidays_public_config` (Attributes, Optional) — `{ country_codes: [String] }`. - `team_ids` (Set of String, Optional). - `id` (String, Read-Only). **Import:** ```shell terraform import incident_schedule.example 01ABC123DEF456GHI789JKL ``` --- ### `incident_escalation_path` Configure escalation paths — branching on-call escalation logic with support for conditional routing, multi-level escalation, delays, repeats, and channel notifications. It is recommended to build escalation paths in the incident.io web dashboard. ```terraform resource "incident_schedule" "primary_on_call" { name = "Primary On-call" timezone = "Europe/London" rotations = [{ id = "r1", name = "Rotation 1", versions = [{ handover_start_at = "2024-01-01T00:00:00Z", users = [], layers = [{ id = "l1", name = "Layer 1" }], handovers = [{ interval_type = "weekly", interval = 1 }] }] }] } resource "incident_escalation_path" "urgent_support" { name = "Urgent support" path = [ { id = "start" type = "if_else" if_else = { conditions = [{ operation = "is_active" param_bindings = [] subject = "escalation.working_hours[\"UK\"]" }] then_path = [{ id = "working-hours-level" type = "level" level = { targets = [{ type = "schedule" id = incident_schedule.primary_on_call.id urgency = "high" }] time_to_ack_seconds = 300 # 5 minutes to acknowledge } }] else_path = [{ id = "out-of-hours-level" type = "level" level = { targets = [{ type = "schedule" id = incident_schedule.primary_on_call.id urgency = "low" }] time_to_ack_seconds = 600 } }] } } ] # Define what counts as "working hours" working_hours = [{ id = "UK" name = "UK" timezone = "Europe/London" weekday_intervals = [ { weekday = "monday", start_time = "09:00", end_time = "17:00" }, { weekday = "tuesday", start_time = "09:00", end_time = "17:00" }, { weekday = "wednesday", start_time = "09:00", end_time = "17:00" }, { weekday = "thursday", start_time = "09:00", end_time = "17:00" }, { weekday = "friday", start_time = "09:00", end_time = "17:00" }, ] }] # Optionally repeat the escalation path repeat_config = { repeat_times = 2 to_node = "start" } } ``` **Path Node Types:** - **`level`** — Notify one or more targets (schedules or users). Fields: `targets` (list of `{ type, id, urgency }`), `time_to_ack_seconds`. - **`if_else`** — Conditional branching. Fields: `conditions`, `then_path`, `else_path`. - **`delay`** — Pause escalation. Fields: `delay_for_seconds`. - **`repeat`** — Jump back to a previous node. Fields: `repeat_times`, `to_node`. - **`notify_channel`** — Notify a Slack channel or MS Teams. Fields: `targets`. **Schema:** - `name` (String, Required) - `path` (Attributes List, Required) — Ordered list of nodes. - `repeat_config` (Attributes, Optional) — Top-level repeat: `{ repeat_times, to_node }`. - `working_hours` (Attributes List, Optional) — Named working hours windows for `if_else` conditions. - `team_ids` (Set of String, Optional). - `id` (String, Read-Only). **Import:** ```shell terraform import incident_escalation_path.example 01ABC123DEF456GHI789JKL ``` --- ### `incident_workflow` Manage automated workflows triggered by incident lifecycle events. Workflows consist of a trigger, optional conditions, and a sequence of steps. It is recommended to build workflows in the [web dashboard](https://app.incident.io/~/workflows) using the Export flow. ```terraform # Auto-assign incident lead role to the user who acknowledges an escalation resource "incident_workflow" "autoassign_incident_lead" { name = "Auto-assign incident leader" trigger = "escalation.acked" condition_groups = [{ conditions = [{ subject = "user" operation = "is_set" param_bindings = [] }] }] expressions = [] steps = [{ id = "01HY0QG9WT62CEYJN8JD74MJNR" # must be a ULID name = "incident.assign_role" param_bindings = [ { value = { reference = "incident" } }, { value = { literal = "01HB0ZG24MPVF28Z5NF18DQT84" } }, # incident lead role ID { value = { reference = "user" } }, ] }] once_for = ["incident"] include_private_incidents = false continue_on_step_error = false runs_on_incidents = "newly_created_and_active" runs_on_incident_modes = ["standard"] state = "draft" # "active" or "draft" } ``` **Schema:** - `name` (String, Required) - `trigger` (String, Required) — Event that triggers this workflow (e.g., `escalation.acked`, `incident.created`). - `steps` (Attributes List, Required) — Steps to execute; each has `id` (ULID), `name`, `param_bindings`. - `condition_groups` (Attributes List, Required) — Pre-conditions for running the workflow. - `expressions` (Attributes Set, Required) — Computed expressions available to steps. - `once_for` (List of String, Required) — Scoping for deduplication (e.g., `["incident"]`). - `runs_on_incidents` (String, Required) — e.g., `newly_created_and_active`, `all`. - `runs_on_incident_modes` (List of String, Required) — e.g., `["standard"]`, `["test"]`. - `state` (String, Required) — `active` or `draft`. - `include_private_incidents` (Boolean, Required) - `continue_on_step_error` (Boolean, Required) - `id` (String, Read-Only). --- ## Data Sources ### `data "incident_user"` Look up an incident.io user by ID, email address, or Slack user ID. ```terraform # Lookup by incident.io internal ID data "incident_user" "rory" { id = "01HPFH8T92MPGSQS5C1SPAF4V0" } # Lookup by Slack user ID data "incident_user" "martha" { slack_user_id = "U01HJ1J2Z6Z" } # Lookup by email address data "incident_user" "alice" { email = "alice@example.com" } # Use user IDs as schedule participants resource "incident_schedule" "on_call" { name = "On-call" timezone = "UTC" rotations = [{ id = "rotation-1" name = "Rotation 1" versions = [{ handover_start_at = "2024-01-01T00:00:00Z" users = [data.incident_user.alice.id, data.incident_user.rory.id] layers = [{ id = "l1", name = "Primary" }] handovers = [{ interval_type = "weekly", interval = 1 }] }] }] } ``` **Schema:** - `email` (String, Optional) - `slack_user_id` (String, Optional) - `id` (String, Read-Only) — incident.io user ID. - `name` (String, Read-Only) --- ### `data "incident_catalog_type"` Look up an existing catalog type by name or type name. ```terraform data "incident_catalog_type" "service" { name = "Service" } resource "incident_catalog_entries" "services" { id = data.incident_catalog_type.service.id entries = { ... } } ``` **Schema:** - `name` (String, Optional) - `type_name` (String, Optional) - `categories` (List of String, Optional) - `id`, `description`, `source_repo_url`, `use_name_as_identifier` (Read-Only) --- ### `data "incident_alert_attribute"` Look up an existing alert attribute by name. ```terraform data "incident_alert_attribute" "team" { name = "Team" } # Use the attribute ID in an alert source template resource "incident_alert_source" "cloudwatch" { name = "CloudWatch" source_type = "cloudwatch" template = { attributes = [{ alert_attribute_id = data.incident_alert_attribute.team.id binding = { value = { reference = "expressions[\"team\"]" }, merge_strategy = "first_wins" } }] # ... } } ``` --- ## Summary The `terraform-provider-incident` enables infrastructure-as-code management of the full incident.io platform configuration. The core workflow typically starts by defining catalog types and attributes (the organizational schema), populating them with catalog entries (services, teams, tiers), and then building on top with on-call schedules, escalation paths, alert sources, and alert routes. Custom fields and custom field options enable rich metadata on incidents, while severities and incident roles configure how incidents are classified and staffed. Workflows automate incident lifecycle actions based on triggers, such as auto-assigning roles when an escalation is acknowledged. Integration patterns for this provider follow a natural dependency chain: `incident_catalog_type` → `incident_catalog_type_attribute` → `incident_catalog_entries` / `incident_catalog_entry` form the data model layer; `incident_schedule` + `incident_escalation_path` form the on-call layer; `incident_alert_attribute` + `incident_alert_source` + `incident_alert_route` form the alerting layer; and `incident_custom_field` + `incident_custom_field_option` + `incident_severity` + `incident_incident_role` + `incident_workflow` form the incident management layer. The provider is best used alongside the incident.io web dashboard Export feature for complex resources like escalation paths, alert routes, and workflows — which can be configured visually in the UI and then exported as Terraform HCL to be version-controlled and managed at scale.