Devices API
Full CRUD operations for managed network devices including filtering, bulk import, config backups, and credential testing.
Overview
The Devices API provides full CRUD operations for managing network devices in NetStacks. Use it to list, create, update, and delete devices, import devices in bulk via CSV or JSON, sync from NetBox, manage config backups, and test device credentials.
All device endpoints are nested under /api/devices and require authentication with the ManageDevices permission. See API Authentication to obtain a token.
Each device has: id (UUID), name, host (IP or hostname), port, device_type, manufacturer, model, platform, site, source, default_credential_id, created_at, and updated_at.
How It Works
The Devices API follows REST conventions. All endpoints return JSON and accept JSON request bodies. Device IDs are UUIDs assigned by the server on creation.
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /api/devices | List devices with filtering and pagination |
| POST | /api/devices | Create a new device |
| GET | /api/devices/:id | Get a single device by ID |
| PUT | /api/devices/:id | Update a device |
| DELETE | /api/devices/:id | Delete a device |
| POST | /api/devices/import/csv | Bulk import from CSV |
| POST | /api/devices/import/json | Bulk import from JSON |
| POST | /api/devices/bulk/backup | Trigger bulk config backup |
| POST | /api/devices/bulk/test-credentials | Test credentials for multiple devices |
Query Parameters for Listing
limit(int) — Items per page, default 50, max 100offset(int) — Pagination offset, default 0device_type(string) — Filter by device type (e.g.,cisco_ios)site(string) — Filter by site namesource(string) — Filter by source (manual,netbox,csv)
Step-by-Step Guide
1. Authenticate
Obtain a JWT token from the Authentication API. Include it in all device requests as Authorization: Bearer <token>.
2. List Devices with Filtering
Call GET /api/devices with optional query parameters to filter by device type, site, or source. Results are paginated.
3. Get a Single Device
Call GET /api/devices/:id with the device UUID to retrieve full device details including backup status.
4. Create a Device
Send a POST to /api/devices with the device name, host, port, device type, and optional credential ID.
5. Update a Device
Send a PUT to /api/devices/:id with the fields you want to change.
6. Delete a Device
Send a DELETE to /api/devices/:id. Returns 204 No Content on success.
7. Bulk Import
Use POST /api/devices/import/json to import multiple devices at once, or /import/csv for CSV files.
Code Examples
Create a Device
curl -X POST https://netstacks.example.net/api/devices \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"name": "core-rtr-01.dc1.example.net",
"host": "10.0.1.1",
"port": 22,
"device_type": "cisco_ios",
"manufacturer": "Cisco",
"model": "ISR 4451-X",
"platform": "ios-xe",
"site": "dc1-east",
"default_credential_id": "c8a7b6d5-e4f3-2a1b-9c8d-7e6f5a4b3c2d"
}'
# Response (201 Created):
# {
# "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
# "org_id": "a1b2c3d4-0000-0000-0000-000000000000",
# "name": "core-rtr-01.dc1.example.net",
# "host": "10.0.1.1",
# "port": 22,
# "device_type": "cisco_ios",
# "manufacturer": "Cisco",
# "model": "ISR 4451-X",
# "platform": "ios-xe",
# "site": "dc1-east",
# "source": "manual",
# "default_credential_id": "c8a7b6d5-e4f3-2a1b-9c8d-7e6f5a4b3c2d",
# "created_at": "2026-03-10T14:30:00Z",
# "updated_at": "2026-03-10T14:30:00Z"
# }import requests
base_url = "https://netstacks.example.net/api"
headers = {"Authorization": "Bearer eyJhbGciOiJIUzI1NiIs..."}
# Create a device
device = requests.post(f"{base_url}/devices", headers=headers, json={
"name": "core-rtr-01.dc1.example.net",
"host": "10.0.1.1",
"port": 22,
"device_type": "cisco_ios",
"manufacturer": "Cisco",
"model": "ISR 4451-X",
"platform": "ios-xe",
"site": "dc1-east",
"default_credential_id": "c8a7b6d5-e4f3-2a1b-9c8d-7e6f5a4b3c2d"
})
device.raise_for_status()
print(f"Created device: {device.json()['id']}")const BASE_URL = "https://netstacks.example.net/api";
const headers = {
Authorization: "Bearer eyJhbGciOiJIUzI1NiIs...",
"Content-Type": "application/json",
};
// Create a device
const resp = await fetch(`${BASE_URL}/devices`, {
method: "POST",
headers,
body: JSON.stringify({
name: "core-rtr-01.dc1.example.net",
host: "10.0.1.1",
port: 22,
device_type: "cisco_ios",
manufacturer: "Cisco",
model: "ISR 4451-X",
platform: "ios-xe",
site: "dc1-east",
default_credential_id: "c8a7b6d5-e4f3-2a1b-9c8d-7e6f5a4b3c2d",
}),
});
const device = await resp.json();
console.log(`Created device: ${device.id}`);List Devices with Filters
# List Cisco IOS devices in dc1-east, first 25 results
curl "https://netstacks.example.net/api/devices?device_type=cisco_ios&site=dc1-east&limit=25" \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
# Response:
# {
# "devices": [
# {
# "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
# "name": "core-rtr-01.dc1.example.net",
# "host": "10.0.1.1",
# "port": 22,
# "device_type": "cisco_ios",
# "site": "dc1-east",
# "source": "manual",
# "last_backup_status": "success"
# }
# ],
# "total": 42,
# "limit": 25,
# "offset": 0
# }# List devices filtered by type and site
devices = requests.get(
f"{base_url}/devices",
headers=headers,
params={"device_type": "cisco_ios", "site": "dc1-east", "limit": 25}
)
data = devices.json()
print(f"Found {data['total']} Cisco IOS devices in dc1-east")
for d in data["devices"]:
print(f" {d['name']} ({d['host']})")// List devices filtered by type and site
const params = new URLSearchParams({
device_type: "cisco_ios",
site: "dc1-east",
limit: "25",
});
const listResp = await fetch(`${BASE_URL}/devices?${params}`, {
headers: { Authorization: "Bearer eyJhbGciOiJIUzI1NiIs..." },
});
const list = await listResp.json();
console.log(`Found ${list.total} Cisco IOS devices in dc1-east`);
list.devices.forEach((d: any) => console.log(` ${d.name} (${d.host})`));Update a Device
curl -X PUT https://netstacks.example.net/api/devices/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{"site": "dc2-west", "port": 2222}'# Update device site and port
resp = requests.put(
f"{base_url}/devices/f47ac10b-58cc-4372-a567-0e02b2c3d479",
headers=headers,
json={"site": "dc2-west", "port": 2222}
)
resp.raise_for_status()await fetch(`${BASE_URL}/devices/f47ac10b-58cc-4372-a567-0e02b2c3d479`, {
method: "PUT",
headers,
body: JSON.stringify({ site: "dc2-west", port: 2222 }),
});Delete a Device
curl -X DELETE https://netstacks.example.net/api/devices/f47ac10b-58cc-4372-a567-0e02b2c3d479 \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."
# Response: 204 No ContentBulk Import (JSON)
curl -X POST https://netstacks.example.net/api/devices/import/json \
-H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '[
{"name": "dist-sw-01.dc1", "host": "10.0.10.1", "port": 22, "device_type": "cisco_ios", "site": "dc1-east"},
{"name": "dist-sw-02.dc1", "host": "10.0.10.2", "port": 22, "device_type": "cisco_ios", "site": "dc1-east"},
{"name": "fw-01.dc1", "host": "10.0.20.1", "port": 22, "device_type": "paloalto_panos", "site": "dc1-east"}
]'
# Response:
# {
# "imported": 3,
# "failed": 0,
# "errors": []
# }# Bulk import devices from a list
devices_to_import = [
{"name": "dist-sw-01.dc1", "host": "10.0.10.1", "port": 22, "device_type": "cisco_ios", "site": "dc1-east"},
{"name": "dist-sw-02.dc1", "host": "10.0.10.2", "port": 22, "device_type": "cisco_ios", "site": "dc1-east"},
{"name": "fw-01.dc1", "host": "10.0.20.1", "port": 22, "device_type": "paloalto_panos", "site": "dc1-east"},
]
resp = requests.post(f"{base_url}/devices/import/json", headers=headers, json=devices_to_import)
result = resp.json()
print(f"Imported {result['imported']} devices, {result['failed']} failed")Questions & Answers
- How do I list all devices?
- Send a
GETrequest to/api/devices. Results are paginated withlimitandoffsetquery parameters. The response includes atotalcount for pagination. - How do I filter devices by type or site?
- Add query parameters:
/api/devices?device_type=cisco_ios&site=dc1-east. Supported filters aredevice_type,site, andsource. - How do I add a device via the API?
- Send a
POSTrequest to/api/deviceswith a JSON body containing at minimumname,host,port, anddevice_type. The response returns the created device with its assigned UUID. - How do I bulk import devices?
- Use
POST /api/devices/import/jsonwith an array of device objects, orPOST /api/devices/import/csvwith a CSV file upload. Both endpoints return a summary of imported and failed devices. - What device types are supported?
- NetStacks supports many device types including
cisco_ios,cisco_nxos,cisco_asa,juniper_junos,arista_eos,paloalto_panos,fortinet_fortios,linux, and more. The device type determines how NetStacks connects and interacts with the device. - How do I test device credentials?
- Use
POST /api/devices/bulk/test-credentialswith an optional list ofdevice_ids. If no IDs are provided, all devices are tested. The response includes per-device results with connection timing.
Troubleshooting
404 Device Not Found
The device UUID does not exist or belongs to a different organization. Double-check the ID and ensure you are authenticated with the correct account.
409 Conflict (Duplicate Name)
A device with the same name already exists in your organization. Device names must be unique. Choose a different name or update the existing device.
422 Validation Error
The request body is missing required fields or contains invalid values. Check that name, host, port, and device_type are all provided and valid. See Error Codes for field-level error details.
Credential Test Failing After Creation
If the device was created successfully but credential tests fail, verify the IP address and port are correct, the device is reachable from the Controller, and the assigned credential has the correct username/password or SSH key.
Bulk Import Partial Failures
The import response includes an errors array with details about which devices failed and why. Common causes include duplicate names and invalid device types.
Related Features
- API Authentication — Obtain tokens required for all device API calls.
- Templates API — Create configuration templates to deploy to devices.
- Stacks API — Deploy template stacks to multiple devices at once.
- Error Codes — Complete reference for API error responses.
- Adding Devices — Guide to adding devices through the web UI.