# Wazuh Server REST API - Authentication and Endpoints

> Guide to Wazuh 4.14 REST API - JWT authentication, agent and rule management, RBAC, api.yaml configuration and curl/Python request examples

Source: https://opennix.org/en/docs/wazuh/infrastructure/wazuh-server-api/


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:

```json
{
  "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 successfully
- `1` - operation failed
- `2` - 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 response
- `offset` - offset from the beginning of the list
- `sort` - sort results (e.g., `+name` or `-id`)

## Authentication

### Obtaining a JWT Token

Working with the API requires a JWT token obtained through the authentication endpoint using HTTP basic authentication:

```bash
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:

```bash
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:

```bash
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:

```bash
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.

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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

```bash
# 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](/docs/wazuh/infrastructure/wazuh-server-cluster/) section.

### Syscollector (Inventory)

```bash
# 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

```bash
# 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)

```bash
# 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](/docs/wazuh/capabilities/wazuh-sca/).

### Agent Groups

```bash
# 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

```yaml
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: false
```

### Configuration 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:

```bash
systemctl restart wazuh-manager
```

## RBAC - 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

```bash
# 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

```bash
# 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

```bash
# 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_minute` requests per minute (default 300)
- Maximum `max_login_attempts` authentication attempts (default 50)
- IP lockout for `block_time` seconds 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/authenticate
```

Dev Tools automatically handles authentication and the base URL.

## Python Examples

### Authentication and Agent Retrieval

```python
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

```python
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:**

1. Confirm the manager is running:

```bash
systemctl status wazuh-manager
```

2. Verify the API is listening on the expected port:

```bash
ss -tlnp | grep 55000
```

3. Review the API log:

```bash
tail -f /var/ossec/logs/api.log
```

### Authentication 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_minute` parameter in `api.yaml`
- Use `limit` and `offset` parameters to retrieve data in batches instead of multiple requests

### TLS Certificate Errors

- For self-signed certificates, add the `-k` flag in curl or `verify=False` in 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](/docs/wazuh/infrastructure/). Information on cluster interaction through the API is available in the [server cluster](/docs/wazuh/infrastructure/wazuh-server-cluster/) section.

