Wazuh Server REST API - Authentication and Endpoints
The Wazuh REST API provides a programmatic interface for managing all platform components. The API operates over HTTPS on port 55000, authenticates via JWT tokens, and enforces role-based access control. Through the API you can manage agents, rules, decoders, groups, manager configuration, and cluster operations.
API Overview
Core Characteristics
| Parameter | Value |
|---|---|
| Protocol | HTTPS (TLS) |
| Default port | 55000 |
| Data format | JSON |
| Authentication | JWT (JSON Web Token) |
| Authorization | RBAC (Role-Based Access Control) |
| HTTP methods | GET, POST, PUT, DELETE |
| Base URL | https://<WAZUH_SERVER>:55000 |
Response Structure
All API responses follow a standardized format:
{
"data": {
"affected_items": [],
"total_affected_items": 0,
"failed_items": [],
"total_failed_items": 0
},
"message": "Description of the result",
"error": 0
}Error codes in the error field:
0- operation completed successfully1- operation failed2- operation partially completed (some items processed, some failed)
Pagination Parameters
The API limits the number of returned records. The default maximum is 500 items. To retrieve more, use:
limit- maximum number of records per responseoffset- offset from the beginning of the listsort- sort results (e.g.,+nameor-id)
Authentication
Obtaining a JWT Token
Working with the API requires a JWT token obtained through the authentication endpoint using HTTP basic authentication:
TOKEN=$(curl -sk -u wazuh-wui:MyPassword \
-X POST "https://localhost:55000/security/user/authenticate?raw=true")The raw=true parameter returns the token in plain text without JSON wrapping.
Alternative approach with JSON response:
curl -sk -u wazuh-wui:MyPassword \
-X POST "https://localhost:55000/security/user/authenticate" | jq -r '.data.token'Using the Token
Include the token in the Authorization header of every request:
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/?pretty=true"Token Lifetime
JWT tokens have a limited lifetime configured in the API settings. When the token expires, a new one must be obtained. The default lifetime is 900 seconds (15 minutes).
Token Revocation
To forcibly end a session, use the revocation endpoint:
curl -sk -H "Authorization: Bearer $TOKEN" \
-X DELETE "https://localhost:55000/security/user/authenticate"Key Endpoint Groups
Agents
Agent management is one of the most frequently used API functions.
# List all agents
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/agents?pretty=true"
# List active agents with filtering
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/agents?status=active&limit=10&pretty=true"
# Information about a specific agent
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/agents?agents_list=001&pretty=true"
# Agent status summary
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/agents/summary/status?pretty=true"
# Restart an agent
curl -sk -H "Authorization: Bearer $TOKEN" \
-X PUT "https://localhost:55000/agents/001/restart?pretty=true"
# Upgrade an agent
curl -sk -H "Authorization: Bearer $TOKEN" \
-X PUT "https://localhost:55000/agents/001/upgrade?pretty=true"
# Delete an agent
curl -sk -H "Authorization: Bearer $TOKEN" \
-X DELETE "https://localhost:55000/agents?agents_list=001&status=all&older_than=0s&pretty=true"Rules
# List all rules
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/rules?pretty=true&limit=10"
# Get rule by ID
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/rules?rule_ids=100001&pretty=true"
# Rules by level
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/rules?level=12-15&pretty=true"
# Rules by group
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/rules?group=authentication_failed&pretty=true"
# List rule files
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/rules/files?pretty=true"Decoders
# List all decoders
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/decoders?pretty=true&limit=10"
# Search decoder by name
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/decoders?search=sshd&pretty=true"
# List decoder files
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/decoders/files?pretty=true"Manager
# Manager information
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/manager/info?pretty=true"
# Manager status
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/manager/status?pretty=true"
# Manager configuration
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/manager/configuration?pretty=true"
# Manager logs
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/manager/logs?pretty=true&limit=20"
# Restart manager
curl -sk -H "Authorization: Bearer $TOKEN" \
-X PUT "https://localhost:55000/manager/restart?pretty=true"Cluster
# Cluster status
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/cluster/status?pretty=true"
# List cluster nodes
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/cluster/nodes?pretty=true"
# Information about a specific node
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/cluster/nodes/worker-01?pretty=true"
# Cluster configuration
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/cluster/configuration?pretty=true"For details on cluster setup, see the Wazuh server cluster section.
Syscollector (Inventory)
# Agent hardware information
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/syscollector/001/hardware?pretty=true"
# Installed packages
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/syscollector/001/packages?pretty=true&limit=20"
# Network interfaces
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/syscollector/001/netiface?pretty=true"
# Open ports
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/syscollector/001/ports?pretty=true"
# Running processes
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/syscollector/001/processes?pretty=true&limit=20"
# OS information
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/syscollector/001/os?pretty=true"Vulnerabilities
# Detected vulnerabilities for an agent
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/vulnerability/001?pretty=true"
# Filter by severity
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/vulnerability/001?severity=Critical&pretty=true"SCA (Security Configuration Assessment)
# List SCA policies for an agent
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/sca/001?pretty=true"
# Check results for a specific policy
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/sca/001/checks/cis_ubuntu22-04?pretty=true"For more on the SCA module, see Security Configuration Assessment .
Agent Groups
# List groups
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/groups?pretty=true"
# Create a group
curl -sk -H "Authorization: Bearer $TOKEN" \
-X POST "https://localhost:55000/groups?pretty=true" \
-H "Content-Type: application/json" \
-d '{"group_id":"web-servers"}'
# Assign agent to group
curl -sk -H "Authorization: Bearer $TOKEN" \
-X PUT "https://localhost:55000/agents/001/group/web-servers?pretty=true"
# Agents in a group
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/groups/web-servers/agents?pretty=true"
# Delete a group
curl -sk -H "Authorization: Bearer $TOKEN" \
-X DELETE "https://localhost:55000/groups?groups_list=web-servers&pretty=true"API Configuration (api.yaml)
The API configuration is stored in /var/ossec/api/configuration/api.yaml.
Core Parameters
host: 0.0.0.0
port: 55000
https:
enabled: true
key: /var/ossec/api/configuration/ssl/server.key
cert: /var/ossec/api/configuration/ssl/server.crt
logging:
level: info
path: /var/ossec/logs/api.log
cors:
enabled: false
source_route: "*"
expose_headers: "*"
allow_headers: "*"
allow_credentials: false
access:
max_login_attempts: 50
block_time: 300
max_request_per_minute: 300
behind_proxy_server: falseConfiguration Parameter Reference
| Parameter | Description | Default |
|---|---|---|
host | IP address on which the API accepts connections | 0.0.0.0 |
port | API TCP port | 55000 |
https.enabled | Enable HTTPS | true |
https.key | Path to TLS private key | /var/ossec/api/configuration/ssl/server.key |
https.cert | Path to TLS certificate | /var/ossec/api/configuration/ssl/server.crt |
logging.level | Log level (debug, info, warning, error) | info |
cors.enabled | Enable CORS headers | false |
behind_proxy_server | Running behind a reverse proxy (trust X-Forwarded-For header) | false |
access.max_login_attempts | Maximum login attempts before lockout | 50 |
access.block_time | Lockout duration after exceeding attempts (seconds) | 300 |
access.max_request_per_minute | Request rate limit per minute | 300 |
Restart the API after configuration changes:
systemctl restart wazuh-managerRBAC - Role-Based Access Control
RBAC Architecture
The Wazuh API implements a multi-level access control system:
- Users - accounts with JWT authentication
- Roles - sets of policies assigned to users
- Policies - access rules defining permitted actions
- Security rules - dynamic role assignment based on conditions
RBAC Modes
- White list (default) - everything is denied unless explicitly allowed
- Black list - everything is allowed unless explicitly denied
User Management
# Create a user
curl -sk -H "Authorization: Bearer $TOKEN" \
-X POST "https://localhost:55000/security/users" \
-H "Content-Type: application/json" \
-d '{"username":"analyst","password":"Analyst_Pass1"}'
# List users
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/security/users?pretty=true"
# Assign role to user
curl -sk -H "Authorization: Bearer $TOKEN" \
-X POST "https://localhost:55000/security/users/analyst/roles?role_ids=2"Role Management
# List roles
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/security/roles?pretty=true"
# Create a role
curl -sk -H "Authorization: Bearer $TOKEN" \
-X POST "https://localhost:55000/security/roles" \
-H "Content-Type: application/json" \
-d '{"name":"readonly_agents"}'
# Assign policy to role
curl -sk -H "Authorization: Bearer $TOKEN" \
-X POST "https://localhost:55000/security/roles/100/policies?policy_ids=1"Policy Management
# List policies
curl -sk -H "Authorization: Bearer $TOKEN" \
"https://localhost:55000/security/policies?pretty=true"
# Create a policy (allow reading agents)
curl -sk -H "Authorization: Bearer $TOKEN" \
-X POST "https://localhost:55000/security/policies" \
-H "Content-Type: application/json" \
-d '{
"name": "read_agents",
"policy": {
"actions": ["agent:read"],
"resources": ["agent:id:*"],
"effect": "allow"
}
}'Rate Limiting
The API limits request frequency to protect against abuse:
- Maximum
max_request_per_minuterequests per minute (default 300) - Maximum
max_login_attemptsauthentication attempts (default 50) - IP lockout for
block_timeseconds after exceeding the attempt limit
When the limit is exceeded, the API returns HTTP 429 (Too Many Requests).
Using the API from Dashboard Dev Tools
Wazuh Dashboard provides a built-in Dev Tools console for executing API requests without the command line. The console is accessible under Server management > Dev Tools.
Request format in Dev Tools:
GET /agents?status=active&limit=5
GET /manager/info
POST /security/user/authenticateDev Tools automatically handles authentication and the base URL.
Python Examples
Authentication and Agent Retrieval
import requests
import urllib3
from base64 import b64encode
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
WAZUH_API = "https://localhost:55000"
USER = "wazuh-wui"
PASSWORD = "MyPassword"
def get_token() -> str:
"""Obtain JWT token from Wazuh API."""
auth_header = b64encode(f"{USER}:{PASSWORD}".encode()).decode()
headers = {"Authorization": f"Basic {auth_header}"}
response = requests.post(
f"{WAZUH_API}/security/user/authenticate",
headers=headers,
verify=False,
)
response.raise_for_status()
return response.json()["data"]["token"]
def get_active_agents(token: str) -> list[dict]:
"""Retrieve list of active agents."""
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(
f"{WAZUH_API}/agents",
headers=headers,
params={"status": "active", "limit": 500},
verify=False,
)
response.raise_for_status()
return response.json()["data"]["affected_items"]
token = get_token()
agents = get_active_agents(token)
for agent in agents:
print(f"Agent {agent['id']}: {agent['name']} ({agent['status']})")Vulnerability Monitoring
def get_critical_vulnerabilities(token: str, agent_id: str) -> list[dict]:
"""Get critical vulnerabilities for a specific agent."""
headers = {"Authorization": f"Bearer {token}"}
response = requests.get(
f"{WAZUH_API}/vulnerability/{agent_id}",
headers=headers,
params={"severity": "Critical", "limit": 100},
verify=False,
)
response.raise_for_status()
return response.json()["data"]["affected_items"]Comparison with Other SIEM Platform APIs
| Feature | Wazuh API | Splunk REST API | Elastic Security API | QRadar API |
|---|---|---|---|---|
| Protocol | HTTPS (port 55000) | HTTPS (port 8089) | HTTPS (port 9200/5601) | HTTPS (port 443) |
| Authentication | JWT token | Session key / Bearer token | API key / Basic auth | SEC token |
| Authorization | RBAC | Capabilities | RBAC / Spaces | User roles |
| Response format | JSON | JSON/XML | JSON | JSON |
| Documentation | OpenAPI / ReDoc | REST API Reference | OpenAPI | Interactive |
| Cost | Free | Commercial | Free (Basic) / Commercial | Commercial |
| SDK | Python (requests) | splunk-sdk | elasticsearch-py | Python SDK |
| Rate limiting | Configurable | Not by default | Not by default | Yes |
Key Differences
Splunk REST API provides configuration access through namespace-based endpoints (/servicesNS/) with a hierarchical namespace structure. The Wazuh API uses a flat endpoint structure grouped by functionality.
Elastic Security API splits its API across Elasticsearch (indices, search) and Kibana (rules, alerts) layers. Wazuh consolidates all management functions into a single API.
QRadar API uses static authorization tokens that do not expire. Wazuh uses JWT with a limited lifetime, providing a higher level of security.
Troubleshooting
API Not Responding
Checks:
- Confirm the manager is running:
systemctl status wazuh-manager- Verify the API is listening on the expected port:
ss -tlnp | grep 55000- Review the API log:
tail -f /var/ossec/logs/api.logAuthentication Error (HTTP 401)
- Verify that credentials are correct
- Check whether the JWT token has expired (default lifetime is 15 minutes)
- Obtain a new token through the authentication endpoint
Authorization Error (HTTP 403)
- Review the roles and policies assigned to the user
- Confirm that the policy allows the requested action and resource
- Check the RBAC mode (white list / black list)
Rate Limit Exceeded (HTTP 429)
- Reduce request frequency
- Increase the
max_request_per_minuteparameter inapi.yaml - Use
limitandoffsetparameters to retrieve data in batches instead of multiple requests
TLS Certificate Errors
- For self-signed certificates, add the
-kflag in curl orverify=Falsein Python - For production environments, replace self-signed certificates with certificates from a trusted CA
- Verify certificate paths in
api.yaml
For a general infrastructure overview, see the Wazuh infrastructure section . Information on cluster interaction through the API is available in the server cluster section.