How to Create a Custom Monitor Type Plugin for Uptime Kuma

Yes, you can create custom monitor type plugins for Uptime Kuma by extending the MonitorType base class, implementing the required check method, and registering your implementation in UptimeKumaServer.monitorTypeList located in server/uptime-kuma-server.js.

Uptime Kuma is an open-source monitoring tool that exposes a class-based extension system for adding new monitoring capabilities. Whether you need to query a proprietary API or implement a specialized health check, you can build a custom monitor type that integrates natively with the existing UI and heartbeat engine without modifying core files beyond the registration step.

Understanding the Monitor Type Architecture

Uptime Kuma’s monitoring engine relies on a registry pattern that maps string identifiers to instantiated monitor classes. The architecture consists of three primary layers:

  • MonitorType base class (server/monitor-types/monitor-type.js): Defines the contract for all monitor types, including the abstract check method and UI metadata properties like name, type, and description.
  • UptimeKumaServer.monitorTypeList (server/uptime-kuma-server.js): A global registry object that stores instantiated monitor types. The server constructor populates this list at startup.
  • Real-time UI synchronization (server/client.js): The sendMonitorTypeList function serializes the registry and emits it to connected clients via WebSocket, allowing the frontend (src/mixins/socket.js) to dynamically populate the "Add Monitor" dropdown without requiring static frontend builds.

When a heartbeat cycle executes, the server retrieves the monitor’s type string from the database, looks up the corresponding class in monitorTypeList, and invokes the check method with the monitor record and a fresh heartbeat object.

Step-by-Step: Creating a Custom Monitor Plugin

Step 1: Extend the MonitorType Base Class

Create a new file under server/monitor-types/ that imports the base class and status constants. Every custom monitor must export a class that extends MonitorType.

// server/monitor-types/custom-api.js
const { MonitorType } = require("./monitor-type");
const { UP, DOWN } = require("../../src/util");
const axios = require("axios");

class CustomApiMonitor extends MonitorType {
    name = "Custom API Check";
    type = "custom-api";
    description = "Monitor a custom REST endpoint with Bearer token authentication.";
    supportsConditions = true;
    conditionVariables = [
        { name: "responseTime", type: "number", label: "Response Time (ms)" }
    ];
    allowCustomStatus = false;
}

module.exports = { CustomApiMonitor };

Step 2: Implement the Check Method

The check method is the only required override. It receives two arguments: the monitor object (containing database fields like url and interval) and the heartbeat object (which you populate with status, message, and timing data).

async check(monitor, heartbeat) {
    const start = Date.now();
    
    try {
        const response = await axios.get(monitor.url, {
            headers: { "Authorization": `Bearer ${monitor.apiToken}` },
            timeout: monitor.timeout || 15000
        });
        
        const duration = Date.now() - start;
        
        if (response.status === 200) {
            heartbeat.status = UP;
            heartbeat.msg = "Service healthy";
            heartbeat.time = duration;
            
            // Expose variables for conditions if supportsConditions is true
            heartbeat.responseTime = duration;
        } else {
            throw new Error(`Unexpected status code: ${response.status}`);
        }
    } catch (error) {
        heartbeat.status = DOWN;
        heartbeat.msg = error.message || "Connection failed";
    }
}

Key implementation details:

  • Set heartbeat.status to UP, DOWN, or PENDING (imported from src/util.js).
  • Set heartbeat.time to record response duration in milliseconds.
  • If allowCustomStatus is false (default), the framework expects UP for success; any thrown error or DOWN status triggers a failure.
  • Throwing an exception automatically results in a DOWN status if unhandled.

Step 3: Register Your Monitor Type

Open server/uptime-kuma-server.js and locate the constructor where monitorTypeList is populated. Import your class and instantiate it:

const { CustomApiMonitor } = require("./monitor-types/custom-api");

// Inside the UptimeKumaServer constructor, after existing registrations:
UptimeKumaServer.monitorTypeList["custom-api"] = new CustomApiMonitor();

The string key ("custom-api") must match the type property defined in your class. Once registered, the server automatically includes your monitor in the list sent to clients via client.sendMonitorTypeList.

Step 4: Configure UI Behavior

Control how your monitor appears and behaves in the dashboard by setting these boolean and array properties:

  • supportsConditions: Set to true if you want your monitor to appear in conditional logic (e.g., "alert when response time > 500ms").
  • conditionVariables: An array of objects defining variables available for conditions. Each object requires name, type ("number" or "string"), and label.
  • allowCustomStatus: Set to true only if your monitor sets non-standard status strings beyond UP/DOWN/PENDING.

If supportsConditions is false, the UI displays only standard fields (name, URL, interval) and omits condition configuration panels.

Complete Working Example: HTTP Status Monitor

Here is a production-ready example that monitors a JSON endpoint and validates the response structure:

// server/monitor-types/json-validator.js
const { MonitorType } = require("./monitor-type");
const { UP, DOWN } = require("../../src/util");
const axios = require("axios");

class JsonValidatorMonitor extends MonitorType {
    name = "JSON Validator";
    type = "json-validator";
    description = "Verify that a JSON endpoint returns expected schema fields.";
    supportsConditions = false;
    conditionVariables = [];
    allowCustomStatus = false;

    async check(monitor, heartbeat) {
        const startTime = Date.now();
        
        try {
            const res = await axios.get(monitor.url, {
                timeout: monitor.timeout || 10000,
                validateStatus: () => true // Handle status codes manually
            });
            
            heartbeat.time = Date.now() - startTime;
            
            if (res.status !== 200) {
                throw new Error(`HTTP ${res.status}`);
            }
            
            // Validate required JSON field exists
            if (!res.data || !res.data.status) {
                throw new Error("Missing 'status' field in JSON response");
            }
            
            if (res.data.status === "healthy") {
                heartbeat.status = UP;
                heartbeat.msg = "Schema valid and status healthy";
            } else {
                heartbeat.status = DOWN;
                heartbeat.msg = `Service reports status: ${res.data.status}`;
            }
        } catch (err) {
            heartbeat.status = DOWN;
            heartbeat.msg = err.message;
        }
    }
}

module.exports = { JsonValidatorMonitor };

Register this in server/uptime-kuma-server.js:

const { JsonValidatorMonitor } = require("./monitor-types/json-validator");
UptimeKumaServer.monitorTypeList["json-validator"] = new JsonValidatorMonitor();

After restarting the Uptime Kuma server, "JSON Validator" appears immediately in the monitor type dropdown.

Key Files for Plugin Development

  • server/monitor-types/monitor-type.js: The abstract base class defining the check method signature and UI metadata properties.
  • server/monitor-types/*.js (e.g., tcp.js, dns.js): Reference implementations showing database interaction and heartbeat population patterns.
  • server/uptime-kuma-server.js: Contains the monitorTypeList registry where you must instantiate and register your plugin.
  • server/client.js: Implements sendMonitorTypeList, which serializes your monitor’s metadata for the frontend.
  • src/mixins/socket.js: Frontend handler that receives the monitor type list and updates the UI state.
  • src/util.js: Exports status constants (UP, DOWN, PENDING) used to set heartbeat results.

Summary

  • Extend MonitorType: Create a new file in server/monitor-types/ that inherits from the base class and implements the async check(monitor, heartbeat) method.
  • Register in UptimeKumaServer.monitorTypeList: Import and instantiate your class in server/uptime-kuma-server.js using a unique string key.
  • Set UI flags: Configure supportsConditions, conditionVariables, and allowCustomStatus to control frontend behavior without modifying React components.
  • Return standard statuses: Import UP and DOWN from src/util.js and assign them to heartbeat.status, setting heartbeat.time for latency tracking.
  • Automatic UI integration: The frontend receives new monitor types via WebSocket at runtime, so your custom type appears in the "Add Monitor" dialog immediately after server restart.

Frequently Asked Questions

Do I need to modify the frontend code to add a custom monitor type?

No. Uptime Kuma’s frontend receives the monitor type list dynamically through the WebSocket connection handled in src/mixins/socket.js. As long as you register your class in UptimeKumaServer.monitorTypeList and set the appropriate metadata properties (name, type, description), the "Add Monitor" dropdown will automatically include your custom type. You only need frontend modifications if you require custom input fields beyond the standard URL, interval, and notification options.

What methods are absolutely required when creating a monitor type?

You must implement only the check method. This async method accepts monitor (the database record) and heartbeat (the response object) as arguments. You must populate heartbeat.status with either UP or DOWN (constants from src/util.js), and optionally set heartbeat.msg for the status message and heartbeat.time for response duration. The base class handles all other lifecycle management.

How do I add custom condition variables for alerting logic?

Set supportsConditions = true in your class definition, then populate the conditionVariables array with objects containing name, type ("number" or "string"), and label. Inside your check method, assign values to the heartbeat object using these variable names (e.g., heartbeat.responseTime = duration). The UI will then allow users to create rules like "alert when responseTime > 500" without additional frontend code.

Can I use third-party npm packages in my custom monitor?

Yes. Since custom monitor types are standard Node.js modules loaded by server/uptime-kuma-server.js, you can require() any package available in the project’s node_modules or install new dependencies. Ensure you handle exceptions properly within your check method to prevent unhandled promise rejections, as errors thrown will result in a DOWN status unless caught and handled manually.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →