Network Toolsv7.0.20
Drive the appliance’s on-box diagnostics from the API — ping and MTR (streaming or blocking), traceroute, live SNMP walks, TCP port scans, throughput tests, and IP intelligence lookups.
These endpoints expose the appliance’s on-box network diagnostics — ping, MTR, traceroute, SNMP walk, TCP port scan, throughput testing (Ookla speed test and iPerf3), and IP intelligence (WHOIS, GeoIP). They back the Tools and Throughput pages in the web UI and are also the surface most heavily exercised by the MCP client.
These endpoints belong to the tools functional area; an MCP or OAuth token needs the mcp:tools scope, and the calling user needs the tools permission shown on each endpoint.
Ping and MTR stream their results; ping also ships a blocking JSON shape:
- A Server-Sent Events (SSE) variant (
SSEgetPingInfo,SSEgetMTRInfo) that streams onedata:frame per probe as the command runs. Consume it withcurl -N; the connection stays open until the command finishes. - A plain-JSON sibling (
getPingInfo) that blocks until the command completes and returns the full result in a single response. It exists primarily for the MCP client, which cannot consume an event stream. MTR has no JSON sibling — its SSE stream is the only shape.
Most targets (a hostname or IP) are supplied as a path segment, not a request body. Reverse-DNS (PTR) lookups are only performed on real IP literals — an attacker-supplied hostname is never resolved back, so a returned hostname for a hostname target is just the target echoed back.
The SNMP walk and last-walk endpoints are tag-scoped: a tag-restricted operator can only walk or read devices within their assigned tags; a user with no tag restriction sees every device, and sa bypasses scoping entirely.
Ping
Stream a ping (SSE)
GET/api/SSEgetPingInfo/{pingTarget}tools
Runs ping -c 10 against the target and streams each reply as it arrives, then a final summary frame. The stream stays open until all ten probes complete (roughly ten seconds). Use the JSON sibling below if you need a single blocking response.
Path parameters
| Name | Type | Notes |
|---|---|---|
pingTarget | string | Hostname or IP to ping. |
Response text/event-stream
One frame per successful reply carries the sequence number and round-trip time; a final frame carries the packet-loss summary:
data: {"icmp_seq":"1","latency":"12.4","summary":null}
data: {"icmp_seq":"2","latency":"11.9","summary":null}
data: {"summary":{"total_transmitted":"10","total_received":"10","packet_loss":"0"}}
On a processing error a named error event is emitted instead:
event: error
data: {"message":"Failed to start the process."}
Example
curl -N https://APPLIANCE/api/SSEgetPingInfo/8.8.8.8 \
-H "Authorization: Bearer $TOKEN"
Ping (single JSON response)
POST/api/getPingInfo/{pingTarget}tools
Runs ping -c 4 against the target and returns one summarized result. This is the blocking, MCP-friendly counterpart to the SSE stream above. The shell-out is bounded (per-packet and overall deadlines) so an unreachable target returns within about ten seconds.
Path parameters
| Name | Type | Notes |
|---|---|---|
pingTarget | string | Hostname or IP to ping. |
Response 200
The result is JSON-encoded into the message string. latency is the average RTT in milliseconds (rounded), status is true when at least one reply was received, and hostname is the PTR record when the target was an IP literal (otherwise the target is echoed back).
{
"status": 201,
"message": "{\"address\":\"8.8.8.8\",\"latency\":11.8,\"status\":true,\"hostname\":\"dns.google\"}"
}
On failure (unknown host or unexpected output):
{ "status": false, "message": "Ping failed: unknown host" }
Example
curl -sS -X POST https://APPLIANCE/api/getPingInfo/8.8.8.8 \
-H "Authorization: Bearer $TOKEN"
MTR
Stream an MTR report (SSE)
GET/api/SSEgetMTRInfo/{mtrTarget}tools
Runs mtr -n --raw -c 10 against the target and streams one frame per probe event, so a client can build the hop table live. Each frame is typed: sent when a probe is dispatched to a hop, host when a hop’s IP is discovered, and reply when a response is received (with latency in milliseconds). DNS is suppressed (-n), so hops are reported as IPs. A terminal stream-complete event marks end-of-stream (emitted on success and on error).
Path parameters
| Name | Type | Notes |
|---|---|---|
mtrTarget | string | Hostname or IP to trace. |
Response text/event-stream
data: {"type":"sent","hop":0}
data: {"type":"host","hop":0,"host":"10.0.0.1"}
data: {"type":"reply","hop":0,"latency":1.42}
event: stream-complete
data: {}
On error, an error frame precedes the terminal event:
event: error
data: {"message":"Failed to start the process."}
event: stream-complete
data: {}
Example
curl -N https://APPLIANCE/api/SSEgetMTRInfo/8.8.8.8 \
-H "Authorization: Bearer $TOKEN"
Traceroute
Run a traceroute
POST/api/getTracerouteInfo/{traceTarget}tools
Runs traceroute --mtu -m 10 against the target and returns the full hop list in one blocking response. PTR lookups are performed only when a hop address is an IP literal; otherwise hostname is "N/A".
Path parameters
| Name | Type | Notes |
|---|---|---|
traceTarget | string | Hostname or IP to trace. |
Response 200
message is an array of hop objects. latency is in milliseconds, mtu is the path-MTU value when traceroute reported one (otherwise null).
{
"status": 201,
"message": [
{ "hop": 1, "address": "10.0.0.1", "latency": 1.2, "hostname": "gateway.local", "mtu": 1500 },
{ "hop": 2, "address": "203.0.113.1", "latency": 8.7, "hostname": "N/A", "mtu": null }
]
}
Example
curl -sS -X POST https://APPLIANCE/api/getTracerouteInfo/8.8.8.8 \
-H "Authorization: Bearer $TOKEN"
SNMP walk
Run a fresh SNMP walk
POST/api/getSNMPWalkInfo/{target}tools
Performs a live SNMP walk against a monitored device using its stored credentials and returns the decoded result. This is a long operation (the walk tool runs with a generous timeout), so prefer the cached last walk endpoint below when a recent result is acceptable.
Path parameters
| Name | Type | Notes |
|---|---|---|
target | integer | Device id to walk. Must be a device visible to the caller’s tags. |
Response 200
message is the decoded walk output (the shape depends on what the device returns).
{
"status": 201,
"message": { "…": "decoded SNMP walk output" }
}
If the device id is unknown or outside the caller’s tag scope:
{ "status": false, "message": "Invalid device specified" }
Example
curl -sS -X POST https://APPLIANCE/api/getSNMPWalkInfo/42 \
-H "Authorization: Bearer $TOKEN"
Get the last SNMP walk
GET/api/getLastWalk/{device}tools
Returns the most recent stored walk for a device without running a fresh one. Tag-scoped identically to the live walk above.
Path parameters
| Name | Type | Notes |
|---|---|---|
device | integer | Device id whose stored walk to fetch. |
Response 200
walk is the stored walk row, or null if the device has no stored walk yet.
{
"status": 201,
"walk": { "device_id": 42, "…": "stored walk row" }
}
If the device id is unknown or outside the caller’s tag scope:
{ "status": false, "message": "Invalid device specified" }
Example
curl -sS https://APPLIANCE/api/getLastWalk/42 \
-H "Authorization: Bearer $TOKEN"
Port scan
Scan TCP ports
POST/api/getPortscanInfotools
Runs an nmap-based TCP port scan against a target. The scan is bounded by a per-host timeout so even a wide range returns partial results rather than running until the request times out.
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
ip | string | yes | Target IP to scan. |
portlist | string | yes | Port specification passed to the scanner (e.g. 1-1024 or 80,443,8080). |
timing | string | no | Scan speed: 3, 4, or 5 (nmap timing template). Any other value falls back to 4 (Fast). |
service | boolean | no | When true, enables service/version detection (slower). |
Response 200
On success, message is the raw scanner output as a string:
{ "status": 201, "message": "…raw nmap output…" }
Errors
| Status | Body | When |
|---|---|---|
200 | {"status":"timeout","message":"The scan timed out before completing…"} | Scan exceeded the host and request budgets. Try a smaller range, faster speed, or disable service detection. |
200 | {"status":false,"message":"Failed to process portscan request"} | The scanner process failed. |
Timeout and failure are reported with an HTTP 200 and a status field ("timeout" or false), not a non-2xx status code. Inspect status rather than relying on the HTTP code.
Example
curl -sS -X POST https://APPLIANCE/api/getPortscanInfo \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"ip":"10.0.0.5","portlist":"1-1024","timing":"4","service":false}'
List TCP service names
GET/api/getPortServiceNamestools
Returns the operator-maintained TCP service-name catalogue (Settings → Protocols), keyed by port number, used by the Port Scan tool to label discovered ports with friendly names. The catalogue is sparse — only ports an operator has named appear.
Response 200
services is an object mapping port number to friendly name.
{
"status": 200,
"services": { "22": "SSH", "443": "HTTPS", "8080": "Web Proxy" }
}
Example
curl -sS https://APPLIANCE/api/getPortServiceNames \
-H "Authorization: Bearer $TOKEN"
Speed test
Run an Ookla speed test
POST/api/getSpeedTestInfotools
Runs an Ookla speedtest-cli measurement from the appliance and returns the full JSON result. The result is also recorded in the throughput history (kind: "speedtest").
Response 201
message is the decoded speedtest JSON (download/upload throughput, ping, server, client, etc.).
{
"message": {
"download": 94300000,
"upload": 11200000,
"ping": 13.7,
"server": { "…": "…" }
}
}
Errors
| Status | Body | When |
|---|---|---|
500 | {"message":"Failed to process speedtest request, …"} | The speedtest process failed. |
500 | {"status":false,"message":"JSON decode error: …"} | Output could not be parsed. |
Example
curl -sS -X POST https://APPLIANCE/api/getSpeedTestInfo \
-H "Authorization: Bearer $TOKEN"
Get throughput history
GET/api/getSpeedTestHistorytools
Returns the shared throughput history feed — both Ookla speed-test runs and iPerf3 client runs, newest first. The kind field discriminates the two result shapes; target carries the iPerf client’s host. Rows are retained for twelve weeks by a background janitor.
Response 200
{
"data": [
{ "id": 88, "timestamp": "2026-06-15T10:02:00Z", "kind": "iperf_client", "target": "10.0.0.9", "result": { "…": "…" } },
{ "id": 87, "timestamp": "2026-06-15T09:40:00Z", "kind": "speedtest", "target": null, "result": { "…": "…" } }
]
}
Example
curl -sS https://APPLIANCE/api/getSpeedTestHistory \
-H "Authorization: Bearer $TOKEN"
Delete a throughput history row
DELETE/api/speedtest-history/{id}tools
Deletes a single throughput history row (any kind) by id.
This permanently removes the history row. It cannot be undone.
Path parameters
| Name | Type | Notes |
|---|---|---|
id | integer | History row id to delete. |
Response 200
{ "status": 200 }
Example
curl -sS -X DELETE https://APPLIANCE/api/speedtest-history/88 \
-H "Authorization: Bearer $TOKEN"
iPerf
The iPerf3 surface has two halves. Client mode is a one-shot measurement against a remote iPerf server. Server mode is a singleton listener on port 5201, managed as a systemd unit — its start/stop/status form a small lifecycle with no database row (systemd is the source of truth).
Starting the iPerf server opens an unauthenticated, bandwidth-saturating listening socket on port 5201. The appliance runs no host firewall, so reachability on its network segment is the operator’s responsibility. Stop the server when the test is done.
Run an iPerf client measurement
POST/api/iperf/client/runtools
Runs iperf3 -c <host> against a remote iPerf server and returns the full JSON result. This is a synchronous, blocking call (it waits for the test duration plus a margin). The result is recorded in the throughput history with kind: "iperf_client".
Request body
| Field | Type | Required | Notes |
|---|---|---|---|
host | string | yes | Target iPerf server (IP or hostname). Max 255. |
port | integer | no | Server port, 1–65535. Defaults to 5201. |
duration | integer | no | Test length in seconds, 1–60. Defaults to 10. |
protocol | string | no | tcp (default) or udp. |
direction | string | no | download (default, server→client) or upload (client→server). |
Response 201
message is the decoded iPerf3 JSON result.
{ "message": { "start": { "…": "…" }, "end": { "sum_received": { "bits_per_second": 9.4e8 } } } }
Errors
| Status | Body | When |
|---|---|---|
422 | {"status":false,"message":"Invalid host"} | Host failed the argv-clean check. |
502 | {"status":false,"message":"iperf3: …"} | iperf3 reported a connection/run error (e.g. server unreachable). |
502 | {"status":false,"message":"iperf3 run failed: …"} | Process failed or output was not parseable JSON. |
500 | {"status":false,"message":"…"} | Unexpected server error. |
Example
curl -sS -X POST https://APPLIANCE/api/iperf/client/run \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"host":"10.0.0.9","duration":10,"protocol":"tcp","direction":"download"}'
Start the iPerf server
POST/api/iperf/server/starttools
Starts the singleton iPerf3 listener (systemd unit) on port 5201. Returns the current server state.
Response 200
{ "active": true, "state": "active", "port": 5201, "connectHost": "APPLIANCE" }
Errors
| Status | Body | When |
|---|---|---|
500 | {"status":false,"message":"Failed to start iperf server"} | The systemd unit failed to start. |
Example
curl -sS -X POST https://APPLIANCE/api/iperf/server/start \
-H "Authorization: Bearer $TOKEN"
Stop the iPerf server
POST/api/iperf/server/stoptools
Stops the iPerf3 listener. Idempotent — stopping an already-stopped unit succeeds. Returns the current server state.
Response 200
{ "active": false, "state": "inactive", "port": 5201, "connectHost": "APPLIANCE" }
Errors
| Status | Body | When |
|---|---|---|
500 | {"status":false,"message":"Failed to stop iperf server"} | The systemd unit failed to stop. |
Example
curl -sS -X POST https://APPLIANCE/api/iperf/server/stop \
-H "Authorization: Bearer $TOKEN"
Get the iPerf server status
GET/api/iperf/server/statustools
Returns the current iPerf3 server state without changing it. connectHost is the host the caller reached the appliance on — the address to point an iperf3 -c client at.
Response 200
{ "active": true, "state": "active", "port": 5201, "connectHost": "APPLIANCE" }
Example
curl -sS https://APPLIANCE/api/iperf/server/status \
-H "Authorization: Bearer $TOKEN"
IP lookup
WHOIS lookup
GET/api/tools/whois/{ip}tools
Runs a whois lookup for an IP and returns the parsed key/value pairs. The IP is validated server-side; comment and blank lines are stripped, and each key: value line becomes an entry in message.
Path parameters
| Name | Type | Notes |
|---|---|---|
ip | string | IP address to look up. Must be a valid IPv4/IPv6 literal. |
Response 200
{
"status": 201,
"message": { "NetName": "EXAMPLE-NET", "Organization": "Example Org", "Country": "US" }
}
On an invalid IP or lookup failure:
{ "status": false, "message": "Invalid IP address format" }
Example
curl -sS https://APPLIANCE/api/tools/whois/203.0.113.10 \
-H "Authorization: Bearer $TOKEN"
GeoIP lookup
GET/api/tools/geoip/{ip}tools
Returns geolocation data for an IP in message.
The appliance serves its own stored geolocation when it already has one — the name resolver geolocates the public addresses it resolves — and queries the external GeoIP service only on a miss, caching that result for later callers. The response shape is the same either way, so a cached answer is indistinguishable from a live one and carries no freshness guarantee.
Only globally-routable addresses can be looked up. Private, loopback, link-local, CGNAT, multicast and reserved addresses are rejected — they have no public geolocation.
Path parameters
| Name | Type | Notes |
|---|---|---|
ip | string | IP address to look up. Must be a valid IPv4/IPv6 literal, and globally routable. |
Response 200
message is the decoded GeoIP provider response (country, region, city, coordinates, etc.).
{
"status": 201,
"message": { "countryName": "United States", "regionName": "California", "cityName": "Mountain View", "latitude": 37.39, "longitude": -122.08 }
}
On an invalid IP or upstream failure:
{ "status": false, "message": "Invalid IP address format" }
Example
curl -sS https://APPLIANCE/api/tools/geoip/203.0.113.10 \
-H "Authorization: Bearer $TOKEN"