NetFlow & VNEv7.0.20
Read the enriched traffic feed that powers the Visual Network Explorer — the raw per-flow feed, the aggregated conversation rollup, and the saved per-user filters that trim both.
The appliance ingests flow records (NetFlow / sFlow / IPFIX) exported by routers and switches, plus its own on-box deep-packet-inspection flow data, and surfaces them as a searchable traffic feed. The Visual Network Explorer (VNE) is built on top of this feed: each flow record is enriched with the source and destination device id, hostname, and device profile so the explorer can draw the conversation graph. Two views are available — the raw per-flow netflow feed, and an aggnetflow rollup that collapses a conversation’s source ports into a single record for a higher-level traffic picture.
These endpoints belong to the VNE functional area; an MCP or OAuth token needs the mcp:vne scope, and the calling user needs the vne Laravel permission shown on each endpoint. The permission is enforced regardless of how the bearer token was obtained.
Tag-scoping applies to the flow feeds. The two list endpoints scope results on the conversation endpoints: a tag-restricted user sees only flows whose source or destination IP belongs to a device inside their tags. A user with no tag restriction sees every flow, and the sa (super-admin) role bypasses scoping entirely. Note the axis is the conversation endpoints, not the exporting device — a flow is visible if either side of the conversation is in scope, even when the exporter is not.
Filters are personal exclusion rules. A “flow filter” is a saved, per-user exclusion: when enabled, flows matching it are removed from your netflow and aggnetflow results (the same saved filters apply to both feeds). Filters never broaden what you can see and never affect other users. The ad-hoc filters query parameter on the list endpoints, by contrast, narrows a single request inline.
Flow records
List flow records
GET/api/netflow/listvne
Returns flow records ordered by byte count (largest first), enriched with device id / hostname / profile for both endpoints, a resolved protocol name, and a computed bits-per-second value. Without an explicit time window the feed returns only currently-active flows (those whose end time is now or later).
Query parameters
| Name | Type | Notes |
|---|---|---|
startTime | datetime | Window start. Must be paired with endTime; must be before it. |
endTime | datetime | Window end. When both times are given, records with start_time >= startTime and end_time <= endTime are returned. |
limit | integer | Page size (default 1000). The response is paginated. |
page | integer | Page number (standard Laravel pagination). |
filters | string (JSON) | Inline ad-hoc filter object. Keys: src_ip, src_port, dst_ip, dst_port, bytes, packets, start_time, end_time, protocol, in_iface, out_iface, flow_src, vlan, plus the convenience keys ip (matches either source or destination IP) and port (matches either source or destination port). Each value may be a scalar or an array (array = OR-match). |
Response 200
The body is a standard paginated envelope. Each item is a flow row with the enrichment keys (src_id, src_host, src_profile, dst_id, dst_host, dst_profile, prot_name, bps) merged in where a DNS/device match exists. The requested startTime / endTime are echoed back (they are null when no window was supplied).
{
"current_page": 1,
"data": [
{
"src_ip": "10.0.0.5", "src_port": 51344,
"dst_ip": "8.8.8.8", "dst_port": 443,
"protocol": 6, "bytes": 184320, "packets": 220,
"start_time": "2026-06-15T09:00:00Z", "end_time": "2026-06-15T09:00:30Z",
"flow_src": "10.0.0.1", "vlan": 0,
"src_id": 42, "src_host": "workstation-5", "src_profile": "windows",
"prot_name": "https", "bps": 49152
}
],
"per_page": 1000,
"total": 1,
"startTime": null,
"endTime": null
}
Errors
| Status | Body | When |
|---|---|---|
400 | {"status":false,"message":"startTime must be before endTime."} | Time window inverted, or any other processing error. |
Example
curl -sS "https://APPLIANCE/api/netflow/list?limit=50&filters=%7B%22port%22%3A443%7D" \
-H "Authorization: Bearer $TOKEN"
Aggregated flow
List aggregated flow records
GET/api/aggnetflow/listvne
Returns the aggregated flow rollup, where a conversation’s many source ports are collapsed into a single src_ports array per (src_ip, dst_ip, dst_port, protocol, …) tuple. The same endpoint enrichment, protocol-name lookup, and bps calculation as the raw feed are applied. Default sort is by start time (newest first); pass sort=bytes to order by volume.
Query parameters
| Name | Type | Notes |
|---|---|---|
startTime | datetime | Window start. Must be paired with endTime; must be before it. |
endTime | datetime | Window end. Without a window, only currently-active conversations are returned. |
sort | string | start_time (default) or bytes. Any other value falls back to start_time. Always descending. |
limit | integer | Page size (default 1000). |
page | integer | Page number. |
filters | string (JSON) | Inline ad-hoc filter object. Keys: src_ip, dst_ip, dst_port, bytes, start_time, end_time, protocol, in_iface, out_iface, flow_src, vlan, plus ip (either endpoint), port (matches dst_port), and src_port (matched against the aggregated src_ports array). |
Response 200
Same paginated envelope and enrichment as netflow/list; each row additionally carries the aggregated src_ports array instead of a single src_port.
{
"current_page": 1,
"data": [
{
"src_ip": "10.0.0.5", "src_ports": [51344, 51345, 51360],
"dst_ip": "8.8.8.8", "dst_port": 443,
"protocol": 6, "bytes": 552960,
"start_time": "2026-06-15T09:00:00Z", "end_time": "2026-06-15T09:05:00Z",
"src_id": 42, "src_host": "workstation-5", "src_profile": "windows",
"prot_name": "https", "bps": 14745
}
],
"per_page": 1000,
"total": 1,
"startTime": null,
"endTime": null
}
Errors
| Status | Body | When |
|---|---|---|
400 | {"status":false,"message":"startTime must be before endTime."} | Time window inverted, or any other processing error. |
Example
curl -sS "https://APPLIANCE/api/aggnetflow/list?sort=bytes&limit=20" \
-H "Authorization: Bearer $TOKEN"
Flow filters
Flow filters are saved per-user exclusion rules shared between the raw and aggregated feeds. The four operations below mirror the filter pattern used by the log streams.
List flow filters
GET/api/netflow/filtersvne
Returns the calling user’s saved flow filters.
Response 200
{
"message": "Filters retrieved successfully!",
"filters": [
{ "id": 7, "label": "ignore backups", "filter": {"dst_port": 873}, "enabled": 1 }
]
}
Create or update a flow filter
POST/api/netflow/filtersvne
Creates a new saved filter, or updates an existing one when an id is supplied. A filter must contain at least one criterion with a non-empty value, and every criterion key must be a recognized flow column.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
label | string | yes | Max 255 characters. |
filter | string (JSON) | yes | A JSON object. Allowed keys: src_ip, src_port, dst_ip, dst_port, protocol, in_iface, out_iface, flow_src, vlan, plus ip and port. At least one key must carry a value. |
id | integer | no | Present = update that filter (must belong to you). Absent = create. |
Response 201 (create) / 200 (update)
{
"message": "Filter created successfully!",
"filter": { "id": 8, "users_id": 3, "label": "ignore backups", "filter": {"dst_port": 873}, "enabled": true }
}
Errors
| Status | Body | When |
|---|---|---|
422 | {"label":["The label field is required."]} | Validation failed (label/filter/id). |
422 | {"error":"Filter cannot be empty."} | filter decoded to an empty object. |
422 | {"error":"Filter must contain at least one criterion 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 the filter is missing or owned by another user. |
Example
curl -sS -X POST https://APPLIANCE/api/netflow/filters \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"label":"ignore backups","filter":"{\"dst_port\":873}"}'
Toggle a flow filter
POST/api/netflow/filters/toggle/{filterId}vne
Flips the enabled state of one of your filters. The full updated filter list is returned so a client can re-render immediately.
Path parameters
| Name | Type | Notes |
|---|---|---|
filterId | integer | Filter id. Must belong to you. |
Response 201
{
"message": "Filter toggled successfully!",
"filters": [ { "id": 7, "label": "ignore backups", "filter": {"dst_port": 873}, "enabled": false } ]
}
Errors
| Status | Body | When |
|---|---|---|
404 | {"error":"Filter not found or access denied."} | No such filter owned by you. |
Delete a flow filter
DELETE/api/netflow/filters/{filterId}vne
Permanently deletes one of your saved 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. |