Netmon Docs · API Reference

Packet Capturev7.0.20

Cut a pcapng capture straight from the appliance’s live monitoring stream: define an optional L4 filter, then either poll the growing capture in chunks or download the finished file.

Packet captures are cut directly from the appliance’s live monitoring stream — no separate capture process, no temporary tap to configure. You define an optional L4 filter (hosts, ports, protocols, VLANs, interfaces), the appliance starts writing matching packets to disk as a pcapng stream, and you either poll the growing capture in chunks or download the finished file. Captures are bounded by a byte cap and a deadline so a forgotten capture cannot fill the disk.

These endpoints belong to the capture functional area; an MCP or OAuth token needs the mcp:capture scope, and the calling user needs the capture permission (shown on each endpoint). The permission is enforced regardless of how the bearer token was obtained.

Captures are user-scoped and tag-scoped. A non-admin user sees and operates on only their own captures; requesting a capture you do not own returns 404, indistinguishable from a non-existent id. The sa (super-admin) role bypasses this and sees every capture. Tag-scoping folds in at the device-association layer where a capture targets a specific device.

Lifecycle. A capture moves through startingrunningstopped/expired/failed. Create returns a row in starting and transitions it to running once the capture engine accepts it. There is a cap on how many captures can run at once across the whole appliance; when it is reached, create returns 503 and no row is left behind. Stop is idempotent. A capture cannot be deleted while still active — stop it first.

Captures

List captures

GET/api/capturescapture

Returns the caller’s captures (or all captures for sa), newest first, capped at 200 rows.

Response 200

{
  "captures": [
    {
      "id": 42,
      "user_id": 3,
      "device_id": 88,
      "label": "web-debug",
      "filter": { "ports": [443] },
      "status": "running",
      "started_at": "2026-06-15T14:00:00Z",
      "ended_at": null,
      "expires_at": "2026-06-16T14:00:00Z",
      "packets": 1840,
      "bytes": 2310455,
      "byte_cap": 10485760,
      "created_at": "2026-06-15T14:00:00Z"
    }
  ]
}

Example

curl -sS https://APPLIANCE/api/captures \
  -H "Authorization: Bearer $TOKEN"

Create a capture

POST/api/capturescapture

Starts a new capture against the live stream. The filter key must be present but may be an empty object {}, which means “capture every packet on the chosen interface(s)”. The response returns the capture row already transitioned to running.

Request body

FieldTypeRequiredNotes
labelstringnoFree-text label, max 255.
device_idintegernoAssociate the capture with a device (must exist).
byte_capintegernoStop after this many bytes. Min 65536, max 1073741824 (1 GB). Default 10485760 (10 MB).
deadline_sintegernoStop after this many seconds. Min 10, max 86400. Default 600.
ephemeralbooleannoMark as a short-lived poll-driven capture (reaped quickly when polling stops).
filterobjectyesMust be present; {} captures everything.
filter.hostsarray of stringnoIP addresses to match (any direction).
filter.portsarray of integernoTCP/UDP ports, 1–65535.
filter.protocolsarray of stringnoAny of tcp, udp, icmp.
filter.vlansarray of integernoVLAN ids, 0–4095.
filter.ifacesarray of stringnoInterface names to restrict to, max 32 chars each.

Response 201

{
  "capture": {
    "id": 42,
    "user_id": 3,
    "label": "web-debug",
    "filter": { "ports": [443] },
    "status": "running",
    "started_at": "2026-06-15T14:00:00Z",
    "byte_cap": 10485760
  }
}

Errors

StatusBodyWhen
422{"message":...,"errors":{...}}Validation failed.
422{"status":"error","reason":"…","message":"Filter or interface invalid."}The capture engine rejected the filter or interface.
503{"status":"error","reason":"too-many","message":"Maximum concurrent captures reached. Stop one and try again."}Concurrent-capture cap reached; no row is created.
502{"status":"error","message":"capture daemon unavailable"}Capture engine unreachable.

Example

curl -sS -X POST https://APPLIANCE/api/captures \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"label":"web-debug","filter":{"ports":[443],"protocols":["tcp"]}}'

Get a capture

GET/api/captures/{id}capture

Returns one capture’s status row. If the capture is still starting or running, its packet/byte counters and status are refreshed live before returning.

Path parameters

NameTypeNotes
idintegerCapture id. Out-of-scope or unknown ids return 404.

Response 200

{ "capture": { "id": 42, "status": "running", "packets": 1840, "bytes": 2310455 } }

Errors

StatusBodyWhen
404{"status":"error","message":"not found"}Unknown id, or a capture you do not own.

Stop a capture

POST/api/captures/{id}/stopcapture

Stops a running capture and finalizes its packet/byte totals. Idempotent — stopping an already-stopped, expired, or failed capture simply returns its current row.

Path parameters

NameTypeNotes
idintegerCapture id.

Response 200

{ "capture": { "id": 42, "status": "stopped", "ended_at": "2026-06-15T14:05:00Z", "packets": 5210, "bytes": 7340032 } }

Errors

StatusBodyWhen
404{"status":"error","message":"not found"}Unknown id, or not yours.

Delete a capture

DELETE/api/captures/{id}capture

Removes the capture row, cascade-deletes its chunk pointers, and removes the on-disk chunk files. The capture must be stopped (or expired/failed) first.

Destructive

This permanently deletes the capture and all of its chunk files. The captured packets cannot be recovered afterward.

Path parameters

NameTypeNotes
idintegerCapture id.

Response 200

{ "status": "ok" }

Errors

StatusBodyWhen
404{"status":"error","message":"not found"}Unknown id, or not yours.
409{"status":"error","reason":"still-active","message":"Stop the capture before deleting."}Capture is still starting or running.

Capturable interfaces

List interfaces

GET/api/captures/interfacescapture

Returns the appliance’s configured capture interface names — the set you may reference in filter.ifaces when creating a capture.

Response 200

{ "interfaces": ["eth0", "eth1"] }

Example

curl -sS https://APPLIANCE/api/captures/interfaces \
  -H "Authorization: Bearer $TOKEN"

Polling chunks

Poll new chunks

GET/api/captures/{id}/chunkscapture

Polls for capture data written since a given sequence number, for streaming consumers (such as the Wireshark extcap integration). Each call returns the new chunks (base64-encoded pcapng fragments) and the highest sequence number it covered; pass that back as since on the next poll. The response is capped at 4 MB of chunk data per call, so a busy capture may take several polls to drain — keep polling while status is running. The first poll (since=0) also returns the pcapng section header block (pcapng_shb) so the consumer has a complete, valid pcapng stream.

Polling also serves as a liveness signal: ephemeral captures that stop being polled are reaped automatically.

Path parameters

NameTypeNotes
idintegerCapture id.

Query parameters

NameTypeNotes
sinceintegerReturn chunks with seq greater than this. Default 0 (also requests the SHB blob).

Response 200

{
  "status": "running",
  "last_seq": 12,
  "pcapng_shb": "TVCq+gEAAAA…",
  "chunks": [
    { "seq": 1, "data": "BgAAAA…" },
    { "seq": 2, "data": "BgAAAA…" }
  ]
}

The pcapng_shb field is present only on the first poll (since=0). data and pcapng_shb are base64-encoded raw pcapng bytes.

Errors

StatusBodyWhen
404{"status":"error","message":"not found"}Unknown id, or not yours.

Example

curl -sS "https://APPLIANCE/api/captures/42/chunks?since=0" \
  -H "Authorization: Bearer $TOKEN"

Downloading

Download the pcapng file

GET/api/captures/{id}/download.pcapngcapture

Streams the complete capture as a single pcapng file: the section header block followed by every chunk in sequence order. The body is streamed (not buffered), so even a 1 GB capture downloads without loading into memory. Pipe it to a file and open it in Wireshark.

The response is a binary file, not JSON:

Path parameters

NameTypeNotes
idintegerCapture id.

Errors

StatusBodyWhen
404{"status":"error","message":"not found"}Unknown id, or not yours.

Example

curl -sS https://APPLIANCE/api/captures/42/download.pcapng \
  -H "Authorization: Bearer $TOKEN" \
  -o web-debug.pcapng