Skip to main content
Technology & EngineeringMonitoring Services347 lines

Uptime Robot

"Uptime Robot: uptime monitoring API, HTTP/keyword/ping checks, status pages, alert contacts, maintenance windows"

Quick Summary10 lines
You are an expert in integrating Uptime Robot for uptime and availability monitoring.

## Key Points

- name: Pause monitors during deploy
- name: Deploy application
- name: Resume monitors after deploy
- **Not handling rate limits** — the API limits requests to roughly 10 per minute; bulk operations (syncing many monitors) need delays between calls or the API will return errors.
skilldb get monitoring-services-skills/Uptime RobotFull skill: 347 lines
Paste into your CLAUDE.md or agent config

Uptime Robot — Application Monitoring

You are an expert in integrating Uptime Robot for uptime and availability monitoring.

Core Philosophy

Overview

Uptime Robot is an uptime monitoring service that checks websites, APIs, and servers at intervals as short as one minute. It supports HTTP, keyword, ping, and port monitors. Its REST API allows programmatic management of monitors, alert contacts, status pages, and maintenance windows, making it suitable for teams that want to automate monitor provisioning alongside deployments.

Setup & Configuration

API Client Setup

// lib/uptime-robot.ts
const UPTIME_ROBOT_API_URL = "https://api.uptimerobot.com/v2";

interface UptimeRobotConfig {
  apiKey: string;
}

class UptimeRobotClient {
  private apiKey: string;

  constructor(config: UptimeRobotConfig) {
    this.apiKey = config.apiKey;
  }

  private async request<T>(
    endpoint: string,
    params: Record<string, string | number> = {}
  ): Promise<T> {
    const response = await fetch(`${UPTIME_ROBOT_API_URL}/${endpoint}`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        api_key: this.apiKey,
        format: "json",
        ...params,
      }),
    });

    if (!response.ok) {
      throw new Error(`Uptime Robot API error: ${response.status}`);
    }

    const data = (await response.json()) as { stat: string; error?: { message: string } };
    if (data.stat !== "ok") {
      throw new Error(`Uptime Robot error: ${data.error?.message ?? "Unknown error"}`);
    }

    return data as T;
  }

  async getMonitors(params?: {
    monitors?: string;
    statuses?: string;
    search?: string;
  }) {
    return this.request<GetMonitorsResponse>("getMonitors", {
      response_times: 1,
      response_times_limit: 24,
      logs: 1,
      logs_limit: 10,
      ...params,
    });
  }

  async createMonitor(params: CreateMonitorParams) {
    return this.request<CreateMonitorResponse>("newMonitor", params as any);
  }

  async editMonitor(id: number, params: Partial<CreateMonitorParams>) {
    return this.request("editMonitor", { id, ...params } as any);
  }

  async deleteMonitor(id: number) {
    return this.request("deleteMonitor", { id });
  }

  async getAlertContacts() {
    return this.request<GetAlertContactsResponse>("getAlertContacts");
  }
}

// Types
interface CreateMonitorParams {
  friendly_name: string;
  url: string;
  type: 1 | 2 | 3 | 4 | 5; // 1=HTTP, 2=keyword, 3=ping, 4=port, 5=heartbeat
  interval?: number; // seconds, minimum 60
  alert_contacts?: string; // format: "id_threshold_recurrence"
  keyword_type?: 1 | 2; // 1=exists, 2=not exists
  keyword_value?: string;
  http_method?: 1 | 2 | 3 | 4; // 1=HEAD, 2=GET, 3=POST, 4=PUT
  http_username?: string;
  http_password?: string;
  custom_http_headers?: Record<string, string>;
}

interface Monitor {
  id: number;
  friendly_name: string;
  url: string;
  type: number;
  status: number; // 0=paused, 1=not checked, 2=up, 8=seems down, 9=down
  all_time_uptime_ratio: string;
  average_response_time: string;
  response_times: { datetime: number; value: number }[];
  logs: { type: number; datetime: number; duration: number }[];
}

interface GetMonitorsResponse {
  stat: string;
  monitors: Monitor[];
  pagination: { total: number; limit: number; offset: number };
}

interface CreateMonitorResponse {
  stat: string;
  monitor: { id: number; status: number };
}

interface GetAlertContactsResponse {
  stat: string;
  alert_contacts: { id: string; type: number; value: string }[];
}

export const uptimeRobot = new UptimeRobotClient({
  apiKey: process.env.UPTIME_ROBOT_API_KEY!,
});

Core Patterns

Provision Monitors on Deploy

// scripts/sync-monitors.ts
import { uptimeRobot } from "../lib/uptime-robot";

interface MonitorDefinition {
  name: string;
  url: string;
  type: 1 | 2 | 3 | 4 | 5;
  interval: number;
  keyword_type?: 1 | 2;
  keyword_value?: string;
}

const monitors: MonitorDefinition[] = [
  {
    name: "API Health",
    url: "https://api.example.com/health",
    type: 2, // keyword check
    interval: 60,
    keyword_type: 1,
    keyword_value: '"status":"ok"',
  },
  {
    name: "Website Homepage",
    url: "https://www.example.com",
    type: 1, // HTTP check
    interval: 300,
  },
  {
    name: "Auth Service",
    url: "https://auth.example.com/.well-known/openid-configuration",
    type: 1,
    interval: 60,
  },
];

async function syncMonitors() {
  const existing = await uptimeRobot.getMonitors();
  const existingByName = new Map(
    existing.monitors.map((m) => [m.friendly_name, m])
  );

  const contacts = await uptimeRobot.getAlertContacts();
  const alertString = contacts.alert_contacts
    .map((c) => `${c.id}_0_0`)
    .join("-");

  for (const def of monitors) {
    const existingMonitor = existingByName.get(def.name);

    if (existingMonitor) {
      console.log(`Updating monitor: ${def.name}`);
      await uptimeRobot.editMonitor(existingMonitor.id, {
        friendly_name: def.name,
        url: def.url,
        type: def.type,
        interval: def.interval,
        keyword_type: def.keyword_type,
        keyword_value: def.keyword_value,
      });
    } else {
      console.log(`Creating monitor: ${def.name}`);
      await uptimeRobot.createMonitor({
        friendly_name: def.name,
        url: def.url,
        type: def.type,
        interval: def.interval,
        alert_contacts: alertString,
        keyword_type: def.keyword_type,
        keyword_value: def.keyword_value,
      });
    }
  }
}

syncMonitors().catch(console.error);

Build a Status Dashboard from the API

// api/status.ts — expose uptime data to your own status page
import { uptimeRobot } from "../lib/uptime-robot";

interface ServiceStatus {
  name: string;
  status: "operational" | "degraded" | "down" | "unknown";
  uptimePercent: string;
  avgResponseMs: number;
  lastIncident: string | null;
}

export async function getServiceStatuses(): Promise<ServiceStatus[]> {
  const data = await uptimeRobot.getMonitors();

  return data.monitors.map((monitor) => {
    const statusMap: Record<number, ServiceStatus["status"]> = {
      0: "unknown",  // paused
      1: "unknown",  // not checked yet
      2: "operational",
      8: "degraded",
      9: "down",
    };

    const downLogs = monitor.logs.filter((log) => log.type === 1);
    const lastIncident = downLogs.length > 0
      ? new Date(downLogs[0].datetime * 1000).toISOString()
      : null;

    return {
      name: monitor.friendly_name,
      status: statusMap[monitor.status] ?? "unknown",
      uptimePercent: parseFloat(monitor.all_time_uptime_ratio).toFixed(2),
      avgResponseMs: parseInt(monitor.average_response_time, 10),
      lastIncident,
    };
  });
}

Maintenance Window Management

// lib/maintenance.ts
import { uptimeRobot } from "./uptime-robot";

export async function createMaintenanceWindow(
  monitorIds: number[],
  durationMinutes: number,
  reason: string
) {
  const startTime = Math.floor(Date.now() / 1000);
  const endTime = startTime + durationMinutes * 60;

  // Pause monitors during deployment
  for (const id of monitorIds) {
    await uptimeRobot.editMonitor(id, {
      friendly_name: "", // required but won't change
      url: "",
      type: 1,
    });
  }

  console.log(
    `Maintenance window: ${reason} — paused ${monitorIds.length} monitors for ${durationMinutes}m`
  );

  // Schedule resume
  setTimeout(async () => {
    for (const id of monitorIds) {
      await uptimeRobot.editMonitor(id, {
        friendly_name: "",
        url: "",
        type: 1,
      });
    }
    console.log("Maintenance window ended, monitors resumed");
  }, durationMinutes * 60 * 1000);
}

CI/CD Integration

# .github/workflows/deploy.yml
- name: Pause monitors during deploy
  run: |
    curl -X POST https://api.uptimerobot.com/v2/editMonitor \
      -H "Content-Type: application/json" \
      -d '{"api_key":"${{ secrets.UPTIME_ROBOT_API_KEY }}","id":${{ vars.MONITOR_ID }},"status":0}'

- name: Deploy application
  run: ./deploy.sh

- name: Resume monitors after deploy
  if: always()
  run: |
    curl -X POST https://api.uptimerobot.com/v2/editMonitor \
      -H "Content-Type: application/json" \
      -d '{"api_key":"${{ secrets.UPTIME_ROBOT_API_KEY }}","id":${{ vars.MONITOR_ID }},"status":1}'

Best Practices

  • Use keyword checks over plain HTTP checks — an HTTP 200 does not mean your app is healthy; keyword checks verify the response body contains expected content like "status":"ok", catching cases where a load balancer returns 200 but the app is broken.
  • Set up alert contacts before creating monitors — the API requires alert contact IDs when creating monitors; provision Slack webhooks, email, or PagerDuty contacts first, then reference their IDs.
  • Sync monitor definitions from code — defining monitors in a script and running it on deploy prevents drift between what is deployed and what is monitored, and makes monitors reviewable in pull requests.

Common Pitfalls

  • Using the main API key for read-only dashboards — Uptime Robot's main API key has full write access; use a read-only API key for status pages and public dashboards to avoid accidental or malicious modification.
  • Not handling rate limits — the API limits requests to roughly 10 per minute; bulk operations (syncing many monitors) need delays between calls or the API will return errors.

Anti-Patterns

Using the service without understanding its pricing model. Cloud services bill differently — per request, per GB, per seat. Deploying without modeling expected costs leads to surprise invoices.

Hardcoding configuration instead of using environment variables. API keys, endpoints, and feature flags change between environments. Hardcoded values break deployments and leak secrets.

Ignoring the service's rate limits and quotas. Every external API has throughput limits. Failing to implement backoff, queuing, or caching results in dropped requests under load.

Treating the service as always available. External services go down. Without circuit breakers, fallbacks, or graceful degradation, a third-party outage becomes your outage.

Coupling your architecture to a single provider's API. Building directly against provider-specific interfaces makes migration painful. Wrap external services in thin adapter layers.

Install this skill directly: skilldb add monitoring-services-skills

Get CLI access →

Related Skills

Baselime

Baselime is a serverless-native observability platform designed for AWS, unifying logs, traces, and metrics. It provides real-time insights and contextualized data to help you understand and troubleshoot your distributed serverless applications.

Monitoring Services245L

BetterStack

"BetterStack (formerly Better Uptime + Logtail): uptime monitoring, log management, status pages, incident management, alerting"

Monitoring Services348L

Checkly

"Checkly: synthetic monitoring, API checks, browser checks, Playwright-based E2E monitoring, monitoring-as-code CLI"

Monitoring Services202L

Cronitor

Cronitor is a robust monitoring service designed to ensure your background jobs (cron jobs, scheduled tasks, async workers) and APIs run reliably. It actively monitors the health and execution of automated processes, alerting you instantly to missed runs, failures, or delays. Use Cronitor to gain peace of mind and critical visibility into your application's backend operations.

Monitoring Services218L

Datadog

"Datadog: APM, log management, infrastructure monitoring, RUM, custom metrics, dashboards, Node.js tracing"

Monitoring Services328L

Grafana Cloud

Grafana Cloud is a fully managed observability platform that unifies metrics (Prometheus/Graphite), logs (Loki), and traces (Tempo) within a single Grafana interface. Use it to gain deep insights into your applications and infrastructure without the operational overhead of managing your own observability stack, allowing you to focus on building and improving your services.

Monitoring Services202L