Developers

REST API

Authenticate with a SutramX API key and call the REST API to manage monitors, incidents and status pages, with rate limits, pagination and errors.

The SutramX REST API lets you manage monitors, incidents, status pages and alert channels from your own scripts, CI pipelines and internal tools. It is the same API the dashboard uses, so anything you create through it shows up in the dashboard straight away.

This page covers how to authenticate and how the API behaves. For every endpoint, see the API reference.

Base URL#

All requests go to:

text
https://api.sutramx.com

Paths are appended directly to the base URL, with no version prefix. For example, the monitor list is https://api.sutramx.com/monitors. You can also copy the base URL from the API documentation tab of Alerts → Channels & API.

Requests and responses use JSON. Send Content-Type: application/json on any request that has a body.

Create an API key#

API keys belong to a workspace. Only the workspace owner can create or delete them, and the owner's email address must be verified first.

To create a key:

  1. Open Account settings → API keys.
  2. Click Create API key.
  3. Enter a Key name (up to 100 characters) that tells you where it is used, for example ci-deploy or terraform-prod.
  4. Under Access, choose an access level: Read-only (the default), Standard or Automation. Pick the lowest level that does the job (see Access levels). You can't change it later.
  5. Click Create key.
  6. Copy the key from the banner. It starts with sk_ and is shown only once.

SutramX stores only a hash of the key. If you lose it, delete it and create a new one.

The key list shows each key's name, a Read-only or Automation label (standard keys have no label), its first characters, when it was created and when it was last used.

Delete a key#

Click Delete next to the key and confirm. Anything using the key stops working immediately, and this can't be undone.

If your plan's API key limit goes down (for example after a downgrade), keys over the new limit are disabled and marked Disabled — plan limit. A disabled key is rejected with 401. Delete it, or upgrade to re-enable it.

Authentication#

Send the key as a bearer token in the Authorization header on every request:

http
Authorization: Bearer sk_your_api_key

For example:

bash
export SUTRAMX_API_KEY="sk_..."

curl -s "https://api.sutramx.com/monitors" \
  -H "Authorization: Bearer $SUTRAMX_API_KEY"

A key always acts on the workspace it was created in. You don't need to send a workspace header. If you do send X-Workspace-Id, it must match the key's workspace, or the request is rejected with 403 and code WORKSPACE_ACCESS_DENIED.

Keep keys secret. Store them in your CI secret store or a secrets manager, never in source code or browser JavaScript.

Access levels#

Every key has one of three access levels, chosen when you create it. The dashboard selects Read-only by default.

Access levelWhat it can doWhat it can't do
Read-only (dashboard default)Read everything a workspace viewer can see: monitors, check history, stats, incidents, status pages, alert channels and settings. It can also preview a monitoring-as-code change (POST /automation/monitors/plan), which writes nothing.Create, change, pause or delete anything. Every other write is refused with 403 and code READ_ONLY_ACCESS.
StandardEverything a workspace member can do: create, edit, pause and delete monitors and monitor groups; acknowledge, resolve and annotate incidents; manage status pages; record deploys; apply monitoring-as-code changes.Manage alert channels, the OpenTelemetry export, maintenance windows, alert recipients, escalation policies, on-call schedules, team, billing, API keys or account settings.
AutomationEverything a standard key can do, plus create, edit, delete and route alert channels (including webhooks), set per-monitor alert recipients through monitoring-as-code, and manage the OpenTelemetry export.Team, billing, workspace, API keys and account settings.

Which level to pick:

UseLevel
Dashboards, reporting scripts, AI assistants that only answer questionsRead-only
CI jobs and scripts that create or pause monitors, record deploys, or apply monitoring-as-code changesStandard
Automation that also manages alert channels, webhooks or per-monitor alert recipientsAutomation

Some things stay owner-only for every key, because they change where alerts go or silence them:

  • Creating, editing or deleting maintenance windows.
  • Snoozing an incident (unsnoozing is allowed).
  • Setting per-monitor alert recipients through POST /monitors or PUT /monitors/:id: a config.notification_emails value sent there with an API key is ignored. Automation keys can set it through the monitoring-as-code endpoints; other keys get 403.
  • A monitor group's notification_emails. Changing it with an API key is rejected with 403.
  • Status page access settings (who can view a private page), custom status page domains, monitor dependencies, webhook signing-secret rotation and one-click "Connect with…" flows.

Endpoints that act on the human account (profile, password, two-factor, sessions, workspaces, subscription and checkout) never accept API keys. They answer 403 with code SESSION_AUTH_REQUIRED.

Rate limits#

Every API key can make up to 1,200 requests per minute. Separately, an IP address that sends more than 100 requests with an invalid API key in 15 minutes is blocked for the rest of that window. On top of that, endpoints that do heavy or outbound work have their own limits, listed below.

When you exceed a limit, the API answers 429 Too Many Requests with a Retry-After header (in seconds) and the standard RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset headers. Most 429 responses have a JSON body with code RATE_LIMITED, but some (for example monitor writes, run-check, stats and exports) return the plain-text body Too many requests, please try again later. Check the status code and Retry-After, not the body.

EndpointsLimitCounted per
Every request made with an API key1,200 requests per minuteAPI key
Requests with an invalid API key100 per 15 minutesIP address
Monitor create, update, delete, pause, resume, reset stats, bulk actions, region changes, heartbeat URL rotation120 requests per 15 minutesIP address
Run a check now (/monitors/test, /monitors/:id/run-check and its aliases)30 requests per 5 minutesAccount
Send a test notification (/monitors/:id/test-notification)10 requests per 15 minutesAccount
Subdomain discovery, domain/SSL refresh, check-history CSV export, incident export20 requests per 15 minutes eachAccount
Stats endpoints (/stats/...)1,000 requests per minuteIP address
Test an alert channel30 per hour per account, 60 per hour per IPAccount and IP
Accept DNS record changes120 requests per 15 minutesIP address
Monitoring-as-code apply (/automation/monitors/apply)30 requests per 15 minutesWorkspace
Monitoring-as-code plan (/automation/monitors/plan)120 requests per 15 minutesWorkspace
Keyed monitor writes (/automation/monitors/:key)600 requests per 15 minutesWorkspace
AI incident drafts (summary, postmortem, status update, translation)30 requests per 10 minutesWorkspace
Website health "run now"20 requests per hourAccount
Heartbeat pings (/heartbeat/:token)60 per minute per heartbeat URL; 600 failed requests per minute per IPToken and IP
Public status page endpoints60 requests per minuteIP address

Plan limits (number of monitors, minimum check interval, status pages and so on) are separate from rate limits. Exceeding a plan limit returns 403, not 429. See Errors.

To stay within the limits:

  • Wait for the number of seconds in Retry-After before retrying a 429.
  • Use exponential backoff with jitter for repeated failures.
  • Use the bulk endpoint (POST /monitors/bulk) instead of many single updates.
  • Cache read results such as the monitor list rather than polling them every second.

Pagination#

Most list endpoints return the full list in one response. A few large collections are paginated:

EndpointStyleParametersResponse
GET /incidentsPage numberpage (default 1), page_size (default 25, max 100)items, total, page, page_size, counts
GET /monitors/:id/checksCursorlimit (default 50, 1–500), before (UTC timestamp YYYY-MM-DDTHH:MM:SS[.ffffff][Z])items, next_before
GET /incidents/deploy-eventsLimit onlylimit (default 20, max 100)events

For cursor pagination, pass the next_before value from one response as before in the next request, unchanged. Check timestamps have microsecond precision (for example 2026-10-01T09:12:30.123456Z), so don't round them. When next_before is null, there are no more results.

bash
# First page of checks
curl -s "https://api.sutramx.com/monitors/$MONITOR_ID/checks?limit=100" \
  -H "Authorization: Bearer $SUTRAMX_API_KEY"

# Next page
curl -s "https://api.sutramx.com/monitors/$MONITOR_ID/checks?limit=100&before=2026-10-01T09:12:30.123456Z" \
  -H "Authorization: Bearer $SUTRAMX_API_KEY"

GET /monitors is not paginated. It returns every monitor in the workspace, newest first. You can filter it with ?tag=<tag>.

Errors#

The API uses standard HTTP status codes. Error responses have a JSON body in which error is a human-readable string, and code (machine-readable) and details are included where useful. A few responses have no code: for example, a missing or invalid API key returns 401 with only error (No token provided or Invalid API key), and some rate-limit responses are plain text (see Rate limits).

json
{
  "error": "Feature not available on your plan",
  "code": "FEATURE_NOT_AVAILABLE",
  "details": "SLO tracking is not available on the Starter plan. Upgrade to Growth to use it.",
  "plan": "starter",
  "required_plan": "growth",
  "upgradePath": "/subscription"
}

Request bodies that fail validation return 400 with code: "VALIDATION_ERROR" and a list of the fields that are wrong:

json
{
  "error": "Validation failed",
  "code": "VALIDATION_ERROR",
  "errors": [
    { "field": "interval_seconds", "message": "Too small: expected number to be >=15" }
  ]
}

Status codes#

StatusMeaning
200, 201Success. 201 means a resource was created.
204Success with no body (for example, deleting a monitor).
207Partial success from a monitoring-as-code apply. Check each result.
400The request is invalid: bad JSON, a failed validation, or a value the service rejects.
401No key, an invalid key, a deleted key or a disabled key.
403The key isn't allowed to do this (for example, a read-only key making a change), or your plan doesn't include it.
404The resource doesn't exist in this workspace. IDs from another workspace also return 404.
409Conflict, for example resolving an incident that is already resolved, or a monitoring-as-code apply whose plan changed since you reviewed it.
413The request body is too large.
428A monitoring-as-code apply would delete or replace monitors without confirming the reviewed plan.
429Rate limited. Wait for Retry-After seconds.
500, 503An error on our side (500) or the API is briefly unavailable (503). Retry with backoff.

Error codes#

CodeStatusWhat it means
VALIDATION_ERROR400A field value was rejected. The message says which and why.
BAD_REQUEST400The body isn't valid JSON.
PAYLOAD_TOO_LARGE413The body is over the size limit (100 KB for most endpoints, 2 MB for /automation/monitors/plan and /apply).
NOT_FOUND404The resource wasn't found.
UNAUTHORIZED401The request isn't authenticated. A missing or invalid API key returns 401 without a code.
API_KEY_DISABLED401The key was disabled because your plan's API key limit went down. Delete it, or upgrade to re-enable it.
SESSION_AUTH_REQUIRED403The endpoint only accepts a signed-in dashboard session, not an API key.
WORKSPACE_OWNER_REQUIRED403Only the workspace owner can do this. API keys never have owner rights.
READ_ONLY_ACCESS403The key is read-only and the request would change something. Use a standard or automation key.
AUTOMATION_KEY_REQUIRED403The endpoint needs a key with the Automation access level.
ALERT_ROUTING_NOT_ALLOWED403A monitoring-as-code spec sets config.notification_emails, which needs an automation key.
WORKSPACE_ACCESS_DENIED403X-Workspace-Id doesn't match the key's workspace.
FEATURE_NOT_AVAILABLE403Your plan doesn't include this feature. required_plan names the cheapest plan that does.
ENTITLEMENT_LIMIT_REACHED403You've reached a plan limit (for example, the number of monitors). details has resource, current and limit.
EMAIL_VERIFICATION_REQUIRED403The workspace owner must verify their email address before monitors can be created.
INCIDENT_RESOLVED409The incident is already resolved.
PLAN_CHANGED409A monitoring-as-code apply sent an expected_fingerprint that no longer matches. Run plan again.
PRUNE_CONFIRMATION_REQUIRED428A monitoring-as-code apply would delete or replace monitors, but sent neither expected_fingerprint nor allow_prune_without_fingerprint.
CONNECTION_LIMIT_REACHED409You already have 10 connections of this alert channel type.
CHANNEL_UNAVAILABLE503The alert channel is temporarily unavailable.
RATE_LIMITED429Too many requests. Some 429 responses are plain text without a code.
CORS_REJECTED403A browser request came from an origin that isn't allowed. See CORS.
INTERNAL_ERROR500An unexpected error. Retry later, and contact support if it continues.

Retries and idempotency#

The API doesn't support an Idempotency-Key header. Plan your retries with that in mind:

  • GET, PUT and DELETE requests are safe to retry. Repeating a PUT sets the same values again, and deleting something twice returns 404 the second time.
  • POST /monitors is not idempotent. If a create request times out and you retry it, you may get two monitors. List monitors first and check by name, or use a keyed upsert (PUT /automation/monitors/:key), which creates the monitor the first time and updates it after that. See the API reference.
  • Some actions protect themselves. Creating a manual incident for a monitor that already has an open one returns 409, and resolving a resolved incident returns 409 with INCIDENT_RESOLVED.

Retry 429 after Retry-After and 5xx errors with exponential backoff. Don't retry 400, 401, 403 or 404 without changing the request.

CORS#

The API is meant to be called from servers, scripts and CI jobs, not from web pages on your own domain. Requests without an Origin header (curl, server-side code, CI runners) are always allowed. Browser requests from other websites are rejected with 403 and code CORS_REJECTED.

If you need SutramX data on a web page, call the API from your backend and pass the result to the browser. Never put an API key in front-end code.

Examples#

List monitors that are down#

bash
curl -s "https://api.sutramx.com/monitors" \
  -H "Authorization: Bearer $SUTRAMX_API_KEY" \
  | jq '.[] | select(.current_status == "down") | {id, name, url}'

Create an HTTP monitor#

bash
curl -s -X POST "https://api.sutramx.com/monitors" \
  -H "Authorization: Bearer $SUTRAMX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Marketing site",
    "type": "http",
    "url": "https://www.example.com",
    "interval_seconds": 60,
    "tags": ["web", "prod"],
    "config": { "method": "GET", "timeout": 10000, "keyword": "Welcome" }
  }'

Pause a monitor during a deploy#

bash
curl -s -X POST "https://api.sutramx.com/monitors/$MONITOR_ID/pause" \
  -H "Authorization: Bearer $SUTRAMX_API_KEY"

# ... deploy ...

curl -s -X POST "https://api.sutramx.com/monitors/$MONITOR_ID/resume" \
  -H "Authorization: Bearer $SUTRAMX_API_KEY"

Record a deployment#

bash
curl -s -X POST "https://api.sutramx.com/incidents/deploy-events" \
  -H "Authorization: Bearer $SUTRAMX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "service_name": "checkout-api", "environment": "production", "version": "v2.14.0" }'

Deploy events need a plan that includes deployment correlation. See Deployment correlation.

List open incidents#

bash
curl -s "https://api.sutramx.com/incidents?status=ongoing&page_size=50" \
  -H "Authorization: Bearer $SUTRAMX_API_KEY"

Check who a key belongs to#

bash
curl -s "https://api.sutramx.com/automation/whoami" \
  -H "Authorization: Bearer $SUTRAMX_API_KEY"

The response shows the workspace, the key's access level, your plan and its main limits. It's a quick way to test a key in CI.

Common questions#

Why do I get 401 "Invalid API key"?#

The key is wrong or was deleted. (A key disabled because your plan's key limit went down returns 401 with code API_KEY_DISABLED instead.) Check that the header is exactly Authorization: Bearer sk_... with no extra spaces or quotes.

Why do I get 403 with WORKSPACE_OWNER_REQUIRED?#

The endpoint is owner-only, and API keys never have owner rights. Do it in the dashboard as the owner instead. For alert channels, create a key with the Automation access level.

Why do I get 403 with READ_ONLY_ACCESS?#

The key was created as Read-only, which is the dashboard default. Access levels can't be changed, so create a new key with the Standard or Automation level for scripts that make changes.

Can a key access more than one workspace?#

No. Create a separate key in each workspace.

Is there a sandbox?#

No. Every request acts on your real workspace, so test against monitors you create for that purpose, and pause or delete them afterwards.

Last updated . Something unclear or missing on this page? Tell us at support@sutramx.com.