Terraform provider
Manage SutramX monitors, status pages and alert channels with Terraform using the sutramx/sutramx provider, with import and full argument reference.
The SutramX Terraform provider lets you manage monitors, status pages and alert channels next to the rest of your infrastructure, and read maintenance windows and escalation policies. It talks to the SutramX API with a workspace API key, and every resource lives in the workspace that key belongs to.
The provider is published on the Terraform Registry as sutramx/sutramx. Add it to required_providers as shown below and terraform init downloads it.
At a glance#
| Source address | sutramx/sutramx on the Terraform Registry |
| Version | ~> 0.1 (0.1.0 is the current release) |
| Resources | sutramx_monitor, sutramx_status_page, sutramx_alert_channel |
| Data sources | sutramx_regions, sutramx_plans, sutramx_maintenance_windows, sutramx_escalation_policies |
| Import | Monitors by id or key; status pages and alert channels by id |
Configure the provider#
Pin the provider to the 0.1 series, then run terraform init:
terraform {
required_providers {
sutramx = {
source = "sutramx/sutramx"
version = "~> 0.1"
}
}
}
# The API key can also come from SUTRAMX_API_KEY.
provider "sutramx" {
api_key = var.sutramx_api_key
}
variable "sutramx_api_key" {
type = string
sensitive = true
}| Argument | What it does | Default |
|---|---|---|
api_key | SutramX API key (sk_...). Sensitive. | SUTRAMX_API_KEY environment variable |
api_url | API base URL. Must use https:// (plain http:// only for localhost). | SUTRAMX_API_URL, else https://api.sutramx.com |
The simplest setup is an empty provider "sutramx" {} block with SUTRAMX_API_KEY set in the environment.
Which API key you need#
Create a key in Account settings → API keys → Create API key. Whether you can create API keys, and how many, depends on your plan: see Plans & limits.
Every key has one of three access levels: Read-only (the dashboard default), Standard or Automation. The level is fixed when the key is created, so pick the one your configuration needs:
| What you do | Lowest access level |
|---|---|
terraform plan (refresh and data sources), for example in a plan-only CI job or for drift detection | Read-only. terraform apply with this key fails with 403 READ_ONLY_ACCESS. |
Apply sutramx_monitor and sutramx_status_page | Standard |
Apply sutramx_alert_channel, or a sutramx_monitor whose config_json sets notification_emails (per-monitor alert recipients) | Automation |
sutramx_maintenance_windows, sutramx_escalation_policies | Read-only |
sutramx_regions, sutramx_plans | No key |
Example#
resource "sutramx_monitor" "website" {
key = "web/home"
name = "Website"
url = "https://www.example.com"
interval_seconds = 60
regions = ["fra1", "usa-az-probe"]
tags = ["prod", "web"]
config_json = jsonencode({
timeout = 10000
expected_status_codes = [200]
keyword = "Example Domain"
})
}
resource "sutramx_monitor" "postgres" {
key = "infra/postgres"
name = "Postgres"
type = "port"
config_json = jsonencode({
host = "db.example.com"
port = 5432
})
}
resource "sutramx_status_page" "public" {
title = "Example status"
slug = "example-status"
description = "Live status of Example's website and API."
is_public = true
show_response_times = true
accent_color = "#0d9488"
monitors = [
{ monitor_id = sutramx_monitor.website.id },
{ monitor_id = sutramx_monitor.postgres.id, section = "Infrastructure" },
]
}
resource "sutramx_alert_channel" "ops_slack" {
type = "slack"
name = "Ops alerts"
config = {
webhook_url = var.slack_webhook_url
}
routing_scope = "monitors"
monitor_ids = [sutramx_monitor.website.id]
}
variable "slack_webhook_url" {
type = string
sensitive = true
}sutramx_monitor#
An uptime monitor. Checks run from SutramX probe regions; see Regions & confirmation for how regions confirm an outage.
| Argument | What it does | Default / limits |
|---|---|---|
name | Display name. Required. | 1–255 characters |
key | Stable key, unique in the workspace. The same key sutramx.yml uses. | Generated (tf-...) when not set. 1–128 characters: letters, digits and . _ : / -, starting with a letter or digit |
type | http, api, ping, port, udp, cron, dns, multistep or mcp. Changing it replaces the monitor. | http |
url | Target URL. Required for http, api and mcp monitors (mcp needs https://). Sensitive, so plans don't show it. | Ping, port and UDP monitors use host, and DNS monitors hostname, in config_json |
interval_seconds | Seconds between checks | Plan default; 15–900 and not below your plan's minimum |
regions | Set of probe location codes, for example ["fra1", "usa-az-probe"] (see sutramx_regions) | Omit for the plan's default locations. At least one; lower-case codes; order doesn't matter. Not allowed on cron monitors |
tags | Set of tags | Up to 20, each 1–32 characters. Must be written in lower case, without leading or trailing spaces, or plan fails. Left untouched when omitted. |
config_json | Type-specific settings as a JSON object string, usually with jsonencode(). Sensitive, so plans don't show it, and an output that uses it needs sensitive = true | Managed as a whole when set; left untouched when omitted (it then shows the stored settings) |
paused | Pause checks | false |
| Attribute | What it contains |
|---|---|
id | Monitor id (UUID) |
heartbeat_url | For cron monitors, the URL your job calls on each run. Sensitive. |
What goes in config_json depends on the type: cron monitors need cron_expression; ping monitors need host; port and UDP monitors need host and port; DNS monitors need hostname (plus optional settings such as record_type and expected_values); multi-step checks need steps. Multi-step secrets are write-only: Terraform keeps your value and doesn't detect changes made elsewhere. HTTP and API monitors accept settings such as timeout, expected_status_codes, keyword, method and headers. See HTTP & keyword, API & multi-step checks, Ping, TCP & UDP, DNS, Heartbeat & cron and MCP servers for every option.
How it behaves:
- Monitors are written with an idempotent create-or-update by key, so a retried
applynever creates a duplicate. config_jsonandtagsthat you leave out are not managed: whatever is set in the dashboard stays. Once you setconfig_json, it is managed as a whole, so keys you remove are removed from the monitor.- Unlike
config_jsonandtags, leaving outregionsmeans "use the plan's default locations". - Stored credentials in
config_json(secret headers, tokens, passwords) are read back as[REDACTED]; Terraform keeps your configured values for them. - Per-monitor alert recipients (
notification_emailsinconfig_json) are ignored unless your configuration sets them. Setting them needs an Automation key; with any other key the apply fails with403 ALERT_ROUTING_NOT_ALLOWED. - Changing
typedestroys the monitor (with its check history) and creates a new one. - Plan limits are enforced by the API exactly as in the dashboard. Errors such as
ENTITLEMENT_LIMIT_REACHEDappear as Terraform diagnostics. terraform destroydeletes the monitor and its history.
Use the heartbeat URL of a cron monitor in your job:
resource "sutramx_monitor" "nightly_job" {
key = "jobs/nightly"
name = "Nightly job"
type = "cron"
config_json = jsonencode({
cron_expression = "0 2 * * *"
})
}
output "nightly_job_heartbeat_url" {
value = sutramx_monitor.nightly_job.heartbeat_url
sensitive = true
}sutramx_status_page#
A status page showing the state of selected monitors. It counts against your plan's status page limit.
| Argument | What it does | Default / limits |
|---|---|---|
title | Page title. Required. | 1–255 characters |
slug | URL slug | Generated from the title when not set. 3–64 lower-case letters, digits or hyphens |
description | Text under the title | Up to 1000 characters; removed from the page when not set |
is_public | Whether the page is published | Server default when not set |
logo_url | https:// image URL | Removed from the page when not set |
accent_color | Hex colour like #0d9488 | Removed from the page when not set |
show_response_times | Show response times on the page | Server default when not set |
hide_powered_by | Remove SutramX branding | Only on plans with white-label status pages |
monitors | Monitors shown on the page, in display order: a list of { monitor_id, section } | Omit to manage the list in the dashboard (the attribute then shows the current list) |
In each monitors entry, monitor_id is required (usually sutramx_monitor.<name>.id) and section is an optional heading the monitor is grouped under.
The only attribute is id. Custom domains, private access and subscribers are managed in the dashboard: see Branding & custom domains. terraform destroy deletes the page.
sutramx_alert_channel#
An alert channel (integration connection) such as Slack, Discord, Microsoft Teams, a webhook, PagerDuty or Opsgenie. Creating, changing and deleting it requires an API key with the Automation access level. Which channel types you can use depends on your plan.
| Argument | What it does | Default / limits |
|---|---|---|
type | Channel type as shown in the dashboard's integration list, for example slack, discord, msteams, webhook, pagerduty, opsgenie or telegram. Changing it replaces the channel. Required. | |
name | Display name, unique among channels of the same type. Required. | 1–80 characters |
config | Map of the channel's fields, for example { webhook_url = var.slack_webhook_url } for Slack or { integration_key = ... } for PagerDuty. Sensitive. Required. | |
routing_scope | all (every monitor), groups (monitors in the groups in group_ids) or monitors (only monitor_ids) | all |
group_ids | Monitor group ids this channel alerts for. Required when routing_scope = "groups", not allowed otherwise | Up to 500 |
monitor_ids | Monitors this channel alerts for. Required when routing_scope = "monitors", not allowed otherwise | Up to 500 |
| Attribute | What it contains |
|---|---|
id | Connection id |
status | Connection status reported by SutramX |
signing_secret | For webhook channels, the secret SutramX signs payloads with. Only known when Terraform created the channel. Sensitive. |
resource "sutramx_alert_channel" "incident_webhook" {
type = "webhook"
name = "Incident pipeline"
config = { webhook_url = "https://hooks.example.com/sutramx" }
}
output "webhook_signing_secret" {
value = sutramx_alert_channel.incident_webhook.signing_secret
sensitive = true
}The fields each channel type needs are described in Slack, Teams & chat apps, Webhooks and PagerDuty & Opsgenie.
Data sources#
sutramx_regions#
SutramX probe locations. Use code in sutramx_monitor.regions. Doesn't need an API key. Which codes a monitor may use depends on your plan and billing market.
data "sutramx_regions" "online" {
online_only = true
}
output "region_codes" {
value = data.sutramx_regions.online.codes
}| Name | Kind | What it contains |
|---|---|---|
online_only | Optional argument | Only locations whose probes are online now |
codes | Attribute | Location codes, in activation order |
regions | Attribute | List of objects with code, name, city, country (ISO 3166-1 alpha-2), continent, latitude, longitude and online |
sutramx_plans#
The current SutramX plans with prices and main limits, as listed on the pricing page. Doesn't need an API key.
data "sutramx_plans" "all" {}
output "plan_prices_usd" {
value = { for plan in data.sutramx_plans.all.plans : plan.id => plan.price_monthly_usd }
}Each entry in plans has id, name, description, markets (global for USD and/or india for INR), price_monthly_usd, price_annual_usd, price_monthly_inr, price_annual_inr, monitors, min_interval_seconds, probe_locations (null means every active location), status_pages (null means unlimited), api_keys (null means unlimited), popular and sort_order.
sutramx_maintenance_windows#
The workspace's maintenance windows, newest start first. Needs an API key; any access level works, including read-only. Terraform can only read windows: creating, changing and deleting them is done by the workspace owner in the dashboard, see Maintenance windows.
data "sutramx_maintenance_windows" "ongoing" {
effective_status = "ongoing"
}
output "in_maintenance" {
value = length(data.sutramx_maintenance_windows.ongoing.windows) > 0
}| Name | Kind | What it contains |
|---|---|---|
effective_status | Optional argument | Only windows in this live state: scheduled, ongoing, completed or cancelled |
ids | Attribute | Ids of the returned windows, in order |
windows | Attribute | List of windows, described below |
Each entry in windows has:
| Attribute | What it contains |
|---|---|
id, title, description | The window's id, title and description |
status | Stored status: scheduled, ongoing, completed or cancelled |
effective_status | Status worked out from the current time (the stored status can lag behind) |
start_time, end_time | RFC 3339 times in UTC |
timezone | IANA time zone the window was scheduled in |
impact | low, medium or high |
scope_type | global (every monitor), monitor or group |
monitor_ids | Monitors covered when scope_type is monitor |
group_ids | Monitor groups covered when scope_type is group |
affected_services | List of affected services |
recurrence_type | none, daily or weekly |
recurrence_weekdays | For weekly windows, the days of the week (0 = Sunday) |
recurrence_until | Last day a recurring window repeats; null when it repeats indefinitely or doesn't recur |
sutramx_escalation_policies#
The workspace's escalation policies, newest first. Needs an API key; any access level works, including read-only. Terraform can only read policies: the workspace owner creates and changes them in the dashboard, see Escalation & on-call.
data "sutramx_escalation_policies" "primary" {
name = "Primary on-call"
}
output "primary_policy_id" {
value = one(data.sutramx_escalation_policies.primary.policies[*].id)
}| Name | Kind | What it contains |
|---|---|---|
name | Optional argument | Only policies with exactly this name |
policies | Attribute | List of policies, described below |
Each entry in policies has id, name, enabled, max_depth (how many steps an incident escalates through at most) and steps, in escalation order. Each step has:
| Attribute | What it contains |
|---|---|
id | Step id |
step_order | Position of the step |
delay_minutes | Minutes after the previous step before this one notifies |
channel | Delivery channel, for example email, slack or webhook |
target_type | email, on_call_primary, phone or integration |
target_value | Address, number or integration connection id the step notifies |
target_label | Readable target, as shown in the dashboard |
Import existing resources#
Monitors can be imported by id (UUID) or by key:
# A monitor made in the dashboard: it gets a key on the next apply
terraform import sutramx_monitor.website 6f1c8f7e-6f2a-4a71-9d0b-0b8c1d2e3f40
# A monitor created by sutramx.yml or Terraform
terraform import sutramx_monitor.website web/homeImporting also fills in config_json, so a configuration that matches the monitor plans no changes. A dashboard monitor without a key gets one on the next apply: the key you set in HCL, or a generated tf-... key.
Status pages and alert channels are imported by id:
terraform import sutramx_status_page.public 0b6f1c2a-9e4d-4f7a-8c3b-2d1e0f9a8b7c
terraform import sutramx_alert_channel.ops_slack 7d1e0f9a-8b7c-4c3b-9e4d-0b6f1c2a2d1eAlert channel secrets aren't read back: set config in HCL and the next apply writes it.
Using Terraform with sutramx.yml#
The provider and the CLI use the same monitor keys. Pick one tool per monitor. If you use both in one workspace, don't turn on pruning in sutramx.yml: pruning deletes every keyed monitor that isn't in the file, including monitors created by Terraform.
Troubleshooting#
| Problem | What to do |
|---|---|
| Authentication errors | Set SUTRAMX_API_KEY or api_key. Keys start with sk_. |
sutramx_alert_channel fails with AUTOMATION_KEY_REQUIRED | Use a key created with the Automation access level. A key's level can't be changed, so create a new key. |
403 READ_ONLY_ACCESS on apply | The key is read-only, which only works for terraform plan. Use a Standard key, or Automation for alert channels and alert recipients. |
ALERT_ROUTING_NOT_ALLOWED | A monitor's config_json sets notification_emails. Use an Automation key, or remove the field. |
ENTITLEMENT_LIMIT_REACHED or FEATURE_NOT_AVAILABLE | Your plan doesn't allow the change (monitor count, interval, locations, status pages or channel type). See Plans & limits. |
Invalid tag (... has upper-case letters; SutramX stores tags lower-case) | A tag has an upper-case letter or surrounding spaces. Write every tag in lower case, without spaces at the ends. |
| A plan wants to replace a monitor | You changed type. Replacing deletes the old monitor's history. |
Related
- CLI & monitors as code
- REST API
- Monitors overview
- Status pages overview
- Developer overview
- Features: API Monitoring
- Guides: Monitoring APIs Effectively
- Integrations: Webhooks alerts setup and GitHub issues alerts setup
- Use cases: Monitoring for Developers & Indie Hackers
- More from SutramX: Developers & API
Last updated . Something unclear or missing on this page? Tell us at support@sutramx.com.