Administration API
EnterpriseManage NetStacks Controller users, roles, organizations, settings, and license, and read the audit log through the API.
Overview
Administrative endpoints live under /api/admin. They back the Administration and Settings areas of the Admin Console. Most need users.manage, system.manage, or platform.admin, as shown in each table. Everything is scoped to the organization in your token, except organizations themselves.
Users
| Method | Path | Purpose | Permission |
|---|---|---|---|
GET | /api/admin/users | List users: {"users":[…],"total":n}. Query: search, limit, offset | users.manage |
POST | /api/admin/users | Create a local user | users.manage |
GET | /api/admin/users/:id | Get a user with their roles | users.manage |
PUT | /api/admin/users/:id | Update a user | users.manage |
DELETE | /api/admin/users/:id | Delete a user | users.manage |
GET | /api/admin/users/:id/roles | List the user's roles | users.manage |
POST | /api/admin/users/:id/roles | Add one role. Body: {"role_id"} | users.manage |
PUT | /api/admin/users/:id/roles | Replace all roles. Body: {"role_ids":[…]} | users.manage |
DELETE | /api/admin/users/:id/roles/:role_id | Remove one role | users.manage |
Create a user and give it a role:
NS=https://controller.example.com:3000
USER_ID=$(curl -s --cacert netstacks-ca.pem -X POST $NS/api/admin/users \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"username":"automation","display_name":"Automation","email":"[email protected]","password":"<at least 12 characters>"}' \
| jq -r .id)
curl -s --cacert netstacks-ca.pem -X PUT $NS/api/admin/users/$USER_ID/roles \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"role_ids":["<operator role id>"]}'| Field | Type | Notes |
|---|---|---|
username | string | Required. Unique. |
password | string | Required. At least 12 characters and not a common password. |
email, display_name | string | Optional. |
org_id | UUID | Optional. Platform administrators only: create the user in another organization. |
PUT /api/admin/users/:id accepts email, display_name (send null to clear), and password to set a new password. You can't delete your own account.
Roles
| Method | Path | Purpose | Permission |
|---|---|---|---|
GET | /api/admin/roles | List roles | users.manage |
POST | /api/admin/roles | Create a role. Body: {"name","description","permissions":[…]} | users.manage |
GET | /api/admin/roles/permissions | The permission catalog, grouped by category | users.manage |
GET | /api/admin/roles/:id | Get a role | users.manage |
PUT | /api/admin/roles/:id | Update name, description, or permissions | users.manage |
DELETE | /api/admin/roles/:id | Delete a role. Built-in protected roles return 400 | users.manage |
{
"name": "automation",
"description": "Service account for config backup scripts",
"permissions": ["devices.access"]
}Role names must be unique within the organization. See Roles and permissions for what each permission covers.
Organizations
| Method | Path | Purpose | Permission |
|---|---|---|---|
GET | /api/admin/organizations | List organizations | platform.admin |
POST | /api/admin/organizations | Create an organization. Body: {"name"} | platform.admin |
GET / PUT | /api/admin/organizations/:id | Get or rename an organization | platform.admin |
DELETE | /api/admin/organizations/:id | Delete an empty organization (409 if it still has users or devices) | platform.admin |
A new organization starts with no users and no roles. To work inside it, switch to it with POST /api/auth/switch-org and create roles and users there.
Audit log
| Method | Path | Purpose |
|---|---|---|
GET | /api/admin/audit | Page through audit events |
GET | /api/admin/audit/event-types | All event types that have been recorded (array of strings) |
| Field | Type | Notes |
|---|---|---|
page / limit | integer | Page number (from 1) and page size (default 10, maximum 100) |
event_type | string | For example auth.login.success, auth.login.failed, or auth.logout |
actor_id | UUID | Events by one user |
from_date / to_date | ISO datetime | Time range |
search | string | Free-text search |
curl -s --cacert netstacks-ca.pem \
"https://controller.example.com:3000/api/admin/audit?event_type=auth.login.success&from_date=2026-10-01T00:00:00Z&limit=100" \
-H "Authorization: Bearer $TOKEN"{
"data": [
{
"id": "b19c...",
"event_type": "auth.login.success",
"actor_id": "3f6c...",
"actor_email": "[email protected]",
"resource_type": "auth",
"resource_id": null,
"details": { "username": "automation", "method": "local" },
"ip_address": "10.20.0.15",
"created_at": "2026-10-12T13:58:41Z"
}
],
"total": 1,
"page": 1,
"limit": 100,
"total_pages": 1
}resource_type is the part of event_type before the first dot. To export the log, page through it and write the results to a file. See also Audit log.
Settings
Settings are key/value pairs that apply to the whole Controller (all organizations). Secret values are masked when you read them.
| Method | Path | Purpose | Permission |
|---|---|---|---|
GET | /api/admin/settings | List all settings | Signed in |
GET | /api/admin/settings/:key | Get one setting | Signed in |
PUT | /api/admin/settings/:key | Change one setting. Body: {"value": …} | system.manage |
curl -s --cacert netstacks-ca.pem -X PUT \
https://controller.example.com:3000/api/admin/settings/session.access_token_hours \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"value": 8}'Some settings are read only when the API starts (for example the login rate limits and LDAP/OIDC configuration). The Settings page notes which ones need a restart.
License, health, and system
| Method | Path | Purpose | Permission |
|---|---|---|---|
GET | /api/admin/license/status | License tier, seats used and total, expiry, status | Signed in |
POST | /api/admin/license/activate | Activate a license key. Body: {"license_key"} | system.manage |
GET | /api/admin/health | Component health (database, scheduler, vault, Valkey) and uptime | Signed in |
GET | /api/admin/ha-status | Single-instance or active-active mode and the running instances | Signed in |
GET | /api/admin/system/info | Deployment information | system.manage |
POST | /api/admin/system/backup | Download a full database backup (.sql) | system.manage |
POST | /api/admin/system/restore | Restore from an uploaded backup (multipart) | system.manage |
GET | /api/admin/sessions | Live terminal sessions | users.manage |
POST | /api/admin/sessions/:id/terminate | End a live session | users.manage |