Skip to content

API, tokens and webhooks

Read status, events and reports with scoped, read-only tokens, browse the OpenAPI reference, and receive signed webhooks for every event.

5 min read · For admins and integrators

Other systems can work with a collector in two ways. They can ask, by calling the API with a read-only token, or be told, by webhooks that send each event as it happens. These webhooks are for systems; the alert webhooks in Settings › Alerts post a short message for people.

1. Create an API token

  1. Open Settings › API tokens.
  2. Under Create a token, enter a Name (what will use it) and choose Expires after: 30 days, 90 days or 1 year.
  3. To limit what it sees, tick device types under Limit to device types and sites under Limit to sites. Leave both empty for every device.
  4. Choose Create token and copy the token now. It isn't shown again: only a hash of it is stored.
curl -H "Authorization: Bearer mtr_…" https://monitoring.example.com/api/v1/status
curl -H "Authorization: Bearer mtr_…" "https://monitoring.example.com/api/v1/reports/availability?hours=720&format=csv"
  • GET /api/v1/status: every sensor in scope with its status, value and message.
  • GET /api/v1/events?limit=100: recent status changes.
  • GET /api/v1/availability?hours=24: for each sensor, how often it was checked in that time and how often it wasn't Down.
  • GET /api/v1/reports/availability?hours=168&group=device&format=csv|json: the availability report.
  • Tokens can also read sensor history, the Windows health and health review reports, traffic and the map. Settings › API lists them all.

Tokens are read-only: they can't change anything, sign in to the collector's pages or see users. A token sees only its device types and sites; anything else answers 404, as if it didn't exist. Revoke a token at any time; the list shows its last four characters, what it sees and when it was last used. AI assistants connect with a token too: see the AI assistant guide.

The API reference

The collector describes its whole API, including the routes its features add, as OpenAPI 3.1 at /api/v1/openapi.json. Settings › API shows it as a searchable page; set Who to API tokens to see what a token can read, or choose Download openapi.json for an API client or code generator. Every /api/ route also answers under /api/v1/, which scripts should use: endpoints marked stable keep working within version 1 and only gain additions, so ignore fields you don't know. A breaking change would come as /api/v2/, with /api/v1/ kept for at least 12 months; endpoints marked internal or experimental can change sooner.

2. Send events with webhooks

  1. Open Settings › Webhooks and choose + Add endpoint.
  2. Enter a Name and the receiver's Address, such as https://psa.example.com/hooks/monitaria.
  3. Under Events to send, keep All events, including kinds added later, or choose Only these and tick kinds such as sensor.status or incident.*. Optionally tick the sites and device types the events must be about.
  4. Choose Add endpoint, then copy the signing secret (whsec_…) into the receiver. It isn't shown again.
  5. Choose Send test. A webhook.test event goes out at once, and the result shows next to the endpoint.
  6. Under Settings, tick Send webhooks and choose Save settings. Events are only delivered from then on.

Each delivery is a POST with a JSON body (id, kind, ts, summary, collector, data and version) and an X-Monitaria-Signature header: t=<unix seconds>,v1=<hex>. The v1 value is the HMAC-SHA256 of the timestamp, a full stop and the raw body, keyed with the whole signing secret; check it against the raw bytes before parsing, and refuse timestamps more than five minutes old. Answer with any 2xx within 10 seconds; anything else is retried with growing pauses for up to 24 hours. A delivery can arrive more than once or out of order, so skip duplicates by the event id and order by ts.

import hashlib, hmac, time

def verify(secret: str, header: str, body: bytes, tolerance: int = 300) -> bool:
    """True when X-Monitaria-Signature matches the raw request body and is recent."""
    parts = [p.split("=", 1) for p in (header or "").split(",") if "=" in p]
    stamps = [v.strip() for k, v in parts if k.strip() == "t"]
    signatures = [v.strip() for k, v in parts if k.strip() == "v1"]
    if not stamps or not stamps[0].isdigit() or abs(time.time() - int(stamps[0])) > tolerance:
        return False
    expected = hmac.new(secret.encode(), stamps[0].encode() + b"." + body, hashlib.sha256).hexdigest()
    return any(hmac.compare_digest(expected, s) for s in signatures)

Good to know

  • Webhooks go to https:// addresses. A receiver on your own network (a private address, or plain http:// to one) needs Allow addresses on your own network. Link-local and cloud metadata addresses are always refused, and every address is checked again before each delivery.
  • New secret makes another signing secret. For 24 hours deliveries carry signatures made with both, so the receiver can switch over without missing anything.
  • After 20 failed attempts in a row (about 13 hours; you can change the number in the settings), or a 410 Gone answer, an endpoint is paused and Settings › Webhooks shows a notice. Fix the receiver and choose Resume: deliveries less than 24 hours old go out then.
  • sensor.status is sent for every status change, including ones the alert rules don't notify about; data.wanted is false for those.
  • Each delivery also carries X-Monitaria-Event (the kind), X-Monitaria-Delivery (the same id on every retry) and X-Monitaria-Attempt. The Checking the signature panel on Settings › Webhooks shows how to check it in Python and Node.js.
  • There can be up to 50 endpoints, and the delivery log keeps 7 days. Deliveries go straight to the receiver, without an HTTP proxy.
  • The collector's clock signs each delivery, so keep the collector and the receiver on NTP.