Skip to content

Give your agent a pager and a status page.

UpButler is uptime monitoring your agent can run by itself. It can create a workspace, plug in services, prove its own jobs ran, tell customers what broke, and react when something it depends on goes down. You claim the workspace whenever you're ready.

MCP tools
94
Calls to go live
2
Humans required
0
Webhook signing
Standard Webhooks

From zero to a public status page in two calls.

  1. 1

    Bootstrap a workspace

    No sign-up and no key. The response has an API key to use right away and a claim link for the human who will own the workspace.

    Request
    curl -X POST https://upbutler.com/api/v1/agent/bootstrap \
      -H "Content-Type: application/json" \
      -d '{"agentName": "deploy-bot", "workspaceName": "Acme"}'
    201 Created
    {
      "workspace": { "id": "ws_3kd9…", "name": "Acme", "plan": "free",
                     "unclaimedUntil": "2026-10-16T09:12:00.000Z" },
      "apiKey": "ub_live_8Hq2…",
      "claimUrl": "https://upbutler.com/claim/clm_Vx…",
      "next": [ "Store apiKey securely; …", "POST /api/v1/services …", "Share claimUrl …" ],
      "mcp": "https://upbutler.com/mcp"
    }
  2. 2

    Plug in a service

    One call creates the monitor, the status page (from the slug) and the component. Pass periodSec instead of url to get a heartbeat URL for a job.

    Request
    curl https://upbutler.com/api/v1/services \
      -H "Authorization: Bearer ub_live_8Hq2…" \
      -H "Content-Type: application/json" \
      -d '{"name": "Search API", "url": "https://api.acme.dev/health",
           "statusPage": "acme", "group": "APIs"}'
  3. 3

    Hand the claim link to your human

    Monitoring, status pages, webhooks and AI reports work before anyone claims the workspace. Claiming makes a person the owner and unlocks email. Unclaimed workspaces are deleted after 7 days.

    deploy-bot

    I set up monitoring for the Search API and published it at upbutler.com/s/acme. To own the workspace and get email alerts, claim it here within 7 days:

    https://upbutler.com/claim/clm_Vx…

Connect over MCP.

One streamable-HTTP endpoint, the same Bearer key as the REST API. Every operation is a typed tool with read-only and destructive hints, and the server tells your agent the common flows when it connects.

No key yet? Connect without one and call agent_bootstrap, then reconnect with the key it returns.

claude mcp add --transport http upbutler https://upbutler.com/mcp \
  --header "Authorization: Bearer ub_live_..."

All 94 tools

Agents

  • agent_bootstrap
  • services_add
  • heartbeat_ping
  • components_push
  • agent_whoami

Monitors

  • monitors_list
  • monitors_create
  • monitors_get
  • monitors_update
  • monitors_delete
  • monitors_check
  • monitors_checks
  • checks_get
  • regions_list
  • monitors_regions

Status pages

  • pages_list
  • pages_create
  • pages_get
  • pages_update
  • pages_delete
  • pages_verifyDomain
  • pages_preview
  • pages_groups
  • pages_subscribers
  • subscribers_delete

Components

  • components_create
  • components_update
  • components_delete
  • components_override
  • pages_push

Incidents

  • incidents_list
  • incidents_get
  • incidents_create
  • incidents_update
  • incidents_resolve
  • incidents_analyze
  • maintenance_create
  • incidents_ack
  • incidents_unack
  • incidents_postmortem
  • incidents_postmortem_get
  • incidents_postmortem_save
  • incidents_postmortem_publish
  • templates_list
  • templates_create
  • templates_update
  • templates_delete
  • templates_render

Alerts

  • channels_list
  • channels_create
  • channels_update
  • channels_delete
  • channels_test

Public status

  • public_status
  • public_incidents
  • public_incident
  • public_subscribe
  • public_subscriber_get
  • public_subscriber_update
  • public_unsubscribe
  • public_responseTimes

Workspace

  • workspace_get
  • workspace_update
  • members_list
  • keys_list
  • keys_create
  • keys_revoke
  • audit_list

Events

  • events_list

Billing

  • plans_list
  • billing_checkout

Import

  • import_preview
  • import_apply
  • import_status
  • import_jobs

On-call

  • oncall_current
  • oncall_schedules_list
  • oncall_schedules_get
  • oncall_schedules_create
  • oncall_schedules_update
  • oncall_schedules_delete
  • oncall_overrides_create
  • oncall_overrides_delete
  • oncall_members
  • escalation_list
  • escalation_create
  • escalation_update
  • escalation_delete

Deploys

  • deploys_create
  • deploys_list
  • deploys_delete

Digest

  • digest_settings
  • digest_settings_update
  • digest_preview

Prompts to copy.

Paste these into Claude Code, Cursor or your own agent once UpButler is connected.

Monitor everything in this repo
Use the UpButler MCP server to monitor this project. Find our public URLs and health endpoints, add each one with services_add to the status page "acme", grouped as APIs, Web or Jobs. For every cron job or worker, create a heartbeat (services_add with periodSec) and add the ping to the job. Show me the status page URL at the end.
Guard every deploy
After each deploy, watch UpButler for 10 minutes: poll events_list with after=<last id> for monitor.down or monitor.degraded on the services you changed. If one fires, open an incident with incidents_create (polish: true), roll back, and resolve it with incidents_resolve once monitors are up again.
Write the update for me
Post an UpButler update on the open incident: "found the bad migration, rolled back, error rate dropping". Use incidents_update with status monitoring and polish: true so customers get a clear message.
Watch a provider we depend on
Our payment provider publishes an UpButler status page with the slug "paycorp". Subscribe our endpoint https://ops.acme.dev/hooks/paycorp to it with public_subscribe (type webhook, components ["payments-api"]). When a component.status_changed event says it's degraded or down, switch checkout to the fallback provider.

React to downtime automatically.

Subscribe a webhook to any public UpButler status page, yours or a provider's, and your agent receives incident.*, maintenance.* and per-component component.status_changed events.

  • Your endpoint proves it's yours by echoing a challenge once.
  • Every delivery is signed with webhook-id, webhook-timestamp and webhook-signature, so any Standard Webhooks library can verify it.
  • Failed deliveries retry after 30 s, 2 min, 10 min, 30 min, 1 h, 3 h and 6 h.
  • Limit a subscription to the components you care about.
Webhook reference
Subscribe (no API key needed)
curl -X POST https://upbutler.com/api/v1/public/pages/paycorp/subscribers \
  -H "Content-Type: application/json" \
  -d '{"type": "webhook", "url": "https://ops.acme.dev/hooks/paycorp",
       "components": ["payments-api"], "agent": "checkout-guard"}'
hooks/paycorp.ts
import { createHmac, timingSafeEqual } from "node:crypto";

// whsec_... from the subscribe response (or the channel's signingSecret)
const secret = Buffer.from(process.env.UPBUTLER_SECRET!.replace(/^whsec_/, ""), "base64");

export async function POST(req: Request) {
  const body = await req.text();
  const event = JSON.parse(body);

  // 1. Handshake: echo the challenge to activate the subscription.
  if (event.type === "subscription.verify") {
    return Response.json({ challenge: event.challenge });
  }

  // 2. Verify the Standard Webhooks signature on everything else.
  const id = req.headers.get("webhook-id")!;
  const ts = req.headers.get("webhook-timestamp")!;
  const expected = "v1," + createHmac("sha256", secret).update(`${id}.${ts}.${body}`).digest("base64");
  const valid = (req.headers.get("webhook-signature") ?? "").split(" ").some(
    (s) => s.length === expected.length && timingSafeEqual(Buffer.from(s), Buffer.from(expected)),
  );
  if (!valid || Math.abs(Date.now() / 1000 - Number(ts)) > 300) {
    return new Response("invalid signature", { status: 401 });
  }

  // 3. React. webhook-id is stable across retries: use it to dedupe.
  if (event.type === "component.status_changed" && event.data.component.key === "payments-api") {
    if (event.data.to === "operational") await useProvider("paycorp");
    else await useProvider("fallback");
  }
  return new Response("ok");
}

Prove your agents are still working.

A long-running agent that silently stops is worse than one that crashes loudly. Give it a heartbeat: if no ping arrives within the period plus grace time, the monitor goes down and you're alerted. A ping to /fail alerts immediately.

Heartbeat URLs need no API key; the token is the secret. GET or POST, with an optional message.

import requests, time

HB = "https://upbutler.com/hb/hb_7Qx2kd"   # services_add {"name": "Triage agent", "periodSec": 600}

while True:
    try:
        triaged = run_triage_cycle()
        requests.post(HB, json={"message": f"triaged {triaged} tickets"}, timeout=10)
    except Exception as e:
        requests.post(f"{HB}/fail", json={"message": str(e)[:400]}, timeout=10)
    time.sleep(300)

Tell it what you shipped.

Record a deploy marker from CI or from the agent that ran the release. When something breaks soon after, the AI analysis connects the two: "errors began 2 minutes after deploy 1.4.2". Deploys never show up in public text.

Scope a deploy to a service, specific monitors or a status page, or leave it workspace-wide.

Deploy markers
- uses: upbutler/action@v1
  with:
    api-key: ${{ secrets.UPBUTLER_API_KEY }}
    version: ${{ github.ref_name }}
    environment: production
    service: api

Agent questions.

Does my agent need an account to start?

No. agent_bootstrap (or POST /api/v1/agent/bootstrap) creates a free workspace and returns an API key immediately. It is rate-limited to 5 workspaces per hour per IP address.

What happens if nobody claims the workspace?

Unclaimed workspaces are deleted after 7 days. Claiming takes one click on the claim link and a sign-in by email; after that a person owns it and email alerts and subscribers are unlocked.

Which tools work without an API key?

Bootstrap, heartbeats, component pushes by token, plan listing and the public status tools (public_status, public_incidents, public_subscribe and friends). Everything that reads or changes a workspace needs a key.

How are agent actions shown to humans?

Create a key per agent with keys_create and an agent name. Incident updates, monitors and subscriptions are attributed to that agent in the dashboard and timelines.

Should I use webhooks, the live stream or polling?

Webhooks if your agent has a public HTTPS endpoint: they are signed, retried with backoff for about 11 hours, and unmetered. If it can hold a connection open, stream GET /api/v1/stream (Server-Sent Events) and resume with Last-Event-ID. Otherwise poll events_list with after set to the last event id you saw.

Hand your agent the keys.

Read the agent quickstart, or sign in and create a key for it yourself.