NetStacksNetStacks

API Tokens

How NetStacks uses API tokens: the local agent's single Bearer auth token, and the 'API Token' vault credential type for third-party sources like NetBox.

Overview

The term "API token" means two different things in NetStacks, and it is worth keeping them separate:

  1. The agent auth token — a single bearer token that the local NetStacks agent requires on every call to its localhost HTTP API. This is an internal authentication mechanism between the NetStacks desktop app (or a remote deployment) and its bundled agent process. You rarely touch it directly.
  2. The "API Token" credential type — a kind of secret you can store in the vault, used to hold third-party API tokens such as a NetBox or LibreNMS token so NetStacks can authenticate to those external systems on your behalf.
No token-management dashboard

NetStacks does not expose a token-management UI with creatable, expiring, or individually revocable platform tokens. The agent uses one auth token per running session, and external tokens are stored as ordinary vault credentials. This page documents exactly what exists.

The Agent Auth Token

The NetStacks agent serves its REST API on a localhost-only listener (bound to 127.0.0.1) over TLS, on an ephemeral port chosen at startup. Every request to that API — except the health check — must carry a valid bearer token in the Authorization header.

The token is a 256-bit value, hex-encoded (64 hex characters). It is obtained in one of two ways:

  • Provided by the parent app. When the desktop app launches the agent as a sidecar, it generates the token and passes it to the agent through the NETSTACKS_AUTH_TOKEN environment variable. The agent accepts the value if it is at least 32 characters long.
  • Generated by the agent. If no usable NETSTACKS_AUTH_TOKEN is supplied (for example, in a remote deployment), the agent generates a fresh random 256-bit token and prints it to stdout as NETSTACKS_AUTH_TOKEN=<hex> so the launcher can capture it from the session.
# Example of what the agent prints on stdout when it self-generates a token
NETSTACKS_AUTH_TOKEN=3f9c1a7e0b54d2986af31c0d77e5b2148c690fa3de1b4476a2e8c5d019f3ab7c

After reading the token, the agent removes NETSTACKS_AUTH_TOKEN from its own environment so that child processes it spawns (scripts, PTY commands, and so on) do not inherit the secret.

How the Auth Token Works

Bearer authentication on every route

An auth middleware runs in front of the API. It reads the Authorization header, requires it to begin with Bearer , and compares the remaining token to the session token held in memory. Missing or non-matching tokens get a 401 Unauthorized JSON response of the form {"error": "unauthorized"}.

Constant-time comparison

The token comparison is constant-time (it does not short-circuit on the first differing byte), which avoids leaking information about the token through timing.

The health endpoint is exempt

Exactly one route is exempt from authentication: GET /api/health. The exemption is an exact-path match, so parameterized routes that merely end in the string health are not exempt — they still require the token. The health endpoint returns the plain-text body ok.

No expiration, no revocation list, no rate limiting

The auth token is valid for the lifetime of the agent process. There is no per-token expiration date, no revocation list, and no built-in API rate limiter. Restarting the agent rotates the token: the old one stops working and a new one takes its place. Because the API is bound to localhost over TLS, the token is not exposed on the network.

Calling the Local API

If you need to call the agent API directly, send the token as a bearer token. The base URL is https://127.0.0.1:<port>, where the port is the ephemeral port the agent bound at startup. The TLS certificate is a locally generated cert for 127.0.0.1, so a generic HTTP client will need to trust it (or skip verification for local debugging).

Health check (no token required)

health.shbash
# Health endpoint is the only route exempt from auth.
# Replace 54321 with the agent's actual ephemeral port.
curl -k https://127.0.0.1:54321/api/health
# -> ok

Authenticated request

authed-request.shbash
# Every other route requires the bearer token.
export NETSTACKS_AUTH_TOKEN=3f9c1a7e0b54d2986af31c0d77e5b2148c6...
export AGENT_PORT=54321

curl -k https://127.0.0.1:${AGENT_PORT}/api/info \
  -H "Authorization: Bearer ${NETSTACKS_AUTH_TOKEN}"
Header format matters

The middleware only accepts headers that start with the literal prefix Bearer (capital B, single trailing space). A missing prefix, a lowercase bearer, or stray whitespace around the token will produce a 401 Unauthorized.

Python example

agent_client.pypython
import os
import requests

PORT = os.environ["AGENT_PORT"]
TOKEN = os.environ["NETSTACKS_AUTH_TOKEN"]
BASE = f"https://127.0.0.1:{PORT}"

headers = {"Authorization": f"Bearer {TOKEN}"}

# verify=False is only for local debugging against the self-signed localhost cert.
resp = requests.get(f"{BASE}/api/health", verify=False)
print(resp.text)  # "ok"

resp = requests.get(f"{BASE}/api/info", headers=headers, verify=False)
print(resp.status_code)  # 401 if the token is missing or wrong

The "API Token" Credential Type

Separately from the agent auth token, the vault supports an API Token credential type for storing the API tokens of external systems. The credential types NetStacks can store are:

  • ssh_password — SSH password
  • ssh_key — SSH private key
  • api_token — an API token for a third-party service
  • snmp_community — SNMP community string
  • generic_secret — any other secret value

A common use of api_token is integration with inventory and monitoring sources. For example, NetStacks authenticates to NetBox by sending the stored token in an Authorization: Token header (not Bearer). LibreNMS instead expects the token in an X-Auth-Token header:

source-auth.shbash
# How NetStacks authenticates to a NetBox source using a stored token.
curl https://netbox.example.net/api/dcim/devices/ \
  -H "Authorization: Token ${NETBOX_API_TOKEN}" \
  -H "Accept: application/json"

# How NetStacks authenticates to a LibreNMS source using a stored token.
curl https://librenms.example.net/api/v0/devices \
  -H "X-Auth-Token: ${LIBRENMS_API_TOKEN}"
Where these live

API Token credentials are managed in the vault alongside SSH and SNMP secrets, so they benefit from the same encryption at rest. See the related links below for how the vault stores secrets and how to wire up a NetBox source.

Questions & Answers

Q: Does NetStacks have a dashboard to create and revoke API tokens?
A: No. There is no platform token manager with creatable, expiring, or individually revocable tokens. The agent uses a single bearer token per running session, and external service tokens are stored as ordinary vault credentials of the api_token type.
Q: Where does the agent auth token come from?
A: From the NETSTACKS_AUTH_TOKEN environment variable supplied by the parent app (sidecar mode), or, if none is provided, the agent generates a random 256-bit hex token at startup and prints it to stdout for the launcher to capture.
Q: What is the auth header format for the local agent API?
A: Authorization: Bearer <token> — the header must start with the exact prefix Bearer followed by the 64-character hex token.
Q: Which endpoints require the token?
A: All of them except GET /api/health, which is exempt by exact-path match and returns the body ok. Every other route returns 401 Unauthorized without a valid token.
Q: Does the auth token expire?
A: There is no expiration date. The token is valid for the lifetime of the agent process. Restarting the agent effectively rotates it — the previous token stops working.
Q: Is there API rate limiting on the agent?
A: No built-in rate limiter ships with the local agent API. Authentication is the single gate, and the API is bound to 127.0.0.1 over TLS.
Q: How do I store a NetBox or LibreNMS token?
A: Store it as an api_token credential in the vault. NetStacks sends a NetBox token in an Authorization: Token <token> header, and a LibreNMS token in an X-Auth-Token header.

Troubleshooting

401 Unauthorized from the agent API

  • Confirm the header is exactly Authorization: Bearer <token> with a capital B and a single space before the token.
  • Make sure you are using the current token. The token rotates on every agent restart, so a value captured from a previous run will be rejected.
  • Strip stray whitespace or newlines from the token — the comparison is exact.
  • Remember that only GET /api/health is exempt. A route that merely ends in health still needs the token.
verify-token.shbash
# Quick check that the agent is up (no token needed):
curl -k -s -o /dev/null -w "%{http_code}\n" https://127.0.0.1:${AGENT_PORT}/api/health
# Expected: 200, body "ok"

# Check that your token is accepted on an authenticated route:
curl -k -s -o /dev/null -w "%{http_code}\n" https://127.0.0.1:${AGENT_PORT}/api/info \
  -H "Authorization: Bearer ${NETSTACKS_AUTH_TOKEN}"
# 200 = good, 401 = bad/missing token

TLS certificate errors against 127.0.0.1

The agent serves over TLS with a locally generated certificate for 127.0.0.1. A generic HTTP client will not trust it by default. For local debugging you can disable verification (-k in curl, verify=False in requests); in the NetStacks app the certificate is trusted automatically.

External source returns 403 with a stored API Token

If a NetBox or LibreNMS integration fails to authenticate, verify the stored api_token credential is current and that you are using the header the source expects — NetBox uses Authorization: Token, while LibreNMS uses X-Auth-Token. Regenerate the token in the source system and update the vault credential if needed.

Learn more about credentials and integrations: