Netrinos Edgenode API Documentation

Authentication

Login to Obtain Access Token

To access the API, you must first log in to the device and obtain an access token.
The account used also needs the API role assigned in the portal.
The token will be valid for the duration of the client login.

Alternatively, if the reqest is received on localhost (127.0.0.1) the token requirement will be ignored.

Request

POST http://edgedevice:88/api/login
{
    "Username": "username",
    "Password": "password"
}

Response

Status: 200 OK
{
  "success": "Login successful",
  "error": "",
  "data": {
    "AuthToken": "e0db2c0d81...d52cd273db",
    "Username": "username"
  }
}

Error Response

Status: 401 Unauthorized
{
  "success": "",
  "error": "Invalid username or password",
  "data": null
}

Use AuthToken as a Bearer token in the header of API requests:

Authorization: Bearer e0db2c0d81...d52cd273db

Test the Token

Check if the token is valid, send a ping request to the API.

Request

GET http://edgedevice:88/api/ping

Response

Status: 200 OK
{
  "success": "Success",
  "error": "",
  "data": null
}

Error Response

Status: 401 Unauthorized
Unauthorized - Invalid token

Networks

Create or Update

Request

POST http://edgedevice:88/api/edge/network/192.168.2.0-24
POST http://edgedevice:88/api/edge/network/192.168.2.0

Response

Status: 200 OK
{
  "success": "Network created",
  "error": "",
  "data": {
    "Network": {
      "Name": "192.168.2.0/24",
      "IFname": "",
      "HostIPMask": "",
      "HostIP": "",
      "HostMask": 0,
      "NetIPMask": "192.168.2.0/24",
      "NetIP": "192.168.2.0",
      "NetMask": 24,
      "IPint": 3232236032,
      "LastScan": "0001-01-01T00:00:00Z",
      "Updated": "0001-01-01T00:00:00Z"
    }
  }
}

Get Network(s)

Manipulate networks registered on the device. Specify CIDR notation in URLs with a - in place of a /.

Request

GET http://edgedevice:88/api/edge/network/192.168.2.0-24
GET http://edgedevice:88/api/edge/network/192.168.2.0

Response

Status: 200 OK
{
  "success": "Network found",
  "error": "",
  "data": {
    "Network": {
      "Name": "192.168.2.0/24",
      "IFname": "",
      "HostIPMask": "",
      "HostIP": "",
      "HostMask": 0,
      "NetIPMask": "192.168.2.0/24",
      "NetIP": "192.168.2.0",
      "NetMask": 24,
      "IPint": 3232236032,
      "LastScan": "0001-01-01T00:00:00Z",
      "Updated": "0001-01-01T00:00:00Z"
    }
  }
}

Request

GET http://edgedevice:88/api/edge/network

Response

Status: 200 OK
{
  "success": "Networks found",
  "error": "",
  "data": {
    "Count": 2,
    "Networks": [
      {
        "Name": "192.168.2.0/24",
        "IFname": "",
        "HostIPMask": "",
        "HostIP": "",
        "HostMask": 0,
        "NetIPMask": "192.168.2.0/24",
        "NetIP": "192.168.2.0",
        "NetMask": 24,
        "IPint": 3232236032,
        "LastScan": "0001-01-01T00:00:00Z",
        "Updated": "0001-01-01T00:00:00Z"
      },
      ...
    ]
  }
}

Error Response

Status: 404 Not Found
{
  "success": "",
  "error": "Network not found",
  "data": null
}

Delete

Request

DELETE http://edgedevice:88/api/edge/network/192.168.2.0-24
DELETE http://edgedevice:88/api/edge/network/192.168.2.0

Response

Status: 200 OK
{
  "success": "Network deleted",
  "error": "",
  "data": null
}

Error Response

Status: 404 Not Found
{
  "success": "",
  "error": "Network not found",
  "data": null
}

Devices

Create or Update Device

Create or update a device in the network.

Request

POST http://edgedevice:88/api/edge/device/192.168.8.10
{
  "Name": "Brother MFC",
  "Hostname": "brother",
  "IP": "192.168.8.10",
  "Network": "192.168.8.0/24",
  "Vendor": "Brother Industries Ltd."
}

Response

Status: 200 OK
{
  "success": "Network updated",
  "error": "",
  "data": {
    "Device": {
      "Name": "Brother MFC",
      "Hostname": "brother",
      "IP": "192.168.8.10",
      "IPint": 3232237578,
      "Network": "192.168.8.0/24",
      "MAC": "",
      "Vendor": "Brother Industries Ltd.",
      "Notes": "",
      "Ports": null,
      "Forwards": null,
      "ProxyMap": null,
      "ForwardsMap": null,
      "Created": "0001-01-01T00:00:00Z",
      "Updated": "0001-01-01T00:00:00Z"
    }
  }
}

Get Device Information

Retrieve information about a specific device (node) in a network.

Request

GET http://edgedevice:88/api/edge/device/192.168.8.10

Response

Status: 200 OK
{
  "success": "Device found",
  "error": "",
  "data": {
    "Node": {
      "Name": "brother",
      "Hostname": "brother",
      "IP": "192.168.8.10",
      "IPint": 3232237578,
      "Network": "192.168.8.0/24",
      "MAC": "e8:65:38:28:7d:53",
      "Vendor": "CLOUD NETWORK TECHNOLOGY SINGAPORE PTE. LTD.",
      "Notes": "",
      "Ports": null,
      "Forwards": [
        {
          "Name": "Admin UI",
          "Nodename": "",
          "IP": "192.168.8.10",
          "IPint": 3232237578,
          "PortNum": 443,
          "Protocol": "tcp",
          "Method": "Forward",
          "Service": "",
          "SourceIP": "0.0.0.0",
          "SourcePort": 10000,
          "OpenAs": "https",
          "Command": "https://device.account.2ho.ca:10000",
          "Enabled": true,
          "Updated": "0001-01-01T00:00:00Z"
        }
      ],
      "ProxyMap": null,
      "ForwardsMap": null,
      "Created": "0001-01-01T00:00:00Z",
      "Updated": "2024-12-11T10:55:33.768678777-05:00"
    }
  }
}

Get All Devices

Retrieve a list of all devices in the network. Specify the network CIDR in the URL. If the network is not specified, all devices are returned. Use a - in place of a / in the CIDR notation.

Request

GET http://edgedevice:88/api/edge/devices
GET http://edgedevice:88/api/edge/devices/192.168.8.0-24

Response

Status: 200 OK
{
  "success": "Devices found",
  "error": "",
  "data": {
    "Count": 19,
    "Network": [
      {
        "Name": "unifi",
        "Hostname": "unifi",
        "IP": "192.168.8.1",
        "IPint": 3232237569,
        "Network": "192.168.8.0/24",
        "MAC": "0e:ea:14:4d:1a:cc",
        "Vendor": "Unknown Vendor",
        "Notes": "",
        "Ports": null,
        "Forwards": [...],
        "ProxyMap": null,
        "ForwardsMap": null,
        "Created": "0001-01-01T00:00:00Z",
        "Updated": "2024-12-13T14:18:11.800682015-05:00"
      },
      ...
    ]
  }
}

Delete Device

Delete a device from the network.

Request

DELETE http://edgedevice:88/api/edge/device/192.168.8.10

Response

Status: 200 OK
{
  "success": "Device deleted",
  "error": "",
  "data": null
}

Forwarding Rules

Create or Update a Rule

Creates a new forwarding rule or updates an existing one if the port already exists. If the device does not exist, it is automatically created.

Request

POST http://edgedevice:88/api/edge/forward
{
"Name": "Admin UI",
"IP": "192.168.8.10",
"PortNum": 80,
"Protocol": "tcp",
"OpenAs": "http",
"Enabled": true
}

Response

{
"success": "Forward created successfully",
"error": "",
"data": {
 "Forward": {
   "Name": "Admin UI",
   "Nodename": "",
   "IP": "192.168.8.10",
   "IPint": 3232237578,
   "PortNum": 80,
   "Protocol": "tcp",
   "Method": "Forward",
   "Service": "",
   "SourceIP": "0.0.0.0",
   "SourcePort": 10000,
   "OpenAs": "http",
   "Command": "",
   "Enabled": true,
   "Updated": "0001-01-01T00:00:00Z"
 }
}
}

Read One

Read a specified forwarding rule by port.

Request

GET http://edgedevice:88/api/edge/forward/192.168.8.10/443

Response

Status: 200 OK
{
"success": "Forward found",
"error": "",
"data": {
 "Forward": {
   "Name": "Admin UI",
   "Nodename": "",
   "IP": "192.168.8.10",
   "IPint": 3232237578,
   "PortNum": 80,
   "Protocol": "tcp",
   "Method": "Forward",
   "Service": "",
   "SourceIP": "0.0.0.0",
   "SourcePort": 10000,
   "OpenAs": "http",
   "Command": "",
   "Enabled": true,
   "Updated": "0001-01-01T00:00:00Z"
 }
}
}

Read All

Read all the forwarded ports from a device.

Request

GET http://edgedevice:88/api/edge/forward/192.168.8.10

Response

Status: 200 OK
{
"success": "Forwards found",
"error": "",
"data": {
 "Forwards": [
   {
     "Name": "Admin UI",
     "Nodename": "",
     "IP": "192.168.8.10",
     "IPint": 3232237578,
     "PortNum": 80,
     "Protocol": "tcp",
     "Method": "Forward",
     "Service": "",
     "SourceIP": "0.0.0.0",
     "SourcePort": 10000,
     "OpenAs": "http",
     "Command": "",
     "Enabled": true,
     "Updated": "0001-01-01T00:00:00Z"
   },
   ...
 ]
}
}

Delete a Forward

Delete a forwarding rule from the device.

Request

DELETE http://edgedevice:88/api/edge/forward/192.168.8.10/80

Response

Status: 200 OK
{
  "success": true,
  "error": "",
  "message": "Forward deleted successfully"
}

Scanner

Start a Network Scan

Start a network scan.

Request

GET http://edgedevice:88/api/edge/scan/start

Response

Status: 200 OK
{
  "success": "Continuous scanning started",
  "error": "",
  "data": null
}

Stop a Network Scan

Stop a network scan.

Request

GET http://edgedevice:88/api/edge/scan/stop

Response

Status: 200 OK
{
  "success": "Scanning stopped",
  "error": "",
  "data": null
}

Scan Once

Scan a network once. i.e. Not continuously.

Request

GET http://edgedevice:88/api/edge/scan/once

Response

Status: 200 OK
{
  "success": "Single scan initiated",
  "error": "",
  "data": null
}

Scan with ONVIF

Scan a network for ONVIF devices using the ONVIF protocol only.

Request

GET http://edgedevice:88/api/edge/scan/onvif

Response

Status: 200 OK
{
  "success": "ONVIF scan initiated",
  "error": "",
  "data": null
}

Scan a Specific Host

Scan a single host for open ports.

Request

GET http://edgedevice:88/api/edge/scan/192.168.8.1

Response

Status: 200 OK
{
  "success": "Host scan initiated",
  "error": "",
  "data": null
}

Configuration

Get Configuration

Get the configuration of the Netrinos Edge Services

Request

GET http://edgedevice:88/api/edge/config

Response

Status: 200 OK
{
  "success": "Edge config found",
  "error": "",
  "data": {
    "Config": {
      "LocalNet": {
        "Hostname": "",
        "IsStatic": false,
        "LocalIPn": "",
        "Gateway": "",
        "DNS": ""
      },
      "Server": {
        "IP": "0.0.0.0",
        "Port": "88"
      },
      "Proxy": {
        "IP": "0.0.0.0",
        "ServeIP": "192.168.8.20",
        "PortStart": 10000,
        "PortRange": 1000
      },
      "Socks": {
        "IP": "0.0.0.0",
        "Port": 1080
      },
      "Scan": {
        "Auto": false,
        "Interval": 0,
        "Workers": 0,
        "Continuous": false,
        "NoScanSubnets": "",
        "OnvifScan": false
      },
      "Monitor": {
        "Auto": false,
        "Target": ""
      }
    }
  }
}

Get Scan Configuration

Get the scan configuration of the Netrinos Edge Services

Request

GET http://edgedevice:88/api/edge/config/config

Response

Status: 200 OK
{
  "success": "Scanner config found",
  "error": "",
  "data": {
    "Scan": {
      "Auto": false,
      "Interval": 0,
      "Workers": 0,
      "Continuous": false,
      "NoScanSubnets": "",
      "OnvifScan": false
    }
  }
}

Set Scanner Configuration

Set parameters of the scan configuration

Request

POST http://edgedevice:88/api/edge/scan/config
{
  "Auto": false
}

Response

Status: 200 OK
{
  "success": "Scan configuration updated",
  "error": "",
  "data": {
    "Scanner": {
      "Auto": false,
      "Interval": 0,
      "Workers": 0,
      "Continuous": false,
      "NoScanSubnets": "",
      "OnvifScan": false
    }
  }
}

Request

POST http://edgedevice:88/api/edge/config
{
  "Continuous": true
}

Response

Status: 200 OK
{
  "success": "Scan configuration updated",
  "error": "",
  "data": {
    "Scanner": {
      "Auto": false,
      "Interval": 0,
      "Workers": 0,
      "Continuous": true,
      "NoScanSubnets": "",
      "OnvifScan": false
    }
  }
}

Example Usage

These examples are far from optimal. They are meant as simplified examples of how to use the API.

Login and set a forward rule

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
)

const apiURL = "http://localhost:88" // API URL

var client *http.Client // Global HTTP client

func main() {

	client = &http.Client{}

	// Previously authenticated token. May not be current.
	token := "1234abcdthismayormaynotbeavalidtokenab6abcd1234"

	// Login credentials - be sure the account has the API role in the admin portal
	credentials := map[string]string{
		"Username": "username",
		"Password": "password",
	}

	// Check if the token is valid
	req, _ := http.NewRequest("GET", apiURL+"/api/ping", nil)
	req.Header.Set("Authorization", "Bearer "+token)
	tokenResp, _ := client.Do(req)

	if tokenResp.StatusCode == http.StatusOK {
		fmt.Printf("Token is valid.")

	} else {
		fmt.Println("Token is invalid. Logging in to get a new token.")

		// Login to get a new token
		jsonData, _ := json.Marshal(credentials)

		resp, _ := http.Post(apiURL+"/api/login", "application/json", bytes.NewBuffer(jsonData))
		body, _ := io.ReadAll(resp.Body)
		defer resp.Body.Close()

		// Check that the login was successful
		if resp.StatusCode != http.StatusOK {
			fmt.Printf("Login failed. Status code: %d\n", resp.StatusCode)
			return
		}

		var loginResp map[string]interface{}
		json.Unmarshal(body, &loginResp)

		// Get the auth token from the nested response structure
		loginData := loginResp["data"].(map[string]interface{})
		token = loginData["AuthToken"].(string)
		fmt.Printf("Received token: %s\n", token)
	}

	// Create forward rule
	IP := "192.168.8.254"
	forwardRule := map[string]interface{}{
		"Name":     "RTSP Stream",
		"IP":       IP,
		"PortNum":  554,
		"Protocol": "tcp",
		"OpenAs":   "rtsp",
		"Enabled":  true,
	}
	ruleJSON, _ := json.Marshal(forwardRule)

	req, _ = http.NewRequest("POST", apiURL+"/api/edge/forward/"+IP, bytes.NewBuffer(ruleJSON))
	req.Header.Set("Authorization", "Bearer "+token)
	req.Header.Set("Content-Type", "application/json")

	resp, _ := client.Do(req)
	body, _ := io.ReadAll(resp.Body)
	defer resp.Body.Close()

	fmt.Printf("Forward rule response: %s\n", string(body))
}

Result

Token is invalid. Logging in to get a new token.
Received token: 1fbcc8daf8d212ca91285a7ee4772b6208b3cb6d56a14e682847616aaab6490a
Forward rule response: {
    "success": "Forward created successfully",
    "error": "",
    "data": {
        "Forward": {
            "Name": "RTSP Stream",
            "Nodename": "unknown",
            "IP": "192.168.8.254",
            "IPint": 3232237822,
            "PortNum": 554,
            "Protocol": "tcp",
            "Method": "Forward",
            "Service": "rtsp",
            "SourceIP": "0.0.0.0",
            "SourcePort": 10000,
            "OpenAs": "rtsp",
            "Command": "",
            "Enabled": true,
            "Updated": "2024-12-16T19:36:06.642964426-05:00"
        }
    }
}

Perform an ONVIF Scan

Scan the network for ONVIF devices and list the results

Example Code

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"time"
)

const apiURL = "http://edgedevice:88"

func main() {
	// Known token from previous authentication
	token := "1234abcdthismayormaynotbeavalidtokenab6abcd1234"
	client := &http.Client{}

	// Start ONVIF scan
	req, _ := http.NewRequest("GET", apiURL+"/api/edge/scan/onvif", nil)
	req.Header.Set("Authorization", "Bearer "+token)
	resp, _ := client.Do(req)
	body, _ := io.ReadAll(resp.Body)
	resp.Body.Close()

	fmt.Printf("Scan initiated: %s\n", string(body))

	// Poll scan status until complete
	for {
		req, _ = http.NewRequest("GET", apiURL+"/api/edge/scan", nil)
		req.Header.Set("Authorization", "Bearer "+token)
		resp, _ = client.Do(req)
		body, _ = io.ReadAll(resp.Body)
		resp.Body.Close()

		var respData map[string]interface{}
		json.Unmarshal(body, &respData)
		data := respData["data"].(map[string]interface{})

		if !data["running"].(bool) {
			break
		}
		time.Sleep(3 * time.Second)
	}
	fmt.Println()

	// Get discovered devices
	req, _ = http.NewRequest("GET", apiURL+"/api/edge/devices", nil)
	req.Header.Set("Authorization", "Bearer "+token)
	resp, _ = client.Do(req)
	body, _ = io.ReadAll(resp.Body)
	resp.Body.Close()

	var result map[string]interface{}
	json.Unmarshal(body, &result)

	fmt.Println("\nDiscovered devices:")
	devices := result["data"].(map[string]interface{})["Network"].([]interface{})
	for _, device := range devices {
		dev := device.(map[string]interface{})
		fmt.Printf("Name: %s\nIP: %s\nVendor: %s\n\n",
			dev["Name"],
			dev["IP"],
			dev["Vendor"])
	}
}

Result

Scan initiated: {
    "success": "Onvif scan initiated",
    "error": "",
    "data": null
}

Discovered devices:
Name: unknown
IP: 192.168.8.254
Vendor: Speco Technologies