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. |
| 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
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.readto see contacts andalert_contacts.updateto 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.
Unsubscribe links¶
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 asalert.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.failurefor an Agent installation failure carriesfailure_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_overridecarriesdeployment_window_override-reason(expires_before_window),window_opens_at,certificate_expires_atandmargin_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.executestep; the combined output of a Linuxhook.runscript (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_outputtofalsefor 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) |
| 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.