Skip to content
Terraform Overview

Terraform Overview

The Status200 Terraform provider manages your Status200 project as code. Describe monitors, status pages, on-call policies, teams, labels and the other records of your project in .tf files, see what will change with terraform plan, and make the change with terraform apply. It works with Status200 Cloud and with a self-hosted Status200, and with OpenTofu as well as Terraform.

How the provider works

The provider is a plugin that Terraform downloads from a registry. On terraform apply, it turns each change in the plan into a request to the Status200 REST API, made with an API key of your project. Terraform keeps what it created in its state, so the next plan shows only what changed since.

flowchart TB C["Your configuration:<br/>the .tf files"] --> T["terraform plan<br/>terraform apply"] T --> P["The Status200 provider"] K["An API key<br/>of your project"] --> P P -->|"REST API requests"| O["Your Status200 project"] T --> S["Terraform state"]

From your configuration to your project

An API key belongs to one project and decides what Terraform may read and change in it, so one configuration manages one project. To manage several, give the provider one alias for each.

Before you begin

  • Terraform 1.5 or later, or OpenTofu 1.6 or later. The import blocks the dashboard writes need these versions.
  • An API key of your project. The Quick Start shows how to create one in Project Settings → Advanced → API Keys.
  • On Status200 Cloud, the Growth plan or above. A project's API keys work only on it.

Install the provider

Add the provider to a .tf file. terraform init downloads it from the Terraform Registry, and tofu init from the OpenTofu Registry:

main.tfHCL
terraform {
  required_providers {
    oneuptime = {
      source  = "oneuptime/status200"
      version = "~> 14.0"
    }
  }
}

provider "oneuptime" {
  # The API key comes from the STATUS200_API_KEY environment variable.
  # On a self-hosted Status200, add your Status200's address:
  # status200_url = "https://status200.example.com"
}

Keep the key out of your files: export it before you run Terraform, or pass it in a variable marked sensitive. The Complete Guide lists every way to give the provider its key and address.

Pick a version

Provider versions follow Status200's: provider 14.x is made from Status200 14.x. The constraint above, ~> 14.0, takes the newest 14.x release, which is right for Status200 Cloud. On a self-hosted Status200, use the newest provider that is not newer than your Status200: Self-Hosted Setup shows how to pin it.

Let the dashboard write it

You do not have to write a resource you already have by hand. Every resource in the Status200 dashboard (a monitor, a status page, a workflow, an on-call policy and the others) has a Developer section in its side menu, collapsed until you open it. Its Terraform page writes the configuration for you, filled in from your own project.

  1. Open the resource

    Open the monitor, status page or other resource you want Terraform to manage.

  2. Open its Terraform page

    In the side menu, open Developer, then Terraform.

  3. Copy the configuration

    The page writes the resource's configuration from its current settings, with an import block. A comment after each ID names the record it points at (incident_severity_id = "..." # Критический инцидент).

  4. Plan and apply

    Run terraform plan: it shows the resource being imported and nothing to change. Apply it, and Terraform manages the resource from then on.

Below the configuration, Build on it has what people often add next to the resource, referring to it by its address: an owner team for an incident, a group of monitors for a status page, an escalation rule for an on-call policy.

The list pages (for example Incidents or Monitors) have the same section. There, the Terraform page writes a new resource with the fields most people set, using your project's own records: an incident with one of your severities, a monitor with the criteria a new monitor gets in the dashboard, wired to your statuses. It gives ready-made Common setups (a status page with a group and a monitor, an on-call policy that pages a team, a weekly on-call rotation), and an import block for each resource you already have (the first 100), ready for terraform plan -generate-config-out. Both pages also give the provider block for your Status200: the right status200_url, and a version constraint that matches your Status200.

Secrets are never shown on these pages. When the configuration needs one (for example a monitor's Authorization header), it reads it from a Terraform variable marked sensitive. Secrets it does not need are left out, and Terraform leaves them as they are in Status200.

The same section has an API page, with curl commands for the resource, and an AI Assistants page, which connects Claude, GitHub Copilot or Cursor to the MCP server.

What you can manage

The provider has a resource for each kind of record you can create over the Status200 API, named status200_<name>. These are the ones most configurations start with:

ResourceWhat it is
status200_monitorA monitor: website, API, ping, port, SSL certificate, server, incoming request, manual and every other type
status200_monitor_statusA monitor status, such as Работает, Снижение производительности or Не в сети
status200_monitor_groupA group of monitors, shown with one status
status200_status_pageA public or private status page
status200_status_page_domainA custom domain of a status page
status200_domainA domain of your project, verified for status pages
status200_labelA label, to sort and filter records
status200_team, status200_team_memberA team, and who is in it
status200_on_call_policy, status200_escalation_ruleAn on-call policy, and the rules it pages in order
status200_incident, status200_incident_severity, status200_incident_stateIncidents, their severities and their states
status200_alert, status200_alert_severity, status200_alert_stateAlerts, their severities and their states
status200_scheduled_maintenance_eventA scheduled maintenance window
status200_probeA probe of your own, which checks from your network

The Terraform Registry lists every resource with each of its attributes.

Read what already exists

Every resource has a data source of the same name, such as data "status200_label". A data source reads a record that this configuration does not manage, for example one made in the dashboard. Look it up by its id, or by its other plain arguments: each one you set must match, and exactly one record may match them all.

HCL
data "status200_monitor_status" "offline" {
  name = "Не в сети"
}

# Any plain argument works. Set several, and all of them must match.
data "status200_monitor_status" "offline_state" {
  is_offline_state = true
}

No match, or more than one, is an error rather than an empty or arbitrary answer. The Complete Guide has the rules.

Renamed resources

Resource names keep words such as IoT and vCenter whole: status200_iot_fleet and status200_vcenter, where older providers had status200_io_t_fleet and status200_v_center (and the same for their label rules, owners and feeds). The old names still work as deprecated aliases, and a plan that uses one says so. To switch, rename the resource in your configuration and add a moved block, and Terraform keeps the existing resource instead of replacing it:

HCL
# Was: resource "status200_io_t_fleet" "factory"
resource "status200_iot_fleet" "factory" {
  name = "Factory floor"
}

moved {
  from = status200_io_t_fleet.factory
  to   = status200_iot_fleet.factory
}

Moving a resource to another type needs Terraform 1.8 or later. On an older engine, keep the old name for now: it keeps working.

How attributes are written

Attributes follow the Status200 API, in snake_case:

Kind of valueHow you write itExample
Text, numbers, true or falseAs they areis_public_status_page = false
A reference to another recordIts ID, usually another resource's idincident_severity_id = status200_incident_severity.sev1.id
A list of referencesA set of IDs, whose order makes no differencelabels = [status200_label.critical.id]
A color, a domain and other wrapped valuesTheir plain valuecolor = "#FF5733"
A date and timeRFC 3339 textstarts_at = "2030-06-01T02:00:00Z"
A monitor's checksTyped nested attributes: see Monitor Stepsmonitor_steps = [{ ... }]
Other structured settingsJSON, written with jsonencode()log_monitor = jsonencode({ ... })

Two kinds of value are the server's, and you leave them out:

  • IDs inside a resource. A monitor's steps and criteria, and their incident and alert templates, have IDs the server gives and keeps across every apply, so incidents keep pointing at the criteria that raised them.
  • What the server keeps up to date. A monitor's current status, or when it last received a heartbeat, can change between terraform plan and the end of terraform apply. The provider keeps the planned value for anything you did not set, and the next refresh reads the server's, so this never fails an apply or shows as a change.

Get help

Next steps