CLI & monitors as code
Manage SutramX monitors from the terminal and keep monitors, status pages and alert channels in a sutramx.yml file with plan, diff and apply.
The sutramx command line tool lets you list and change monitors from your terminal, and keep your whole monitoring setup in a version-controlled sutramx.yml file. You describe monitors, status pages and alert channels in the file, review what would change with sutramx plan, then make it so with sutramx apply.
Install#
The CLI is the npm package @sutramx/cli. It needs Node.js 20 or newer.
npm install -g @sutramx/cli # or run it without installing: npx @sutramx/cli <command>
sutramx login # paste an API key
sutramx monitors listThe source is at github.com/SutramX/cli.
Authenticate#
The CLI uses a workspace API key (it starts with sk_). Create one in Account settings → API keys → Create API key. A key acts on the one workspace it was created in. Whether you can create API keys, and how many, depends on your plan: see Plans & limits.
Every key has one of three access levels, chosen when you create it. The dashboard selects Read-only by default, and the level can't be changed later, so pick the level that the commands you run need:
| Access level | What it can do from the CLI |
|---|---|
| Read-only | whoami, monitors list and get, incidents list and get, maintenance list, init --from-workspace, plan and diff. Every change is refused with 403 READ_ONLY_ACCESS. |
| Standard | Everything above, plus monitors create, pause, resume, delete and adopt, incidents ack and resolve, and apply for monitors and status pages |
| Automation | Everything above, plus apply for a file that manages integrations (alert channels) or sets per-monitor alert recipients (config.notification_emails) |
login works with any level. regions, validate and init without --from-workspace don't need a key at all. plan and diff of a file that sets config.notification_emails also need the Automation level: with any other key the API refuses them with 403 ALERT_ROUTING_NOT_ALLOWED. See REST API for more about keys.
Log in interactively#
sutramx loginThe key is read from a hidden prompt (or from stdin when you pipe it in), checked against the API, and saved to a credentials file with permissions 0600. You can also pass it directly with sutramx login --api-key sk_..., but that leaves the key in your shell history.
To remove the saved key:
sutramx logoutEnvironment variables#
Environment variables take priority over the saved file, which makes them the right choice for CI.
| Variable | What it does |
|---|---|
SUTRAMX_API_KEY | API key to use. Overrides the saved credentials. |
SUTRAMX_API_URL | API base URL. Default https://api.sutramx.com. You only need this for a non-default API. It must use https:// (plain http:// only for localhost). Same as the global --api-url flag. |
SUTRAMX_CONFIG | Full path of the credentials file to read and write. |
XDG_CONFIG_HOME | When set (and SUTRAMX_CONFIG isn't), credentials go to $XDG_CONFIG_HOME/sutramx/credentials.json. |
SUTRAMX_ALLOWED_ENV | Comma-separated variable names, or prefixes ending in *, that ${VAR} references in sutramx.yml may read. See Environment variables in the file. |
NO_COLOR | Any value turns off coloured output. Colour is also off when output isn't a terminal. |
The default credentials file is ~/.config/sutramx/credentials.json. It holds JSON with api_key, and optionally api_url and workspace_id.
Commands#
Every command supports --help. The global flags are --api-url <url> (also SUTRAMX_API_URL), -V, --version and -h, --help.
| Command | What it does | Key level |
|---|---|---|
sutramx login [--api-key sk_...] | Verify and save an API key | Any |
sutramx logout | Remove the saved key | None |
sutramx whoami [--json] | Show the workspace, plan, key access level and limits | Any |
sutramx monitors list | List monitors with live status | Read-only |
sutramx monitors get <id-or-key> | Print one monitor as JSON | Read-only |
sutramx monitors create ... | Create a monitor, or create-or-update with --key | Standard |
sutramx monitors update <id-or-key> ... | Change a monitor; only the options you pass change | Standard |
sutramx monitors checks <id-or-key> | Show a monitor's check history, newest first | Read-only |
sutramx monitors run-check <id-or-key> | Run one real check now and record it | Standard |
sutramx monitors pause <id-or-key> | Stop checking a monitor | Standard |
sutramx monitors resume <id-or-key> | Restart checks on a paused monitor | Standard |
sutramx monitors delete <id-or-key> | Delete a monitor and its history | Standard |
sutramx monitors adopt <id> <key> | Give an existing monitor a key so sutramx.yml manages it | Standard |
sutramx incidents list | List incidents, newest first | Read-only |
sutramx incidents get <id> | Show one incident | Read-only |
sutramx incidents ack <id> | Acknowledge an ongoing incident (stops escalation) | Standard |
sutramx incidents resolve <id> | Resolve an ongoing incident by hand | Standard |
sutramx incidents note <id> <text> | Add a note to an incident timeline (internal unless --public) | Standard |
sutramx why <monitor-or-incident> | Why a monitor is down, or why an alert fired: region votes, quorum, failure class, fault verdict, vendor signals and flakiness | Read-only |
sutramx maintenance list | List maintenance windows | Read-only |
sutramx status-pages list | List status pages | Read-only |
sutramx status-pages get <id-or-slug> | Show one status page with its monitors | Read-only |
sutramx uptime | Uptime report: uptime, incidents, MTTR and health per monitor, plus SLO error budgets | Read-only |
sutramx regions [--json] | List probe location codes | None |
sutramx init | Write a starter sutramx.yml | None (Read-only with --from-workspace) |
sutramx validate | Check sutramx.yml locally | None |
sutramx plan | Show what apply would change | Read-only (see Authenticate) |
sutramx diff | Like plan, with every changed field shown old -> new | Read-only (see Authenticate) |
sutramx apply | Make SutramX match the file | Standard, or Automation for integrations and alert recipients |
"Key level" is the lowest access level the command works with; a higher level works too.
monitors also works as monitor, incidents as incident, status-pages as status-page, uptime as report, and list as ls (monitors ls, incidents ls, maintenance ls, status-pages ls). monitors delete also works as monitors rm, and incidents ack as incidents acknowledge. Wherever a command takes <id-or-key>, you can pass the monitor's UUID or its monitors-as-code key. Incident commands take the incident's UUID, which incidents list shows.
whoami#
Prints the workspace id, plan and billing market, the key's access level (read_only, standard or automation), the plan's limits (monitors, minimum interval, locations per monitor, status pages) and whether the key can manage integrations. Add --json for the raw response, which also has read_only: true for a read-only key.
monitors list#
| Flag | What it does |
|---|---|
--tag <tag> | Only monitors with this tag |
--status <status> | Only monitors in this status: up, down, degraded, paused, pending or maintenance |
--json | Print the full JSON instead of a table |
The table shows ID, KEY, NAME, TYPE, STATUS, 24H uptime, EVERY (interval in seconds) and TARGET.
monitors create#
| Flag | What it does | Default / limits |
|---|---|---|
--name <name> | Display name (required) | 1–255 characters |
--url <url> | Target URL for http, api and mcp monitors (mcp needs https://) | |
--type <type> | Monitor type: http, api, ping, port, udp, cron, dns, multistep or mcp | http |
--interval <seconds> | Seconds between checks, a whole number | Plan default; 15–900 and not below your plan's minimum |
--region <code> | Probe location; repeat for several | Plan default locations |
--tag <tag> | Tag; repeat for several | |
--config <json> | Type-specific settings as JSON | |
--key <key> | Stable key: creates the monitor once and updates it on later runs | |
--paused | Create it paused | |
--json | Print { action, monitor } as JSON |
# A website check from two locations
sutramx monitors create --name "Homepage" --url https://example.com --region fra1 --region usa-az-probe --tag prod
# A TCP port check, idempotent thanks to --key
sutramx monitors create --key infra/postgres --name "Postgres" --type port \
--config '{"host":"db.example.com","port":5432}'Without --key, every run creates a new monitor. With --key, the first run creates it and later runs update it, so the command is safe to repeat in scripts. The settings available in --config depend on the monitor type; see Monitors overview and the page for each type.
monitors update#
Takes the same --name, --url, --interval, --tag, --region, --config and --json flags as create, and changes only what you pass. --tag and --region replace all tags or locations, and --config replaces the whole config, so start from sutramx monitors get <id-or-key>.
monitors checks and run-check#
sutramx monitors checks <id-or-key> lists checks, newest first. Flags: --limit <n> (1–500, default 50), --before <time> (ISO-8601, to page back), --region <code>, --status <status> and --json. sutramx monitors run-check <id-or-key> runs one real check now and records it.
monitors delete#
Asks you to type yes before deleting. In scripts, pass -y or --yes; without it, a non-interactive run refuses to delete. Deleting removes the monitor's check history.
monitors adopt#
sutramx monitors adopt 6f1c8f7e-6f2a-4a71-9d0b-0b8c1d2e3f40 web/homeSets the key of a monitor that was created in the dashboard, so the sutramx.yml entry with that key manages it from now on instead of creating a duplicate.
incidents list#
| Flag | What it does | Default / limits |
|---|---|---|
--status <status> | all, ongoing, resolved, acknowledged or suppressed | all |
--monitor <id-or-key> | Only incidents of this monitor | |
--search <text> | Search the monitor name or URL | Up to 200 characters |
--from <time> | Incidents that started at or after this time | ISO-8601, for example 2026-01-31 or 2026-01-31T12:00:00Z |
--to <time> | Incidents that started at or before this time | ISO-8601 |
--page <n> | Page number | 1 (1–10000) |
--page-size <n> | Incidents per page | 25 (1–100) |
--json | Print the full JSON instead of a table |
The table shows ID, MONITOR, STATE (ongoing, acknowledged or resolved), STARTED, DURATION and the REGIONS that confirmed the outage. When there are more incidents, the last line tells you the --page to ask for next.
sutramx incidents list --status ongoing
sutramx incidents list --monitor api/health --from 2026-09-01incidents get, ack and resolve#
| Command | Flags |
|---|---|
sutramx incidents get <id> | --json prints the full response, with the incident's timeline |
sutramx incidents ack <id> | --json |
sutramx incidents resolve <id> | --note <text>: what was done, shown on the incident timeline (up to 5000 characters). --json |
sutramx incidents note <id> <text> adds an internal note to the timeline. With --public, it's published as a public update on your status pages; the CLI asks you to confirm unless you pass -y or --yes.
Acknowledging an ongoing incident marks that someone is on it and stops escalation to the next on-call step. Incidents resolve on their own when checks recover, so resolve by hand only when you know the issue is fixed. See Incidents.
sutramx incidents ack 0d7c2a9e-4b1f-4e8a-9c3d-6f2e1a0b9c8d
sutramx incidents resolve 0d7c2a9e-4b1f-4e8a-9c3d-6f2e1a0b9c8d --note "Rolled back the release"why#
sutramx why <target> prints the Why this alert explanation in the terminal. The target is an incident id, or a monitor id, key, exact name or part of its name or URL.
| Flag | What it does |
|---|---|
--no-last-incident | For a monitor without an open incident, don't also explain its most recent incident |
--json | Print the structured result (the same shape as the MCP tool sutramx_explain_incident) |
The output starts with a one-line summary, then the verdict, whose fault it is (yours, external, checker or unknown), the failure class, the quorum rule and whether it was met, and a table of region votes. Regions whose checks were blocked by bot protection or were inconclusive on our side are marked "abstains": they don't count toward the quorum. Vendor signals and the 7- and 30-day flakiness score follow. A monitor with an open incident explains that incident; otherwise you get its current state and its most recent incident. Paused monitors and active maintenance windows are called out. When several monitors match, the CLI lists them and exits with status 1 instead of guessing.
sutramx why checkout-api
sutramx why 0d7c2a9e-4b1f-4e8a-9c3d-6f2e1a0b9c8d --jsonmaintenance list#
| Flag | What it does |
|---|---|
--status <status> | Only windows in this state: scheduled, ongoing, completed or cancelled |
--json | Print the full JSON instead of a table |
The table shows ID, TITLE, STATUS, STARTS, ENDS, REPEATS and SCOPE (all monitors, or the monitors or groups the window covers). The status is the window's live state, so a scheduled window whose start time has passed shows as ongoing. Alerts are silenced while a window is active. The CLI only lists windows: creating, changing and deleting them is done by the workspace owner in the dashboard, see Maintenance windows.
status-pages and uptime#
sutramx status-pages list and sutramx status-pages get <id-or-slug> show your status pages; manage them with sutramx.yml or the dashboard. sutramx uptime prints uptime, incidents, MTTR and health per monitor, plus SLO error budgets. Flags: --days 7|14|30|90 (default 30), --monitor <id-or-key> and --json.
init#
| Flag | What it does |
|---|---|
-f, --file <path> | File to write (default sutramx.yml) |
--from-workspace | Describe the monitors that exist in the workspace now |
--force | Overwrite an existing file |
Without --from-workspace, init writes a commented starter file. With it, init exports every monitor with a key, except browser checks, which it skips with a warning. Monitors that had no key get one made from their name (for example "Checkout API" becomes checkout-api), and the file sets adopt_by_name: true so the first apply links them instead of creating copies. If several monitors share a name and type, init lists them: give each one a key with sutramx monitors adopt before you apply.
The export leaves out per-monitor alert recipients (config.notification_emails). Stored credentials, such as secret header values, are written as [REDACTED] because the API never reveals them; apply keeps the stored value as long as the URL's origin is unchanged. Replace [REDACTED] with a value, for example ${ENV_VAR}, to manage it from the file.
validate#
Checks the file's structure, environment variable references and duplicate keys without calling the API. Field rules such as intervals, config and plan limits are checked by plan.
plan, diff and apply#
These three share the same flags:
| Flag | What it does |
|---|---|
-f, --file <path> | Configuration file (default sutramx.yml) |
--prune | Delete keyed monitors that are not in the file. This flag is the only way to delete monitors |
--no-prune | Never delete monitors |
--adopt-by-name | Link existing unkeyed monitors with the same name and type |
--prune-integrations | Delete integrations of the declared types that are not in the file |
--workspace <id> | The workspace you mean to change: refuse unless the API key acts on it |
--json | JSON output |
plan and diff also take --detailed-exitcode. apply also takes:
| Flag | What it does |
|---|---|
--auto-approve | Apply without asking. Required when there is no terminal (CI). -y and --yes do the same |
--continue-on-error | Keep going after a failed change instead of stopping |
--allow-replace | Allow monitors whose type changed to be deleted, with their history, and created again (--prune also allows it) |
--allow-delete-all | Allow a prune that deletes every managed monitor because the file declares no monitors |
--force-prune-without-plan-check | With --prune, delete even when the API can't verify that the plan is unchanged |
--allow-delete-all is a safety catch: when pruning is on and the file has no monitors at all (for example an empty or truncated file), apply refuses to start unless you pass it.
The sutramx.yml file#
By default the CLI reads sutramx.yml from the current directory; use -f for another path. The file is YAML, and because YAML accepts JSON, a JSON file works too.
version: 1
defaults: # merged into every monitor
interval_seconds: 60
tags: [prod]
settings:
adopt_by_name: false # true: first apply links existing monitors with the same name and type
monitors:
- key: web/home
name: Website
url: https://www.example.com
regions: [fra1, usa-az-probe]
config:
keyword: Example Domain
- key: api/health
name: Public API
type: api
url: https://api.example.com/v1/health
interval_seconds: 30
config:
method: GET
expected_status_codes: [200]
headers:
Accept: application/json
- key: infra/postgres
name: Postgres
type: port
config:
host: db.example.com
port: 5432
- key: jobs/nightly-report
name: Nightly report job
type: cron
config:
cron_expression: "30 1 * * *"
status_pages:
- slug: example-status
title: Example status
description: Live status of Example's website and API.
is_public: true
show_response_times: true
monitors:
- web/home
- key: api/health
section: API
integrations: # needs an API key with the Automation access level
- name: Ops alerts
type: slack
config:
webhook_url: ${SLACK_WEBHOOK_URL}
routing:
scope: monitors
monitors: [web/home, api/health]The same idea as JSON:
{
"version": 1,
"monitors": [
{ "key": "homepage", "name": "Homepage", "url": "https://example.com" },
{ "key": "nightly-backup", "name": "Nightly backup", "type": "cron", "config": { "cron_expression": "0 2 * * *" } }
]
}sutramx plan -f sutramx.jsonTop-level fields#
| Field | What it does | Default / limits |
|---|---|---|
version | File format version | 1 (the only value) |
defaults | Values merged into every monitor | Optional |
settings | Reconcile behaviour (adoption, workspace check) | Optional |
monitors | Monitors to manage | Up to 500 |
status_pages | Status pages to manage | Up to 100; optional |
integrations | Alert channels to manage | Up to 100; optional |
Unknown fields anywhere in the file are an error, so typos don't go unnoticed.
defaults#
| Field | What it does |
|---|---|
type | Type for monitors that don't set one |
interval_seconds | Interval for monitors that don't set one |
regions | Regions for monitors that don't set them (a list, or null for the plan default) |
tags | Added to every monitor's own tags |
config | Merged under each monitor's config (the monitor's own keys win) |
settings#
| Field | What it does | Default |
|---|---|---|
prune | Has no effect except a warning: monitors are only deleted with --prune on the command line | false |
adopt_by_name | On apply, link an existing unkeyed monitor that has exactly the same name and type, instead of creating a new one | false |
prune_integrations | Has no effect except a warning: integrations are only deleted with --prune-integrations on the command line | false |
workspace_id | The workspace this file describes. apply refuses destructive changes when the API key acts on another workspace |
--adopt-by-name on the command line overrides adopt_by_name for a single run. Deleting is never turned on by the file.
monitors#
| Field | What it does | Default / limits |
|---|---|---|
key | Stable identifier, unique in the workspace. Required. | 1–128 characters: letters, digits and . _ : / -, starting with a letter or digit |
name | Display name. Required. | 1–255 characters |
type | http, api, ping, port, udp, cron, dns, multistep or mcp | http for new monitors |
url | Target URL for http, api and mcp monitors (mcp needs https://) | Up to 2048 characters |
interval_seconds | Seconds between checks | 15–900, not below your plan's minimum |
config | Type-specific settings (timeout, expected status codes, keyword, headers, host, port, cron expression...) | Managed as a whole when present |
tags | Tags | Stored lower-case |
regions | Probe location codes, or null | Omit to leave as is; null resets to the plan's default locations |
paused | true stops checks, false resumes them | Omit to leave as is |
The config keys for each type are the same as in the dashboard and API. See HTTP & keyword, API & multi-step checks, Ping, TCP & UDP, DNS and Heartbeat & cron. Run sutramx regions for the location codes.
status_pages#
| Field | What it does | Default / limits |
|---|---|---|
slug | Page identifier and URL slug. Required. Pages are matched by slug. | 3–64 lower-case letters, digits and hyphens |
title | Page title. Required. | 1–255 characters |
description | Text under the title | Up to 1000 characters; null clears it |
is_public | Whether the page is published | |
logo_url | Logo image URL | Up to 2048 characters; null clears it |
favicon_url | Favicon URL | Up to 2048 characters; null clears it |
accent_color | Accent colour | Hex like #0d9488; null clears it |
show_response_times | Show response times on the page | |
hide_powered_by | Remove SutramX branding | Only on plans with white-label status pages |
monitors | Monitors on the page, in display order | Up to 500. Each entry is a monitor key, or { key, section } to group it under a heading |
Fields you leave out are not changed. Custom domains, private access and subscribers are set up in the dashboard: see Status pages overview.
integrations#
| Field | What it does | Default / limits |
|---|---|---|
name | Display name. Required. Integrations are matched by type + name. | 1–80 characters |
type | Integration type, for example slack, discord, msteams, webhook, pagerduty, opsgenie or telegram | Which types you can use depends on your plan |
config | The channel's fields, such as webhook_url for Slack | String, number or boolean values |
routing.scope | all (every monitor) or monitors (only the listed ones) | all |
routing.monitors | Monitor keys from this file (or monitor UUIDs) that this channel alerts for | Up to 500 |
The config fields for each channel are described in Slack, Teams & chat apps, Webhooks and PagerDuty & Opsgenie.
Environment variables in the file#
String values can read from the environment, so secrets stay out of your repository:
| Syntax | Result |
|---|---|
${VAR} | The value of VAR. If it is unset or empty, the command fails and names the missing variable. |
${VAR:-default} | The value of VAR, or default when it is unset or empty |
$${VAR} | The literal text ${VAR} |
A file can never read the CLI's own credentials or CI tokens, such as SUTRAMX_API_KEY, SUTRAMX_CONFIG, GITHUB_TOKEN, GH_TOKEN, ACTIONS_*, INPUT_*, NPM_TOKEN or CI_JOB_TOKEN. When SUTRAMX_ALLOWED_ENV is set, for example SUTRAMX_ALLOWED_ENV=SLACK_WEBHOOK_URL,MYAPP_*, only the listed names and prefixes can be read. Set it in CI, where a pull request may have changed the file. A reference that isn't allowed fails with sutramx.yml references environment variables it may not read.
How plan and apply reconcile#
plan reads the file, asks the SutramX API what would change and prints it. Nothing is changed. Each line has a symbol:
| Symbol | Action | Meaning |
|---|---|---|
+ | create | The item doesn't exist yet |
~ | update | Some fields change; plan lists their names, diff shows old -> new |
-/+ | replace | The monitor's type changed, which can't be done in place |
- | delete | Removed because of pruning |
Monitors
+ create api/health "Public API" [api]
~ update web/home "Website" [http]
interval_seconds, regions
Plan: 1 to create, 1 to update, 0 to replace, 0 to delete.apply builds the same plan, shows it, asks you to type yes, then makes the changes and prints one line per change (✓ applied, ✗ failed, · skipped).
Monitors#
- Monitors are matched by
key. Monitors created in the dashboard have no key and are never changed or deleted byapply, unless you adopt them withsutramx monitors adoptoradopt_by_name. - A field you leave out is not managed: an existing monitor keeps its current value, and a new monitor gets the same default as in the dashboard.
config, when present, is managed as a whole: keys you remove from the file are removed from the monitor. The one exception isnotification_emails(per-monitor alert recipients), which is kept unless the file sets it. Setting it needs a key with the Automation access level; with any other key,planandapplyfail with403 ALERT_ROUTING_NOT_ALLOWED.- Changing
typeshows as a replace: the old monitor is deleted, with its check history and incidents, and a new one is created.applyrefuses a replace unless you pass--allow-replace(or--prune). - Monitors are validated by the API with the same rules as the dashboard: plan limits, minimum interval, allowed locations and URL safety.
planwarns when your plan's monitor allowance or minimum interval would makeapplyfail.
Status pages#
Status pages are matched by slug and are created or updated. apply never deletes a status page, because pages have public subscribers; delete a page in the dashboard. A page's monitor list can refer to monitors created in the same run.
Integrations#
Integrations are created or updated. Secrets are stored encrypted and only read back masked (for example …abcd), so the CLI compares the visible part: a secret counts as changed when its visible tail differs from your value. A secret changed in the dashboard to something with the same tail isn't detected.
Order and failures#
Apply runs in this order: monitors first, then integrations, then status pages. That way new monitors can be referenced by key in the same file.
By default, apply stops at the first failed change. Changes that already succeeded are kept, and later changes are skipped. Fix the problem and run apply again: only what is still different is changed. With --continue-on-error, apply keeps going and reports every failure at the end.
If the file changes integrations but the key doesn't have the Automation access level, plan shows an error line and apply refuses to start and changes nothing. A read-only key can still run plan and diff, but apply fails with 403 READ_ONLY_ACCESS and changes nothing.
Pruning#
Pruning deletes keyed monitors that exist in the workspace but are no longer in the file.
- Turn it on for a run with
--prune.settings.prune: truein the file only prints a warning. - It only touches monitors that have a key. That includes monitors created by the Terraform provider or by an AI tool through the MCP server with a key, so don't enable pruning if other tools manage keyed monitors in the same workspace.
- Deleting a monitor removes its check history.
--prune-integrationsdeletes integrations that aren't in the file, but only of the types the file declares. A file that only lists Slack channels never removes a PagerDuty connection.- If the file declares no monitors at all,
applyrefuses a prune that would delete every managed monitor unless you pass--allow-delete-all.
Always run sutramx plan before an apply that prunes and check the - lines.
Move an existing workspace to code#
- Run
sutramx init --from-workspace. It writes a key for every monitor and setsadopt_by_name: true. - Run
sutramx plan. It should show no changes except the links to existing monitors, marked "(adopting existing monitor)". - Run
sutramx apply. - Commit
sutramx.yml. You can removeadopt_by_nameonce the monitors are linked.
Exit codes#
| Code | Meaning |
|---|---|
0 | Success. For plan and diff, also "no changes" when you pass --detailed-exitcode. |
1 | Error: invalid file, missing variable, not logged in, API error, cancelled apply or a failed change |
2 | plan or diff with --detailed-exitcode found changes |
Without --detailed-exitcode, plan and diff exit 0 whether or not there are changes.
Use in CI#
In CI, pass the key with SUTRAMX_API_KEY from your CI secrets and use --auto-approve, because apply refuses to run without confirmation when there is no terminal. A job that only runs validate, plan or diff (for example on pull requests or to detect drift) can use a read-only key, unless the file sets config.notification_emails, which needs an Automation key even to plan; the job that runs apply needs a Standard key, or an Automation key when the file manages integrations or alert recipients.
export SUTRAMX_API_KEY="$SUTRAMX_API_KEY_SECRET"
sutramx validate
sutramx plan --detailed-exitcode # exit 2 = there are changes to review
sutramx apply --auto-approveFor GitHub, the GitHub Action wraps these steps, posts the plan on pull requests and applies on merge.
For machine-readable output, add --json. plan --json returns the full plan (monitor changes, status page and integration changes, warnings, blockers and hasChanges); apply --json returns { ok, changed, steps }.
Troubleshooting#
| Message | What to do |
|---|---|
Not logged in. Run sutramx login or set SUTRAMX_API_KEY. | Log in, or set the environment variable |
SutramX API keys start with "sk_". | You pasted something other than an API key |
Environment variables referenced in sutramx.yml are not set | Export the listed variables, or give them a default with ${VAR:-default} |
sutramx.yml references environment variables it may not read | Add the variables to SUTRAMX_ALLOWED_ENV, or stop referencing a credential the file may never read |
... changed type and would be deleted with its history and created again | Pass --allow-replace if you mean to replace the monitor |
Refusing to apply without confirmation | Add --auto-approve in non-interactive runs |
Managing integrations needs an API key with the "Automation" access level. (code AUTOMATION_KEY_REQUIRED) or integrations can only be changed with an API key whose access level is "Automation" | Create a new key with the Automation access level; a key's level can't be changed |
READ_ONLY_ACCESS | The key is read-only. Use a Standard key for changes (or Automation for integrations and alert recipients) |
ALERT_ROUTING_NOT_ALLOWED | The file sets config.notification_emails. Use an Automation key, or remove the field from the listed monitors |
the file declares no monitors, so prune would delete all ... managed monitors | Check the file. Pass --allow-delete-all only if you really want to delete every managed monitor |
ENTITLEMENT_LIMIT_REACHED or FEATURE_NOT_AVAILABLE | Your plan doesn't allow the change. Check sutramx whoami and Plans & limits. |
| HTTP 429 | You were rate limited; wait a few minutes and run again |
Validation errors from the API name the monitor key and the field, for example monitor api/health: interval_seconds: ....
Common questions#
Will apply touch monitors I made in the dashboard? No. Only monitors with a key are managed. Adopt a dashboard monitor if you want the file to manage it.
Can I split the configuration over several files? Each run reads one file. If you use several files against one workspace, give them different keys and leave pruning off, or one file's apply will delete the other's monitors.
What happens if apply fails half-way? Completed changes stay. Run apply again after fixing the cause; it only changes what is still different.
Related
- GitHub Action
- Terraform provider
- REST API
- Monitors 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.