The Gap Between Zabbix Alerts and the Right Person
Zabbix is excellent at detecting problems. It watches your hosts, evaluates triggers, and fires notifications the moment something crosses a threshold. What it does not do is figure out who should be woken up at 2 a.m., escalate if that person does not respond, or track the incident through resolution.
The standard workaround is to point all Zabbix media at a team email address or a shared Slack channel. That works until it does not — when the channel is noisy, when the on-call rotation changes and nobody updates the user media config, or when a severity-5 database failure gets the same treatment as a warning about disk space.
Wiring Zabbix to Alert24 via webhook closes that gap without replacing either tool. Zabbix keeps doing what it does. Alert24 handles the on-call schedule, escalation policy, and incident lifecycle.
How the Integration Works
When a Zabbix trigger fires, it evaluates which users have media configured and sends them a notification. Instead of configuring media on individual users, you create a single webhook media type that posts to Alert24's inbound webhook endpoint. Alert24 receives the payload, maps the severity to a priority, applies your routing rules, and pages the engineer on call.
The flow looks like this:
- Zabbix trigger enters PROBLEM state
- Zabbix evaluates actions and finds a media type with your webhook script
- Script runs in Zabbix's JavaScript sandbox, POSTs JSON to Alert24
- Alert24 matches the payload against routing rules (host group, service tag, or custom field)
- Alert24 notifies the on-call engineer via SMS, phone call, push, or email
- If no acknowledgment, Alert24 escalates to the next tier
Recovery events follow the same path — Zabbix sends a RECOVERY notification, Alert24 auto-resolves the open incident.
Creating the Webhook Media Type in Zabbix
In Zabbix, go to Administration > Media types and click Create media type. Set the type to Webhook.
The script runs in Zabbix's Duktape JavaScript engine. It has access to the built-in CurlHttpRequest object for outbound HTTP.
var Alert24 = {
endpoint: 'https://app.alert24.com/api/v1/inbound/{YOUR_INTEGRATION_KEY}',
severityMap: {
'0': 'info', // Not classified
'1': 'low', // Information
'2': 'low', // Warning
'3': 'medium', // Average
'4': 'high', // High
'5': 'critical' // Disaster
},
send: function(payload) {
var req = new CurlHttpRequest();
req.AddHeader('Content-Type: application/json');
req.AddHeader('Accept: application/json');
var resp = req.Post(Alert24.endpoint, JSON.stringify(payload));
if (req.Status() !== 200 && req.Status() !== 202) {
throw 'Alert24 returned HTTP ' + req.Status() + ': ' + resp;
}
return resp;
}
};
try {
var params = JSON.parse(value);
var payload = {
title: params.subject,
message: params.message,
priority: Alert24.severityMap[params.severity] || 'medium',
source: 'zabbix',
host: params.host,
host_groups: params.host_groups,
event_id: params.event_id,
trigger_id: params.trigger_id,
event_value: params.event_value, // 1 = PROBLEM, 0 = RECOVERY
tags: params.tags // Zabbix event tags as key:value string
};
return Alert24.send(payload);
} catch (error) {
throw 'Alert24 webhook failed: ' + error;
}
Under Parameters, define the variables the script reads from value. Zabbix passes these as a JSON object assigned to the value variable:
| Parameter name | Value (Zabbix macro) |
|---|---|
subject |
{ALERT.SUBJECT} |
message |
{ALERT.MESSAGE} |
severity |
{EVENT.SEVERITY.NUM} |
host |
{HOST.NAME} |
host_groups |
{HOST.GROUPS} |
event_id |
{EVENT.ID} |
trigger_id |
{TRIGGER.ID} |
event_value |
{EVENT.VALUE} |
tags |
{EVENT.TAGS} |
Replace {YOUR_INTEGRATION_KEY} in the endpoint URL with the key from your Alert24 integration settings.
Severity Mapping
Zabbix uses six severity levels numbered 0 through 5. Alert24 uses a four-level priority model. The mapping in the script above is a reasonable starting point, but you may want to adjust it based on how your team actually triages:
| Zabbix severity | Zabbix label | Alert24 priority |
|---|---|---|
| 0 | Not classified | info |
| 1 | Information | low |
| 2 | Warning | low |
| 3 | Average | medium |
| 4 | High | high |
| 5 | Disaster | critical |
If your organization treats Average-level triggers as high-priority (common in production database environments), change '3' to 'high' in the map. Alert24's routing rules can also filter by priority, so you could route critical to an immediate phone call and medium to a push notification only.
Configuring the Zabbix Action
The media type script only handles the HTTP call. You still need a Zabbix action that decides when to invoke it.
Go to Configuration > Actions > Trigger actions and create a new action. Set the conditions to match the scope you want — all hosts, a specific host group, or triggers above a certain severity. In the Operations tab:
- Operation type: Send message
- Send to users: A dedicated user (e.g.,
alert24-webhook) with only this media type configured - Send only to: Your webhook media type
For the Recovery operations tab, add the same operation. When Zabbix sends the recovery notification, {EVENT.VALUE} will be 0, and the script passes that through to Alert24 in the event_value field. Configure your Alert24 integration to auto-resolve incidents when it receives a payload with event_value: 0.
Routing Rules in Alert24
Once the payload arrives, Alert24 applies routing rules to determine which escalation policy (and therefore which on-call schedule) handles the incident.
Routing rules match on any field in the incoming payload. The most common patterns for Zabbix:
By host group — Zabbix's {HOST.GROUPS} macro returns a comma-separated list. You can write a routing rule that matches when host_groups contains "Database Servers" and routes to your DBA on-call schedule.
By event tag — If you tag Zabbix triggers with a service tag (e.g., service:payments), the tag lands in the tags field of the payload. Route on tags contains "service:payments" to hit the payments team escalation policy.
By priority — Use Alert24's priority field as a catch-all tier. Anything that does not match a more specific rule can fall through to a default policy based on critical vs. medium.
Rules evaluate in order. The first match wins. Keep your most specific rules at the top.
Testing Before You Go Live
Before enabling the action in production, use Zabbix's Test button on the media type configuration screen. It lets you supply dummy parameter values and fire a real HTTP request so you can confirm the payload reaches Alert24 and the integration key is valid.
On the Alert24 side, check the Incident log — even test payloads that do not match a routing rule will appear there with a "no matching rule" status, which is useful for debugging field names and values before you write routing conditions.
Once you are satisfied, enable the Zabbix action and trigger a test alert on a non-production host to confirm the end-to-end path: trigger fires, webhook executes, Alert24 receives, routing rule matches, engineer gets paged.
Next Steps
If your Zabbix instance monitors dozens of host groups across different teams, start with one group and one escalation policy before rolling out globally. That gives you a chance to tune severity mapping and routing rules based on real alert volume before the configuration affects every team.
From there, you can build out Alert24 with on-call schedules for each team, multi-tier escalation policies (primary, then secondary, then manager), and a status page that updates automatically when a critical incident opens. Zabbix detects and reports; Alert24 routes, escalates, and tracks through resolution.