Zabbix Knows Something Is Wrong. It Just Won't Remember.
Zabbix is excellent at detecting problems. You can write nuanced trigger expressions, correlate events across hosts, and get visibility into nearly anything running in your environment. What it does not do is manage the incident lifecycle that follows a trigger fire.
When a trigger fires, Zabbix logs the event and sends a notification. What happens next is largely up to your team: who's on-call, whether someone acknowledged it, how long it took to resolve, and whether a post-incident review ever happened. Zabbix stores event history, but it has no concept of MTTR, acknowledgment workflows, on-call rotations, or a timeline you can hand to stakeholders after the fact.
That gap is where incident management tools fit. The good news is that Zabbix's webhook media type lets you close this gap without replacing Zabbix or building a custom integration from scratch.
How Zabbix Webhooks Work
Zabbix supports JavaScript-based webhook media types. When an action fires (trigger problem, trigger recovery), Zabbix runs your script with a set of predefined macro variables: the trigger name, severity, event ID, host information, and whether this is a problem or a recovery event.
Your script can call any HTTP API. Alert24 exposes an incidents API that accepts a POST to create an incident and a PUT to resolve it. You can use Zabbix's EVENT.ID as a stable alias so that Zabbix's recovery notification finds and closes the same incident that the problem notification opened.
The flow looks like this:
| Zabbix Event | API Call | Effect |
|---|---|---|
| Trigger fires (PROBLEM) | POST /v1/incidents with alias set to EVENT.ID |
Alert24 creates incident, pages on-call team |
| Trigger recovers (OK) | POST /v1/incidents with same alias, status = resolved |
Alert24 resolves the incident, logs MTTR |
Alert24 deduplicates on the alias field, so if the same trigger fires twice before recovering, you get one incident, not two.
Setting Up the Webhook Media Type
In Zabbix, go to Administration > Media types > Create media type. Set the type to Webhook.
Add the following parameters — these map Zabbix macros to variables your script can reference:
| Parameter name | Value |
|---|---|
alert_subject |
{TRIGGER.NAME} |
alert_message |
{ALERT.MESSAGE} |
event_id |
{EVENT.ID} |
event_value |
{EVENT.VALUE} |
trigger_severity |
{TRIGGER.SEVERITY} |
host_name |
{HOST.NAME} |
alert24_api_key |
(your Alert24 API key) |
alert24_service_id |
(your Alert24 service ID) |
EVENT.VALUE is 1 for a problem and 0 for a recovery. Your script branches on this value to decide whether to create or resolve the incident.
The Full Webhook Script
Paste this into the Script field of your media type:
var params = JSON.parse(value);
var apiKey = params.alert24_api_key;
var serviceId = params.alert24_service_id;
var eventId = params.event_id;
var eventValue = parseInt(params.event_value);
var subject = params.alert_subject;
var message = params.alert_message;
var hostName = params.host_name;
var severity = params.trigger_severity;
var baseUrl = 'https://app.alert24.io/v1/incidents';
var request = new HttpRequest();
request.addHeader('Content-Type: application/json');
request.addHeader('Authorization: Bearer ' + apiKey);
var body;
var response;
if (eventValue === 1) {
// Trigger fired — create or re-open the incident
body = JSON.stringify({
service_id: serviceId,
title: subject,
description: '[' + hostName + '] ' + message,
severity: severity.toLowerCase(),
alias: 'zabbix-' + eventId,
status: 'open'
});
response = request.post(baseUrl, body);
if (request.getStatus() !== 200 && request.getStatus() !== 201) {
throw 'Alert24 incident creation failed: HTTP ' + request.getStatus() + ' — ' + response;
}
} else if (eventValue === 0) {
// Trigger recovered — resolve the incident by alias
body = JSON.stringify({
service_id: serviceId,
alias: 'zabbix-' + eventId,
status: 'resolved',
resolution_note: 'Resolved automatically by Zabbix trigger recovery.'
});
response = request.post(baseUrl + '/resolve-by-alias', body);
if (request.getStatus() !== 200 && request.getStatus() !== 204) {
throw 'Alert24 incident resolution failed: HTTP ' + request.getStatus() + ' — ' + response;
}
}
return 'OK';
The alias format zabbix-{EVENT.ID} is consistent across the problem and recovery notifications for the same trigger event. Zabbix assigns a single EVENT.ID when a trigger enters PROBLEM state and reuses it for the corresponding RECOVERY event, so the alias naturally ties the two calls together.
Wiring It Into an Action
Creating the media type is only half the setup. You also need an action that fires it.
Go to Configuration > Actions > Trigger actions > Create action. Give the action a name and set your conditions (you likely want it scoped to specific host groups or trigger severities).
Under Operations, add an operation with:
- Operation type: Send message
- Send to users: the user linked to your Alert24 media type
- Send only to: Alert24 (your new media type)
Under Recovery operations, add the same setup. This is the step most teams miss — without a recovery operation, Zabbix fires the webhook on problem but never calls it again when the trigger clears, and your incidents stay open indefinitely.
Testing Before You Roll Out
Zabbix's media type editor has a Test button. Use it. It sends a simulated payload to your script and shows you the response. Set event_value to 1 in the test parameters and verify you see a new incident appear in Alert24. Then set it to 0 and verify the incident resolves.
One thing to check: the test runner uses the literal parameter values you've entered in the UI, not expanded macros. Your API key and service ID should be static strings, so those will work fine. For trigger name and event ID, use realistic placeholder values so you can verify the title and alias end up looking the way you expect.
What You Get on the Alert24 Side
Once the integration is running, each Zabbix trigger creates a structured incident record in Alert24 with a full timeline: when it opened, who was notified, who acknowledged, when it resolved, and total duration. Alert24 routes the incident to whoever is on-call based on your schedule, escalates if nobody acknowledges within your configured window, and posts to your status page if you've marked the service as customer-facing.
The incident history is separate from Zabbix's event log. Your Zabbix database can age out old events on whatever retention schedule you run, and the incident records in Alert24 remain available for post-incident reviews, trend analysis, and reporting.
Next Steps
- Create the Alert24 webhook media type in Zabbix using the script above.
- Link it to a user account in Zabbix Administration > Users > Media.
- Create a trigger action that sends to that user, with both Operations and Recovery operations configured.
- Test with a low-severity trigger on a non-critical host before enabling it broadly.
- In Alert24, review the Services settings to confirm your on-call schedule and escalation policy are configured for the service you're routing Zabbix alerts to.
If your team uses multiple Zabbix instances or separates environments into different host groups, you can create separate Alert24 services for each and pass a different alert24_service_id parameter per action. The same media type script handles all of them.