Skip to content
Docs/REST API reference

Agents & API

REST API reference

99 endpoints, generated from the same operation registry that powers the server, the OpenAPI spec and the MCP tools.

Basics

Base URLhttps://upbutler.com/api/v1
AuthAuthorization: Bearer ub_live_… with a read or write scope. Get one from the dashboard or POST /agent/bootstrap
FormatJSON in, JSON out. Send Content-Type: application/json with bodies
Errors{"error": {"code", "message", "hint?", "details?"}}. See Errors
RetriesIdempotency-Key header on POST, replayed for 24 h
Live eventsGET /api/v1/stream streams workspace events as Server-Sent Events (same auth, types filter, resume with Last-Event-ID). Not part of the OpenAPI spec; see Events
Spec/api/v1/openapi.json (OpenAPI 3.1)
IDsWherever a pageId is expected, a page slug works too

Agents

Create a workspace + API key with no human in the loop

POST/api/v1/agent/bootstrap
Public — no keyMCP agent_bootstrapReturns 201

For autonomous agents. Returns an API key immediately and a claim URL. Give the claim URL to your human: unclaimed workspaces are deleted after 7 days, and email features unlock once claimed. Rate-limited per IP.

FieldTypeDescription
agentNamerequiredstringWho you are, e.g. "claude-code" or "deploy-bot"max length 80
workspaceNamestringmax length 80
Example
curl -X POST https://upbutler.com/api/v1/agent/bootstrap \
  -H "Content-Type: application/json" \
  -d '{
    "agentName": "..."
  }'

Plug in a service: monitor + status page component in one call

POST/api/v1/services
API key · writeMCP services_addReturns 201

The fastest path: creates a monitor for the URL (or a heartbeat when you pass periodSec), creates the status page if needed (statusPage = slug or name), and adds a component that follows the monitor. Returns everything you need, including heartbeat ping URLs.

FieldTypeDescription
namerequiredstringHuman-friendly name, e.g. "Search API"max length 120
descriptionstring | nullnull or "" clears itmax length 1,000 · nullable
kindstringInferred when omitted: url → http, host+port → tcp, periodSec → heartbeathttptcpdnsheartbeatmanifestscriptbrowser
urlstring (url)http/manifest: URL to checkmax length 2,000
methodstringGETHEADPOSTPUTPATCHDELETEOPTIONS
headersmap<string, string>
bodystring | nullnull clears itmax length 100,000 · nullable
followRedirectsboolean
expectedStatusstringe.g. "200-299" (default), "200,204", "401"max length 100
keywordstringhttp: response body must contain this textmax length 500
keywordAbsentstringhttp: response body must NOT contain this textmax length 500
degradedAfterMsinteger | nullMark degraded when slower than this (null clears)min 50 · max 120,000 · nullable
sslExpiryDaysinteger | nullMark degraded when the TLS cert expires within N days (null clears)min 1 · max 365 · nullable
hoststringtcp/dns hostmax length 255
portintegermin 1 · max 65,535
recordTypestringAAAAACNAMEMXTXTNS
expectedstring[]dns: values that must be presentmax 20 items
periodSecintegerheartbeat: expected ping intervalmin 30 · max 2,678,400
graceSecintegerheartbeat: extra time before alertingmin 0 · max 86,400
codestringscript/browser: test codemax length 50,000
viewportobject
viewport.widthrequiredintegermin 320 · max 3,840
viewport.heightrequiredintegermin 240 · max 2,160
assertionsobject[]max 30 items
assertions[].sourcerequiredstringstatuslatencyheaderbodyjsonssl_days
assertions[].pathstringmax length 300
assertions[].oprequiredstringeqneqltltegtgtecontainsnot_containsmatchesexistsnot_exists
assertions[].valuestring | number | booleanmax length 2,000
assertions[].severitystringdowndegraded
intervalSecintegerSeconds between checks (default 60, limited by plan)min 10 · max 86,400
timeoutMsintegermin 1,000 · max 120,000
failureThresholdintegerConsecutive failures before DOWN (default 2)min 1 · max 10
recoveryThresholdintegermin 1 · max 10
channelIdsstring[]Alert channels. Default: channels marked as defaultmax 50 items
reminderMinutesinteger[]max 10 items
aibooleanAI incident analysis (default true)
tagsstring[]max 20 items
pausedboolean
regionsstring[]Check regions (GET /api/v1/regions). With several, a round only counts as DOWN when a majority of regions agree. Default: main region onlymax 10 items
statusPagestringStatus page slug or id; created (by name) if it does not exist. Omit to only monitor.max length 100
groupstringComponent group on the status page, e.g. "APIs"max length 80
componentNamestringPublic name (defaults to name)max length 100
Example
curl -X POST https://upbutler.com/api/v1/services \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Search API",
    "url": "https://api.example.com/health",
    "statusPage": "acme",
    "group": "APIs"
  }'

Send a heartbeat (no API key needed — the token is the secret)

POST/api/v1/heartbeat/:token
Public — no keyMCP heartbeat_pingReturns 200

Call at least every periodSec. status=down (or POST to /hb/{token}/fail) reports an explicit failure and alerts immediately. Short form: GET/POST https://upbutler.com/hb/{token}.

FieldTypeDescription
tokenrequiredpathstring
statusstringupdowndegraded
messagestringmax length 500
durationMsintegerHow long the job tookmin 0
Example
curl -X POST https://upbutler.com/api/v1/heartbeat/hb_Xf3kq9LmR2vT8wYzN4bC1dE7

Push one component status by its push token (no API key needed)

POST/api/v1/push/:token
Public — no keyMCP components_pushReturns 200
FieldTypeDescription
tokenrequiredpathstring
statusrequiredstring | boolean | numberoperational | degraded | partial_outage | major_outage | maintenance, or ok/up/fail/down/true/false
messagestringmax length 500
confirmedbooleanSkip blip protection: the sender already confirmed this status
observedAtanyWhen this status was observed; re-sending the same observation does not count as a new confirmation
Example
curl -X POST https://upbutler.com/api/v1/push/push_Qm7vB2xK9pL4sT1nW8cZ3yH6 \
  -H "Content-Type: application/json" \
  -d '{
    "status": "degraded",
    "message": "p95 latency above 2s"
  }'

Identify the calling key

GET/api/v1/agent/whoami
API key · readMCP agent_whoamiReturns 200

No parameters.

Example
curl https://upbutler.com/api/v1/agent/whoami \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Monitors

List monitors

GET/api/v1/monitors
API key · readMCP monitors_listReturns 200

All monitors in the workspace with their current state and last check.

FieldTypeDescription
statequerystringupdowndegradedpendingpaused
tagquerystring
Example
curl https://upbutler.com/api/v1/monitors \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Create a monitor

POST/api/v1/monitors
API key · writeMCP monitors_createReturns 201

Create an uptime monitor. Minimal input is {"name","url"}. Kinds: http (status/keyword/JSON/latency/TLS assertions), tcp, dns, heartbeat (your job pings us), manifest (one JSON endpoint reporting many components), script, browser.

FieldTypeDescription
namerequiredstringHuman-friendly name, e.g. "Search API"max length 120
descriptionstring | nullnull or "" clears itmax length 1,000 · nullable
kindstringInferred when omitted: url → http, host+port → tcp, periodSec → heartbeathttptcpdnsheartbeatmanifestscriptbrowser
urlstring (url)http/manifest: URL to checkmax length 2,000
methodstringGETHEADPOSTPUTPATCHDELETEOPTIONS
headersmap<string, string>
bodystring | nullnull clears itmax length 100,000 · nullable
followRedirectsboolean
expectedStatusstringe.g. "200-299" (default), "200,204", "401"max length 100
keywordstringhttp: response body must contain this textmax length 500
keywordAbsentstringhttp: response body must NOT contain this textmax length 500
degradedAfterMsinteger | nullMark degraded when slower than this (null clears)min 50 · max 120,000 · nullable
sslExpiryDaysinteger | nullMark degraded when the TLS cert expires within N days (null clears)min 1 · max 365 · nullable
hoststringtcp/dns hostmax length 255
portintegermin 1 · max 65,535
recordTypestringAAAAACNAMEMXTXTNS
expectedstring[]dns: values that must be presentmax 20 items
periodSecintegerheartbeat: expected ping intervalmin 30 · max 2,678,400
graceSecintegerheartbeat: extra time before alertingmin 0 · max 86,400
codestringscript/browser: test codemax length 50,000
viewportobject
viewport.widthrequiredintegermin 320 · max 3,840
viewport.heightrequiredintegermin 240 · max 2,160
assertionsobject[]max 30 items
assertions[].sourcerequiredstringstatuslatencyheaderbodyjsonssl_days
assertions[].pathstringmax length 300
assertions[].oprequiredstringeqneqltltegtgtecontainsnot_containsmatchesexistsnot_exists
assertions[].valuestring | number | booleanmax length 2,000
assertions[].severitystringdowndegraded
intervalSecintegerSeconds between checks (default 60, limited by plan)min 10 · max 86,400
timeoutMsintegermin 1,000 · max 120,000
failureThresholdintegerConsecutive failures before DOWN (default 2)min 1 · max 10
recoveryThresholdintegermin 1 · max 10
channelIdsstring[]Alert channels. Default: channels marked as defaultmax 50 items
reminderMinutesinteger[]max 10 items
aibooleanAI incident analysis (default true)
tagsstring[]max 20 items
pausedboolean
regionsstring[]Check regions (GET /api/v1/regions). With several, a round only counts as DOWN when a majority of regions agree. Default: main region onlymax 10 items
Example
curl -X POST https://upbutler.com/api/v1/monitors \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Search API",
    "url": "https://api.example.com/health",
    "keyword": "\"ok\"",
    "intervalSec": 60
  }'

Get a monitor with recent checks and stats

GET/api/v1/monitors/:id
API key · readMCP monitors_getReturns 200
FieldTypeDescription
idrequiredpathstringMonitor id (mon_...)
checksqueryintegermin 0 · max 200
Example
curl https://upbutler.com/api/v1/monitors/mon_0n3q8kz1m4hx7c2v9rt \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Update a monitor

PATCH/api/v1/monitors/:id
API key · writeMCP monitors_updateReturns 200

Partial update; any create field may be sent. Set paused=true/false to pause or resume.

FieldTypeDescription
idrequiredpathstringMonitor id (mon_...)
namestringHuman-friendly name, e.g. "Search API"max length 120
descriptionstring | nullnull or "" clears itmax length 1,000 · nullable
kindstringInferred when omitted: url → http, host+port → tcp, periodSec → heartbeathttptcpdnsheartbeatmanifestscriptbrowser
urlstring (url)http/manifest: URL to checkmax length 2,000
methodstringGETHEADPOSTPUTPATCHDELETEOPTIONS
headersmap<string, string>
bodystring | nullnull clears itmax length 100,000 · nullable
followRedirectsboolean
expectedStatusstringe.g. "200-299" (default), "200,204", "401"max length 100
keywordstringhttp: response body must contain this textmax length 500
keywordAbsentstringhttp: response body must NOT contain this textmax length 500
degradedAfterMsinteger | nullMark degraded when slower than this (null clears)min 50 · max 120,000 · nullable
sslExpiryDaysinteger | nullMark degraded when the TLS cert expires within N days (null clears)min 1 · max 365 · nullable
hoststringtcp/dns hostmax length 255
portintegermin 1 · max 65,535
recordTypestringAAAAACNAMEMXTXTNS
expectedstring[]dns: values that must be presentmax 20 items
periodSecintegerheartbeat: expected ping intervalmin 30 · max 2,678,400
graceSecintegerheartbeat: extra time before alertingmin 0 · max 86,400
codestringscript/browser: test codemax length 50,000
viewportobject
viewport.widthrequiredintegermin 320 · max 3,840
viewport.heightrequiredintegermin 240 · max 2,160
assertionsobject[]max 30 items
assertions[].sourcerequiredstringstatuslatencyheaderbodyjsonssl_days
assertions[].pathstringmax length 300
assertions[].oprequiredstringeqneqltltegtgtecontainsnot_containsmatchesexistsnot_exists
assertions[].valuestring | number | booleanmax length 2,000
assertions[].severitystringdowndegraded
intervalSecintegerSeconds between checks (default 60, limited by plan)min 10 · max 86,400
timeoutMsintegermin 1,000 · max 120,000
failureThresholdintegerConsecutive failures before DOWN (default 2)min 1 · max 10
recoveryThresholdintegermin 1 · max 10
channelIdsstring[]Alert channels. Default: channels marked as defaultmax 50 items
reminderMinutesinteger[]max 10 items
aibooleanAI incident analysis (default true)
tagsstring[]max 20 items
pausedboolean
regionsstring[]Check regions (GET /api/v1/regions). With several, a round only counts as DOWN when a majority of regions agree. Default: main region onlymax 10 items
Example
curl -X PATCH https://upbutler.com/api/v1/monitors/mon_0n3q8kz1m4hx7c2v9rt \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Delete a monitor and its history

DELETE/api/v1/monitors/:id
API key · writeMCP monitors_deleteReturns 200
FieldTypeDescription
idrequiredpathstringMonitor id (mon_...)
Example
curl -X DELETE https://upbutler.com/api/v1/monitors/mon_0n3q8kz1m4hx7c2v9rt \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Run a check right now

POST/api/v1/monitors/:id/check
API key · writeMCP monitors_checkReturns 200

Runs the monitor immediately and returns the full result with evidence. Does not change monitor state unless apply=true.

FieldTypeDescription
idrequiredpathstringMonitor id (mon_...)
applybooleanFeed the result into the state machine (may open/resolve incidents)
Example
curl -X POST https://upbutler.com/api/v1/monitors/mon_0n3q8kz1m4hx7c2v9rt/check \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

List checks (raw results, 30 days)

GET/api/v1/monitors/:id/checks
API key · readMCP monitors_checksReturns 200
FieldTypeDescription
idrequiredpathstringMonitor id (mon_...)
outcomequerystringupdegradeddown
beforequerystring (date-time)pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
limitqueryintegermin 1 · max 500
evidencequeryboolean | string
Example
curl https://upbutler.com/api/v1/monitors/mon_0n3q8kz1m4hx7c2v9rt/checks \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Get one check with full evidence

GET/api/v1/checks/:id
API key · readMCP checks_getReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl https://upbutler.com/api/v1/checks/chk_0n3q9a10e9n3p5s7hz2 \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

List check regions and probe health

GET/api/v1/regions
API key · readMCP regions_listReturns 200

Regions monitors can be checked from (use the ids in a monitor's "regions"). With several regions a round only counts as DOWN when a majority of the reporting regions agree; regions whose probe is unhealthy are skipped, never counted as failures.

No parameters.

Example
curl https://upbutler.com/api/v1/regions \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Per-region latency and failures for a monitor

GET/api/v1/monitors/:id/regions
API key · readMCP monitors_regionsReturns 200
FieldTypeDescription
idrequiredpathstringMonitor id (mon_...)
hoursqueryintegermin 1 · max 168
Example
curl https://upbutler.com/api/v1/monitors/mon_0n3q8kz1m4hx7c2v9rt/regions \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Status pages

List status pages

GET/api/v1/pages
API key · readMCP pages_listReturns 200

No parameters.

Example
curl https://upbutler.com/api/v1/pages \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Create a status page

POST/api/v1/pages
API key · writeMCP pages_createReturns 201

Theme presets: midnight, grid, daylight, paper. Add components afterwards with POST /pages/{pageId}/components.

FieldTypeDescription
namerequiredstringmax length 100
slugstringpattern ^[a-z0-9](?:[a-z0-9-]{1,46}[a-z0-9])?$
descriptionstringmax length 500
customDomainstring | nullpattern ^(?=.{4,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$ · nullable
visibilitystringpublicprivate
themeobject
theme.presetstringmax length 30
theme.modestringdarklight
theme.accentstringpattern ^#[0-9a-fA-F]{6}$
theme.tokensmap<string, string>
theme.fontSansstringmax length 40
theme.fontMonostringmax length 40
theme.radiusintegermin 0 · max 24
theme.customCssstringmax length 50,000
brandingobject
branding.logoUrlstring | nullmax length 1,000 · nullable
branding.logoDarkUrlstring | nullmax length 1,000 · nullable
branding.logoTextstring | nullmax length 60 · nullable
branding.faviconUrlstring | nullmax length 1,000 · nullable
branding.websiteUrlstring (url) | nullmax length 500 · nullable
branding.supportUrlstring (url) | nullmax length 500 · nullable
branding.headerLinksobject[]max 8 items
branding.headerLinks[].labelrequiredstringmax length 60
branding.headerLinks[].urlrequiredstring (url)max length 500
branding.footerLinksobject[]max 20 items
branding.footerLinks[].labelrequiredstringmax length 60
branding.footerLinks[].urlrequiredstring (url)max length 500
branding.footerTextstring | nullmax length 300 · nullable
branding.hidePoweredByboolean
settingsobject
settings.uptimeDaysintegermin 7 · max 90
settings.showUptimePercentboolean
settings.showResponseTimesbooleanAllow public response-time charts (components opt in with showResponseTimes)
settings.languagestringPublic page + subscriber email language; auto = visitor Accept-Languageautoendefresitptnlelpltrja
settings.autoIncidentsboolean
settings.incidentMinStatusstringLowest component status that opens an automatic incidentdegradedpartial_outagemajor_outage
settings.aiPublicUpdatesboolean
settings.aiGuidelinesstringRules for AI-written public text, e.g. "Never mention internal infrastructure"max length 2,000
settings.aiAvoidTermsstring[]AI public text containing any of these is replaced by a neutral templatemax 50 items
settings.subscriptionsobject
settings.subscriptions.emailboolean
settings.subscriptions.webhookboolean
settings.subscriptions.slackboolean
settings.subscriptions.rssboolean
settings.timezonestringmax length 60
seoobject
seo.titlestringmax length 120
seo.descriptionstringmax length 300
seo.noindexboolean
Example
curl -X POST https://upbutler.com/api/v1/pages \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Acme Status",
    "slug": "acme",
    "theme": {
      "preset": "midnight",
      "accent": "#22c55e"
    }
  }'

Get a status page with components

GET/api/v1/pages/:pageId
API key · readMCP pages_getReturns 200
FieldTypeDescription
pageIdrequiredpathstringStatus page id (pg_...) or slug
Example
curl https://upbutler.com/api/v1/pages/pg_0n3q8kz0b2fd81mka5e \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Update page settings, theme, branding or domain

PATCH/api/v1/pages/:pageId
API key · writeMCP pages_updateReturns 200
FieldTypeDescription
namestringmax length 100
slugstringpattern ^[a-z0-9](?:[a-z0-9-]{1,46}[a-z0-9])?$
descriptionstringmax length 500
customDomainstring | nullpattern ^(?=.{4,253}$)([a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$ · nullable
visibilitystringpublicprivate
themeobject
theme.presetstringmax length 30
theme.modestringdarklight
theme.accentstringpattern ^#[0-9a-fA-F]{6}$
theme.tokensmap<string, string>
theme.fontSansstringmax length 40
theme.fontMonostringmax length 40
theme.radiusintegermin 0 · max 24
theme.customCssstringmax length 50,000
brandingobject
branding.logoUrlstring | nullmax length 1,000 · nullable
branding.logoDarkUrlstring | nullmax length 1,000 · nullable
branding.logoTextstring | nullmax length 60 · nullable
branding.faviconUrlstring | nullmax length 1,000 · nullable
branding.websiteUrlstring (url) | nullmax length 500 · nullable
branding.supportUrlstring (url) | nullmax length 500 · nullable
branding.headerLinksobject[]max 8 items
branding.headerLinks[].labelrequiredstringmax length 60
branding.headerLinks[].urlrequiredstring (url)max length 500
branding.footerLinksobject[]max 20 items
branding.footerLinks[].labelrequiredstringmax length 60
branding.footerLinks[].urlrequiredstring (url)max length 500
branding.footerTextstring | nullmax length 300 · nullable
branding.hidePoweredByboolean
settingsobject
settings.uptimeDaysintegermin 7 · max 90
settings.showUptimePercentboolean
settings.showResponseTimesbooleanAllow public response-time charts (components opt in with showResponseTimes)
settings.languagestringPublic page + subscriber email language; auto = visitor Accept-Languageautoendefresitptnlelpltrja
settings.autoIncidentsboolean
settings.incidentMinStatusstringLowest component status that opens an automatic incidentdegradedpartial_outagemajor_outage
settings.aiPublicUpdatesboolean
settings.aiGuidelinesstringRules for AI-written public text, e.g. "Never mention internal infrastructure"max length 2,000
settings.aiAvoidTermsstring[]AI public text containing any of these is replaced by a neutral templatemax 50 items
settings.subscriptionsobject
settings.subscriptions.emailboolean
settings.subscriptions.webhookboolean
settings.subscriptions.slackboolean
settings.subscriptions.rssboolean
settings.timezonestringmax length 60
seoobject
seo.titlestringmax length 120
seo.descriptionstringmax length 300
seo.noindexboolean
pageIdrequiredpathstringStatus page id (pg_...) or slug
Example
curl -X PATCH https://upbutler.com/api/v1/pages/pg_0n3q8kz0b2fd81mka5e \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Delete a status page, its components and subscribers

DELETE/api/v1/pages/:pageId
API key · writeMCP pages_deleteReturns 200
FieldTypeDescription
pageIdrequiredpathstringStatus page id (pg_...) or slug
Example
curl -X DELETE https://upbutler.com/api/v1/pages/pg_0n3q8kz0b2fd81mka5e \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Check the custom domain DNS now

POST/api/v1/pages/:pageId/domain/verify
API key · writeMCP pages_verifyDomainReturns 200

Verified when the domain CNAMEs to the target shown in pages.get dns.value (or resolves to the same IPs).

FieldTypeDescription
pageIdrequiredpathstringStatus page id (pg_...) or slug
Example
curl -X POST https://upbutler.com/api/v1/pages/pg_0n3q8kz0b2fd81mka5e/domain/verify \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Get the rendered public status data (as visitors see it)

GET/api/v1/pages/:pageId/preview
API key · readMCP pages_previewReturns 200
FieldTypeDescription
pageIdrequiredpathstringStatus page id (pg_...) or slug
Example
curl https://upbutler.com/api/v1/pages/pg_0n3q8kz0b2fd81mka5e/preview \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Replace the ordered list of component groups

PUT/api/v1/pages/:pageId/groups
API key · writeMCP pages_groupsReturns 200
FieldTypeDescription
pageIdrequiredpathstringStatus page id (pg_...) or slug
groupsrequiredobject[]
groups[].idstring
groups[].namerequiredstringmax length 80
groups[].descriptionstringmax length 300
groups[].collapsedboolean
Example
curl -X PUT https://upbutler.com/api/v1/pages/pg_0n3q8kz0b2fd81mka5e/groups \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "groups": []
  }'

List subscribers of a status page

GET/api/v1/pages/:pageId/subscribers
API key · readMCP pages_subscribersReturns 200
FieldTypeDescription
pageIdrequiredpathstringStatus page id (pg_...) or slug
statusquerystringpendingactiveunsubscribeddisabled
limitqueryintegermin 1 · max 1,000
Example
curl https://upbutler.com/api/v1/pages/pg_0n3q8kz0b2fd81mka5e/subscribers \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Remove a subscriber

DELETE/api/v1/subscribers/:id
API key · writeMCP subscribers_deleteReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl -X DELETE https://upbutler.com/api/v1/subscribers/sub_0n3q9b40t2m8w6k1c5v \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Components

Add a component to a status page

POST/api/v1/pages/:pageId/components
API key · writeMCP components_createReturns 201

A component is a row on the status page. Its status comes from one of: monitorIds (follows monitors), push=true (you POST statuses to its push URL), manifest {monitorId,key} (read from a manifest monitor), or manual (default).

FieldTypeDescription
pageIdrequiredpathstringStatus page id (pg_...) or slug
namerequiredstringmax length 100
keystringStable machine key used by pushes and manifests (default: slug of name)pattern ^[a-z0-9][a-z0-9_.-]{0,62}$
descriptionstringmax length 500
groupstringGroup name or id; created if it does not existmax length 80
monitorIdsstring[]Status follows these monitorsmax 20 items
aggregatestringworstmajority
pushbooleanStatus is pushed via the component push URL
pushTtlSecinteger | nullBecome "unknown" when no push arrives for this long (null clears it)min 60 · max 604,800 · nullable
manualbooleanSwitch the component to manual status (set via overrides/incidents)
manifestobjectStatus read from a manifest monitor key
manifest.monitorIdrequiredstring
manifest.keyrequiredstringmax length 120
showUptimeboolean
showResponseTimesbooleanPublic response-time chart (monitor-backed components only; page setting showResponseTimes must be on)
hiddenboolean
orderintegermin 0 · max 10,000
confirmationsintegerPush/manifest: consecutive fresh bad reports before a worse status shows (default 2; 1 = immediate)min 1 · max 10
Example
curl -X POST https://upbutler.com/api/v1/pages/acme/components \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Search API",
    "group": "APIs",
    "monitorIds": [
      "mon_..."
    ]
  }'

Update a component (name, group, source, visibility)

PATCH/api/v1/components/:id
API key · writeMCP components_updateReturns 200
FieldTypeDescription
idrequiredpathstring
namestringmax length 100
keystringStable machine key used by pushes and manifests (default: slug of name)pattern ^[a-z0-9][a-z0-9_.-]{0,62}$
descriptionstringmax length 500
groupstringGroup name or id; created if it does not existmax length 80
monitorIdsstring[]Status follows these monitorsmax 20 items
aggregatestringworstmajority
pushbooleanStatus is pushed via the component push URL
pushTtlSecinteger | nullBecome "unknown" when no push arrives for this long (null clears it)min 60 · max 604,800 · nullable
manualbooleanSwitch the component to manual status (set via overrides/incidents)
manifestobjectStatus read from a manifest monitor key
manifest.monitorIdrequiredstring
manifest.keyrequiredstringmax length 120
showUptimeboolean
showResponseTimesbooleanPublic response-time chart (monitor-backed components only; page setting showResponseTimes must be on)
hiddenboolean
orderintegermin 0 · max 10,000
confirmationsintegerPush/manifest: consecutive fresh bad reports before a worse status shows (default 2; 1 = immediate)min 1 · max 10
Example
curl -X PATCH https://upbutler.com/api/v1/components/cmp_0n3q8kz2p7wd4yx0s3a \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Delete a component

DELETE/api/v1/components/:id
API key · writeMCP components_deleteReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl -X DELETE https://upbutler.com/api/v1/components/cmp_0n3q8kz2p7wd4yx0s3a \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Manually set (or clear) a component status

POST/api/v1/components/:id/override
API key · writeMCP components_overrideReturns 200

Overrides win over automatic status until cleared with status=null. For outages prefer creating an incident, which also notifies subscribers.

FieldTypeDescription
idrequiredpathstring
statusrequiredstring | nulloperationaldegradedpartial_outagemajor_outagemaintenancenullable
reasonstringmax length 300
Example
curl -X POST https://upbutler.com/api/v1/components/cmp_0n3q8kz2p7wd4yx0s3a/override \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "status": "operational"
  }'

Push statuses for many components at once

POST/api/v1/pages/:pageId/status
API key · writeMCP pages_pushReturns 200

Body: {"statuses": {"<component key>": "operational" | {"status": "major_outage", "message": "..."}}}. Accepts ok/up/fail/down/true/false too. Failing components open (or join) an automatic incident when the page has autoIncidents on; recovery resolves it.

FieldTypeDescription
pageIdrequiredpathstringStatus page id (pg_...) or slug
statusesrequiredmap<string, any>
Example
curl -X POST https://upbutler.com/api/v1/pages/acme/status \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "statuses": {
      "search": "operational",
      "billing": {
        "status": "degraded",
        "message": "Stripe latency"
      }
    }
  }'

Incidents

List incidents and maintenance

GET/api/v1/incidents
API key · readMCP incidents_listReturns 200
FieldTypeDescription
openqueryboolean | stringOnly unresolved
kindquerystringincidentmaintenance
pageIdquerystring
monitorIdquerystring
limitqueryintegermin 1 · max 200
Example
curl https://upbutler.com/api/v1/incidents \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Get an incident with its timeline and AI reports

GET/api/v1/incidents/:id
API key · readMCP incidents_getReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl https://upbutler.com/api/v1/incidents/inc_0n3q9a11v8k2h5n0qzc \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Report an incident

POST/api/v1/incidents
API key · writeMCP incidents_createReturns 201

Declare an incident (agents: use this when you detect a problem yourself). Affected components switch to the given status and page subscribers are notified. Set polish=true to have AI rewrite rough notes into a clear public update.

FieldTypeDescription
titlerequiredstringmax length 200
messagerequiredstringFirst public updatemax length 10,000
statusstringinvestigatingidentifiedmonitoring
impactstringnoneminormajorcritical
pageIdsstring[]max 20 items
componentsobject[]Affected components and their status during the incidentmax 200 items
components[].componentIdrequiredstring
components[].statusrequiredstringoperationaldegradedpartial_outagemajor_outagemaintenance
publicbooleanShow on status pages (default: true when pages/components are given)
polishboolean
notifybooleanNotify subscribers (default true)
Example
curl -X POST https://upbutler.com/api/v1/incidents \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Elevated API errors",
    "message": "We are seeing 5xx errors on search and are investigating.",
    "components": [
      {
        "componentId": "cmp_...",
        "status": "partial_outage"
      }
    ]
  }'

Post an incident update

POST/api/v1/incidents/:id/updates
API key · writeMCP incidents_updateReturns 200

Adds a timeline update, optionally changing status and component impact. status=resolved resolves the incident.

FieldTypeDescription
idrequiredpathstring
messagerequiredstringmax length 10,000
statusstringinvestigatingidentifiedmonitoringresolvedscheduledin_progresscompleted
componentsobject[]Affected components and their status during the incidentmax 200 items
components[].componentIdrequiredstring
components[].statusrequiredstringoperationaldegradedpartial_outagemajor_outagemaintenance
publicbooleanfalse = internal note (not shown or sent to subscribers)
polishboolean
notifyboolean
Example
curl -X POST https://upbutler.com/api/v1/incidents/inc_0n3q9a11v8k2h5n0qzc/updates \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": "We are looking into it."
  }'

Resolve an incident

POST/api/v1/incidents/:id/resolve
API key · writeMCP incidents_resolveReturns 200

Without a message, UpButler writes the resolution note (AI recovery summary when available).

FieldTypeDescription
idrequiredpathstring
messagestringmax length 10,000
polishboolean
Example
curl -X POST https://upbutler.com/api/v1/incidents/inc_0n3q9a11v8k2h5n0qzc/resolve \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Generate (or regenerate) the AI report for an incident

POST/api/v1/incidents/:id/analyze
API key · writeMCP incidents_analyzeReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl -X POST https://upbutler.com/api/v1/incidents/inc_0n3q9a11v8k2h5n0qzc/analyze \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Schedule maintenance

POST/api/v1/maintenance
API key · writeMCP maintenance_createReturns 201

Components show "Under maintenance" during the window; it starts and completes automatically. Subscribers are notified.

FieldTypeDescription
titlerequiredstringmax length 200
messagerequiredstringmax length 10,000
scheduledStartrequiredany
scheduledEndrequiredany
pageIdsstring[]max 20 items
componentIdsstring[]max 200 items
notifyboolean
Example
curl -X POST https://upbutler.com/api/v1/maintenance \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "title": "Elevated API errors",
    "message": "We are looking into it.",
    "scheduledStart": "2026-11-02T22:00:00Z",
    "scheduledEnd": "2026-11-02T23:00:00Z"
  }'

Acknowledge an incident or a down monitor

POST/api/v1/incidents/:id/ack
API key · writeMCP incidents_ackReturns 200

Take ownership: stops "still down" reminders and escalation, records an internal timeline entry and emits incident.acknowledged to the channels that were alerted. `id` may be an incident id or a monitor id (acknowledges its open incident). Idempotent.

FieldTypeDescription
idrequiredpathstringIncident id (inc_…) or monitor id (mon_…)
notestringe.g. "Looking into it, rolling back deploy"max length 1,000
Example
curl -X POST https://upbutler.com/api/v1/incidents/inc_0n3q9a11v8k2h5n0qzc/ack \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "note": "On it, rolling back the last deploy"
  }'

Remove an acknowledgement

POST/api/v1/incidents/:id/unack
API key · writeMCP incidents_unackReturns 200

Reminders and escalation resume where they stopped.

FieldTypeDescription
idrequiredpathstring
Example
curl -X POST https://upbutler.com/api/v1/incidents/inc_0n3q9a11v8k2h5n0qzc/unack \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Draft a postmortem with AI

POST/api/v1/incidents/:id/postmortem
API key · writeMCP incidents_postmortemReturns 200

Writes a blameless markdown postmortem (summary, impact, timeline from updates, checks and deploy markers, root-cause hypotheses, contributing factors, what went well/poorly, action items) plus a customer-safe summary, and stores it as a new version. Uses one AI report. When AI is unavailable the 503 response carries a template draft in error.details.template.

FieldTypeDescription
idrequiredpathstring
modestringtemplate = return an unsaved fill-in-the-blanks draft without using AIaitemplate
Example
curl -X POST https://upbutler.com/api/v1/incidents/inc_0n3q9a11v8k2h5n0qzc/postmortem \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Get an incident's postmortem

GET/api/v1/incidents/:id/postmortem
API key · readMCP incidents_postmortem_getReturns 200

Current markdown, the public summary, publish state and the version list (history=true includes every version's markdown). 404 when none exists yet.

FieldTypeDescription
idrequiredpathstring
historyqueryboolean | string
Example
curl https://upbutler.com/api/v1/incidents/inc_0n3q9a11v8k2h5n0qzc/postmortem \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Save an edited postmortem (new version)

PUT/api/v1/incidents/:id/postmortem
API key · writeMCP incidents_postmortem_saveReturns 200

Send baseVersion (the version you edited) to get a 409 instead of overwriting someone else's changes.

FieldTypeDescription
idrequiredpathstring
markdownrequiredstringmax length 60,000
publicSummarystringCustomer-safe text used by publishmax length 5,000
baseVersionintegermin 1
Example
curl -X PUT https://upbutler.com/api/v1/incidents/inc_0n3q9a11v8k2h5n0qzc/postmortem \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "markdown": "..."
  }'

Publish a post-incident report to status pages

POST/api/v1/incidents/:id/postmortem/publish
API key · writeMCP incidents_postmortem_publishReturns 200

Posts body (default: the postmortem's public summary) as a public update on the resolved incident and notifies subscribers. The text must pass the page's AI policy and may not contain hostnames, IPs or error output.

FieldTypeDescription
idrequiredpathstring
bodystringmax length 10,000
notifyboolean
Example
curl -X POST https://upbutler.com/api/v1/incidents/inc_0n3q9a11v8k2h5n0qzc/postmortem/publish \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

List incident templates

GET/api/v1/incident-templates
API key · readMCP templates_listReturns 200

Reusable title/status/impact/message presets. Bodies support {{component}}, {{duration}}, {{status_page}} and {{title}}. New workspaces start with sensible defaults.

No parameters.

Example
curl https://upbutler.com/api/v1/incident-templates \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Create an incident template

POST/api/v1/incident-templates
API key · writeMCP templates_createReturns 201
FieldTypeDescription
namerequiredstringShown in the "Use template" pickermax length 80
kindstringDefault incidentincidentmaintenance
titlerequiredstringIncident title; placeholders allowedmax length 200
statusstringinvestigatingidentifiedmonitoringresolvedscheduledin_progresscompleted
impactstringnoneminormajorcriticalmaintenance
bodyrequiredstringUpdate text. Placeholders: {{component}}, {{duration}}, {{status_page}}, {{title}}max length 10,000
componentIdsstring[]Components affected by defaultmax 200 items
componentStatusstringStatus the default components get (default partial_outage)operationaldegradedpartial_outagemajor_outagemaintenance
orderintegermin 0 · max 10,000
Example
curl -X POST https://upbutler.com/api/v1/incident-templates \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Payment provider outage",
    "title": "Payments delayed on {{component}}",
    "status": "identified",
    "impact": "major",
    "body": "Our payment provider is having issues. {{component}} payments may be delayed; no charges are lost."
  }'

Update an incident template

PATCH/api/v1/incident-templates/:id
API key · writeMCP templates_updateReturns 200
FieldTypeDescription
idrequiredpathstring
namestringShown in the "Use template" pickermax length 80
kindstringDefault incidentincidentmaintenance
titlestringIncident title; placeholders allowedmax length 200
statusstringinvestigatingidentifiedmonitoringresolvedscheduledin_progresscompleted
impactstringnoneminormajorcriticalmaintenance
bodystringUpdate text. Placeholders: {{component}}, {{duration}}, {{status_page}}, {{title}}max length 10,000
componentIdsstring[]Components affected by defaultmax 200 items
componentStatusstringStatus the default components get (default partial_outage)operationaldegradedpartial_outagemajor_outagemaintenance
orderintegermin 0 · max 10,000
Example
curl -X PATCH https://upbutler.com/api/v1/incident-templates/id_... \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Delete an incident template

DELETE/api/v1/incident-templates/:id
API key · writeMCP templates_deleteReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl -X DELETE https://upbutler.com/api/v1/incident-templates/id_... \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Fill in a template

POST/api/v1/incident-templates/:id/render
API key · readMCP templates_renderReturns 200

Returns title, message, status, impact and components ready for POST /incidents or POST /incidents/{id}/updates. With incidentId, the incident's components and duration fill the placeholders; otherwise componentIds (or the template defaults) do.

FieldTypeDescription
idrequiredpathstring
incidentIdstring
componentIdsstring[]max 200 items
Example
curl -X POST https://upbutler.com/api/v1/incident-templates/id_.../render \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Alerts

List alert channels

GET/api/v1/channels
API key · readMCP channels_listReturns 200

No parameters.

Example
curl https://upbutler.com/api/v1/channels \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Create an alert channel

POST/api/v1/channels
API key · writeMCP channels_createReturns 201

Where your team (or your agent) gets alerted. Webhook channels receive Standard Webhooks-signed JSON (headers webhook-id, webhook-timestamp, webhook-signature); the signing secret is returned once in the response.

FieldTypeDescription
namerequiredstringmax length 80
typerequiredstringemailwebhookslackdiscordtelegram
emailsstring (email)[]email: recipientsmax 20 items
urlstring (url)webhook/slack/discord: URLmax length 1,000
headersmap<string, string>webhook: extra headers
botTokenstringtelegram: bot tokenmax length 200
chatIdstringtelegram: chat idmax length 100
eventsstring[]Event types to receive (default: alerts). One of: monitor.down, monitor.up, monitor.degraded, monitor.reminder, incident.created, incident.updated, incident.resolved, maintenance.scheduled, maintenance.started, maintenance.updated, maintenance.completed, incident.acknowledged, incident.escalated, incident.unacknowledged, component.status_changed, monitor.created, monitor.deleted, deploy.created, digest.weekly, test.ping, or "*"max 30 items
isDefaultbooleanAttach to new monitors automatically (default true)
enabledboolean
Example
curl -X POST https://upbutler.com/api/v1/channels \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ops agent",
    "type": "webhook",
    "url": "https://agent.example.com/hooks/upbutler"
  }'

Update an alert channel

PATCH/api/v1/channels/:id
API key · writeMCP channels_updateReturns 200
FieldTypeDescription
idrequiredpathstring
namestringmax length 80
typestringemailwebhookslackdiscordtelegram
emailsstring (email)[]email: recipientsmax 20 items
urlstring (url)webhook/slack/discord: URLmax length 1,000
headersmap<string, string>webhook: extra headers
botTokenstringtelegram: bot tokenmax length 200
chatIdstringtelegram: chat idmax length 100
eventsstring[]Event types to receive (default: alerts). One of: monitor.down, monitor.up, monitor.degraded, monitor.reminder, incident.created, incident.updated, incident.resolved, maintenance.scheduled, maintenance.started, maintenance.updated, maintenance.completed, incident.acknowledged, incident.escalated, incident.unacknowledged, component.status_changed, monitor.created, monitor.deleted, deploy.created, digest.weekly, test.ping, or "*"max 30 items
isDefaultbooleanAttach to new monitors automatically (default true)
enabledboolean
rotateSecretboolean
Example
curl -X PATCH https://upbutler.com/api/v1/channels/ch_0n3q8kz3j6d0q2b5ny8 \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Delete an alert channel

DELETE/api/v1/channels/:id
API key · writeMCP channels_deleteReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl -X DELETE https://upbutler.com/api/v1/channels/ch_0n3q8kz3j6d0q2b5ny8 \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Send a test notification

POST/api/v1/channels/:id/test
API key · writeMCP channels_testReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl -X POST https://upbutler.com/api/v1/channels/ch_0n3q8kz3j6d0q2b5ny8/test \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Public status

Public status of a page (no auth)

GET/api/v1/public/pages/:slug
Public — no keyMCP public_statusReturns 200

Overall status, components with 90-day uptime, active incidents and maintenance. Safe to poll every 30s.

FieldTypeDescription
slugrequiredpathstring
historyqueryboolean | stringInclude per-day uptime bars (default true)
Example
curl https://upbutler.com/api/v1/public/pages/acme

Public incident history of a page

GET/api/v1/public/pages/:slug/incidents
Public — no keyMCP public_incidentsReturns 200
FieldTypeDescription
slugrequiredpathstring
limitqueryintegermin 1 · max 100
beforequerystring (date-time)pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z))$
Example
curl https://upbutler.com/api/v1/public/pages/acme/incidents

One public incident with its updates

GET/api/v1/public/pages/:slug/incidents/:id
Public — no keyMCP public_incidentReturns 200
FieldTypeDescription
slugrequiredpathstring
idrequiredpathstring
Example
curl https://upbutler.com/api/v1/public/pages/acme/incidents/inc_0n3q9a11v8k2h5n0qzc

Subscribe to a status page (email, webhook, Slack or Discord)

POST/api/v1/public/pages/:slug/subscribers
Public — no keyMCP public_subscribeReturns 201

Agents: subscribe with {"type":"webhook","url":"https://your-agent/hook"} to receive signed incident.*, maintenance.* and component.status_changed events and automate downtime handling. We first POST {"type":"subscription.verify","challenge":"..."} and your endpoint must echo the challenge. The response contains the signing secret (Standard Webhooks) and a manage token for unsubscribing. Optionally limit to components (ids or keys).

FieldTypeDescription
slugrequiredpathstring
typerequiredstringemailwebhookslackdiscord
emailstring (email)pattern ^(?:[A-Za-z0-9_'+\-]+\.)*[A-Za-z0-9_'+\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$
urlstring (url)max length 1,000
componentsstring[]Component ids or keys; omit for everythingmax 200 items
agentstringName of the subscribing agent (shown to the page owner)max length 80
incidentstringIncident id: only that incident's updates, until it is resolved ("subscribe to this incident")max length 60
languagestringEmail language (en, de, fr, es, it, pt, nl, el, pl, tr, ja); default = page language or Accept-Languagemax length 10
Example
curl -X POST https://upbutler.com/api/v1/public/pages/fetchlayer/subscribers \
  -H "Content-Type: application/json" \
  -d '{
    "type": "webhook",
    "url": "https://my-agent.example.com/upbutler",
    "components": [
      "reddit"
    ],
    "agent": "scraper-orchestrator"
  }'

View a subscription (requires its manage token)

GET/api/v1/public/subscribers/:id
Public — no keyMCP public_subscriber_getReturns 200
FieldTypeDescription
idrequiredpathstring
tokenrequiredquerystring
Example
curl "https://upbutler.com/api/v1/public/subscribers/sub_0n3q9b40t2m8w6k1c5v?token=..."

Change which components a subscription follows (requires the manage token)

PATCH/api/v1/public/subscribers/:id
Public — no keyMCP public_subscriber_updateReturns 200
FieldTypeDescription
idrequiredpathstring
tokenrequiredstring
componentsrequiredstring[]Component ids or keys; [] = everythingmax 200 items
Example
curl -X PATCH https://upbutler.com/api/v1/public/subscribers/sub_0n3q9b40t2m8w6k1c5v \
  -H "Content-Type: application/json" \
  -d '{
    "token": "...",
    "components": "..."
  }'

Unsubscribe (requires the manage token)

DELETE/api/v1/public/subscribers/:id
Public — no keyMCP public_unsubscribeReturns 200
FieldTypeDescription
idrequiredpathstring
tokenrequiredquerystring
Example
curl -X DELETE "https://upbutler.com/api/v1/public/subscribers/sub_0n3q9b40t2m8w6k1c5v?token=..."

Public response-time series of a component (p50/p95)

GET/api/v1/public/pages/:slug/components/:component/response-times
Public — no keyMCP public_responseTimesReturns 200

Only for components the page owner published (page settings.showResponseTimes + component showResponseTimes, monitor-backed). 24h = 30-min buckets and 7d = 3-hour buckets with p50/p95 in ms from raw checks; 30d = daily averages (p95 null). Values are averaged across the component's monitors.

FieldTypeDescription
slugrequiredpathstring
componentrequiredpathstringComponent key or id
rangequerystring24h (default), 7d or 30d24h7d30d
Example
curl "https://upbutler.com/api/v1/public/pages/fetchlayer/components/api/response-times?range=7d"

Workspace

Current workspace, plan, limits and usage

GET/api/v1/workspace
API key · readMCP workspace_getReturns 200

Useful first call for agents: shows what the key can do and how much quota is left.

No parameters.

Example
curl https://upbutler.com/api/v1/workspace \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Rename the workspace

PATCH/api/v1/workspace
API key · writeMCP workspace_updateReturns 200
FieldTypeDescription
namerequiredstringmax length 80
Example
curl -X PATCH https://upbutler.com/api/v1/workspace \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Search API"
  }'

List workspace members and pending invites

GET/api/v1/members
API key · readMCP members_listReturns 200

No parameters.

Example
curl https://upbutler.com/api/v1/members \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Invite a teammate by email

POST/api/v1/members/invites
API key · writeREST onlyReturns 200
FieldTypeDescription
emailrequiredstring (email)pattern ^(?:[A-Za-z0-9_'+\-]+\.)*[A-Za-z0-9_'+\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$
rolestringadminmember
Example
curl -X POST https://upbutler.com/api/v1/members/invites \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "[email protected]"
  }'

Revoke a pending invite

DELETE/api/v1/members/invites/:id
API key · writeREST onlyReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl -X DELETE https://upbutler.com/api/v1/members/invites/id_... \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Remove a member

DELETE/api/v1/members/:userId
API key · writeREST onlyReturns 200
FieldTypeDescription
userIdrequiredpathstring
Example
curl -X DELETE https://upbutler.com/api/v1/members/usr_0n3q8jy7w2e4r6t8y0u \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

List API keys

GET/api/v1/keys
API key · readMCP keys_listReturns 200

No parameters.

Example
curl https://upbutler.com/api/v1/keys \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Create an API key

POST/api/v1/keys
API key · writeMCP keys_createReturns 201

The secret is returned once. Give agents their own key (with agent set) so their actions are attributed in incident timelines.

FieldTypeDescription
namerequiredstringmax length 80
scopesstring[]readwrite
agentstringName of the agent using this key, e.g. "deploy-bot"max length 80
expiresInDaysintegermin 1 · max 3,650
Example
curl -X POST https://upbutler.com/api/v1/keys \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Search API"
  }'

Revoke an API key

DELETE/api/v1/keys/:id
API key · writeMCP keys_revokeReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl -X DELETE https://upbutler.com/api/v1/keys/key_0n3q8jy9x1c4v7b2n6m \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Require two-factor authentication for every member (owners only)

PATCH/api/v1/workspace/security
API key · writeREST onlyReturns 200
FieldTypeDescription
require2farequiredboolean
Example
curl -X PATCH https://upbutler.com/api/v1/workspace/security \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "require2fa": true
  }'

Audit log: sign-ins, 2FA changes, keys, members, billing, deletions, domains

GET/api/v1/audit
API key · readMCP audit_listReturns 200

Newest first, kept 400 days. Filter by action (exact like "api_key.created" or a prefix like "auth" / "member."), actor id or time range; page with ?before=<next>. Owners and admins (or keys with the write scope).

FieldTypeDescription
actionquerystringmax length 60
actorIdquerystringmax length 60
fromqueryany
toqueryany
beforequerystringmax length 60
limitqueryintegermin 1 · max 200
Example
curl https://upbutler.com/api/v1/audit \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Events

Poll the event stream

GET/api/v1/events
API key · readMCP events_listReturns 200

Every state change in the workspace (monitor.down/up/degraded, incident.*, maintenance.*, component.status_changed …), newest first. Agents without a public webhook endpoint can poll with ?after=<last event id> to get only new events (oldest first). For push instead of polling, open GET /api/v1/stream (Server-Sent Events, same auth; resume with Last-Event-ID; ?types= filter; ?checks=1 for live check results).

FieldTypeDescription
afterquerystringReturn events after this id, oldest first
typesquerystringComma-separated event types, e.g. "monitor.down,monitor.up"
limitqueryintegermin 1 · max 500
Example
curl https://upbutler.com/api/v1/events \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Billing

Available plans and limits

GET/api/v1/plans
Public — no keyMCP plans_listReturns 200

No parameters.

Example
curl https://upbutler.com/api/v1/plans

Start a checkout to upgrade the workspace

POST/api/v1/billing/checkout
API key · writeMCP billing_checkoutReturns 200

Returns a Polar checkout URL. Agents: hand this URL to your human — payment needs a person.

FieldTypeDescription
planrequiredstringstarterprobusiness
intervalstringmonthyear
Example
curl -X POST https://upbutler.com/api/v1/billing/checkout \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "plan": "pro",
    "interval": "month"
  }'

Open the billing portal (invoices, payment method, cancel)

POST/api/v1/billing/portal
API key · writeREST onlyReturns 200

No parameters.

Example
curl -X POST https://upbutler.com/api/v1/billing/portal \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Import

Dry run: what an import would create

POST/api/v1/import/preview
API key · writeMCP import_previewReturns 200

Reads your UptimeRobot, Better Stack or Statuspage.io account and returns every item with action create | exists (already imported) | skip (with reason), plus plan-limit warnings. Nothing is written. Statuspage.io works with just a public URL.

FieldTypeDescription
sourcerequiredstringWhere to import fromuptimerobotbetterstackstatuspage
apiKeystringUptimeRobot read-only API key, Better Stack Uptime API token, or Statuspage.io API key. Used for this request only and never stored.min length 4 · max length 500
pageIdstringStatuspage.io page id (with apiKey)max length 100
urlstringStatuspage.io: any public status page URL (no key needed), e.g. https://www.githubstatus.commax length 500
monitorsbooleanImport monitors and heartbeats (default true)
channelsbooleanImport alert contacts as alert channels (default true)
pagesbooleanImport status pages, groups and components (default true)
incidentsbooleanStatuspage.io: import past incidents and maintenance (default true)
mirrorbooleanStatuspage.io: add a manifest monitor that keeps mirroring their components.json (default false)
targetPageIdstringImport components into this existing status page instead of creating one
excludestring[]Refs from the preview ("monitor:123") to leave outmax 2000 items
Example
curl -X POST https://upbutler.com/api/v1/import/preview \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "statuspage",
    "url": "https://www.githubstatus.com",
    "mirror": true
  }'

Run an import (background job)

POST/api/v1/import
API key · writeMCP import_applyReturns 202

Starts the import and returns the job right away; poll import.status. Idempotent: re-running creates only what is new. Credentials are kept in memory for the job and never stored.

FieldTypeDescription
sourcerequiredstringWhere to import fromuptimerobotbetterstackstatuspage
apiKeystringUptimeRobot read-only API key, Better Stack Uptime API token, or Statuspage.io API key. Used for this request only and never stored.min length 4 · max length 500
pageIdstringStatuspage.io page id (with apiKey)max length 100
urlstringStatuspage.io: any public status page URL (no key needed), e.g. https://www.githubstatus.commax length 500
monitorsbooleanImport monitors and heartbeats (default true)
channelsbooleanImport alert contacts as alert channels (default true)
pagesbooleanImport status pages, groups and components (default true)
incidentsbooleanStatuspage.io: import past incidents and maintenance (default true)
mirrorbooleanStatuspage.io: add a manifest monitor that keeps mirroring their components.json (default false)
targetPageIdstringImport components into this existing status page instead of creating one
excludestring[]Refs from the preview ("monitor:123") to leave outmax 2000 items
Example
curl -X POST https://upbutler.com/api/v1/import \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source": "uptimerobot",
    "apiKey": "ur123456-..."
  }'

Progress and result of an import job

GET/api/v1/import/jobs/:id
API key · readMCP import_statusReturns 200
FieldTypeDescription
idrequiredpathstringImport job id (imp_...)
Example
curl https://upbutler.com/api/v1/import/jobs/id_... \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Recent import jobs

GET/api/v1/import/jobs
API key · readMCP import_jobsReturns 200
FieldTypeDescription
limitqueryintegermin 1 · max 100
Example
curl https://upbutler.com/api/v1/import/jobs \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

On-call

Who is on call right now

GET/api/v1/oncall/current
API key · readMCP oncall_currentReturns 200

For every schedule (or one with scheduleId): the person on call now, until when, and whether it is an override. Agents: use this to decide whom to tell about a problem.

FieldTypeDescription
scheduleIdquerystring
Example
curl https://upbutler.com/api/v1/oncall/current \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

List on-call schedules

GET/api/v1/oncall/schedules
API key · readMCP oncall_schedules_listReturns 200
FieldTypeDescription
daysqueryintegerInclude upcoming shifts for this many daysmin 0 · max 42
Example
curl https://upbutler.com/api/v1/oncall/schedules \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Get a schedule with upcoming shifts

GET/api/v1/oncall/schedules/:id
API key · readMCP oncall_schedules_getReturns 200
FieldTypeDescription
idrequiredpathstring
daysqueryintegerDefault 14min 1 · max 42
Example
curl https://upbutler.com/api/v1/oncall/schedules/id_... \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Create a weekly on-call rotation (Business plan)

POST/api/v1/oncall/schedules
API key · writeMCP oncall_schedules_createReturns 201
FieldTypeDescription
namerequiredstringmax length 80
timezonerequiredstringIANA timezone, e.g. "Europe/Berlin"max length 64
handoffDayrequiredintegerHandoff weekday: 0 = Monday … 6 = Sundaymin 0 · max 6
handoffTimerequiredstringLocal handoff time "HH:MM" (24h)pattern ^\d{1,2}:\d{2}$
participantsrequiredstring[]Ordered member user ids; each is on call for one weekmax 50 items
startDaystringLocal date whose rotation week the first participant takes (default: the current week)pattern ^\d{4}-\d{2}-\d{2}$
Example
curl -X POST https://upbutler.com/api/v1/oncall/schedules \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Primary",
    "timezone": "Europe/Berlin",
    "handoffDay": 0,
    "handoffTime": "09:00",
    "participants": [
      "usr_…",
      "usr_…"
    ]
  }'

Update a schedule

PATCH/api/v1/oncall/schedules/:id
API key · writeMCP oncall_schedules_updateReturns 200
FieldTypeDescription
idrequiredpathstring
namestringmax length 80
timezonestringIANA timezone, e.g. "Europe/Berlin"max length 64
handoffDayintegerHandoff weekday: 0 = Monday … 6 = Sundaymin 0 · max 6
handoffTimestringLocal handoff time "HH:MM" (24h)pattern ^\d{1,2}:\d{2}$
participantsstring[]Ordered member user ids; each is on call for one weekmax 50 items
startDaystringLocal date whose rotation week the first participant takes (default: the current week)pattern ^\d{4}-\d{2}-\d{2}$
Example
curl -X PATCH https://upbutler.com/api/v1/oncall/schedules/id_... \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Delete a schedule

DELETE/api/v1/oncall/schedules/:id
API key · writeMCP oncall_schedules_deleteReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl -X DELETE https://upbutler.com/api/v1/oncall/schedules/id_... \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Put someone on call for a period (override)

POST/api/v1/oncall/schedules/:id/overrides
API key · writeMCP oncall_overrides_createReturns 201

Overrides win over the rotation; the most recently created one wins when they overlap.

FieldTypeDescription
idrequiredpathstring
userIdrequiredstring
startrequiredany
endrequiredany
notestringmax length 200
Example
curl -X POST https://upbutler.com/api/v1/oncall/schedules/id_.../overrides \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "userId": "...",
    "start": {},
    "end": {}
  }'

Remove an override

DELETE/api/v1/oncall/schedules/:id/overrides/:overrideId
API key · writeMCP oncall_overrides_deleteReturns 200
FieldTypeDescription
idrequiredpathstring
overrideIdrequiredpathstring
Example
curl -X DELETE https://upbutler.com/api/v1/oncall/schedules/id_.../overrides/<overrideId> \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Members with their paging contact status

GET/api/v1/oncall/members
API key · readMCP oncall_membersReturns 200

No parameters.

Example
curl https://upbutler.com/api/v1/oncall/members \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

List escalation policies

GET/api/v1/escalation-policies
API key · readMCP escalation_listReturns 200

No parameters.

Example
curl https://upbutler.com/api/v1/escalation-policies \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Create an escalation policy (Business plan)

POST/api/v1/escalation-policies
API key · writeMCP escalation_createReturns 201

Ordered levels: level 1 is paged as soon as an incident opens; each next level after `afterMinutes` if nobody acknowledged. Applies to incidents of `monitorIds`/`pageIds`, or to everything when isDefault. Without any policy, alerts follow each monitor's channels and reminders.

FieldTypeDescription
namerequiredstringmax length 80
isDefaultbooleanUse for incidents no monitor/page-specific policy claims (the first policy becomes default)
monitorIdsstring[]max 250 items
pageIdsstring[]max 20 items
levelsrequiredobject[]max 10 items
levels[].afterMinutesrequiredintegerWait after the previous level (ignored for level 1)min 0 · max 1,440
levels[].targetsrequiredobject[]max 20 items
levels[].targets[].typerequired"channel"
levels[].targets[].idrequiredstringAlert channel id
repeatintegerRepeat the whole chain this many times while unacknowledgedmin 0 · max 5
repeatAfterMinutesintegermin 1 · max 1,440
Example
curl -X POST https://upbutler.com/api/v1/escalation-policies \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Default",
    "levels": [
      {
        "afterMinutes": 0,
        "targets": [
          {
            "type": "schedule",
            "id": "sch_…"
          }
        ]
      },
      {
        "afterMinutes": 15,
        "targets": [
          {
            "type": "channel",
            "id": "ch_…"
          }
        ]
      }
    ],
    "repeat": 1
  }'

Update an escalation policy

PATCH/api/v1/escalation-policies/:id
API key · writeMCP escalation_updateReturns 200
FieldTypeDescription
idrequiredpathstring
namestringmax length 80
isDefaultbooleanUse for incidents no monitor/page-specific policy claims (the first policy becomes default)
monitorIdsstring[]max 250 items
pageIdsstring[]max 20 items
levelsobject[]max 10 items
levels[].afterMinutesrequiredintegerWait after the previous level (ignored for level 1)min 0 · max 1,440
levels[].targetsrequiredobject[]max 20 items
levels[].targets[].typerequired"channel"
levels[].targets[].idrequiredstringAlert channel id
repeatintegerRepeat the whole chain this many times while unacknowledgedmin 0 · max 5
repeatAfterMinutesintegermin 1 · max 1,440
Example
curl -X PATCH https://upbutler.com/api/v1/escalation-policies/id_... \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Delete an escalation policy

DELETE/api/v1/escalation-policies/:id
API key · writeMCP escalation_deleteReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl -X DELETE https://upbutler.com/api/v1/escalation-policies/id_... \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Deploys

Record a deploy

POST/api/v1/deploys
API key · writeMCP deploys_createReturns 201

Mark a release so incidents can be correlated with it (AI reports, charts, incident timelines). Minimal input {"version":"1.4.2"} applies to the whole workspace; narrow it with monitorIds, service (matches monitor tags/names) or pageId. Emits deploy.created.

FieldTypeDescription
versionstringRelease version or tag, e.g. "1.4.2"max length 100
commitstringCommit SHA (shown shortened)max length 80
urlstring (url)Link to the release, CI run or PRmax length 2,000
environmentstringe.g. "production", "staging"max length 40
descriptionstringmax length 2,000
servicestringService name; monitors tagged or named like this are linked automaticallymax length 120
monitorIdsstring[]Limit the deploy to these monitors (default: whole workspace)max 100 items
monitorIdstringmax length 60
pageIdstringLimit the deploy to one status pagemax length 60
pageIdsstring[]max 100 items
atstring (date-time)When it went out (ISO 8601, default now)pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
Example
curl -X POST https://upbutler.com/api/v1/deploys \
  -H "Authorization: Bearer $UPBUTLER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "version": "1.4.2",
    "commit": "abc1234def",
    "environment": "production",
    "service": "api"
  }'

List deploys

GET/api/v1/deploys
API key · readMCP deploys_listReturns 200

Newest first. monitorId/pageId include workspace-wide deploys; incidentId returns the deploys from the hour before the incident through its end.

FieldTypeDescription
monitorIdquerystring
pageIdquerystring
incidentIdquerystring
environmentquerystring
sincequerystring (date-time)pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
untilquerystring (date-time)pattern ^(?:(?:\d\d[2468][048]|\d\d[13579][26]|\d\d0[48]|[02468][048]00|[13579][26]00)-02-29|\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\d|30)|(?:02)-(?:0[1-9]|1\d|2[0-8])))T(?:(?:[01]\d|2[0-3]):[0-5]\d:[0-5]\d(?:\.\d+)?(?:Z|([+-](?:[01]\d|2[0-3]):[0-5]\d)))$
limitqueryintegermin 1 · max 500
Example
curl https://upbutler.com/api/v1/deploys \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Delete a deploy marker

DELETE/api/v1/deploys/:id
API key · writeMCP deploys_deleteReturns 200
FieldTypeDescription
idrequiredpathstring
Example
curl -X DELETE https://upbutler.com/api/v1/deploys/id_... \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Digest

Weekly digest settings

GET/api/v1/digest/settings
API key · readMCP digest_settingsReturns 200

Workspace timezone, who receives the Monday 08:00 email, when the next one goes out and the last runs. Webhook channels subscribed to "digest.weekly" get the full JSON.

No parameters.

Example
curl https://upbutler.com/api/v1/digest/settings \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Change the workspace timezone or your weekly digest opt-in

PATCH/api/v1/digest/settings
API key · writeMCP digest_settings_updateReturns 200

subscribed applies to the signed-in member (owners are subscribed by default). timezone (IANA, e.g. "Europe/Berlin") needs owner/admin and also sets when Monday 08:00 is.

FieldTypeDescription
subscribedboolean
timezonestringmax length 60
Example
curl -X PATCH https://upbutler.com/api/v1/digest/settings \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Build the weekly digest on demand

POST/api/v1/digest/preview
API key · readMCP digest_previewReturns 200

Returns the digest JSON (same shape as the digest.weekly event) and, with format=html, the rendered email. period=last_week is exactly what Monday's email covers; last_7_days is rolling. ai=true writes the "what to look at" section with AI (uses one AI report from the monthly quota); otherwise a rule-based version is returned.

FieldTypeDescription
periodstringlast_weeklast_7_days
aiboolean
formatstringjsonhtml
Example
curl -X POST https://upbutler.com/api/v1/digest/preview \
  -H "Authorization: Bearer $UPBUTLER_API_KEY"

Dashboard-only

These need a signed-in user session (the dashboard cookie) and aren't available with API keys or over MCP:

  • GET /api/v1/me/workspaces: Workspaces of the signed-in user
  • POST /api/v1/me/workspaces: Create another workspace
  • POST /api/v1/me/workspaces/:id/switch: Switch the dashboard to another workspace
  • GET /api/v1/me/contact: Your paging contact profile
  • PATCH /api/v1/me/contact: Update your paging contact profile
  • GET /api/v1/me/security: Two-factor status, connected sign-in providers and active sessions
  • DELETE /api/v1/me/sessions/:id: Sign out one session
  • POST /api/v1/me/sessions/revoke-others: Sign out every other session
  • POST /api/v1/me/2fa/setup: Start two-factor enrolment (returns secret, otpauth URI and QR SVG)
  • POST /api/v1/me/2fa/enable: Confirm enrolment with a code; returns 10 one-time recovery codes
  • POST /api/v1/me/2fa/disable: Turn off two-factor authentication
  • POST /api/v1/me/2fa/recovery-codes: Replace all recovery codes (old ones stop working)
  • DELETE /api/v1/me/identities/:provider: Disconnect a Google or GitHub sign-in