Integrations setup
Integrations can be configured only via the YAML file!
Also, don't forget to restart the Kuvasz container after modifying the YAML file for the changes to take effect!
Don't want your webhook URLs and API keys in your YAML file?
Since integrations are typically full of sensitive data, you might want to check the Keeping secrets out of your configuration file recipe, which shows you how to reference environment variables from your YAML file, or how to move your integrations into a separate, secret file.
Your integrations are the channels through which Kuvasz sends notifications about the status of your monitors. You can use Kuvasz without any integrations, but it won't make much sense in most of the cases, because you won't be notified about any issues with your monitors.
Where to put them exactly?
You're free to put your integrations under integrations: in your YAML configuration file, wherever you like. The only restriction is that under integrations you can only use the integration types that are supported by Kuvasz.
How can they be referenced?
You can reference your integrations in your monitors by their ID, which is always dynamically generated by concatenating the type and name of the integration, separated by a colon (:). For example, if you have a Slack integration with the name slack-example, its ID will be slack:slack-example.
Common settings
All the integrations share some common, generic settings , which means that it doesn't matter which integration you configure, you can use the same settings for all of them.
Name
2.0.0
string
name
The name of the integration. It must be unique across the given type of integration, so you can have multiple Slack integrations, for example, but they must have different names, and vice versa: you can have multiple integrations of different types with the same name. Can't be a blank string!
Enabled
2.0.0
true
boolean
enabled
Whether the integration is enabled or not. If it's set to false, the integration won't be used, and no notifications will be sent through it, however you can still reference it in your monitors.
Global
2.0.0
false
boolean
global
Whether the integration is global or not. If it's set to true, the integration will be used for all monitors by default, even if they don't have a specific integration assigned to them. If it's set to false, the integration will only be used for monitors that explicitly reference it.
Excluded events
3.8.0
empty
list
excluded-events
Integrations are listening to every event by default, but you can configure them to exclude specific events if you don't want to receive notifications for them.
The valid options are the following:
HTTP_UPHTTP_DOWNPUSH_UPPUSH_DOWNSSL_VALIDSSL_INVALIDSSL_WILL_EXPIREICMP_UPICMP_DOWNTCP_UPTCP_DOWNDNS_UPDNS_DOWNDNS_RECORDS_CHANGED
In case you don't specify any event types, or you provide an empty list, the integration will receive all the events.
integrations:
pagerduty:
- name: pd_global
global: true
excluded-events:
- PUSH_DOWN
- PUSH_UP
- SSL_WILL_EXPIRE
integration-key: YourOwnIntegrationKey
Slack
Configuration alias: slack
The Slack integration allows you to send notifications to a Slack channel via a webhook URL.
Webhook URL
2.0.0
string
webhook-url
The webhook URL of the Slack channel where the notifications will be sent. You can create a webhook URL in your Slack workspace by following the official documentation.
integrations:
slack:
- name: slack-example
webhook-url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXX'
- name: slack-global
webhook-url: 'https://hooks.slack.com/services/T00000000/B00000000/XXXXXXXXXXXXXXXX'
global: true
# ... other Slack integrations
Discord
Configuration alias: discord
The Discord integration allows you to send notifications to a Discord channel via a webhook URL.
Webhook URL
2.3.0
string
webhook-url
The webhook URL of the Discord channel where the notifications will be sent. You can create a webhook URL in your Discord server by following these steps:
- Go to your Discord server settings
- Navigate to Integrations → Webhooks
- Click New Webhook
- Configure the webhook name and select the target channel
- Copy the Webhook URL
For more information, see the official Discord documentation.
integrations:
discord:
- name: discord-example
webhook-url: 'https://discord.com/api/webhooks/123456789/abcdef1234567890abcdef1234567890'
- name: discord-global
webhook-url: 'https://discord.com/api/webhooks/987654321/fedcba0987654321fedcba0987654321'
global: true
# ... other Discord integrations
Microsoft Teams
Configuration alias: ms-teams
The Microsoft Teams integration sends notifications to a Teams channel or chat as an Adaptive Card, color-coded by the severity of the event.
Workflows only, not the retired Microsoft 365 Connectors
Microsoft is retiring Microsoft 365 (Office 365) Connectors, so their https://<tenant>.webhook.office.com/...
URLs are not supported. Use the Workflows app (powered by Power Automate) instead, as described below.
Webhook URL
4.3.0
string
webhook-url
The URL of the Teams workflow the notifications will be sent to. To create one:
- In Microsoft Teams, go to the team and channel where you want to receive the notifications
- Select More options (...) next to the channel, then Workflows
- Search for and select the Send webhook alerts to a channel template
- Configure the workflow parameters, then select Save
- Copy the webhook URL the workflow generated
For more information, see the official documentation.
Treat the URL as a secret
Anyone who has the URL can post messages to the channel, since it carries its own signature and needs no further authentication. Check the examples on how to keep it out of your configuration file.
integrations:
ms-teams:
- name: ms-teams-example
webhook-url: 'https://prod-11.westeurope.logic.azure.com:443/workflows/.../triggers/manual/paths/invoke?...'
- name: ms-teams-global
webhook-url: 'https://prod-22.westeurope.logic.azure.com:443/workflows/.../triggers/manual/paths/invoke?...'
global: true
# ... other Microsoft Teams integrations
A successful request doesn't guarantee a delivered message
The workflow's trigger accepts the request eagerly, answering with an empty 202 Accepted before the
flow itself runs. Kuvasz therefore logs the notification as sent even when the flow fails afterwards, for
example because it was turned off. If a card never shows up in the channel despite a successful test, check
the run history of the workflow in Power Automate.
Apprise
Configuration alias: apprise
Apprise API is a self-hosted REST gateway that forwards a single notification to 80+ services at once - Slack, Discord, Telegram, ntfy, Gotify, Matrix, Pushover, email, SMS providers and many more. Instead of configuring each of them in Kuvasz separately, you can hand the notification to Apprise and let it fan out.
The notifications are sent with a title, a body and a type that carries the severity of the event, which Apprise translates to whatever the target service understands: the color of a Discord embed, the priority of an ntfy message, or the icon of a desktop notification.
| Event | Apprise type |
|---|---|
| A monitor or a certificate recovered, a maintenance window ended | success |
| A monitor went down, a certificate became invalid | failure |
| A certificate is about to expire | warning |
| DNS records drifted, a maintenance window started | info |
URL
4.3.0
string
url
The notify endpoint of your Apprise API instance. Apprise can be used in two ways, and this URL decides which one you get:
- Stateful: you store your service URLs in Apprise under a key (e.g.
POST /add/kuvasz), then point Kuvasz athttp://your-apprise-host:8000/notify/kuvasz. No secrets end up in the Kuvasz configuration, which is why this is the recommended setup. - Stateless: you point Kuvasz at
http://your-apprise-host:8000/notifyand list the target services intarget-urlsinstead. Nothing is persisted on the Apprise side, so it needs no volume.
Target URLs
4.3.0
empty
list
target-urls
The Apprise service URLs the notifications should be delivered to, for the stateless mode. Leave it empty when you use a stored configuration.
Every entry is an Apprise URL, not a regular one - slack://TokenA/TokenB/TokenC, tgram://bottoken/ChatID,
ntfy://topic, and so on. The full list of the supported formats is in the
Apprise wiki.
Treat these URLs as secrets
Apprise service URLs embed the tokens of the target services, so anyone who has them can post messages in your name. Check the examples on how to keep them out of your configuration file, or avoid the problem entirely by using the stateful mode.
Tag
4.3.0
string
tag
Routes the notifications to a subset of a stored Apprise configuration, for the stateful mode. Only makes sense if the entries of your configuration are tagged.
Apprise has its own little grammar here, where a comma means OR and a space means AND:
| Value | Matches |
|---|---|
devops |
the entries tagged devops |
devops, oncall |
the entries tagged devops or oncall |
devops critical |
the entries tagged devops and critical |
devops critical, oncall |
the entries tagged (devops and critical) or oncall |
all |
every entry, tagged or not |
Leaving it empty does not mean everything
When no tag is given, Apprise matches the notification against the untagged entries only. So if every
entry of your stored configuration is tagged, nothing is delivered and Apprise answers with a
424 Failed Dependency, which shows up as a failed notification in the Kuvasz logs.
Set tag: all to reach every entry regardless of its tags.
Note that this only affects the stateful mode: on the stateless endpoint Apprise itself defaults to
all, so the same Kuvasz configuration behaves differently in the two modes.
Request headers
4.3.0
empty
map
request-headers
Optional HTTP headers that will be included in the requests sent to your Apprise instance.
Apprise API ships no authentication of its own, so unlike a Slack or a Discord webhook URL - which carries its own signature - an Apprise endpoint is only as protected as the network it sits on. If you put yours behind a reverse proxy that requires a token, you can pass it here.
integrations:
apprise:
# Stateful: the target services are stored in Apprise under the "kuvasz" key
- name: apprise-example
url: 'http://your-apprise-host:8000/notify/kuvasz'
# ...routing to a subset of that stored configuration
- name: apprise-devops
url: 'http://your-apprise-host:8000/notify/kuvasz'
tag: 'devops, oncall'
global: true
# Stateless: the target services travel in every request
- name: apprise-stateless
url: 'http://your-apprise-host:8000/notify'
target-urls:
- 'slack://TokenA/TokenB/TokenC'
- 'tgram://bottoken/ChatID'
# ... other Apprise integrations
Pushover
Configuration alias: pushover
Pushover delivers push notifications to your phone, tablet and desktop, without you having to run anything yourself.
The notifications carry a title that names the monitor or the maintenance window the event belongs to, and a body that leads with the summary of the event, followed by its details. The severity decides the priority, which is what tells Pushover whether the notification is allowed to break through the quiet hours of the recipient.
| Event | Priority |
|---|---|
| A monitor went down, a certificate became invalid | 1 (high), or 2 (emergency, if enabled) |
| Everything else | 0 (normal) |
Getting your user key and API token
- Sign up at pushover.net and copy your User Key from the dashboard. This is
your
user-key. A group key works just as well, if you want to notify a whole team. - Create a new application at the bottom of the dashboard, under Your Applications. The token you get
there is your
api-token.
API token
4.3.0
string
api-token
The API token of the Pushover application that sends the notifications. You get it when you register a new application on the Pushover dashboard.
User key
4.3.0
string
user-key
The user key or group key the notifications are delivered to. Your user key is on your Pushover dashboard; a group key comes from a delivery group, and lets you notify several people with one integration.
Device
4.3.0
empty
string
device
Limits the delivery to specific devices instead of every device of the user. Separate the device names with commas, exactly as Pushover expects them:
Leave it empty to reach every device, which is what you usually want for an uptime alert.
Sound
4.3.0
empty
string
sound
The notification sound to play, instead of the recipient's default. The list of the available names is in the
Pushover API documentation - siren, alien and persistent are the
ones that stand out from an ordinary notification.
Emergency priority
4.3.0
false
boolean
emergency-enabled
Sends the critical events with emergency priority (2), which makes Pushover repeat the notification
until someone acknowledges it. Only the events that would otherwise get the high priority are escalated: a
monitor going down, and a certificate becoming invalid. Recoveries, expiry warnings, DNS drift, maintenance
windows and the test notification are never escalated.
Kuvasz calls the alert off when the monitor recovers
You don't have to acknowledge an emergency notification just because the service came back on its own. When the monitor recovers - or the certificate becomes valid again - Kuvasz cancels the outstanding notification for you, and the repeating stops.
It does that without storing anything: the notification is tagged with an identifier derived from the monitor
(kuvasz_uptime_<monitor id> and kuvasz_ssl_<monitor id>), and the recovery cancels that same tag.
Two consequences are worth knowing about:
- If you exclude the recovery event of a monitor with
excluded-events, there is nothing left to trigger the cancellation, so the notification keeps repeating until it expires.
Emergency retry seconds
4.3.0
60
integer
emergency-retry-seconds
How often an emergency notification is repeated, in seconds. Only has an effect when
emergency-enabled is turned on. Pushover requires at least 30 seconds here, so
Kuvasz refuses to start with anything lower.
Emergency expire seconds
4.3.0
1800
integer
emergency-expire-seconds
How long Pushover keeps repeating an unacknowledged emergency notification, in seconds. Only has an effect
when emergency-enabled is turned on. The maximum is 10800 seconds (3 hours), and
Kuvasz refuses to start above it. Pushover stops after 50 attempts regardless of this value.
integrations:
pushover:
# The simplest setup: every device of the user, default sound
- name: pushover-example
api-token: 'YourApplicationToken'
user-key: 'YourUserKey'
global: true
# An on-call setup that nags until someone acknowledges it, but calls itself off on recovery
- name: pushover-oncall
api-token: 'YourApplicationToken'
user-key: 'YourGroupKey'
sound: 'siren'
emergency-enabled: true
emergency-retry-seconds: 60
emergency-expire-seconds: 1800
# ... other Pushover integrations
Configuration alias: email
The email integration allows you to send notifications via email. You can have multiple email integrations, each with its own sender and recipient addresses.
Warning
To make the email integration work, it's not enough to just configure the integration itself, you also need to set up the SMTP configuration. You can have multiple email integrations, but they will all use the same SMTP configuration.
For more information, see the SMTP configuration section of the documentation.
From address
2.0.0
string
from-address
The email address from which the notifications will be sent. This is the address that will appear in the "From" field of the email.
To address
2.0.0
string
to-address
The email address to which the notifications will be sent.
integrations:
email:
- name: email_implicitly_enabled
from-address: noreply@kuvasz-uptime.dev
to-address: your@email.address
- name: email_disabled
from-address: noreply@other-sender.com
to-address: other-recipient@blabla.com
enabled: false
# ... other email integrations
PagerDuty
Configuration alias: pagerduty
The PagerDuty integration allows you to trigger incidents in PagerDuty when a monitor goes down, and to automatically resolve them when the monitor comes back up.
Things to do in PagerDuty first
- From the Configuration menu, select Services.
- There are two ways to add an integration to a service:
- If you are adding your integration to an existing service: Click the name of the service you want to add the integration to. Then, select the Integrations tab and click the New Integration button.
- If you are creating a new service for your integration: Please read our documentation in section Configuring Services and Integrations and follow the steps outlined in the Create a New Service section, selecting "Kuvasz" as the Integration Type in step 4. Continue with the "In Kuvasz" section (below) once you have finished these steps.
- Enter an Integration Name in the format
monitoring-tool-service-name(e.g. Kuvasz-Your-Service) and select "Kuvasz" from the Integration Type menu. - Click the Add Integration button to save your new integration. You will be redirected to the Integrations tab for your service.
- An Integration Key will be generated on this screen. Keep this key saved in a safe place, as it will be used when you configure the integration with Kuvasz in the next section.

Integration Key
2.0.0
string
integration-key
The integration key of the PagerDuty service where the incidents will be created. You can find this key in your PagerDuty service settings.
integrations:
pagerduty:
- name: pd_global
integration-key: YourOwnIntegrationKey
global: true
- name: pd_disabled
integration-key: YourOtherIntegrationKey
enabled: false
# ... other PagerDuty integrations
Telegram
Configuration alias: telegram
The Telegram integration allows you to send notifications to a Telegram chat via a bot.
Getting your bot token and chat ID
- Create a new bot by talking to the BotFather on Telegram.
- After creating the bot, you will receive a bot token, this will be your
api-token. - Invite your bot to the chat where you want to receive notifications, or create a new group and add the bot to it.
-
To get your chat ID, send a message to your desired chat and then visit
https://api.telegram.org/bot<YourApiToken>/getUpdatesin your browser, where<YourApiToken>is the token you received from the BotFather. Look for something like this in the response, this will be yourchat-id:
API token
2.0.0
string
api-token
The API token of the Telegram bot that will send the notifications. You can get this token from the BotFather when you create your bot.
Chat ID
2.0.0
string
chat-id
The chat ID of the Telegram chat where the notifications will be sent. You can get this ID by following the steps outlined in the Getting your bot token and chat ID section.
integrations:
telegram:
- name: telegram_global
api-token: 'YourToken'
chat-id: '-1232642423121'
global: true
- name: telegram_disabled
api-token: 'YourOtherToken'
chat-id: '-1232546142423121'
enabled: false
# ... other Telegram integrations
Webhooks
Configuration alias: webhook
The Webhook integration allows you to send notifications to any endpoint that can receive HTTP requests. You can use it to integrate with 3rd party services that are not natively supported by Kuvasz, or to implement custom notification logic within your own infrastructure.
Warning
Make sure that your target endpoint handles the configured HTTP method and is able to process the payload sent by Kuvasz. Otherwise, you might end up with failed notifications and missed alerts.
The generic webhook message (if you don't use a custom template) has the following structure:
{
"monitorId": "234 (6)",
"monitorUrn": "http:GitHub API (1)",
"monitorName": "GitHub API (2)",
"monitorDetailsUrl": "/http-monitors/1 (7)",
"timestamp": "1777661064488 (3)",
"type": "HTTP_DOWN (4)",
"eventDetails": "Your monitor \"GitHub API\" (https://api.github.com) is DOWN. Reason: Connect Error: Connection refused: api.github.com (5)"
}
- monitorUrn: A unique identifier of a monitor, formatted as 'type:name'.
- monitorName: The name of the monitor, which must be unique.
- timestamp: The timestamp of the event that triggered the webhook, in milliseconds since the Unix epoch.
- type: The type of the event that triggered the webhook, which can be one of the following values:
HTTP_UP,HTTP_DOWN,PUSH_UP,PUSH_DOWN,ICMP_UP,ICMP_DOWN,TCP_UP,TCP_DOWN,DNS_UP,DNS_DOWN,DNS_RECORDS_CHANGED,SSL_VALID,SSL_INVALID,SSL_WILL_EXPIRE. - eventDetails: A human-readable message with more details about the event.
- monitorId: A unique, numeric ID of a monitor.
- monitorDetailsUrl: The relative URL to the monitor details page in the Kuvasz web interface.
GenericWebhookMessage:
required:
- monitorId
- monitorUrn
- monitorName
- monitorDetailsUrl
- timestamp
- type
- eventDetails
type: object
properties:
monitorId:
type: integer
format: int64
monitorUrn:
type: string
monitorName:
type: string
monitorDetailsUrl:
type: string
timestamp:
type: integer
format: int64
type:
type: string
enum:
- HTTP_UP
- HTTP_DOWN
- PUSH_UP
- PUSH_DOWN
- ICMP_UP
- ICMP_DOWN
- TCP_UP
- TCP_DOWN
- DNS_UP
- DNS_DOWN
- DNS_RECORDS_CHANGED
- SSL_VALID
- SSL_INVALID
- SSL_WILL_EXPIRE
eventDetails:
type: string
Header & payload templates
Kuvasz uses the Pebble templating engine, so you can use all the features provided by Pebble in your templates, including conditionals, loops, filters, and more. Pebble is very similar to Twig (PHP) and Jinja (Python) in order to make it easy to use and understand, even if you didn't work with a JVM templating engine before.
For further information on how to use Pebble templates, please refer to the official documentation.
Strict variables
Keep in mind that template variables are handled in a strict way, which means that if you try to use a variable that is not available in the context, or if you make a typo in the variable name, the template rendering will fail and the request won't be sent. So make sure to double-check your templates and test them before using them in production.
Available context variables
The context variables are available in an object named ctx, and the structure is the same as the generic webhook message described above, so for example you can use {{ctx.monitorName}} to include the name of the monitor in your payload, or {{ctx.type}} to include the type of the event that triggered the webhook.
Having conflicting characters in your hard-coded headers?
In case your template would contain some characters that interfere with Pebble's own syntax, you can use the {% verbatim %} tag to bypass parsing them, like this:
URL
3.8.0
string
url
The URL of the endpoint where the notifications will be sent. This can be any URL that can receive HTTP requests, for example, an API endpoint of a 3rd party service, or an endpoint of your own backend.
Starting from version 3.11.0, you can also use templates in the URL, which allows you to construct dynamic endpoint URLs based on the context of the event that triggered the webhook. For example, you can route notifications to different paths based on the event type:
Request headers
3.8.0
map
request-headers
Optional HTTP headers that will be included in the requests sent to the target URL. This can be useful, for example, to include an Authorization header if the target endpoint requires authentication.
The only header that is always included in the requests is the Content-Type header, which is set to application/json by default, but you can override it with your own value if needed.
Starting from version 3.9.0, you can also use templates in the header values, which allows you to include dynamic information in the headers based on the context of the event that triggered the webhook. For example, you can include the monitor name or the event type in a custom header by using a template like this:
HTTP method
3.11.0
POST
string
http-method
The HTTP method used when sending requests to the target URL. The valid options are POST, PUT, PATCH, and GET. Defaults to POST if not specified, which is the correct choice for most services. Use PUT or PATCH when your target endpoint explicitly requires it. Use GET for endpoints that only accept GET requests — note that in this case the payload will not be sent as a request body.
integrations:
webhook:
- name: matrix
url: 'http://your-matrix-webhook-host:4785/!roomid:your-homeserver/your-shared-token'
http-method: PUT
Payload template
3.8.0
string
payload-template
You can customize the payload of the requests sent to the target URL by providing a payload template. This template can include any of the available context variables, which will be replaced with their actual values when the request is sent. This allows you to create custom payloads that fit the requirements of your target endpoint.
webhook:
- name: webhook_templated
url: https://any-other-http.service/webhooks
http-method: POST
excluded-events:
- PUSH_UP
- HTTP_UP
- SSL_WILL_EXPIRE
request-headers:
Accept: '*/*'
Authorization: Bearer your-webhook-secret-token
X-Custom-Header: custom-value
payload-template: |
{
"monitorName": "{{ctx.monitorName}}",
"type": "{{ctx.type}}"
}
- name: webhook_put
url: https://any-other-http.service/resource/123
http-method: PUT
payload-template: |
{
"monitorName": "{{ctx.monitorName}}",
"type": "{{ctx.type}}"
}
# ... other Webhook integrations
Webhook examples
Here are some examples of webhook configurations that you can use for different 3rd party services as a starting point. Kuvasz is using Pebble as a templating engine under the hood, for further information on how to use Pebble templates, please refer to the official documentation.
Sharing is caring!
Did you make a cool webhook configuration that you would like to share with the community? Feel free to open a PR on GitHub with your example, and we will add it to the documentation!
Signal (via signal-cli-rest-api)
This example sends notifications to a Signal chat using signal-cli-rest-api — a self-hosted, dockerized REST wrapper around signal-cli. You need a dedicated Signal number registered with the container (see the project's README for setup).
integrations:
webhook:
- name: signal
url: 'http://your-signal-api-host:8080/v2/send'
payload-template: |
{
"message": "{{ ctx.eventDetails | escape(strategy="js") }}",
"number": "+15550001234",
"recipients": ["+15550005678"]
}
Twilio — SMS
This example sends an SMS via the Twilio Messaging API.
Content type
Twilio's Messaging API requires application/x-www-form-urlencoded payloads, not JSON. The example below overrides the default Content-Type header accordingly, and uses escape(strategy="url_param") to URL-encode the dynamic message body.
Twilio setup:
- Log in to the Twilio Console.
- On the dashboard, note your Account SID and Auth Token.
- Make sure you have a Twilio phone number capable of sending SMS. You can get one under Phone Numbers → Manage → Buy a number.
-
Compute your Base64-encoded credentials by running the following command, then copy the output:
integrations:
webhook:
- name: twilio-sms
url: 'https://api.twilio.com/2010-04-01/Accounts/ACxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/Messages.json'
request-headers:
Content-Type: "application/x-www-form-urlencoded"
Authorization: "Basic <your-base64-encoded-credentials>"
payload-template: |
From=%2B15551234567&To=%2B15550005678&Body={{ ctx.eventDetails | escape(strategy="url_param") }}
Replace %2B15551234567 with your Twilio number and %2B15550005678 with the recipient number — both with the leading + pre-encoded as %2B.
ntfy
This example sends notifications to an ntfy topic — a lightweight, self-hostable push notification service. ntfy supports both the hosted ntfy.sh server and self-hosted instances.
integrations:
webhook:
- name: ntfy_test
url: https://ntfy.sh
payload-template: |
{
"topic": "kuvasz_uptime_test",
"message": "{{ ctx.eventDetails | escape(strategy="js") }}",
"title": "Kuvasz Uptime Alert",
"tags": [ "rotating_light" ],
"priority": 4,
"attach": null,
"filename": null,
"click": null,
"actions": [ { "action": "view", "label": "View details", "url": "https://demo.kuvasz-uptime.dev{{ctx.monitorDetailsUrl}}" } ]
}
Pushover
Pushover has a first-class integration since version 4.3.0...
... so there is no need to hand-craft a webhook payload for it anymore. See the Pushover section above: it sends a proper title, body and priority, it can escalate an outage to the emergency priority, and it calls that alert off by itself once the monitor recovers.
Home Assistant — webhook automation
This example triggers a Home Assistant webhook automation when a monitor event occurs, letting you react to uptime events natively within Home Assistant — for example, to send a mobile notification, toggle a switch, or run a script.
Tip
If you want to read monitor data from Kuvasz instead of receiving push events, see the official Home Assistant integration.
Home Assistant setup:
- Go to Settings → Automations & Scenes → Automations and click + Create automation.
- Select "Create new automation" and add a Webhook trigger. Copy the generated, secure webhook ID and make sure POST is listed under Allowed HTTP methods. The resulting webhook URL is something like:
http://your-ha-instance:8123/api/webhook/yourVerySecretWebhookId - Add any actions you like, and save the automation.
The fields from the Kuvasz payload are available in Home Assistant automation templates via trigger.json, for example:
| Kuvasz field | Home Assistant template |
|---|---|
type |
{{ trigger.json.type }} |
monitorName |
{{ trigger.json.monitorName }} |
message |
{{ trigger.json.message }} |
integrations:
webhook:
- name: home-assistant
url: 'http://your-ha-instance:8123/api/webhook/yourVerySecretWebhookId'
payload-template: |
{
"type": "{{ ctx.type }}",
"monitorName": "{{ ctx.monitorName | escape(strategy="js") }}",
"message": "{{ ctx.eventDetails | escape(strategy="js") }}"
}
Webhook ID is the secret
Home Assistant webhook triggers don't require an Authorization header — the webhook ID itself acts as the shared secret. Keep it reasonably hard to guess and, where possible, restrict external access to the endpoint via your firewall or reverse proxy.
Google Chat
This example posts a message to a Google Chat space via an incoming webhook.
Google Chat setup:
- Open the target space in Google Chat and click the space name at the top.
- Go to Integrations → Webhooks → Add webhook.
- Give the webhook a name (e.g. Kuvasz) and click Save. Copy the generated Webhook URL.
integrations:
webhook:
- name: google-chat
url: 'https://chat.googleapis.com/v1/spaces/SPACE_ID/messages?key=KEY&token=TOKEN'
payload-template: |
{
"text": "{{ ctx.eventDetails | escape(strategy="js") }}"
}
Apprise API
Apprise has a first-class integration since version 4.3.0...
... so there is no need to hand-craft a webhook payload for it anymore. See the Apprise section above: it sends a proper title, body and severity, and it supports both the stateful and the stateless mode.
Mattermost
This example posts a message to a Mattermost channel via an incoming webhook. Mattermost's webhook format is compatible with Slack's, so the payload is identical.
Mattermost setup:
- In Mattermost, go to Main menu → Integrations → Incoming webhooks → Add incoming webhook.
- Select the target channel, give the webhook a display name, and click Save.
- Copy the generated webhook URL.
Incoming webhooks may be disabled
If you don't see the Integrations menu, ask your Mattermost system administrator to enable incoming webhooks.
integrations:
webhook:
- name: mattermost
url: 'https://your-mattermost-instance/hooks/your_webhook_token'
payload-template: |
{
"text": "{{ ctx.eventDetails | escape(strategy="js") }}"
}
You can also target a different channel than the one set during webhook creation, set a custom username, or override the icon — all via standard Mattermost payload fields:
integrations:
webhook:
- name: mattermost-custom
url: 'https://your-mattermost-instance/hooks/your_webhook_token'
payload-template: |
{
"channel": "town-square",
"username": "Kuvasz",
"icon_url": "https://kuvasz-uptime.dev/images/kuvasz-logo.webp",
"text": "{{ ctx.eventDetails | escape(strategy="js") }}"
}
Rocket.Chat
This example posts a message to a Rocket.Chat channel via an incoming webhook. Like Mattermost, Rocket.Chat uses a Slack-compatible webhook format.
Rocket.Chat setup:
- Go to Administration → Integrations → New and select Incoming webhook.
- Set Enabled to
true, choose the target channel, and give the integration a name. - Click Save and copy the generated webhook URL.
integrations:
webhook:
- name: rocketchat
url: 'https://your-rocketchat-instance/hooks/your_token/your_secret'
payload-template: |
{
"text": "{{ ctx.eventDetails | escape(strategy="js") }}"
}
Rocket.Chat supports the same optional fields as Mattermost (channel, username, icon_url, icon_emoji) so you can use the same overrides shown in the Mattermost example above.
Testing integrations
It's vital to ensure that your integrations are correctly set up to receive notifications. You can test your integrations (even the disabled ones) directly either:
- From the web interface by navigating to the Integrations page and clicking the button next to the integration you want to test. In this case you'll see the result in a visual way, at the same place where you initiated the test.
- Via the API by sending a
POSTrequest to/api/v2/integrations/{integrationId}/test, where{integrationId}is the ID of the integration you want to test (for example,slack:your-desired-name). In this case the payload of the response should be straightforward to understand whether the test was successful or not.
Testing PagerDuty integrations
Please note that when testing PagerDuty integrations, a real incident will be created in your account, which will be immediately resolved by Kuvasz.
Testing webhook integrations
When you test a Webhook integration, a separate test message will be generated and sent for every event type that the integration watches, so for example if you have an integration that watches both HTTP_UP and HTTP_DOWN events, you will receive two separate messages in your target endpoint when you test the integration: one for the UP event and one for the DOWN event. The "down" events will be always fired first to simulate a real downtime scenario, and the "up" events will be fired immediately after to simulate the recovery of the monitor.
Do you miss an integration?
If you miss an integration, please open an issue, or consider contributing it yourself! We are always open to new integrations and would love to see your contribution.

