Developer Documentation

REST API, webhook payloads, and integration guides for Vigilmon.

API Reference

Authentication

All API requests require a personal API token. Create one in Settings → API tokens. Pass the token as a Bearer token in the Authorization header.

curl -H "Authorization: Bearer vtk_your_token_here" \
     https://vigilmon.online/api/v1/monitors

Base URL

https://vigilmon.online/api/v1

Rate limit: 60 requests per minute per token.

Monitors

GET /api/v1/monitors

List all monitors for the authenticated user. Paginated (20 per page).

Example

curl -H "Authorization: Bearer vtk_your_token" \
     https://vigilmon.online/api/v1/monitors
{
  "data": [
    {
      "id": 1,
      "name": "Production API",
      "url": "https://api.example.com/health",
      "method": "GET",
      "check_interval_seconds": 60,
      "is_active": true,
      "current_status": "up",
      "last_checked_at": "2024-01-15T10:30:00+00:00"
    }
  ],
  "meta": { "current_page": 1, "total": 1 }
}
POST /api/v1/monitors

Create a new monitor.

Request body

{
  "name": "Production API",          // required
  "url": "https://api.example.com",  // required
  "method": "GET",                   // optional, default GET
  "expected_status_code": 200,       // optional, default 200
  "check_interval_seconds": 60,      // optional, plan minimum applies
  "keyword": "healthy",              // optional, check response body
  "regions": ["us-east", "eu-west"]  // optional
}

Example

curl -X POST \
     -H "Authorization: Bearer vtk_your_token" \
     -H "Content-Type: application/json" \
     -d '{"name":"Prod API","url":"https://api.example.com","check_interval_seconds":60}' \
     https://vigilmon.online/api/v1/monitors
GET /api/v1/monitors/{id}

Get monitor details including uptime percentages for the last 24h, 7d, and 30d.

curl -H "Authorization: Bearer vtk_your_token" \
     https://vigilmon.online/api/v1/monitors/1
{
  "data": {
    "id": 1,
    "name": "Production API",
    "url": "https://api.example.com/health",
    "current_status": "up",
    "uptime": {
      "24h": 100.0,
      "7d": 99.95,
      "30d": 99.87
    }
  }
}
GET /api/v1/monitors/{id}/incidents

List incidents for a monitor. Returns the 30 most recent per page, ordered newest first. Each incident includes start time, resolution time, duration, and status.

curl -H "Authorization: Bearer vtk_your_token" \
     https://vigilmon.online/api/v1/monitors/1/incidents
{
  "data": [
    {
      "id": 42,
      "started_at": "2024-01-15T08:12:00+00:00",
      "resolved_at": "2024-01-15T08:34:00+00:00",
      "duration_seconds": 1320,
      "cause": "HTTP 503 Service Unavailable",
      "confirmed_regions": ["za-vps"],
      "status": "resolved"
    },
    {
      "id": 41,
      "started_at": "2024-01-10T22:05:00+00:00",
      "resolved_at": null,
      "duration_seconds": null,
      "cause": "Connection timed out",
      "confirmed_regions": ["za-vps", "eu-west"],
      "status": "ongoing"
    }
  ],
  "meta": { "current_page": 1, "total": 2 }
}
PATCH /api/v1/monitors/{id}

Update a monitor. All fields are optional — only send what you want to change.

curl -X PATCH \
     -H "Authorization: Bearer vtk_your_token" \
     -H "Content-Type: application/json" \
     -d '{"check_interval_seconds":30}' \
     https://vigilmon.online/api/v1/monitors/1
DELETE /api/v1/monitors/{id}

Permanently delete a monitor. Returns 204 No Content on success.

curl -X DELETE \
     -H "Authorization: Bearer vtk_your_token" \
     https://vigilmon.online/api/v1/monitors/1

Error responses

Status Meaning
401Missing or invalid token
403Token does not own this monitor
404Monitor not found
422Validation error (check errors key)
429Rate limit exceeded (60 req/min)

CI/CD integration example

Pause monitoring during a deployment so you don't get false-positive alerts:

TOKEN="vtk_your_token"
MONITOR_ID=1

# Pause before deploy
curl -X PATCH \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"is_active":false}' \
     https://vigilmon.online/api/v1/monitors/$MONITOR_ID

# ... run your deployment ...

# Resume after deploy
curl -X PATCH \
     -H "Authorization: Bearer $TOKEN" \
     -H "Content-Type: application/json" \
     -d '{"is_active":true}' \
     https://vigilmon.online/api/v1/monitors/$MONITOR_ID

Webhooks

Overview

Vigilmon can send an HTTP POST request to any URL when a monitor goes down, recovers, or when an SSL certificate is about to expire. Configure a webhook alert channel in Settings → Alert Channels.

Every webhook POST includes:

  • Content-Typeapplication/json
  • User-AgentVigilmon/1.0
  • X-Vigilmon-Secretyour secret (only if configured)

Event: monitor_down

Fired when a monitor fails its check and the incident is confirmed.

{
  "event": "monitor_down",
  "monitor": {
    "id": 1,
    "name": "Production API",
    "url": "https://api.example.com/health"
  },
  "status": "down",
  "checked_at": "2024-01-15T08:12:00+00:00",
  "region": "za-vps",
  "response_time_ms": null,
  "error": null
}
Field Type Description
eventstringAlways monitor_down
monitor.idintegerMonitor ID
monitor.namestringMonitor display name
monitor.urlstringURL being monitored
checked_atISO 8601Time the incident was detected
regionstring|nullCheck region(s), comma-separated
response_time_msinteger|nullResponse time in ms (null if no response)
errorstring|nullFailure reason if available

Event: monitor_up

Fired when a previously down monitor successfully responds again.

{
  "event": "monitor_up",
  "monitor": {
    "id": 1,
    "name": "Production API",
    "url": "https://api.example.com/health"
  },
  "status": "up",
  "checked_at": "2024-01-15T08:34:00+00:00",
  "region": "za-vps",
  "response_time_ms": null,
  "error": null
}

Event: monitor_escalation

Fired when a monitor has been down for an extended period (escalation threshold). Useful for paging on-call staff for prolonged outages.

{
  "event": "monitor_escalation",
  "monitor": {
    "id": 1,
    "name": "Production API",
    "url": "https://api.example.com/health"
  },
  "status": "down",
  "down_minutes": 30,
  "incident_started_at": "2024-01-15T08:12:00+00:00",
  "region": "za-vps"
}
Field Type Description
down_minutesintegerHow long the monitor has been down
incident_started_atISO 8601When the incident first started

Event: ssl.expiring

Fired when an SSL certificate is within the expiry warning threshold (typically 30 days). Vigilmon checks daily.

{
  "event": "ssl.expiring",
  "monitor_url": "https://api.example.com",
  "days_remaining": 14,
  "threshold": 30,
  "expires_at": "2024-01-29T23:59:59+00:00"
}
Field Type Description
monitor_urlstringURL of the monitor whose cert is expiring
days_remainingintegerDays until the certificate expires
thresholdintegerAlert threshold configured for this channel
expires_atISO 8601Exact certificate expiry timestamp

Security

When you configure a secret on a webhook alert channel, Vigilmon sends it in the X-Vigilmon-Secret header with every request. Verify this header in your receiver to reject requests from untrusted sources.

// Example: verify the secret in Node.js
app.post('/webhook', (req, res) => {
  const secret = req.headers['x-vigilmon-secret'];
  if (secret !== process.env.VIGILMON_SECRET) {
    return res.status(401).json({ error: 'Unauthorized' });
  }
  // handle payload
  res.sendStatus(200);
});

Retries & delivery

Property Value
MethodHTTP POST
Timeout10 seconds
Retries on failure3 attempts (backoff: 10s → 30s → 60s)
ThrottleMax 1 alert per incident per channel per 5 minutes
Delivery logAvailable in Settings → Alert Channels → View history

Respond with any 2xx status code to acknowledge delivery. Vigilmon treats non-2xx responses as failures and will retry.

Integrations

Slack

Vigilmon has a native Slack integration that posts richly-formatted alert messages to any Slack channel using Slack's Incoming Webhooks.

  1. Create a Slack Incoming Webhook. Go to api.slack.com/appsCreate New AppIncoming Webhooks → activate and add to the channel you want. Copy the webhook URL (looks like https://hooks.slack.com/services/T.../B.../xxx).
  2. Add the Slack channel in Vigilmon. Go to Settings → Alert ChannelsAdd Channel → choose Slack → paste the webhook URL.
  3. Assign the channel to your monitors. Edit any monitor and select the Slack channel under Alert Channels.
  4. Test it. Use the Send test alert button in Settings → Alert Channels to confirm delivery.
Vigilmon uses Slack's Block Kit format, so alerts show the monitor name, URL, status, timestamp, and affected regions in a clean card layout.

Discord

Vigilmon has a native Discord integration that sends colour-coded embed messages to any Discord channel.

  1. Create a Discord webhook. In Discord, right-click the channel → Edit ChannelIntegrationsCreate Webhook. Give it a name (e.g., "Vigilmon") and copy the webhook URL.
  2. Add the Discord channel in Vigilmon. Go to Settings → Alert ChannelsAdd Channel → choose Discord → paste the webhook URL.
  3. Assign to monitors and optionally test with Send test alert.
Discord alerts use embed format with red for downtime and green for recovery, including downtime duration and affected regions.

Generic webhook receiver — Node.js

Use a generic Webhook alert channel to POST Vigilmon events to any HTTP endpoint. Here's a minimal Express.js receiver:

// npm install express
const express = require('express');
const app = express();
app.use(express.json());

const VIGILMON_SECRET = process.env.VIGILMON_SECRET; // optional

app.post('/vigilmon', (req, res) => {
  // Verify secret if configured
  if (VIGILMON_SECRET && req.headers['x-vigilmon-secret'] !== VIGILMON_SECRET) {
    return res.status(401).json({ error: 'Unauthorized' });
  }

  const { event, monitor } = req.body;

  switch (event) {
    case 'monitor_down':
      console.log(`DOWN: ${monitor.name} (${monitor.url})`);
      // page on-call, update status page, etc.
      break;
    case 'monitor_up':
      console.log(`RECOVERED: ${monitor.name} is back up`);
      break;
    case 'monitor_escalation':
      console.log(`ESCALATION: ${monitor.name} down ${req.body.down_minutes} min`);
      break;
    case 'ssl.expiring':
      console.log(`SSL: ${req.body.monitor_url} expires in ${req.body.days_remaining} days`);
      break;
  }

  res.sendStatus(200); // respond 2xx to acknowledge
});

app.listen(3000, () => console.log('Listening on :3000'));

Generic webhook receiver — Python

A minimal Flask receiver:

# pip install flask
import os
from flask import Flask, request, abort

app = Flask(__name__)
VIGILMON_SECRET = os.getenv('VIGILMON_SECRET')

@app.route('/vigilmon', methods=['POST'])
def vigilmon_webhook():
    # Verify secret if configured
    if VIGILMON_SECRET:
        if request.headers.get('X-Vigilmon-Secret') != VIGILMON_SECRET:
            abort(401)

    data = request.get_json()
    event = data.get('event')
    monitor = data.get('monitor', {})

    if event == 'monitor_down':
        print(f"DOWN: {monitor.get('name')} ({monitor.get('url')})")
        # your alerting logic here
    elif event == 'monitor_up':
        print(f"RECOVERED: {monitor.get('name')} is back up")
    elif event == 'monitor_escalation':
        print(f"ESCALATION: {monitor.get('name')} down {data.get('down_minutes')} min")
    elif event == 'ssl.expiring':
        print(f"SSL: {data.get('monitor_url')} expires in {data.get('days_remaining')} days")

    return '', 200

if __name__ == '__main__':
    app.run(port=3000)

Generic webhook receiver — Laravel

Add a route to receive Vigilmon webhooks in your own Laravel application:

// routes/web.php or routes/api.php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

Route::post('/webhooks/vigilmon', function (Request $request) {
    // Verify secret if configured
    $secret = config('services.vigilmon.webhook_secret');
    if ($secret && $request->header('X-Vigilmon-Secret') !== $secret) {
        abort(401);
    }

    $event   = $request->input('event');
    $monitor = $request->input('monitor', []);

    match ($event) {
        'monitor_down' => Log::alert('Monitor down', [
            'name' => $monitor['name'],
            'url'  => $monitor['url'],
            'at'   => $request->input('checked_at'),
        ]),
        'monitor_up' => Log::info('Monitor recovered', [
            'name' => $monitor['name'],
        ]),
        'monitor_escalation' => Log::critical('Monitor escalation', [
            'name'         => $monitor['name'],
            'down_minutes' => $request->input('down_minutes'),
        ]),
        'ssl.expiring' => Log::warning('SSL certificate expiring', [
            'url'           => $request->input('monitor_url'),
            'days_remaining' => $request->input('days_remaining'),
        ]),
        default => null,
    };

    return response()->noContent(); // 204 — Vigilmon treats any 2xx as success
})->withoutMiddleware([\App\Http\Middleware\VerifyCsrfToken::class]);

Store the secret in your .env as VIGILMON_WEBHOOK_SECRET and add 'vigilmon' => ['webhook_secret' => env('VIGILMON_WEBHOOK_SECRET')] to config/services.php.