Skip to content

Alerts & notifications

CertIntel can push certificate and security events to a webhook destination as they happen, instead of relying on someone checking the dashboard. Configure destinations on the Alert Settings page, scoped to one organization or (tenant administrators, or a tenant-wide role holding notifications.create) Entire workspace (all organizations). Viewing, creating, editing, testing and deleting destinations are separate permissions (notifications.read / .create / .update / .test / .delete); the built-in Alert Manager role holds all five, and a custom role can hold any subset - see Organizations, users & roles. Alert destinations are a plan feature; a plan without them shows Alert destinations are not included in this subscription. Alert contacts - email recipients without a CertIntel login - have their own permissions, alert_contacts.read and alert_contacts.update.

Destination kinds

Kind Payload shape
Generic webhook A JSON POST in CertIntel's own schema (version 4, below) - the default choice for custom automation.
Slack A Block Kit message: emoji header, the labelled fields, one section per finding category, an Open CertIntel button, plus a plain-text fallback for notifications.
Discord A colour-coded embed (red for critical, amber for warning, green for a resolved renewal): the labelled fields in the description, one field per category.
Microsoft Teams An Adaptive Card 1.4 (full width) with a tinted banner, the labelled fields as a fact set, bold headings per category and an Open CertIntel action.
Email A multipart message: an HTML body styled with your tenant's selected brand preset and palette, plus a plain-text alternative.
Pushover Pushover's API with HTML formatting (bold, coloured headings, link), a severity-shifted priority and a supplementary dashboard URL.
ntfy A Markdown message with Title, Priority, Tags (emoji), Click and an Open CertIntel action on a topic on ntfy or a self-hosted instance.

What every alert says

Every destination receives the same shape, so an alert reads the same whether it lands in Slack, Teams, a mailbox or a phone:

  • Header - <emoji> <event type> โ€” <what happened> โ€” <organization>, for example ๐Ÿšจ ACME renewal failed โ€” api.acme.example โ€” Production or โš ๏ธ Warning digest โ€” 2 certificate(s) approaching expiry โ€” All organizations. Only the header is large.
  • Destination - the name of the alert destination the message was sent to.
  • Type - ACME renewal failed, Security warning, Alert digest ยท Critical, Test message, and so on.
  • Organization - the organization the alert is about. A destination scoped to the entire workspace says so: Production (tenant-wide alert) or All organizations (tenant-wide alert).
  • Description - what happened and why, in a sentence or two: which categories a digest covers, or what an agent reported for a renewal.
  • Links - the renewal, activity log or filtered list page for each finding category, followed by Alert Settings. Links appear only when the platform has a public origin configured.

A digest then lists each finding under its category heading, every item linked to its certificate, endpoint, CRL or agent.

Slack, Discord and Teams are destination kinds of their own, so a generic webhook only offers the JSON format. A destination created earlier with a chat format on a generic webhook keeps working and shows that format as (legacy) when edited.

Severity, emoji and priority

Every message is headed by its severity: ๐Ÿšจ Critical (a certificate inside the critical window, a failing monitor, an overdue or unreadable CRL, a failed renewal), โš ๏ธ Warning (approaching expiry or next update, a security warning, an endpoint still serving an old certificate, a new name set in Certificate Transparency, an overridden deployment window), โœ… Resolved (a successful renewal) or ๐Ÿงช Test. Each finding category inside a digest carries its own heading, emoji and colour.

For Pushover and ntfy the Priority you choose is a baseline: a critical alert is sent one step higher, a test message one step lower, and anything else at the baseline. Pushover never escalates to its emergency priority on its own. ntfy also receives the severity as tags (rotating_light, warning, white_check_mark, test_tube) and certintel, so you can filter or route on them.

When the platform has a public origin configured, chat cards, push messages and emails carry an Open CertIntel button (the first finding category's list page, the renewal, or Alert Settings for a test) beside the Links field.

Email

Platform email server sends from the platform's configured address and needs no further settings; the custom SMTP fields are hidden until you choose Custom SMTP server. Both transports send the same message: an HTML body in the tenant's selected theme (Brutal, Classic Blue, Liquid or Phosphor, with the tenant's primary colour and light-mode palette overrides applied) and a plain-text alternative. The subject starts with the severity emoji followed by CertIntel alert โ€” <organization> [<tier>]. The message is fluid: it fills the reading pane up to 1100 px wide, so a wide preview pane shows more of each line, and a phone gets a single edge-to-edge column. The footer names the destination and links to Alert Settings; scheduled report emails use the same layout and link to Scheduled Reports.

An email destination sends to up to 20 addresses entered under Recipients and up to 50 alert contacts; enter recipients, choose contacts, or both. Every alert and scheduled-report email goes out as one message per recipient, so nobody sees the other recipients' addresses. This includes custom SMTP servers, which earlier platform builds sent a single message with every recipient in To:. Each message carries that recipient's own unsubscribe link.

Alert and report emails never contain a link to download a private key or a certificate.

With MSP co-branding (Enterprise) turned on for an organization, alert emails of destinations scoped to that organization and its scheduled reports are headed for . This is text only; emails carry no client logo.

Alert contacts

An alert contact is a named email recipient who does not need a CertIntel login - an on-call mailbox, a service owner, a customer's administrator. Manage contacts in the Alert contacts section of the Alert Settings page, then choose them under Contacts on an email destination.

  • Permissions - alert_contacts.read to see contacts and alert_contacts.update to add, edit and delete them. The built-in Alert Manager and Administrator roles hold both; Auditor holds read. A custom role can hold either.
  • Scope - a contact belongs to one organization or to the Entire workspace (all organizations). A workspace contact can be chosen on any email destination; an organization's contact only on that organization's destinations. The scope is set when the contact is created and cannot be changed afterwards; delete the contact and add it again instead.
  • Deleting a contact stops every destination that lists it from sending to it.

An address that used its unsubscribe link is marked unsubscribed in the list and on the destination's contact picker. Contacts cannot yet be chosen on scheduled reports; a report's recipients are still typed in, and an unsubscribed address is skipped there too.

Every alert and scheduled-report email has a per-recipient line in its footer and in the plain-text part: Sent to

. Unsubscribe from these emails. The message also carries the List-Unsubscribe and List-Unsubscribe-Post headers, so mail clients that support RFC 8058 one-click unsubscribe offer their own button.

  • Opening the link shows a confirmation page (Unsubscribe from CertIntel email); nothing changes until the recipient chooses Unsubscribe. The same link later offers Subscribe again.
  • An unsubscribe applies to that address across the whole workspace: it stops every alert and scheduled-report email from the workspace to it, whichever destination, contact entry or report named it. An administrator cannot override it; only the recipient can subscribe again, from the same link.
  • The pages are reachable from anywhere, including a workspace with an IP allowlist.
  • Unsubscribing and subscribing again are recorded in the activity log (email.unsubscribed, email.resubscribed). Each skipped send to an unsubscribed address is recorded as alert.recipient_suppressed; it is not a delivery failure.

The links need the platform's public address (CERTINTEL_PUBLIC_BASE_URL). On a deployment without one, the footer says To stop these emails, ask your CertIntel administrator. and no unsubscribe headers are sent.

Generic webhook JSON

The JSON schema is the easiest shape to consume from automation platforms, functions and ticketing systems. Each version keeps every field of the one before it; version 4 adds the labelled fields shown above (destination, type, organization_label, tenant_wide, description, links):

{
  "product": "CertIntel",
  "schema_version": 4,
  "kind": "digest",
  "organization": "Production",
  "tier": "critical",
  "severity_label": "Critical",
  "title": "CertIntel alert โ€” Production [critical]",
  "headline": "๐Ÿšจ Critical digest โ€” 1 certificate(s) expiring soon โ€” Production",
  "summary": "*Critical* โ€” 1 certificate(s) expiring soon:\nโ€ข api.acme.example (expires 2026-10-21)",
  "destination": "Ops Slack",
  "type": "Alert digest ยท Critical",
  "organization_label": "Production",
  "tenant_wide": false,
  "description": "Everything in Production that currently matches the categories this destination subscribes to: 1 certificate(s) expiring soon. Acknowledged and ignored certificates are excluded. Each finding is listed below.",
  "links": [
    {"label": "1 certificate(s) expiring soon", "url": "https://app.certin.tel/certificates?attention=1&tier=critical"},
    {"label": "Alert Settings", "url": "https://app.certin.tel/alerts"}
  ],
  "generated_at": "2026-10-18T14:30:00+00:00",
  "item_count": 1,
  "sections": [
    {"key": "expiring_critical", "severity": "critical",
     "heading": "1 certificate(s) expiring soon", "count": 1, "total": 1,
     "url": "https://app.certin.tel/certificates?attention=1&tier=critical",
     "items": ["api.acme.example (expires 2026-10-21)"],
     "entries": [{"text": "api.acme.example (expires 2026-10-21)",
                  "url": "https://app.certin.tel/certificates?detail=โ€ฆ"}]}
  ],
  "expiring_critical": ["api.acme.example (expires 2026-10-21)"],
  "expiring_warning": [], "expired": [], "revoked": [], "discovered": [],
  "unreachable": [], "cert_invalid": [], "crl_critical": [], "crl_warning": [],
  "served_mismatch": [], "agents_silent": [], "ct_new_name_sets": [],
  "link": "https://app.certin.tel/alerts",
  "delivery_id": "digest:โ€ฆ"
}

kind is digest, event or test. A queued event (renewal.success, renewal.failure, deployment.window_override, auth.warning) also carries event, event_id, organization_id and a one-line summary, with a single section holding that summary. Digest section keys are expiring_critical, expiring_warning, expired, revoked, discovered, unreachable, cert_invalid, crl_critical, crl_warning, served_mismatch, agents_silent and ct_new_name_sets; a queued event uses the event name. The same keys appear as flat top-level lists (empty when the destination does not subscribe to that category or nothing matched).

Two queued events carry an extra object, still within schema version 4:

  • renewal.failure for an Agent installation failure carries failure_output - the step that failed and the redacted end of its output (see Failed step output):
"failure_output": {
  "step_id": "reload-nginx",
  "action": "process.execute",
  "exit_code": 1,
  "stdout_tail": "Testing nginx configuration...\n",
  "stderr_tail": "nginx: [emerg] cannot load certificate key ... (password: [redacted])\n",
  "truncated": false,
  "redacted": true
}
  • deployment.window_override carries deployment_window_override - reason (expires_before_window), window_opens_at, certificate_expires_at and margin_hours.

The two Private CA rotation events carry private_ca - id, label, successor_ca_id and predecessor_ca_id - on a platform build that offers rotation.

Receivers that ignore unknown keys need no change.

A destination must be an HTTPS URL without embedded credentials or a fragment (Use an HTTPS webhook URL without user credentials or a fragment.). At delivery time the host must resolve to a public address: private, loopback, link-local and carrier-grade NAT ranges (including 100.64.0.0/10, used by Tailscale) fail with Last error: BlockedTargetError on the destination's card.

Events

Each destination subscribes to one or more of seventeen event types (fifteen on platform builds without Private CA rotation). The Alert Settings form groups them as shown; a new destination starts with the eleven marked default selected:

Group Event Fires on
Certificates certificate.expiry (default) A certificate inside the critical expiry window
Certificates certificate.expiry_warning (default) A certificate inside the warning expiry window
Certificates certificate.expired (default) An expired certificate still in the inventory
Certificates certificate.revoked (default) A revoked certificate still in the inventory
Certificates certificate.discovered A certificate first seen since the previous digest
Public endpoints monitor.failure (default) A public endpoint unreachable or failing TLS
Public endpoints monitor.cert_invalid (default) A public endpoint presenting an invalid certificate (expired, revoked, untrusted chain, hostname mismatch, self-signed)
Public endpoints monitor.served_mismatch (default) Endpoint still serving an old certificate: an endpoint linked to an Agent-managed certificate that still serves an older certificate after the grace period (see Served versus issued)
CRL distribution points crl.expiry A monitored CRL distribution point whose published CRL is overdue or nearly due for its next update, or could not be read
Agents agent.silent An Agent that stopped reporting
ACME renewals renewal.success A successful ACME renewal
ACME renewals renewal.failure A failed ACME renewal, including an Agent installation failure with its failed step output
ACME renewals deployment.window_override (default) Deployment window overridden: an Agent installed a renewed certificate outside its deployment window because the installed certificate would otherwise expire first
Certificate Transparency ct.new_name_set (default) New name set in Certificate Transparency: a set of names never seen before for a watched domain, on a certificate CertIntel neither issued nor holds (see CT Log Watch)
Private CA private_ca.rotated (default) Private CA rotated: a successor issuing CA now issues new certificates; the previous CA keeps issuing and publishing its CRL until it expires (see Rotation)
Private CA private_ca.rotation_awaiting_signature (default) Private CA rotation awaiting signature: a subordinate CA is due for rotation and its successor's CSR waits to be signed by your root
Security auth.warning Failed sign-ins and other security warnings

The events under ACME renewals, Private CA and Security are queued and sent as they happen. Every other event is a digest category, evaluated once per digest interval. A digest category is evaluated from the current state, so a finding that has been fixed - an endpoint that now serves the renewed certificate, for example - is simply absent from the next digest.

monitor.served_mismatch, ct.new_name_set, deployment.window_override and the two Private CA events are selected by default only on destinations created after they were added. An existing destination keeps exactly the events it subscribed to; tick the new events on it to receive them. ct.new_name_set is sent only for organizations whose plan includes Certificate Transparency monitoring.

An Agent installation failure is reported as a failed renewal event, so it can reach a destination subscribed to renewal.failure. CA certificates on an effective ignore list are excluded from expiry alerts; only CA certificates can be ignored, so acknowledge a site certificate instead. Acknowledging a certificate or a failed renewal also suppresses its attention item without changing its recorded result.

Expiry digests use each certificate's owning organization thresholds, including short-lifetime scaling. Tenant-wide destinations can therefore contain items evaluated under different organization settings. Digest status also includes recorded chain trust, expiry, and hostname validation failures; a successful probe is not automatically a valid certificate. See expiry severity.

Failed step output

When an installation step of an Agent 1.4.0 (or later) workflow fails, the Agent reports which step failed, its action, its exit code and the end of its output. The platform shows it in a Failed step output section of the renewal's detail, open by default on a failure, and adds it to the renewal.failure alert:

  • What is captured - the last 8 KiB of standard output and of standard error for a process.execute step; the combined output of a Linux hook.run script (reported as standard output); and the combined output of a legacy plan's installation program. Output that was cut is marked as truncated.
  • Redaction - before the output leaves the device, the Agent replaces every secret it knows of with [redacted]: workflow secrets, protected step inputs (including passwords and environment values), the platform API key, EAB keys, DNS delegation secrets and legacy archive passwords, each also in its base64 forms, followed by patterns that look like credentials. The platform also strips control characters other than newline and tab.
  • Redaction is best effort. A program that encodes, splits or otherwise transforms a secret before printing it is not caught, and values shorter than four bytes are not replaced. Keep scripts from printing secrets, and turn reporting off where output may still contain them: set report_step_output to false for the whole Agent or for one workflow (see Reporting failed step output). The step, action and exit code are still reported.

Each destination shows the end of each stream, with a leading โ€ฆ when it is shortened:

Destination Shown
Generic webhook The whole failure_output object (up to 8,192 characters per stream)
Email The last 4,000 characters of each stream
Slack The last 2,800 characters, both streams in one block
Microsoft Teams The last 4,000 characters, both streams in one block
Discord The last 1,000 characters of each stream, one field each
ntfy The last 2,000 characters, both streams in one block
Pushover The last 300 characters of standard error, only if the message has room

Older Agents, other ACME clients and failures before installation report no step output; their alerts are unchanged.

Digest interval

Each destination has a Digest interval (seconds) (300 seconds to 30 days, default 3600). Every digest category (certificate expiry, expired and revoked certificates, newly discovered certificates, public endpoint failures and invalid certificates, endpoints still serving an old certificate, CRL next-update problems, silent Agents and new Certificate Transparency name sets) is batched into one digest per interval, so a flapping monitor doesn't turn into a flood of notifications. Renewal, deployment-window and sign-in (security) events are sent as they occur and are not throttled by the interval.

Delivery status

A destination's card shows Last success and, after a failed attempt, Last error with the failure class, so you can tell a genuinely broken webhook URL from a destination that simply hasn't fired yet. Use Send test to verify a new destination end to end before relying on it.

Delivery is at least once. A logical delivery keeps the same ID on retry; generic HTTPS webhooks receive it in the Idempotency-Key header and the delivery_id payload field. Store that ID in your receiver and acknowledge a duplicate without repeating its side effect. A network interruption or worker restart after the receiver accepts a request can cause another attempt; a successful remote request is not an exactly-once guarantee.

Your receiver should answer quickly with a small body: CertIntel reads at most 64 KiB of the response and gives up at the configured timeout, recording the delivery as failed. Pushover responses must be JSON.

Scheduled reports

Alerts tell you about a change as it happens. Scheduled reports are the periodic overview: an email that summarises the inventory for one organization or the entire workspace, generated daily, weekly or monthly. Manage them on Settings โ†’ Scheduled Reports (the Alert Settings page links there). The feature shares the alert-destinations plan entitlement, so a plan without alert destinations shows Scheduled reports are not included in this subscription.

A report has:

  • Scope - one organization, or Entire workspace (all organizations) for a tenant-wide holder of scheduled_reports.create.
  • Recipients - 1 to 20 email addresses.
  • Frequency - Daily, Weekly (with a day of week) or Monthly (day of month 1-28), plus Hour (UTC); the default is weekly on Monday at 07:00 UTC.
  • Sections - any of Inventory summary, Expiring, expired and revoked certificates, ACME renewals since the last report, Certificates discovered since the last report, Public endpoint health, CRL distribution points, Agent reporting status, Alert delivery since the last report, Certificate Transparency findings since the last report and Full list of current certificates (at least one).

The Certificate Transparency section counts the name sets first seen since the last report - new, issued by CertIntel, and already in the inventory - and lists the new ones with a link to each finding. It covers only organizations whose plan includes Certificate Transparency monitoring; see CT Log Watch.

"Since the last report" sections cover the period from the previous successful send (or one period back for the first run). Send now generates and sends a report immediately; every generated report is stored and listed under Generated reports, where Re-send delivers the stored copy to the recipients it was generated for. A send that fails is retried every 15 minutes, up to three attempts in total. Stored copies are kept for 400 days by default (a platform setting). Report emails use the same branded layout as alert emails and end with a link back to Scheduled Reports. Like alert emails, they go out one message per recipient with an unsubscribe link, and an address that unsubscribed is skipped.

Permissions are scheduled_reports.read / .create / .update / .delete / .run (run covers Send now and Re-send); the built-in Alert Manager role holds all five, and custom roles can hold any subset. The same operations are available under /api/v1/scheduled-reports (see the API overview).

Security note

A webhook URL is a secret in its own right - anyone who has it can potentially see that your certificates are about to expire, or (for some destination kinds) receive messages formatted to look like they came from your CertIntel deployment. Treat a destination URL with the same care as an API key.