An alert that only lands in an inbox is an incident with no owner. The Zabbix to GLPI integration exists to turn every detected problem into a trackable ticket - with a number, an assignee, a category, a priority and an SLA - and to close it on its own when Zabbix confirms recovery. The trick is not "creating the ticket": it is not creating forty of them.
What the integration must deliver
A Zabbix to GLPI bridge that holds up in production needs four guarantees, not just "post a ticket":
- Idempotency: one problem opens one ticket, not one per escalation step.
- Problem/recovery correlation: the recovery event must find and close exactly the ticket it opened.
- Severity mapping: Zabbix severity maps to GLPI priority consistently, not at each analyst's discretion.
- Enough context: host, IP, trigger, timestamp and message in the body, so the analyst can act without opening Zabbix.
Architecture: where the webhook becomes a ticket
Zabbix fires on an Action; the Action runs a media operation of type Webhook; the Webhook is a native Zabbix JavaScript script that POSTs to an endpoint on the GLPI side. On the GLPI side we use the receiver of the Automations module, which validates the HMAC signature, applies the field map and creates (or closes) the ticket. We avoid calling the GLPI REST API straight from Zabbix because each call would require the app-token/user-token pair and an initSession/killSession pair - under an alert storm that hammers the API and exhausts sessions.
Artifact: the Zabbix webhook Media Type
The parameters map event macros; the script builds the payload and handles the HTTP status. Problem and recovery use the same Media Type - the event_value field tells them apart (1 = problem, 0 = recovery):
// Zabbix -> Media type -> Webhook -> Parameters
// endpoint = https://glpi.customer.com/plugins/nextool/automations/webhook/zabbix
// event_id = {EVENT.ID} // stable across the problem/recovery pair
// event_value = {EVENT.VALUE} // 1 = problem, 0 = recovery
// host_name = {HOST.NAME}
// host_ip = {HOST.IP}
// trigger_name = {TRIGGER.NAME}
// severity = {TRIGGER.SEVERITY}
// occurred = {EVENT.DATE} {EVENT.TIME}
// message = {ALERT.MESSAGE}
// hmac = {$NEXTOOL_HMAC} // secret macro, never in the alert body
var p = JSON.parse(value);
var req = new HttpRequest();
req.addHeader('Content-Type: application/json');
req.addHeader('X-Nextool-Signature: ' + p.hmac);
var payload = JSON.stringify({
event_id: p.event_id,
recovery: p.event_value === '0',
host: p.host_name,
host_ip: p.host_ip,
trigger: p.trigger_name,
severity: p.severity,
occurred: p.occurred,
message: p.message
});
var resp = req.post(p.endpoint, payload);
var code = req.getStatus();
if (code < 200 || code >= 300) {
Zabbix.log(3, '[nextool] HTTP failure ' + code + ': ' + resp);
throw 'Send to GLPI failed: HTTP ' + code;
}
return resp;
Zabbix severity to GLPI priority map
Zabbix has six severities; GLPI has five priorities. We pin the map in the receiver so it is not left to each analyst:
| Zabbix severity | GLPI priority | Opens a ticket? |
|---|---|---|
| Not classified / Information | - | No (log only) |
| Warning | Low | Yes |
| Average | Medium | Yes |
| High | High | Yes |
| Disaster | Very high | Yes + notifies on-call |
Deduplication and auto-close
This is what separates a toy integration from one that survives production. When it opens the ticket, the receiver stores the GLPI tickets_id as an event tag in Zabbix (or in a correlation table indexed by event_id). When Zabbix sends the recovery with the same event_id, the receiver locates that ticket and adds a recovery follow-up - or closes it, per the customer's policy. Without that key, the recovery has no way to know which ticket to close and you pile up open tickets for problems already resolved.
Common mistakes we fix in support
In day-to-day support, the most common incident is not the alert that never becomes a ticket - it is the alert that becomes forty. A flapping interface at 3 a.m. opened dozens of identical tickets because the Action fired at every escalation step and the receiver did not deduplicate. The fix has two sides: on Zabbix, trigger dependency, hysteresis in the recovery expression and a media operation only on the first step; on GLPI, idempotency by event_id. Two more recurring mistakes: sending the ticket category as free text (GLPI expects a numeric itilcategories_id - a new text string does not match and the ticket lands with no category) and putting the HMAC secret in the alert body instead of a protected macro like {$NEXTOOL_HMAC}.
Integration methods compared
| Method | No code? | Dedup/recovery | When to use |
|---|---|---|---|
| Automations module (receiver) | Yes (JSONPath map) | Native by event_id | Default for most customers |
| GLPI REST API directly | No | You implement it | No module; few hosts |
| External script (Python/Bash) | No | You implement and maintain | Non-standard business rules |
If your operation already runs Zabbix but the alerts die in an inbox nobody reads, NexTool deploys this bridge with the Automations module and keeps the rules tuned in support - triggers, severity map and close policy. Meet the Automations module.
This content was produced with the help of artificial intelligence and reviewed by the Nextool Solutions team.