Skip to cookie settingsSkip to content

Alerts and webhooks

Monitors alert when selected assertions fail or recover. Each alert goes to the workspace channels selected for that monitor.

DocsAlerts and webhooks

Choosing channels

Set up channels under Workspace, in Notifications. Choose each monitor's channels when you add it or later on its page. Alerts work on every paid plan and during the trial.

Email

Every member gets a message. The subject names the target and the change. The message says which selected assertion failed or passed again and links to the monitor. Send test email sends one test message to you only.

From
Netonica
To
You
Subject
DNS check of example.com (A): Records changed

Selected assertion “DNS answer unchanged” fails.

Seen at
Sun, 18 Oct 2026 17:58:20 UTC

Open the monitor for details.

View monitor
The alert email for an example change.

Slack

Slack alerts arrive as one message through an incoming webhook. The steps to create one are under Workspace, in Notifications. Paste its URL into the Slack field.

*DNS check of example.com (A): Records changed*. Selected assertion “DNS answer unchanged” fails. <https://netonica.com/monitors/view?monitor=m-dns|View monitor>
The same alert as the text Slack receives.

Webhook

We send one JSON POST to your URL for each webhook alert.

{
  "version": 1,
  "event_id": "c-m-dns-1",
  "observed_at_ms": 1792346300853,
  "monitor_id": "m-dns",
  "monitor_url": "https://netonica.com/monitors/view?monitor=m-dns",
  "target": {
    "kind": "dns",
    "canonical": "example.com/a"
  },
  "class": {
    "id": "records_changed",
    "label": "Records changed"
  },
  "severity": "alarm",
  "broke": [
    {
      "id": "records-stay",
      "label": "DNS answer unchanged"
    }
  ],
  "fixed": []
}
The same alert as a webhook body.

Fields

  • event_id: The change's ID. Retries use the same ID, so use it to skip a request you've already handled.
  • observed_at_ms: When the scan saw the change, in milliseconds since 1970 UTC. It is null when that time is unknown.
  • monitor_id and monitor_url: The monitor and its page on the site that sent the request.
  • target.kind: The check, such as TLS or DNS.
  • target.canonical: The target as we store it, which can be longer than the name the site shows.
  • class.id and class.label: The change type's ID and label.
  • severity: One of info, notice or alarm.
  • broke and fixed: The selected assertions that now fail and those that pass again. Both are always lists, and either can be empty. Each item has an id and a label.
  • version: The version of this format.

Checking the signature

After you turn on Webhook and save, the workspace page shows a signing secret. Each request then carries a X-Netonica-Signature header. Its value is sha256= followed by the HMAC-SHA256 of the raw request body in hex. The signing secret is the key.

Compute the same value from the body exactly as you received it, before parsing it. Compare the values in constant time. Reject the request if they differ.

The signature covers only the body and has no timestamp. Use event_id to ignore repeated requests.

import hashlib
import hmac

# body is the raw request bytes.
expected = "sha256=" + hmac.new(secret.encode(), body, hashlib.sha256).hexdigest()
verified = hmac.compare_digest(expected, header)

Delivery and retries

Respond with any 2xx status within 10 seconds. We don't follow redirects, so a 3xx counts as a failure. After a failure, we retry the request 5 minutes later, for up to a day.

A 404 or 410 response means the URL is gone. We drop that alert without retrying it. A request can arrive twice, so handle each event_id once.