NetStacksNetStacks

Devices API

Enterprise

List, create, update, import, and delete devices in the NetStacks Controller inventory, plus sites and NetBox sources.

Overview

The devices endpoints manage the Controller's shared inventory: the same list shown under Inventory → Managed Devices in the Admin Console and in the Terminal's device list in enterprise mode.

Every device belongs to one organization and uses one connection profile for its credentials. All endpoints on this page need the devices.access permission.

Endpoints

MethodPathPurposePermission
GET/api/devicesList devices (filters and paging below)devices.access
POST/api/devicesCreate a devicedevices.access
GET/api/devices/:idGet one devicedevices.access
PUT/api/devices/:idUpdate a device (only the fields you send)devices.access
DELETE/api/devices/:idDelete a device (204)devices.access
POST/api/devices/import/csvImport from CSV text. Optional ?profile_id=devices.access
POST/api/devices/import/jsonImport from a JSON array. Optional ?profile_id=devices.access
PATCH/api/devices/bulkSet the same fields on many devicesdevices.access
POST/api/devices/:id/test-credentialTest that the device's credentials can log indevices.access
POST/api/devices/bulk/test-credentialsTest credentials on several devices. Body: {"device_ids":[…]}devices.access
GET/api/devices/with-backup-infoDevices with their latest config backup detailsdevices.access
GET/api/devices/:id/interfacesInterfaces collected by discoverydevices.access
GET/api/devices/:id/neighborsCDP/LLDP neighbors collected by discoverydevices.access
GET/api/devices/:id/arp-tableARP entries collected by discoverydevices.access
GET/api/devices/:id/mac-tableMAC table entries collected by discoverydevices.access
GET/api/devices/:id/vlansVLANs collected by discoverydevices.access
GET/api/devices/:id/statusLatest poll statusdevices.access
POST/api/devices/:id/pollQueue a discovery poll of this device nowdevices.access
GET/api/devices/:id/poll-historyRecent poll resultsdevices.access
GET/api/sitesList sitesdevices.access
POST/api/sitesCreate a sitedevices.access
GET / PUT / DELETE/api/sites/:idGet, update, or delete a sitedevices.access

List and search devices

GET /api/devices returns a page of device summaries. Query parameters (all optional):

FieldTypeNotes
qstringFree-text search across name, host, manufacturer, model, platform, and device type
vendorstringManufacturer, case-insensitive exact match
platformstringPlatform, exact match
device_typestringDevice type, for example cisco_ios
site_idUUIDDevices assigned to this site
sitestringFree-text site name
sourcestringmanual, csv, json, netbox, …
limit / offsetintegerPaging. Default 50, maximum 100
curl -s --cacert netstacks-ca.pem \
  "https://controller.example.com:3000/api/devices?q=core&limit=25" \
  -H "Authorization: Bearer $TOKEN"
{
  "devices": [
    {
      "id": "8d1e...",
      "org_id": "0000...0001",
      "name": "core-sw-01",
      "host": "10.0.0.11",
      "device_type": "cisco_ios",
      "manufacturer": "Cisco",
      "model": "C9300-48P",
      "site": "HQ",
      "source": "manual",
      "profile_id": "51a2...",
      "created_at": "2026-09-14T08:12:00Z",
      "updated_at": "2026-10-01T16:40:00Z"
    }
  ],
  "total": 1,
  "limit": 25,
  "offset": 0
}

GET /api/devices/:id returns the full record, which adds protocol, description, platform, serial_number, asset_tag, tags, metadata, site_id, poll_enabled, poll_interval_minutes, NetBox fields, and audit fields.

Create a device

POST /api/devices returns 201 with the new device. A connection profile is required.

curl -s --cacert netstacks-ca.pem -X POST https://controller.example.com:3000/api/devices \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{
    "name": "edge-rtr-02",
    "host": "10.0.1.2",
    "device_type": "cisco_xe",
    "manufacturer": "Cisco",
    "profile_id": "51a2...",
    "site_id": "c07b...",
    "tags": ["edge", "wan"]
  }'
FieldTypeNotes
namestringRequired. Must be unique in the organization.
hoststringRequired. IP address or hostname.
device_typestringRequired. The Admin Console uses cisco_ios, cisco_nxos, cisco_xe, cisco_xr, juniper_junos, arista_eos, paloalto_panos, fortinet, generic, custom, snmp.
profile_idUUIDRequired. The connection profile to use.
protocolstringDefault ssh.
manufacturer, model, platform, descriptionstringOptional.
serial_number, asset_tagstringOptional.
site_idUUIDOptional. A site from /api/sites.
tagsstring[]Optional.
metadataobjectOptional free-form JSON.
poll_enabledbooleanDefault false. Turns on background polling.
poll_interval_minutesintegerOptional polling interval.

Creating a device with a name that already exists returns 409with {"error":"Device with this name already exists"}.

Update and delete

PUT /api/devices/:id accepts any of the create fields (except source) and changes only the ones you send:

curl -s --cacert netstacks-ca.pem -X PUT https://controller.example.com:3000/api/devices/8d1e... \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"description": "Core switch, rack A3", "poll_enabled": true}'

DELETE /api/devices/:id returns 204, or 404 if the device doesn't exist in your organization.

Bulk import (CSV / JSON)

Both import endpoints create one device per row. Rows that fail don't stop the import. Pass ?profile_id=<uuid> to choose the connection profile for the imported devices. Without it, the default profile from Settings → Manage is used. If neither is set, the call returns 400.

CSV: send the file as the request body. The header row must use these exact column names. name, host, and device_type are required; the rest are optional.

devices.csvtext
name,host,device_type,manufacturer,model,platform,site,description
core-sw-01,10.0.0.11,cisco_ios,Cisco,C9300-48P,,HQ,Core switch
fw-01,10.0.0.1,paloalto_panos,Palo Alto,PA-3220,,HQ,Perimeter firewall
curl -s --cacert netstacks-ca.pem -X POST \
  "https://controller.example.com:3000/api/devices/import/csv?profile_id=51a2..." \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: text/csv" \
  --data-binary @devices.csv

JSON: send an array of objects with the same field names to /api/devices/import/json.

Both return a summary. Row numbers in CSV errors count the header as row 1:

{
  "imported": 1,
  "failed": 1,
  "errors": [
    { "row": 3, "name": "fw-01", "error": "Device with this name already exists" }
  ]
}
Import creates, it doesn't update

Rows whose name already exists fail. Use PUT /api/devices/:id or the bulk edit endpoint to change existing devices. Imported devices use the ssh protocol and get the free-text site value, not a site_id.

Bulk edit

PATCH /api/devices/bulk sets the same values on a list of devices. Send the device IDs and only the fields you want to change. The Admin Console uses it for vendor, platform, model, device type, site, profile, polling, and tags.

{
  "ids": ["8d1e...", "a41f..."],
  "fields": { "profile_id": "51a2..." }
}

The response is {"updated": 2}. An empty ids list or an empty fields object returns 400. To move devices to another profile you can also use POST /api/profiles/assign (see Connection profiles).

Sites

Sites group devices by location. POST /api/sites takes:

FieldTypeNotes
namestringRequired.
descriptionstringOptional.
locationstringOptional, for example a street address.
parent_site_idUUIDOptional parent site, for nesting.

Set a device's site_id to place it in a site. Sites need devices.access, like devices.

NetBox sources

Saved NetBox connections live under /api/devices/sources/netbox. These endpoints back the NetBox import in the Admin Console:

MethodPathPurposePermission
GET/api/devices/sources/netboxList saved NetBox sources (tokens are never returned)devices.access
POST/api/devices/sources/netboxCreate a source: name, url, token, device_filters, verify_ssl, …devices.access
GET / PUT / DELETE/api/devices/sources/netbox/:source_idGet, update, or delete a sourcedevices.access
POST/api/devices/sources/netbox/:source_id/testTest the connection and count matching devicesdevices.access
POST/api/devices/sources/netbox/:source_id/syncImport or update devices from this source nowdevices.access
GET/api/devices/sync/historyPast NetBox sync resultsdevices.access

A sync returns counts: added, updated, unchanged, failed, removed, plus errors and duration_ms. For the UI side, see NetBox import.