Zabbix monitoring system automation via API and Python. Use when: (1) Managing hosts, templates, items, triggers, or host groups, (2) Automating monitoring configuration, (3) Sending data via Zabbix trapper/sender, (4) Querying historical data or events, (5) Bulk operations on Zabbix objects, (6) Maintenance window management, (7) User/permission management
Zabbix monitoring system automation via API and Python. Use when: (1) Managing hosts, templates, items, triggers, or host groups, (2) Automating monitoring configuration, (3) Sending data via Zabbix trapper/sender, (4) Querying historical data or events, (5) Bulk operations on Zabbix objects, (6) Maintenance window management, (7) User/permission management
license
MIT
Zabbix Automation Skill
Overview
This skill provides guidance for automating Zabbix monitoring operations via the API and official Python library zabbix_utils.
Quick Start
Installation
pip install zabbix-utils --break-system-packages
Authentication
from zabbix_utils import ZabbixAPI
# Option 1: Username/password
api = ZabbixAPI(url="https://zabbix.example.com")
api.login(user="Admin", password="zabbix")
# Option 2: API token (Zabbix 5.4+, preferred)
api = ZabbixAPI(url="https://zabbix.example.com")
api.login(token="your_api_token")
# Verify connectionprint(api.api_version())
Environment Variables Pattern
import os
from zabbix_utils ZabbixAPI
api = ZabbixAPI(url=os.environ.get(, ))
api.login(token=os.environ[])
import
"ZABBIX_URL"
"http://localhost/zabbix"
"ZABBIX_TOKEN"
Core API Methods
All APIs follow pattern: api.<object>.<method>() with methods: get, create, update, delete.
# Get triggers
triggers = api.trigger.get(hostids="10084",
output=["triggerid", "description", "priority"],
selectFunctions="extend")
# Create trigger
api.trigger.create(
description="High CPU on {HOST.NAME}",
expression="last(/server01/system.cpu.load[percpu,avg1])>5",
priority=3# 0=not classified, 1=info, 2=warning, 3=average, 4=high, 5=disaster
)
Host Group Operations
# Get groups
groups = api.hostgroup.get(output=["groupid", "name"])
# Create group
api.hostgroup.create(name="Production/Web Servers")
# Add hosts to group
api.hostgroup.massadd(groups=[{"groupid": "5"}],
hosts=[{"hostid": "10084"}])
import csv
from zabbix_utils import ZabbixAPI
api = ZabbixAPI(url="https://zabbix.example.com")
api.login(token="your_token")
withopen("hosts.csv") as f:
for row in csv.DictReader(f):
try:
api.host.create(
host=row["hostname"],
groups=[{"groupid": row["groupid"]}],
interfaces=[{
"type": 1, "main": 1, "useip": 1,
"ip": row["ip"], "dns": "", "port": "10050"
}]
)
print(f"Created: {row['hostname']}")
except Exception as e:
print(f"Failed {row['hostname']}: {e}")
Find Hosts Without Template
# Get all hosts
all_hosts = api.host.get(output=["hostid", "host"],
selectParentTemplates=["templateid"])
# Filter hosts without specific template
template_id = "10001"
hosts_without = [h for h in all_hosts
ifnotany(t["templateid"] == template_id
for t in h.get("parentTemplates", []))]
Disable Triggers by Pattern
triggers = api.trigger.get(
search={"description": "test"},
output=["triggerid"]
)
for t in triggers:
api.trigger.update(triggerid=t["triggerid"], status=1) # 1=disabled
Item Types Reference
Type
Value
Description
Zabbix agent
0
Active checks
Zabbix trapper
2
Passive, data pushed via sender
Simple check
3
ICMP, TCP, etc.
Zabbix internal
5
Server internal metrics
Zabbix agent (active)
7
Agent-initiated
HTTP agent
19
HTTP/REST API monitoring
Dependent item
18
Derived from master item
Script
21
Custom scripts
Value Types Reference
Type
Value
Description
Float
0
Numeric (float)
Character
1
Character string
Log
2
Log file
Unsigned
3
Numeric (integer)
Text
4
Text
Trigger Severity Reference
Severity
Value
Color
Not classified
0
Gray
Information
1
Light blue
Warning
2
Yellow
Average
3
Orange
High
4
Light red
Disaster
5
Red
Error Handling
from zabbix_utils import ZabbixAPI
from zabbix_utils.exceptions import APIRequestError
try:
api.host.create(host="duplicate_host", groups=[{"groupid": "2"}])
except APIRequestError as e:
print(f"API Error: {e.message}")
print(f"Code: {e.code}")
Debugging
import logging
logging.basicConfig(level=logging.DEBUG)
# Now all API calls will be logged
Scripts Reference
See scripts/ directory for ready-to-use automation:
zabbix-bulk-hosts.py - Bulk host management from CSV
zabbix-maintenance.py - Create/manage maintenance windows
zabbix-export.py - Export hosts/templates to JSON/XML
Best Practices
Use API tokens over username/password when possible
Use search/filter - Never fetch all objects and filter in Python
Handle pagination - Large result sets may need limit and offset
Batch operations - Use massadd, massupdate for bulk changes
Error handling - Always wrap API calls in try/except
Idempotency - Check if object exists before creating
Gotchas
api.history.get requires the correct history value_type or returns empty: Passing history=0 (float) on an integer item silently returns [] instead of an error. Always read the item's value_type first; the four-way mismatch (0/1/3/4) is the most common "no data" cause.
output="extend" on large queries melts the server: Fetching every field for thousands of hosts or items causes multi-second responses and OOMs the API frontend. Always pass output=["field1","field2"] with only the columns you need — the API has no implicit pagination protection.
Trigger expressions reference host+key, not item IDs: Renaming a host or key breaks every trigger expression that references it, with no warning until evaluation. Use templates and macros ({HOST.HOST}) instead of hardcoded names in expressions.
API token vs session token confusion in zabbix_utils:api.login(token=...) uses a permanent API token (Zabbix 5.4+); api.login(user=..., password=...) issues a session token. Mixing token auth with api.logout() invalidates the permanent token for everyone using it.
massadd does not deduplicate — massupdate replaces:hostgroup.massadd happily adds the same host to a group twice in some versions; hostgroup.massupdate silently removes hosts not in the payload. Read the verb carefully before bulk operations or you'll detach hosts you meant to keep.
maintenance.create with past active_since is accepted but ignored: Backdating a maintenance window does not retroactively suppress alerts that already fired. Set active_since slightly in the future and verify with maintenance.get before assuming alerts are muted.