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:
https://api.sutramx.comPaths 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:
- Open Account settings → API keys.
- Click Create API key.
- Enter a Key name (up to 100 characters) that tells you where it is used, for example
ci-deployorterraform-prod. - 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.
- Click Create key.
- 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:
Authorization: Bearer sk_your_api_keyFor example:
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 level | What it can do | What 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. |
| Standard | Everything 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. |
| Automation | Everything 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:
| Use | Level |
|---|---|
| Dashboards, reporting scripts, AI assistants that only answer questions | Read-only |
| CI jobs and scripts that create or pause monitors, record deploys, or apply monitoring-as-code changes | Standard |
| Automation that also manages alert channels, webhooks or per-monitor alert recipients | Automation |
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 /monitorsorPUT /monitors/:id: aconfig.notification_emailsvalue sent there with an API key is ignored. Automation keys can set it through the monitoring-as-code endpoints; other keys get403. - A monitor group's
notification_emails. Changing it with an API key is rejected with403. - 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.
| Endpoints | Limit | Counted per |
|---|---|---|
| Every request made with an API key | 1,200 requests per minute | API key |
| Requests with an invalid API key | 100 per 15 minutes | IP address |
| Monitor create, update, delete, pause, resume, reset stats, bulk actions, region changes, heartbeat URL rotation | 120 requests per 15 minutes | IP address |
Run a check now (/monitors/test, /monitors/:id/run-check and its aliases) | 30 requests per 5 minutes | Account |
Send a test notification (/monitors/:id/test-notification) | 10 requests per 15 minutes | Account |
| Subdomain discovery, domain/SSL refresh, check-history CSV export, incident export | 20 requests per 15 minutes each | Account |
Stats endpoints (/stats/...) | 1,000 requests per minute | IP address |
| Test an alert channel | 30 per hour per account, 60 per hour per IP | Account and IP |
| Accept DNS record changes | 120 requests per 15 minutes | IP address |
Monitoring-as-code apply (/automation/monitors/apply) | 30 requests per 15 minutes | Workspace |
Monitoring-as-code plan (/automation/monitors/plan) | 120 requests per 15 minutes | Workspace |
Keyed monitor writes (/automation/monitors/:key) | 600 requests per 15 minutes | Workspace |
| AI incident drafts (summary, postmortem, status update, translation) | 30 requests per 10 minutes | Workspace |
| Website health "run now" | 20 requests per hour | Account |
Heartbeat pings (/heartbeat/:token) | 60 per minute per heartbeat URL; 600 failed requests per minute per IP | Token and IP |
| Public status page endpoints | 60 requests per minute | IP 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-Afterbefore retrying a429. - 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:
| Endpoint | Style | Parameters | Response |
|---|---|---|---|
GET /incidents | Page number | page (default 1), page_size (default 25, max 100) | items, total, page, page_size, counts |
GET /monitors/:id/checks | Cursor | limit (default 50, 1–500), before (UTC timestamp YYYY-MM-DDTHH:MM:SS[.ffffff][Z]) | items, next_before |
GET /incidents/deploy-events | Limit only | limit (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.
# 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).
{
"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:
{
"error": "Validation failed",
"code": "VALIDATION_ERROR",
"errors": [
{ "field": "interval_seconds", "message": "Too small: expected number to be >=15" }
]
}Status codes#
| Status | Meaning |
|---|---|
200, 201 | Success. 201 means a resource was created. |
204 | Success with no body (for example, deleting a monitor). |
207 | Partial success from a monitoring-as-code apply. Check each result. |
400 | The request is invalid: bad JSON, a failed validation, or a value the service rejects. |
401 | No key, an invalid key, a deleted key or a disabled key. |
403 | The key isn't allowed to do this (for example, a read-only key making a change), or your plan doesn't include it. |
404 | The resource doesn't exist in this workspace. IDs from another workspace also return 404. |
409 | Conflict, for example resolving an incident that is already resolved, or a monitoring-as-code apply whose plan changed since you reviewed it. |
413 | The request body is too large. |
428 | A monitoring-as-code apply would delete or replace monitors without confirming the reviewed plan. |
429 | Rate limited. Wait for Retry-After seconds. |
500, 503 | An error on our side (500) or the API is briefly unavailable (503). Retry with backoff. |
Error codes#
| Code | Status | What it means |
|---|---|---|
VALIDATION_ERROR | 400 | A field value was rejected. The message says which and why. |
BAD_REQUEST | 400 | The body isn't valid JSON. |
PAYLOAD_TOO_LARGE | 413 | The body is over the size limit (100 KB for most endpoints, 2 MB for /automation/monitors/plan and /apply). |
NOT_FOUND | 404 | The resource wasn't found. |
UNAUTHORIZED | 401 | The request isn't authenticated. A missing or invalid API key returns 401 without a code. |
API_KEY_DISABLED | 401 | The key was disabled because your plan's API key limit went down. Delete it, or upgrade to re-enable it. |
SESSION_AUTH_REQUIRED | 403 | The endpoint only accepts a signed-in dashboard session, not an API key. |
WORKSPACE_OWNER_REQUIRED | 403 | Only the workspace owner can do this. API keys never have owner rights. |
READ_ONLY_ACCESS | 403 | The key is read-only and the request would change something. Use a standard or automation key. |
AUTOMATION_KEY_REQUIRED | 403 | The endpoint needs a key with the Automation access level. |
ALERT_ROUTING_NOT_ALLOWED | 403 | A monitoring-as-code spec sets config.notification_emails, which needs an automation key. |
WORKSPACE_ACCESS_DENIED | 403 | X-Workspace-Id doesn't match the key's workspace. |
FEATURE_NOT_AVAILABLE | 403 | Your plan doesn't include this feature. required_plan names the cheapest plan that does. |
ENTITLEMENT_LIMIT_REACHED | 403 | You've reached a plan limit (for example, the number of monitors). details has resource, current and limit. |
EMAIL_VERIFICATION_REQUIRED | 403 | The workspace owner must verify their email address before monitors can be created. |
INCIDENT_RESOLVED | 409 | The incident is already resolved. |
PLAN_CHANGED | 409 | A monitoring-as-code apply sent an expected_fingerprint that no longer matches. Run plan again. |
PRUNE_CONFIRMATION_REQUIRED | 428 | A monitoring-as-code apply would delete or replace monitors, but sent neither expected_fingerprint nor allow_prune_without_fingerprint. |
CONNECTION_LIMIT_REACHED | 409 | You already have 10 connections of this alert channel type. |
CHANNEL_UNAVAILABLE | 503 | The alert channel is temporarily unavailable. |
RATE_LIMITED | 429 | Too many requests. Some 429 responses are plain text without a code. |
CORS_REJECTED | 403 | A browser request came from an origin that isn't allowed. See CORS. |
INTERNAL_ERROR | 500 | An 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,PUTandDELETErequests are safe to retry. Repeating aPUTsets the same values again, and deleting something twice returns404the second time.POST /monitorsis 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 returns409withINCIDENT_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#
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#
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#
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#
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#
curl -s "https://api.sutramx.com/incidents?status=ongoing&page_size=50" \
-H "Authorization: Bearer $SUTRAMX_API_KEY"Check who a key belongs to#
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.
Related
- API reference
- Developer overview
- Webhooks
- Plans & limits
- Team members & roles
- Features: API Monitoring
- Free tools: Unix Timestamp Converter
- Integrations: Webhooks 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.