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.
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
importblocks 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:
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.
Open the resource
Open the monitor, status page or other resource you want Terraform to manage.
Open its Terraform page
In the side menu, open Developer, then Terraform.
Copy the configuration
The page writes the resource's configuration from its current settings, with an
importblock. A comment after each ID names the record it points at (incident_severity_id = "..." # Критический инцидент).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:
| Resource | What it is |
|---|---|
status200_monitor | A monitor: website, API, ping, port, SSL certificate, server, incoming request, manual and every other type |
status200_monitor_status | A monitor status, such as Работает, Снижение производительности or Не в сети |
status200_monitor_group | A group of monitors, shown with one status |
status200_status_page | A public or private status page |
status200_status_page_domain | A custom domain of a status page |
status200_domain | A domain of your project, verified for status pages |
status200_label | A label, to sort and filter records |
status200_team, status200_team_member | A team, and who is in it |
status200_on_call_policy, status200_escalation_rule | An on-call policy, and the rules it pages in order |
status200_incident, status200_incident_severity, status200_incident_state | Incidents, their severities and their states |
status200_alert, status200_alert_severity, status200_alert_state | Alerts, their severities and their states |
status200_scheduled_maintenance_event | A scheduled maintenance window |
status200_probe | A 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.
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:
# 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 value | How you write it | Example |
|---|---|---|
| Text, numbers, true or false | As they are | is_public_status_page = false |
| A reference to another record | Its ID, usually another resource's id | incident_severity_id = status200_incident_severity.sev1.id |
| A list of references | A set of IDs, whose order makes no difference | labels = [status200_label.critical.id] |
| A color, a domain and other wrapped values | Their plain value | color = "#FF5733" |
| A date and time | RFC 3339 text | starts_at = "2030-06-01T02:00:00Z" |
| A monitor's checks | Typed nested attributes: see Monitor Steps | monitor_steps = [{ ... }] |
| Other structured settings | JSON, 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 planand the end ofterraform 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
- Bugs and feature requests: git.wilix.dev/status200/status200/issues.
- The provider is generated from the Status200 OpenAPI specification in the main Status200 repository. The published provider repository is read-only, so report problems in the main repository.