Logsv7.0.20
Query the three independent log feeds — syslog, Windows event logs, and IDS (EVE) events — with a shared list / summary / filter shape, plus the configuration endpoints that decide what the appliance collects.
The appliance collects three independent log streams and exposes each as a searchable feed:
- Syslog — RFC-style messages received from network devices, with a numeric facility and severity (0–7).
- Windows event logs — events pulled from Windows hosts by the monitoring agent, keyed by event id, source, and channel.
- IDS events (EVE) — intrusion-detection events in the EVE JSON format, carrying a signature, severity (1–3), and the source/destination addresses of the connection that triggered the alert.
Each stream provides a paginated list, a severity summary (a count per severity level over a time window), and a set of personal filters. The Windows-event stream additionally exposes queries (the named collection rules an agent can run) and per-device trackers (which queries are enabled on a given device). A small syslog access surface controls the minimum severity the appliance accepts from each device.
Most of these endpoints belong to the logs functional area; an MCP or OAuth token needs the mcp:logs scope, and the calling user needs the logs Laravel permission. The exceptions are the configuration endpoints — event-log queries/trackers and syslog access — which require write_devices (they change what the appliance collects, not just what it reads). The permission for each endpoint is shown on its block.
Tag-scoping applies to every list and summary. A tag-restricted user sees only log rows belonging to devices inside their tags; the syslog and event-log streams scope by device id, and the IDS stream scopes by IP address (an event is visible if its source or destination IP belongs to an in-scope device). A user with no tag restriction sees everything, and the sa (super-admin) role bypasses scoping entirely. Requesting a device outside your scope on a configuration endpoint returns 404.
Filters are personal exclusion rules. A saved “filter” is a per-user exclusion: when enabled, rows matching it are removed from your list and summary results. Filters never broaden what you can see and never affect other users. The ad-hoc filters query parameter on the list/summary endpoints, by contrast, narrows a single request inline. The create/toggle/delete operations behave identically across all three streams, so they are described once per stream with only the column lists differing.
Time window idiom. Every list and summary accepts either a startTime/endTime pair or an hours look-back (default 24). The effective window is echoed back in the response. List endpoints are paginated and accept limit (default 1000).
Syslog
List syslog messages
GET/api/syslog/listlogs
Returns syslog messages newest-first within the time window, scoped to your tags, with your enabled exclusion filters applied.
Query parameters
| Name | Type | Notes |
|---|---|---|
startTime | datetime | Window start. Provide together with endTime. |
endTime | datetime | Window end. |
hours | integer | Look-back window when startTime/endTime are omitted (default 24). |
limit | integer | Page size (default 1000). |
page | integer | Page number. |
filters | string (JSON) | Inline filter object. Keys: device_id, timestamp, facility, severity, source, and message (substring match). Each value may be a scalar or an array (OR-match). severity accepts a level number (0–7) or a name (emergency, alert, critical, error, warning, notice, informational/info, debug). |
Response 200
A standard paginated envelope with the window echoed back.
{
"current_page": 1,
"data": [
{
"id": 99812, "device_id": 42, "timestamp": "2026-06-15T09:14:02Z",
"facility": 4, "severity": 3, "source": "10.0.0.1",
"message": "interface GigabitEthernet0/1 down"
}
],
"per_page": 1000,
"total": 1,
"startTime": "2026-06-14T09:14:00Z",
"endTime": "2026-06-15T09:14:00Z"
}
Errors
| Status | Body | When |
|---|---|---|
400 | {"status":false,"message":"…"} | Unparseable time or other processing error. |
Example
curl -sS "https://APPLIANCE/api/syslog/list?hours=6&limit=100&filters=%7B%22severity%22%3A%5B%22error%22%2C%22critical%22%5D%7D" \
-H "Authorization: Bearer $TOKEN"
Syslog severity summary
GET/api/syslog/sevSumlogs
Returns a count of syslog messages per severity level (always all eight levels, 0–7, zero-filled) over the time window, scoped and filtered identically to the list.
Query parameters
Same startTime / endTime / hours / filters as List syslog messages.
Response 200
{
"severityCounts": {"0":0,"1":0,"2":1,"3":14,"4":52,"5":3,"6":120,"7":0},
"startTime": "2026-06-14T09:14:00Z",
"endTime": "2026-06-15T09:14:00Z"
}
List syslog filters
GET/api/syslog/filterslogs
Returns the calling user’s saved syslog exclusion filters.
Response 200
{
"message": "Filters retrieved successfully!",
"filters": [ { "id": 5, "label": "drop debug", "filter": {"severity": "debug"}, "enabled": 1 } ]
}
Create or update a syslog filter
POST/api/syslog/filterslogs
Creates a saved filter, or updates one when id is supplied. At least one criterion must carry a value, and every key must be an allowed column.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
label | string | yes | Max 255 characters. |
filter | string (JSON) | yes | Object. Allowed keys: device_id, severity, facility, message, source. |
id | integer | no | Present = update that filter (must be yours). Absent = create. |
Response 201 (create) / 200 (update)
{
"message": "Filter created successfully!",
"filter": { "id": 6, "users_id": 3, "label": "drop debug", "filter": {"severity": "debug"}, "enabled": true }
}
Errors
| Status | Body | When |
|---|---|---|
422 | {"label":["The label field is required."]} | Validation failed. |
422 | {"error":"Filter cannot be empty."} | filter decoded to an empty object. |
422 | {"error":"Filter must contain at least one criteria with a value."} | Every key was empty. |
422 | {"error":"Filter contains invalid criteria: foo"} | A key is not an allowed column. |
403 | {"message":"Filter not found or access denied."} | id given but missing or owned by another user. |
Example
curl -sS -X POST https://APPLIANCE/api/syslog/filters \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"label":"drop debug","filter":"{\"severity\":\"debug\"}"}'
Toggle a syslog filter
POST/api/syslog/filters/toggle/{filterId}logs
Flips the enabled flag and returns your full filter list.
Path parameters
| Name | Type | Notes |
|---|---|---|
filterId | integer | Filter id. Must belong to you. |
Response 201
{ "message": "Filter toggled successfully!", "filters": [ { "id": 5, "label": "drop debug", "filter": {"severity":"debug"}, "enabled": false } ] }
Errors
| Status | Body | When |
|---|---|---|
404 | {"error":"Filter not found or access denied."} | No such filter owned by you. |
Delete a syslog filter
DELETE/api/syslog/filters/{filterId}logs
Permanently deletes one of your saved syslog filters.
Path parameters
| Name | Type | Notes |
|---|---|---|
filterId | integer | Filter id. Must belong to you. |
Response 200
{ "message": "Filter deleted successfully." }
Errors
| Status | Body | When |
|---|---|---|
404 | {"message":"Filter not found or access denied."} | No such filter owned by you. |
Windows event logs
The Windows event-log stream has the same list / summary / filter shape as syslog. Note the severity scale differs: event-log severities run 0–5 (information/info = 0, critical = 1, error = 2, warning = 3, verbose = 5). The free-text message filter key matches against the event’s data field.
List Windows events
GET/api/eventlog/listlogs
Returns Windows events newest-first within the window, tag-scoped by device, with your enabled exclusion filters applied.
Query parameters
| Name | Type | Notes |
|---|---|---|
startTime | datetime | Window start. Provide together with endTime. |
endTime | datetime | Window end. |
hours | integer | Look-back when times omitted (default 24). |
limit | integer | Page size (default 1000). |
page | integer | Page number. |
filters | string (JSON) | Inline filter object. Keys: device_id, event_id, timestamp, log, source, severity, and message (substring match on the event data). |
Response 200
{
"current_page": 1,
"data": [
{
"id": 4471, "device_id": 88, "timestamp": "2026-06-15T09:20:00Z",
"event_id": 4625, "log": "Security", "source": "Microsoft-Windows-Security-Auditing",
"severity": 2, "data": "An account failed to log on."
}
],
"per_page": 1000, "total": 1,
"startTime": "2026-06-14T09:20:00Z",
"endTime": "2026-06-15T09:20:00Z"
}
Errors
| Status | Body | When |
|---|---|---|
400 | {"status":false,"message":"…"} | Unparseable time or other processing error. |
Example
curl -sS "https://APPLIANCE/api/eventlog/list?limit=100&filters=%7B%22event_id%22%3A4625%7D" \
-H "Authorization: Bearer $TOKEN"
Windows event severity summary
GET/api/eventlog/sevSumlogs
Returns a per-severity count over the window, scoped and filtered like the list. The summary zero-fills buckets 0 through 7, but only levels 0–5 carry meaning for Windows event logs (the scale described above) — buckets 6 and 7 are always present and always zero.
Query parameters
Same startTime / endTime / hours / filters as List Windows events.
Response 200
{
"severityCounts": {"0":540,"1":2,"2":33,"3":71,"4":0,"5":0,"6":0,"7":0},
"startTime": "2026-06-14T09:20:00Z",
"endTime": "2026-06-15T09:20:00Z"
}
List Windows event filters
GET/api/eventlog/filterslogs
Returns the calling user’s saved Windows-event exclusion filters.
Response 200
{ "message": "Filters retrieved successfully!", "filters": [ { "id": 9, "label": "ignore logon noise", "filter": {"event_id": 4625}, "enabled": 1 } ] }
Create or update a Windows event filter
POST/api/eventlog/filterslogs
Creates a saved filter, or updates one when id is supplied.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
label | string | yes | Max 255 characters. |
filter | string (JSON) | yes | Object. Allowed keys: event_id, severity, timestamp, device_id, log, source, message. At least one must carry a value. |
id | integer | no | Present = update (must be yours). Absent = create. |
Response 201 (create) / 200 (update)
{
"message": "Filter created successfully!",
"filter": { "id": 10, "users_id": 3, "label": "ignore logon noise", "filter": {"event_id": 4625}, "enabled": true }
}
Errors
| Status | Body | When |
|---|---|---|
422 | {"label":["The label field is required."]} | Validation failed. |
422 | {"error":"Filter cannot be empty."} | Empty filter object. |
422 | {"error":"Filter must contain at least one criteria with a value."} | Every key empty. |
422 | {"error":"Filter contains invalid criteria: foo"} | Disallowed key. |
403 | {"message":"Filter not found or access denied."} | id missing or owned by another user. |
Toggle a Windows event filter
POST/api/eventlog/filters/toggle/{filterId}logs
Flips enabled and returns your full filter list.
Path parameters
| Name | Type | Notes |
|---|---|---|
filterId | integer | Filter id. Must belong to you. |
Response 201
{ "message": "Filter toggled successfully!", "filters": [ { "id": 9, "label": "ignore logon noise", "filter": {"event_id":4625}, "enabled": false } ] }
Errors
| Status | Body | When |
|---|---|---|
404 | {"error":"Filter not found or access denied."} | No such filter owned by you. |
Delete a Windows event filter
DELETE/api/eventlog/filters/{filterId}logs
Permanently deletes one of your saved Windows-event filters.
Path parameters
| Name | Type | Notes |
|---|---|---|
filterId | integer | Filter id. Must belong to you. |
Response 200
{ "message": "Filter deleted successfully." }
Errors
| Status | Body | When |
|---|---|---|
404 | {"message":"Filter not found or access denied."} | No such filter owned by you. |
Event-log queries & trackers
These endpoints configure what the Windows agent collects, rather than reading what it has collected, and so require write_devices. A query is a named, system-defined collection rule (e.g. “Security Events”); a tracker binds a query to a specific device so the agent starts collecting it there.
List event-log queries
GET/api/eventlog/querieswrite_devices
Returns the catalog of available event-log queries (the choices for a tracker), ordered by id. The response is a bare array.
Response 200
[
{ "id": 1, "label": "Security Events" },
{ "id": 2, "label": "All Error/Critical" }
]
List a device’s trackers
GET/api/eventlog/trackerswrite_devices
Returns the queries currently enabled on one device. The device must be in your tag scope.
Query parameters
| Name | Type | Notes |
|---|---|---|
device_id | integer | Required. The device whose trackers to list. |
Response 200
[
{ "id": 14, "device_id": 88, "query_id": 1 },
{ "id": 15, "device_id": 88, "query_id": 2 }
]
Errors
| Status | Body | When |
|---|---|---|
422 | {"error":"device_id required"} | device_id missing or zero. |
404 | {"error":"Device not found"} | Unknown device, or outside your tag scope. |
Add a tracker
POST/api/eventlog/trackerswrite_devices
Enables a query on a device, so the agent begins collecting it (with one day of backfill on its first poll). The operation is idempotent: re-adding an existing pairing returns the existing row with 200 instead of creating a duplicate.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
device_id | integer | yes | The target device. Must be in your tag scope. |
query_id | integer | yes | A valid eventlog_queries id (validated to exist). |
Response 201 (created) / 200 (already existed)
{ "id": 16, "device_id": 88, "query_id": 1 }
Errors
| Status | Body | When |
|---|---|---|
422 | {"errors":{"query_id":["The selected query id is invalid."]}} | Validation failed (missing field, or unknown query_id). |
404 | {"error":"Device not found"} | Unknown device, or outside your tag scope. |
Example
curl -sS -X POST https://APPLIANCE/api/eventlog/trackers \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"device_id":88,"query_id":1}'
Remove a tracker
DELETE/api/eventlog/trackers/{id}write_devices
Disables a query on its device by deleting the tracker. The tracker’s device must be in your tag scope.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | integer | Tracker id (not the device or query id). |
Response 200
{ "status": true }
Errors
| Status | Body | When |
|---|---|---|
404 | {"error":"Tracker not found"} | No tracker with that id. |
403 | {"error":"Forbidden"} | The tracker’s device is outside your tag scope. |
IDS events
The IDS feed exposes intrusion-detection events in the EVE format. Because an EVE row carries source/destination IPs rather than a device foreign key, tag-scoping here is by IP: an event is visible if its src_ip or dst_ip belongs to an in-scope device. The severity scale is 1–3 (high = 1, med/medium = 2, low = 3). Filters support the same ip and port convenience keys as the flow feeds (matching either endpoint), plus a device_id key that resolves to the device’s IP under the hood.
List IDS events
GET/api/eve/listlogs
Returns IDS events newest-first within the window, joined to their signature and enriched with source/destination device id, hostname, and profile where a device matches. Tag-scoped by endpoint IP.
Query parameters
| Name | Type | Notes |
|---|---|---|
startTime | datetime | Window start. Must be before endTime. |
endTime | datetime | Window end (defaults to now). |
hours | integer | Look-back used to derive startTime when omitted (default 24). |
limit | integer | Page size (default 1000). |
page | integer | Page number. |
filters | string (JSON) | Inline filter object. Keys: signature_id, severity, proto, iface, timestamp, vlan, src_ip, dst_ip, src_port, dst_port, plus device_id (resolved to the device IP), ip (either endpoint), port (either endpoint). |
Response 200
{
"current_page": 1,
"data": [
{
"id": 30211, "timestamp": "2026-06-15T09:25:00Z", "signature_id": 2013028,
"severity": 1, "proto": "TCP", "iface": "eth0", "vlan": 0,
"src_ip": "10.0.0.5", "src_port": 51344, "dst_ip": "203.0.113.9", "dst_port": 80,
"src_id": 42, "src_host": "workstation-5", "src_profile": "windows"
}
],
"per_page": 1000, "total": 1,
"startTime": "2026-06-14T09:25:00Z",
"endTime": "2026-06-15T09:25:00Z"
}
Errors
| Status | Body | When |
|---|---|---|
400 | {"status":false,"message":"startTime must be before endTime."} | Inverted window or other processing error. |
Example
curl -sS "https://APPLIANCE/api/eve/list?hours=12&filters=%7B%22severity%22%3A%22high%22%7D" \
-H "Authorization: Bearer $TOKEN"
Get IDS event detail
GET/api/eve/get/{event}logs
Returns the full EVE JSON record for a single event. The response body is the stored EVE object itself (not wrapped in an envelope). For tag-restricted users, the event must touch an in-scope IP.
Path parameters
| Name | Type | Notes |
|---|---|---|
event | integer | The EVE log id (eve_log_id). |
Response 200
The raw EVE record (shape depends on the event type), e.g.:
{ "alert": { "signature": "ET SCAN Nmap", "severity": 1 }, "flow_id": 12345, "proto": "TCP" }
Errors
| Status | Body | When |
|---|---|---|
400 | {"status":false,"message":"Event ID does not exist."} | Unknown id, or not visible under your tag scope. |
IDS severity summary
GET/api/eve/sevSumlogs
Returns a per-severity count (levels 1–3, zero-filled) over the window, scoped by endpoint IP and with your exclusion filters applied.
Query parameters
Same startTime / endTime / hours / filters as List IDS events.
Response 200
{
"severityCounts": {"1":4,"2":17,"3":92},
"startTime": "2026-06-14T09:25:00Z",
"endTime": "2026-06-15T09:25:00Z"
}
List IDS filters
GET/api/eve/filterslogs
Returns the calling user’s saved IDS exclusion filters.
Response 200
{ "message": "Filters retrieved successfully!", "filters": [ { "id": 3, "label": "ignore scanner", "filter": {"src_ip": "10.0.0.250"}, "enabled": 1 } ] }
Create or update an IDS filter
POST/api/eve/filterslogs
Creates a saved filter, or updates one when id is supplied.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
label | string | yes | Max 255 characters. |
filter | string (JSON) | yes | Object. Allowed keys: id, signature_id, severity, src_ip, src_port, dst_ip, dst_port, proto, iface, vlan, plus ip and port. At least one must carry a value. |
id | integer | no | Present = update (must be yours). Absent = create. |
Response 201 (create) / 200 (update)
{
"message": "Filter created successfully!",
"filter": { "id": 4, "users_id": 3, "label": "ignore scanner", "filter": {"src_ip": "10.0.0.250"}, "enabled": true }
}
Errors
| Status | Body | When |
|---|---|---|
422 | {"label":["The label field is required."]} | Validation failed. |
422 | {"error":"Filter cannot be empty."} | Empty filter object. |
422 | {"error":"Filter must contain at least one criteria with a value."} | Every key empty. |
422 | {"error":"Filter contains invalid criteria: foo"} | Disallowed key. |
403 | {"message":"Filter not found or access denied."} | id missing or owned by another user. |
Toggle an IDS filter
POST/api/eve/filters/toggle/{filterId}logs
Flips enabled and returns your full filter list.
Path parameters
| Name | Type | Notes |
|---|---|---|
filterId | integer | Filter id. Must belong to you. |
Response 201
{ "message": "Filter toggled successfully!", "filters": [ { "id": 3, "label": "ignore scanner", "filter": {"src_ip":"10.0.0.250"}, "enabled": false } ] }
Errors
| Status | Body | When |
|---|---|---|
404 | {"error":"Filter not found or access denied."} | No such filter owned by you. |
Delete an IDS filter
DELETE/api/eve/filters/{filterId}logs
Permanently deletes one of your saved IDS filters.
Path parameters
| Name | Type | Notes |
|---|---|---|
filterId | integer | Filter id. Must belong to you. |
Response 200
{ "message": "Filter deleted successfully." }
Errors
| Status | Body | When |
|---|---|---|
404 | {"message":"Filter not found or access denied."} | No such filter owned by you. |
Syslog access config
These two endpoints control the minimum syslog severity the appliance accepts from a given device — effectively a per-device intake gate, distinct from the personal display filters above. They change collection behavior, so they require write_devices. The device must be in your tag scope.
Get a device’s syslog config
GET/api/syslog/config/{deviceId}write_devices
Returns whether syslog intake is enabled for the device and its minimum-severity threshold. If no config row exists yet, a default (enabled, accept all severities up to debug) is created and returned. Internally, a disabled device is stored as severity -1; the response surfaces that as enabled: false.
Path parameters
| Name | Type | Notes |
|---|---|---|
deviceId | integer | Device id. Must be in your tag scope. |
Response 200
{
"status": true,
"config": { "enabled": true, "min_severity": 7, "device_id": 42 }
}
Errors
| Status | Body | When |
|---|---|---|
404 | {"error":"Device not found"} | Unknown device, or outside your tag scope. |
500 | {"status":false,"message":"Error retrieving syslog configuration: …"} | Unexpected processing error. |
Update a device’s syslog config
POST/api/syslog/config/{deviceId}write_devices
Enables or disables syslog intake for the device and sets its minimum-severity threshold. When enabled is false the threshold is stored as -1 regardless of min_severity.
Path parameters
| Name | Type | Notes |
|---|---|---|
deviceId | integer | Device id. Must be in your tag scope. |
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
enabled | boolean | yes | Whether to accept syslog from this device. |
min_severity | integer | yes | Minimum accepted severity, -1–7. (-1 means disabled.) |
Response 200
{
"status": true,
"message": "Syslog configuration updated successfully",
"config": { "enabled": true, "min_severity": 4, "device_id": 42 }
}
Errors
| Status | Body | When |
|---|---|---|
422 | {"status":false,"message":"Validation failed","errors":{…}} | enabled/min_severity invalid or out of range. |
404 | {"error":"Device not found"} | Unknown device, or outside your tag scope. |
500 | {"status":false,"message":"Error updating syslog configuration: …"} | Unexpected processing error. |
Example
curl -sS -X POST https://APPLIANCE/api/syslog/config/42 \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"enabled":true,"min_severity":4}'