How UpPage behaves for agents.
The REST API and the MCP server follow the same rules. Every write can be retried safely and previewed first, and every error tells you what to do next.
Errors
Errors have the shape { code, message, fix, next_tool, docs_url }. Act on fix, and call next_tool when it is set.
| Code | HTTP | Fix | Next tool |
|---|---|---|---|
INVALID_INPUT | 400 | Correct the field named in the message to match the tool or endpoint schema, then retry. | — |
UNAUTHENTICATED | 401 | Reconnect the UpPage MCP server (OAuth sign-in) or supply a current, unrevoked scoped token from Settings → API tokens. | — |
NOT_FOUND | 404 | IDs belong to one account. List the resources this credential can see and use an ID from that list. | list_monitors |
FORBIDDEN | 403 | This credential lacks the scope or role this operation needs. Ask the owner for a token with the scope listed in the tool description. | — |
ENTITLEMENT_EXCEEDED | 422 | The account plan does not allow this. Choose a value the plan allows, or ask the owner to upgrade in Settings → Billing. | — |
CONFLICT | 409 | The resource changed or this transition is not allowed from its current state. Read it again, then retry against the current state. | list_monitors |
RATE_LIMITED | 429 | Wait 60 seconds, then retry with the same idempotency_key so the retry cannot apply twice. | — |
IDEMPOTENCY_KEY_REUSED | 409 | This idempotency_key was used in the last 24 hours with different arguments. Resend the original arguments exactly, or use a new key for a new request. | — |
MANAGED_BY_REPO | 409 | This resource is managed by uppage.yml in the repository. Edit the file and apply it (uppage apply, or apply_config); dashboard and MCP edits are refused so the repository stays the source of truth. | plan_config |
DRY_RUN_UNSUPPORTED | 400 | This endpoint cannot preview its change. Call it without dry_run, or use a tool that supports dry_run. | — |
UNAVAILABLE | 503 | A server-side dependency is unavailable. Retry later with the same idempotency_key. | — |
Idempotency
Every write accepts an idempotency key: the idempotency_key argument on MCP tools, or the Idempotency-Key header on REST, where it is required. For 24 hours, the same key with the same arguments returns the first result and doesn’t act again. The same key with different arguments fails with IDEMPOTENCY_KEY_REUSED. Without a key, MCP tools scope retries to the JSON-RPC request.
Dry runs
Pass dry_run: true to any MCP write tool, or send UpPage-Dry-Run: true on REST. The response is { dryRun: true, changes, audit, value }: the exact resources that would be created, updated or deleted, and the audit events that would be written. Nothing is stored, and no one-time URL is minted. Writes that can’t preview refuse with DRY_RUN_UNSUPPORTED before doing anything.
Pending monitors
New monitors start pending. Until their first successful ping, passing check or webhook event, they don’t alert, open incidents, write history or appear on the public page. They arm themselves automatically, so create them before the code ships. list_monitors explains any monitor that is still pending, and sets nudge after seven days.
Monitoring as code
Describe every monitor in uppage.yml in your repository (JSON Schema). plan_config shows what would change; apply_config makes the page match the file in one atomic, idempotent change. Monitors removed from the file are deleted only with prune.
Monitors the file manages are refused for edits from the dashboard or MCP (MANAGED_BY_REPO), so the repository stays the source of truth. Status observations and pausing are always allowed. With settings.drift: record, edits are allowed instead: the next plan reports them and the next apply puts the file’s values back.
To apply on merge with no stored token, allow the workflow once with bind_repository. It then applies with its GitHub identity. Pull-request runs never get UpPage access; their plan compares the file with the base branch’s copy.
Signing in
Use OAuth sign-in from an MCP client that supports it, or a scoped API token from Settings → API tokens. A revoked token stops working on its next call.
Scopes
| Scope | Grants |
|---|---|
pages:read / pages:write | Read or change the status page, its publication settings and website checks’ findings. |
components:read / components:write | Read or change services and record status observations. |
heartbeats:read / heartbeats:write | Read or change heartbeats and website/MCP checks. |
incidents:read / incidents:write | Read or change incidents and maintenance windows. |
Each tool’s description names the scopes it needs. incidents:* doesn’t include incidents:publish: give it explicitly to a token that may publish incident text without approval.
| MCP tool | Needs |
|---|---|
create_status_page | pages:write |
get_status_page | pages:read |
update_status_page | pages:write |
get_current_status | pages:read |
get_badge_markdown | pages:read |
list_components | components:read |
add_component | components:write |
update_component | components:write |
set_component_status | components:write |
list_component_groups | components:read |
create_component_group | components:write |
update_component_group | components:write |
remove_component_group | components:write |
add_dependency | components:write |
list_dependencies | components:read |
create_monitor | components:write and heartbeats:write |
list_monitors | pages:read |
update_monitor | heartbeats:write |
apply_fix | heartbeats:write |
create_heartbeat | heartbeats:write |
update_heartbeat | heartbeats:write |
rotate_heartbeat | heartbeats:write |
test_ping | heartbeats:write |
get_heartbeat | heartbeats:read |
list_heartbeats | heartbeats:read |
get_heartbeat_snippet | heartbeats:read |
plan_monitors | pages:read |
apply_plan | pages:write, components:write, heartbeats:write |
plan_config | pages:read and components:read |
apply_config | pages:write, components:write, heartbeats:write |
bind_repository | pages:write |
create_incident | incidents:write (+ incidents:publish for tokens) |
list_incidents | incidents:read |
update_incident | incidents:write (+ incidents:publish for tokens) |
resolve_incident | incidents:write (+ incidents:publish for tokens) |
draft_incident_update | incidents:write |
get_incident_context | incidents:read |
get_component_context | components:read |
list_events | pages:read |
record_deploy | components:write |
update_remediation | incidents:write |
list_audit_events | pages:read |
list_undoable | pages:read |
undo_change | pages:write, components:write, heartbeats:write |
start_maintenance | incidents:write |
end_maintenance | incidents:write |
Test mode and undo
Test tokens (st_test_…, created by the owner) work on a sandbox account with the same plan, whose pages are never public and whose alerts are never delivered. Configuration changes made with a token can be undone for 24 hours with list_undoable and undo_change. The audit log (list_audit_events, exportable as CSV) shows each agent change with its client.
Limits
The API and MCP share a per-account rate limit, 240 requests a minute by default. Plan limits (check intervals, monitor counts) apply the same way they do in the dashboard.
Attribution
Writes made with a token record the client that made them (its User-Agent, or the UpPage-Client header) and an optional UpPage-Session ID in the audit log.