Netmon Docs · API Reference

System Settings & Terminalv7.0.20

Read and write the appliance’s own configuration — network interfaces, hostname and DNS, local networks, clock, SMTP relay, license, HTTPS certificate, protocol labels, downloadables, and daemon services — plus a few diagnostic actions and the in-browser terminal proxy.

These endpoints configure the appliance itself: its network interfaces, hostname and the local DNS map, the monitored local networks (the ranges the discovery scanner sweeps), the system clock and time zone, the SMTP relay used to send alert email, the product license, the HTTPS certificate, the custom-protocol port labels, the downloadable satellite installers, and the running daemon services. It also exposes a few diagnostic actions — read an appliance health snapshot, restart the monitoring stack, pull a log archive, and create or download a full backup.

These endpoints belong to the system functional area; an MCP or OAuth token needs the mcp:system scope. Most endpoints additionally require the calling user to hold the system permission. Four certificate endpoints are super-admin-only and require the sa permission instead — this is called out on each. These are appliance-wide settings with no tag anchor, so tag-scoping does not apply here; every system-permission user sees the same configuration.

Response envelope

Most endpoints in this chapter predate the modern REST conventions and return a custom envelope. Success is typically {"status": 201, "hasError": false, ...} — note that the numeric status is sent as a field in an HTTP 200 response, not as the HTTP status code. Failure is usually {"status": false, "hasError": true, "message": "..."}, also returned with HTTP 200. Do not key automation off the HTTP status alone for these endpoints; read the hasError field. The certificate and license endpoints are the exception — they return real HTTP 4xx/5xx codes, noted per endpoint.

Services

Read the running service table and control individual daemons or the whole monitoring stack.

List services

GET/api/manageNetmonServicessystem

Returns the current state of every monitored service as reported by the service controller. Use it to render a services dashboard or to confirm a daemon is running before acting on it.

Response 200

{
  "status": 201,
  "hasError": false,
  "data": {
    "services": [
      { "name": "snmpmond", "status": "running", "pid": "4123" }
    ]
  }
}

The per-service object keys are whatever attributes the service controller reports for each entry. If the controller cannot be reached the response is {"status": false, "hasError": true, "message": "Cannot communicate with service controller."}.

Start, stop, or restart a service

POST/api/procmonsystem

Sends a control signal to a single daemon through the process supervisor.

Request body

FieldTypeRequiredNotes
servicestringyesDaemon name, e.g. snmpmond.
actionstringyesSupervisor verb, e.g. start, stop, restart, reload.

Response 200

{ "status": 201, "hasError": false, "message": "OK" }

Errors

StatusBodyWhen
400{"hasError":true,"message":"Service and action are required."}Missing service or action.
500{"status":500,"hasError":true,"message":"..."}Supervisor communication failed.
Destructive

Stopping or restarting a daemon interrupts whatever monitoring it performs for the duration of the action.

Example

curl -sS -X POST https://APPLIANCE/api/procmon \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"service":"snmpmond","action":"restart"}'

Restart the monitoring stack

POST/api/restartNetmonsystem

Restarts the entire Netmon service (every daemon at once). There is no request body.

Response 200

{ "status": 200, "hasError": false, "message": "Netmon restarted successfully" }

Errors

StatusBodyWhen
500{"hasError":true,"message":"Failed to restart netmon"}The restart command exited non-zero.
Destructive

This bounces the whole monitoring stack. All polling, capture, and alerting pauses briefly while the daemons come back up.

Network interfaces

Read and write the appliance’s local network-interface configuration. Writes rewrite the per-interface config files and restart networking.

Get network interfaces

POST/api/getNetworkInfosystem

Lists every non-loopback interface with its live addresses and its persisted configuration (addressing mode, gateway, DNS servers, and whether the interface is assigned to packet capture or to the intrusion-detection engine). Despite the POST verb it takes no request body.

Response 200

{
  "status": 201,
  "hasError": false,
  "interfaces": [
    {
      "name": "eth0",
      "ipv4": [ { "address": "10.0.0.5", "netmask": "255.255.255.0" } ],
      "ipv6": [],
      "online": true,
      "config": {
        "allow-hotplug": false,
        "auto": true,
        "type": "static",
        "address": "10.0.0.5",
        "netmask": "255.255.255.0",
        "gateway": "10.0.0.1",
        "dns-nameservers": ["10.0.0.1", "1.1.1.1"],
        "use_sniffer": true,
        "use_suricata": false
      }
    }
  ]
}

An interface with no saved config file reports config.type as "unconfigured" with empty addressing fields. On failure the response is {"status": false, "hasError": true, "message": "..."}.

Set network interfaces

POST/api/setNetworkInfosystem

Rewrites the configuration for one or more interfaces and restarts networking. Submit the same shape returned by getNetworkInfo — an interfaces array, each element carrying a name and a config object.

Request body

FieldTypeRequiredNotes
interfacesarrayyesEach element is an interface object.
interfaces[].namestringyesInterface name (max 15 chars; letters, digits, _ . -).
interfaces[].config.typestringyesOne of static, dhcp, manual, unconfigured.
interfaces[].config.addressstringfor staticIPv4 or IPv4/CIDR.
interfaces[].config.netmaskstringfor staticNetmask.
interfaces[].config.gatewaystringnoIPv4 gateway.
interfaces[].config.dns-nameserversarraynoList of IP literals.
interfaces[].config.allow-hotplugbooleannoAdd an allow-hotplug directive.
interfaces[].config.use_snifferbooleannoAssign the interface to packet capture.
interfaces[].config.use_suricatabooleannoAssign the interface to the IDS engine.

All operator-supplied fields are validated against strict patterns; an invalid value rejects the whole request (no partial writes). Addressing values must be real IP literals.

Response 200

{ "status": 201, "hasError": false }

On error (validation failure or a failed systemctl restart networking) the response is {"status": false, "hasError": true, "message": "..."}.

Destructive

Saving interface configuration restarts host networking. If you apply a bad address you can lose connectivity to the appliance over that interface.

Hostname & DNS

Set the appliance hostname and maintain the local hostname-to-IP map used to resolve names that aren’t in DNS.

Get hostname

GET/api/getHostnamesystem

Returns the appliance’s current hostname.

Response 200

{ "status": 200, "hasError": false, "hostname": "netmon-prod" }

Set hostname

POST/api/setHostnamesystem

Changes the appliance hostname via hostnamectl.

Request body

FieldTypeRequiredNotes
hostnamestringyesMax 255. Must be a valid DNS hostname/label.

Response 200

{ "status": 201, "message": "Hostname successfully updated", "hostname": "netmon-prod" }

Errors

StatusBodyWhen
422{"message":...,"errors":{...}}Validation failed (Laravel validator).
200{"status":false,"hasError":true,"message":"..."}hostnamectl failed.

List host map entries

POST/api/getHostnamessystem

Returns the local hostname database (static name-to-IP records), paginated.

Request body

FieldTypeRequiredNotes
pageintegernoPage number.
limitintegernoRows per page.

The body is a JSON-encoded paginated result of host rows (id, ip, hostname, host_name_type, node_type, timestamp). On error the {"status": false, "hasError": true, "message": "..."} envelope is returned.

Create a host map entry

POST/api/createHostnamesystem

Adds a static hostname record. The combination of ip + hostname + host_name_type + node_type is checked for duplicates first.

Request body

FieldTypeRequiredNotes
ipstringyesIP address.
hostnamestringyesName to map.
host_name_typestringyesRecord type/source.
node_typestringyesNode classification.

Response 200

{ "status": 201, "hasError": false, "message": "..." }

If a matching record already exists the response is {"status": false, "hasError": true, "message": "..."} (already exists).

Update a host map entry

POST/api/updateHostnamesystem

Updates an existing host record by id.

Request body

FieldTypeRequiredNotes
idintegeryesHost record id.
ipstringyesIP address.
hostnamestringyesName to map.
host_name_typestringyesRecord type/source.
node_typestringyesNode classification.

Response 200

{ "status": 201, "hasError": false, "message": "..." }

Delete a host map entry

POST/api/deleteHostsystem

Removes a host record by id.

Request body

FieldTypeRequiredNotes
idintegeryesHost record id (must be > 0).

Response 200

{ "status": 201, "hasError": false, "message": "..." }

A non-positive id returns {"message": "..."} (invalid identifier); a missing record returns {"hasError": true, "message": "..."}.

Destructive

Permanently deletes the host record.

Local networks

Local networks (“localnets”) are the IP ranges the discovery scanner sweeps for new hosts. Each carries a label, a network/broadcast pair, a scan interval, and toggles for discovery and port scanning.

List local networks

GET/api/getLocalnetssystem

Returns every non-ephemeral local network with its settings, associated credential ids, and any attached legacy alerts.

Response 200

{
  "data": [
    {
      "id": 7,
      "label": "Office LAN",
      "network": "10.0.0.0",
      "broadcast": "10.0.0.255",
      "interval": 3600,
      "enable_discovery": true,
      "enable_portscan": false,
      "cred_ids": [3, 5],
      "alerts": null,
      "timestamp": 1718000000
    }
  ]
}

If there are no rows the endpoint returns false. On error it returns the {"status": false, "hasError": true, "message": "..."} envelope.

Create or update local networks

POST/api/updateLocalnetsystem

Upserts one or more local networks in a single call. Each element with no id is created; each with an id is updated. Credential associations are replaced wholesale from cred_ids.

Request body

FieldTypeRequiredNotes
dataarrayyesNon-empty array of localnet objects.
data[].idintegernoOmit to create a new row.
data[].labelstringyesDisplay label.
data[].networkstringyesValid IPv4 network address.
data[].broadcaststringyesValid IPv4 broadcast; must be >= network.
data[].intervalintegeryesScan interval (seconds).
data[].enable_discoverybooleanyesEnable host discovery.
data[].enable_portscanbooleanyesEnable port scanning.
data[].cred_idsarrayyesCredential ids to associate (replaces existing).

The subnet size (broadcast − network + 1) is capped at /16 (65,536 addresses); larger ranges must be split into multiple rows. One out-of-spec row rejects the whole batch.

Response 200

{ "status": 201, "hasError": false, "message": "OK" }

Errors

StatusBodyWhen
422{"status":false,"hasError":true,"message":"network must be a valid IPv4 address"}Invalid network.
422{"status":false,"hasError":true,"message":"broadcast must be >= network"}Broadcast below network.
422{"status":false,"hasError":true,"message":"subnet size exceeds /16 (65536 addresses) — split into multiple localnets rows"}Range too large.

Reset discovery timestamp

POST/api/resetDiscoveryTssystem

Forces a full re-scan of one local network on the next discovery cycle by zeroing its last-scanned timestamp.

Request body

FieldTypeRequiredNotes
idintegeryesLocal network id.

Response 200

{ "status": 201, "hasError": false }

A missing id returns {"status": false, "hasError": true, "message": "Invalid request parameters"}.

Delete a local network

POST/api/deleteLocalnetsystem

Removes a local network by id.

Request body

FieldTypeRequiredNotes
idintegeryesLocal network id (must be > 0).

Response 200

{ "status": 201, "hasError": false, "message": "..." }

A non-positive id returns {"message": "..."} (invalid identifier); a missing record returns {"hasError": true, "message": "..."}.

Destructive

Permanently deletes the local network and stops discovery against that range.

System time

Read the time configuration (time zone, NTP vs. manual mode, available zones) and set it.

Get time settings

GET/api/getTimeSettingssystem

Returns the current time zone, sync mode, configured NTP server (if any), the list of selectable time zones, and the appliance’s current Unix time.

Response 200

{
  "status": 201,
  "hasError": false,
  "data": {
    "tzs": ["Africa/Abidjan", "America/New_York", "..."],
    "tz": "America/New_York",
    "type": "ntp",
    "ntpserver": "pool.ntp.org",
    "time": 1718000000
  }
}

type is ntp or manual. ntpserver is present only in NTP mode. On error the {"status": false, "hasError": true, "message": "..."} envelope is returned.

Set time settings

POST/api/setTimeSettingssystem

Sets the time zone and either enables NTP with a server list or sets the clock manually.

Request body

FieldTypeRequiredNotes
typestringyesntp or manual.
tzstringyesTime zone (e.g. America/New_York).
ntpserverstringfor ntpSpace-separated list of hostnames/IPs.
manualstringfor manualISO-8601 timestamp to set the clock to.

In NTP mode each server entry is validated as a hostname or IP literal. In manual mode NTP is disabled and the clock is set directly.

Response 200

{ "status": 201, "hasError": false, "message": "..." }

On any failure the {"status": false, "hasError": true, "message": "..."} envelope is returned.

SMTP / email

A single endpoint handles reading, writing, and testing the SMTP relay used to send alert email. The behavior is selected by the action field.

Read, set, or test SMTP settings

POST/api/smtpSettingssystem

One endpoint, three actions:

Request body (get)

FieldTypeRequiredNotes
actionstringyes"get".

Request body (set)

FieldTypeRequiredNotes
actionstringyes"set".
senderstringyes“From” display name / address.
emailstringyesSender email address.
smtpserverstringyesSMTP server hostname.
portintegeryesSMTP port.
authbooleanyesWhether the server requires authentication.
usesslbooleanyesUse SSL/TLS.
authnamestringnoAuth username.
authpassstring | objectnoNew password, or the encrypted-field sentinel to keep the existing one.

Request body (test)

FieldTypeRequiredNotes
actionstringyes"test".

Response 200 (get)

{
  "status": 201,
  "hasError": false,
  "smtp": {
    "sender": "Netmon Alerts",
    "email": "alerts@example.com",
    "server": "smtp.example.com",
    "port": "587",
    "auth": "1",
    "usessl": "1",
    "authname": "alerts@example.com",
    "authpass": { "__encrypted__": true }
  }
}

Response 200 (set / test)

{ "status": 201, "hasError": false, "smtp": "Success" }

For a test, smtp is a message such as "Test email queued (id: 42)". An unknown action, a missing mail daemon, or an encryption failure returns {"status": false, "hasError": true, "message": "..."}.

Encrypted field

The SMTP authpass is stored encrypted and never returned in clear text. On get it is masked as {"__encrypted__": true}. On set, replay that exact sentinel (or send authpass empty/null) to keep the stored password unchanged; send a plaintext string only when you intend to set a new password.

Example (read SMTP settings)

curl -sS -X POST https://APPLIANCE/api/smtpSettings \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"action":"get"}'

Example (write SMTP settings)

curl -sS -X POST https://APPLIANCE/api/smtpSettings \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"action":"set","sender":"Netmon Alerts","email":"alerts@example.com",
       "smtpserver":"smtp.example.com","port":587,"auth":true,"usessl":true,
       "authname":"alerts@example.com","authpass":"s3cret"}'

Licensing

Read the product license and activate the appliance with a registration key.

Get license info

GET/api/getLicenseInfosystem

Returns the license record(s): company, license type, and the end-of-license / end-of-maintenance dates.

Response 200

{
  "status": 201,
  "hasError": false,
  "data": [
    {
      "company_name": "Acme Corp",
      "user_name": "admin",
      "user_email": "admin@example.com",
      "activation_key": "ABCDEF-012345-6789AB-CDEF01-234567-89ABCD",
      "license_type": "perpetual",
      "active": true,
      "activation_time": 1700000000,
      "end_of_license": 1800000000,
      "end_of_maintenance": 1800000000
    }
  ]
}

data is an empty array when the appliance is unlicensed. On error the response is {"status": false, "message": "..."}.

Example

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

Validate / apply a registration key

POST/api/validateLicensesystem

Stores a new activation key and restarts the monitoring stack so the new license takes effect.

Request body

FieldTypeRequiredNotes
registrationKeystringyesSix dash-separated groups of six hex characters, e.g. ABCDEF-012345-6789AB-CDEF01-234567-89ABCD.

Response 200

{ "status": 201, "hasError": false, "message": { "activation_key": "ABCDEF-..." } }

Errors

StatusBodyWhen
422{"status":false,"hasError":true,"message":"..."}Key fails the format regex.
200{"status":false,"message":"..."}Save failed.
Destructive

A successful call restarts the entire monitoring stack so the new license is picked up. Monitoring pauses briefly.

HTTPS certificate

The certificate endpoints manage the TLS certificate Apache serves the web UI and API over. All four require the sa (super-admin) permission, not the system permission used by the rest of these endpoints, and they return real HTTP status codes.

Get certificate info

GET/api/getCertificatesa

Permission sa (super-admin)

Returns parsed details of the installed certificate.

Response 200

{
  "subject": { "CN": "netmon.example.com" },
  "issuer": { "CN": "Let's Encrypt R3", "O": "Let's Encrypt" },
  "validFrom": "2026-01-01 00:00:00",
  "validTo": "2026-04-01 00:00:00"
}

Errors

StatusBodyWhen
404{"error":"Public key file not found"}No certificate installed.
400{"error":"Invalid public key"}Stored file is not a valid key.
500{"error":"Unable to ..."}Certificate could not be read/parsed.

Extract a certificate file

POST/api/extractCertificatesa

Permission sa (super-admin)

Parses an uploaded certificate file — a PEM (optionally with an encrypted key), a DER certificate, or a PKCS#12 (.pfx/.p12) bundle — and returns the extracted PEM certificate chain and private key for review before saving. Nothing is persisted. Send the file as multipart/form-data.

Request body (multipart/form-data)

FieldTypeRequiredNotes
filefileyesThe certificate file (max 512 KB).
passwordstringnoPassphrase for an encrypted key or PKCS#12 bundle (max 1024).

Response 200

{
  "status": 200,
  "certificate": "-----BEGIN CERTIFICATE-----\n...",
  "private_key": "-----BEGIN PRIVATE KEY-----\n..."
}

Errors

StatusBodyWhen
422{"status":422,"code":"invalid_request","message":"..."}Missing/oversized file.
400{"status":400,"code":"password_required","message":"..."}File is protected; no password given.
400{"status":400,"code":"bad_password","message":"..."}Wrong password.
400{"status":400,"code":"legacy_cipher","message":"..."}PKCS#12 uses a legacy (RC2/3DES) cipher OpenSSL 3 cannot read.
400{"status":400,"code":"unrecognized","message":"..."}Not a recognized certificate file.

Verify a certificate and key

POST/api/verifyCertificatesa

Permission sa (super-admin)

Validates that a certificate (or full chain) and a private key are well-formed and that they match — without saving anything.

Request body

FieldTypeRequiredNotes
publicstringyesPEM certificate (server cert first if a chain).
privatestringyesPEM private key (unencrypted).

Response 200

{ "status": 200, "message": "ok" }

Errors

StatusBodyWhen
400{"status":400,"message":"Both public and private keys are required"}Missing field.
400{"status":400,"message":"The certificate is not a valid PEM X.509 certificate."}Bad certificate.
400{"status":400,"message":"Certificate block N in the chain could not be parsed."}Truncated chain.
400{"status":400,"message":"The private key is encrypted. ..."}Encrypted key pasted.
400{"status":400,"message":"Invalid private key."}Bad key.
400{"status":400,"message":"Certificate and private key do not match. ..."}Mismatch.

Save a certificate

POST/api/saveCertificatesa

Permission sa (super-admin)

Verifies the certificate and key (same checks as verifyCertificate) and, if they pass, writes them to disk so Apache serves them after its next restart.

Request body

FieldTypeRequiredNotes
publicstringyesPEM certificate / chain.
privatestringyesPEM private key (unencrypted).

Response 201

{ "status": 201, "message": "ok" }

Errors

Returns the same 400 verification errors as verifyCertificate when the certificate/key fail validation.

Destructive

This overwrites the appliance’s installed TLS certificate and private key. An invalid pair that somehow passes can break HTTPS access until corrected, so verify first.

Custom protocols

Custom protocols are operator-defined labels that name a port/protocol pair so traffic to that port is shown with a friendly name throughout the UI.

List custom protocols

POST/api/getProtocolssystem

Returns the protocol labels, paginated. Despite the POST verb this is a read.

Request body

FieldTypeRequiredNotes
pageintegernoPage number.
limitintegernoRows per page.

The body is a JSON-encoded paginated result of protocol rows (id, port, protocol, name). On error the {"status": false, "hasError": true, "message": "..."} envelope is returned.

Get one custom protocol

POST/api/getProtocolsForSinglesystem

Fetches a single protocol label by id.

Request body

FieldTypeRequiredNotes
idintegeryesProtocol id.

Response 200

{
  "status": 201,
  "hasError": false,
  "data": { "id": 12, "port": 8443, "protocol": "tcp", "name": "Admin Console" }
}

A missing record returns {"status": false, "hasError": true, "message": "..."}.

Create a custom protocol

POST/api/createProtocolssystem

Adds a protocol label. The protocol + port + name combination is checked for duplicates first.

Request body

FieldTypeRequiredNotes
portintegeryesPort number.
protocolstringyese.g. tcp, udp.
namestringyesDisplay label.

Response 200

{ "status": 201, "hasError": false, "message": "..." }

A duplicate returns {"status": false, "hasError": true, "message": "..."} (already exists).

Update a custom protocol

POST/api/updateProtocolsystem

Updates a protocol label by id.

Request body

FieldTypeRequiredNotes
idintegeryesProtocol id.
portintegeryesPort number.
protocolstringyesProtocol.
namestringyesDisplay label.

Response 200

{ "status": 201, "hasError": false, "message": "..." }

Delete a custom protocol

POST/api/deleteProtocolsystem

Removes a protocol label by id.

Request body

FieldTypeRequiredNotes
idintegeryesProtocol id (must be > 0).

Response 200

{ "status": 201, "hasError": false, "message": "..." }

A non-positive id returns {"message": "..."} (invalid identifier); a missing record returns {"hasError": true, "message": "..."}.

Destructive

Permanently deletes the protocol label.

Downloadables

The appliance bundles operator-facing satellite installers and reference documents (the Windows agent, the Wireshark plugin, the product guide, the API reference). These two endpoints list and stream them.

List downloadables

GET/api/downloadablessystem

Returns the catalog grouped by category, each with the files staged on the appliance.

Response 200

{
  "categories": [
    {
      "key": "windows-agent",
      "label": "Windows Agent",
      "description": "Installer for the Netmon Windows agent.",
      "files": [
        { "filename": "netmon-agent-installer-7.0.20-amd64.exe", "size": 5242880, "mtime": 1718000000 }
      ]
    }
  ]
}

A category with nothing staged returns an empty files array.

Download a file

GET/api/downloadables/{category}/{filename}system

Streams one staged file as a binary download.

Path parameters

NameTypeNotes
categorystringCatalog category key (e.g. windows-agent).
filenamestringFile name from the catalog. May include one subdirectory segment (<subdir>/<file>); path traversal is rejected.

Response 200 — the file body, Content-Type: application/octet-stream, served as an attachment named after the file.

Errors

StatusBodyWhen
404{"status":false,"message":"File not found."}Unknown category or file.

Example

curl -sS https://APPLIANCE/api/downloadables/windows-agent/netmon-agent-installer-7.0.20-amd64.exe \
  -H "Authorization: Bearer $TOKEN" -o netmon-agent.exe

System health

A read-only self-diagnostic snapshot of the appliance, plus the one repair it offers. These are the endpoints behind the Settings → System → System Health card.

Get the health snapshot

GET/api/system/healthsystem

Runs every appliance self-check and returns one snapshot. Unlike most endpoints in this chapter it uses a plain JSON envelope, not {"status":201,...}. The call never fails on a bad probe: a check that cannot be evaluated is reported with severity unknown rather than raising an error, and the whole snapshot is bounded by a short wall-clock budget so it stays fast on loaded hardware.

Checks are grouped into four groups — scheduler (Scheduled Maintenance), storage (Storage), alerts (Alert Delivery), and platform (Platform). Every check and group carries a severity from ok, warn, crit, unknown — a group takes the worst severity among its checks, and overall the worst among the groups.

Response 200

{
  "overall": "warn",
  "generated_at": "2026-08-10T14:02:11+00:00",
  "groups": [
    {
      "id": "scheduler",
      "label": "Scheduled Maintenance",
      "severity": "warn",
      "checks": [
        {
          "id": "cron.parked",
          "label": "Scheduled jobs enabled",
          "severity": "warn",
          "summary": "3 of 11 scheduled jobs are disabled.",
          "detail": "Disabled: rotate_syslog_partition, cleanup_db, cleanup_hosts_geoip",
          "hint": "This is the signature of an interrupted package upgrade. …",
          "action": "cron-reenable"
        }
      ]
    },
    {
      "id": "storage",
      "label": "Storage",
      "severity": "ok",
      "checks": [
        {
          "id": "storage.backups",
          "label": "Database backups",
          "severity": "ok",
          "summary": "Most recent backup is 2 days old.",
          "link": { "kind": "anchor", "target": "nm-sys-card-backups" }
        }
      ]
    }
  ]
}

Check fields

FieldTypeNotes
idstringStable check identifier, e.g. cron.parked, storage.var_netmon.
labelstringHuman-readable check name.
severitystringok, warn, crit, or unknown.
summarystringOne-line result.
detailstringOptional. Supporting evidence (names, counts, sizes).
hintstringOptional. What the condition usually means and what to do.
linkobjectOptional. {"kind":"anchor"|"route","target":"..."} — the UI target that fixes it.
actionstringOptional. A remediation this API offers; today the only value is cron-reenable.

Example

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

Re-enable parked scheduled jobs

POST/api/system/health/cron-reenablesystem

Re-enables every disabled database scheduled job. An interrupted package upgrade can leave them all switched off, which stops partition rotation and every retention janitor. This is the remediation behind the cron-reenable action. Takes no request body, and is idempotent — a second call re-enables nothing and reports 0.

Response 200

{ "ok": true, "reenabled": 3 }

Example

curl -sS -X POST https://APPLIANCE/api/system/health/cron-reenable \
  -H "Authorization: Bearer $TOKEN"

Diagnostics & logs

Pull a diagnostic log archive and manage full appliance backups.

Download log archive

GET/api/downloadLogssystem

Builds and streams a ZIP of every file under the appliance log directory. Useful when attaching diagnostics to a support ticket.

Response 200 — a ZIP file, Content-Type: application/zip, attachment named logs.zip.

Errors

StatusBodyWhen
500{"error":"Failed to create zip archive"}The archive could not be created.

Example

curl -sS https://APPLIANCE/api/downloadLogs \
  -H "Authorization: Bearer $TOKEN" -o logs.zip

Create a full backup

POST/api/createFullBackupsystem

Dumps the database and the appliance configuration into a compressed archive in the backup directory. Guarded by an advisory lock so concurrent calls don’t collide.

Response 200

{ "status": 201, "hasError": false, "message": "Backup created successfully" }

If a backup is already running, or the database dump / archiving step fails, the response is {"hasError": true, "message": "..."}.

List backups

GET/api/backupssystem

Lists the backup archives on disk with their sizes and timestamps.

Response 200

{
  "backups": [
    { "name": "bk-1718000000.tgz", "size": 10485760, "date": "2026-06-10 04:00:00" }
  ]
}

Download a backup

GET/api/backups/{filename}system

Streams one backup archive as a binary download.

Path parameters

NameTypeNotes
filenamestringBackup file name from the list.

Response 200 — the file body, Content-Type: application/octet-stream, served as an attachment named after the file.

Errors

StatusBodyWhen
403{"message":"PRIVATE_KEY download is restricted to the super-admin account.","hasError":true}The reserved PRIVATE_KEY file is requested by a non-super-admin.
200{"message":"Backup not found.","hasError":true}File does not exist.
Restricted file

The reserved PRIVATE_KEY backup (the appliance RSA private key) can only be downloaded by the super-admin account; all other backups are available to any system-permission user.

Delete a backup

DELETE/api/backups/{filename}system

Deletes a backup archive from disk.

Path parameters

NameTypeNotes
filenamestringBackup file name.

Response 200

{ "message": "Backup deleted successfully.", "hasError": false }

Errors

StatusBodyWhen
403{"message":"PRIVATE_KEY deletion is restricted to the super-admin account.","hasError":true}The reserved PRIVATE_KEY file is targeted by a non-super-admin.
200{"message":"Backup not found.","hasError":true}File does not exist.
Destructive

Permanently deletes the backup archive. Deleting the reserved PRIVATE_KEY file is restricted to the super-admin account.

Alert templates

Read and edit the saved alert email templates (the per-alert-type message bodies). These are exposed here because they are configured from the system settings surface.

List alert templates

GET/api/getAlertTemplatessystem

Returns every alert type with its template fields.

Response 200

{
  "status": 200,
  "hasError": false,
  "data": [
    { "id": 1, "name": "Device Down", "template_up": "...", "template_down": "..." }
  ]
}

Update an alert template field

POST/api/setAlertTemplatesystem

Updates a single template field on one alert type.

Request body

FieldTypeRequiredNotes
idintegeryesAlert type id.
fieldstringyesTemplate field name (e.g. template_up). Must be an existing field on the row.
valuestringyesNew field value.

Response 200

{ "status": 201, "hasError": false, "data": { "id": 1, "template_up": "..." } }

An unknown alert type or an invalid field returns {"status": 400, "hasError": true, "message": "..."}.

System Terminal

The appliance ships an in-browser terminal — a web shell rendered inside the Netmon UI. The single endpoint below is the reverse proxy that bridges the browser to that on-box terminal service. It is not a REST endpoint and is not meant for scripting; it exists so the SPA’s Terminal pane can talk to the local terminal over the same authenticated origin as the rest of the UI.

This endpoint belongs to the system functional area (mcp:system scope), but unlike the rest of the API it authenticates against a browser web session, not a bearer token, and is gated by the system permission.

Proxy to the on-box terminal

ANY/api/term/proxy/{path?}system

Permission system

A transparent reverse proxy to the appliance’s local terminal service. Every HTTP method is accepted, and the optional trailing {path?} (including slashes) is forwarded verbatim along with the request method, headers, body, and query string. The upstream response — status, headers, and body — is returned unchanged. This carries the terminal’s HTML, JavaScript, and its interactive request/response traffic; the payloads are terminal protocol data, not JSON.

Browser-driven, not for scripting

This route is opened by the web UI’s Terminal pane using your logged-in browser session (cookies), not a Passport bearer token. There is no stable JSON contract here — it is a passthrough to a separate terminal service. Drive it through the UI; do not target it from automation.

Path parameters

NameTypeNotes
pathstringOptional. Forwarded verbatim to the upstream terminal service, slashes included. Defaults to the terminal root.

Response

The upstream terminal service’s response, proxied through unchanged (status code, headers, and body). Content type is whatever the terminal emits (HTML, JavaScript, or terminal stream data) — not a JSON envelope.

Errors

StatusBodyWhen
502{"message":"Terminal unavailable"}The upstream terminal service could not be reached.