API

The Nebula Commander backend exposes a REST API under the base path /api. All routes are prefixed with /api. Most endpoints require a valid JWT in the Authorization: Bearer <token> header unless noted otherwise.

OpenAPI docs

When the backend is running in debug mode, interactive documentation is available at:

  • Swagger UI – /api/docs
  • ReDoc – /api/redoc

For full request/response schemas and parameters, use the interactive docs.


Health and root

MethodPathAuthDescription
GET/apiNoRoot response: name, version, status.
GET/api/healthNoHealth check. Returns {"status": "healthy"}.

Auth (/api/auth)

Authentication and session management. OIDC (e.g. Keycloak) is used when configured; otherwise a dev token is available in debug mode.

MethodPathAuthDescription
GET/api/auth/dev-tokenNoDevelopment only. When DEBUG=true or OIDC is not configured, returns a JWT (token, expires_in). Grants full admin access. Returns 404 in production when OIDC is configured.
GET/api/auth/meOptionalCurrent user info. Returns {"authenticated": false} or {"authenticated": true, "sub", "email", "role", "system_role"}.
GET/api/auth/loginNoRedirects to the OIDC provider for login. Returns 501 if OIDC is not configured.
GET/api/auth/oidc-statusNoOIDC provider readiness. Returns {"status": "ok"}, {"status": "disabled"}, or 503 if provider is unavailable.
GET/api/auth/callbackNoOAuth callback. Exchanges authorization code for tokens and redirects to frontend with JWT in query (/auth/callback?token=...).
GET/api/auth/logoutNoLogs out and redirects to OIDC logout (or frontend if OIDC not configured).
POST/api/auth/reauth/challengeYesCreates a reauthentication challenge for critical operations. Body: none. Response: challenge, reauth_url. Used before destructive actions (e.g. delete network).
GET/api/auth/reauth/callbackNoReauth OAuth callback. Validates state (challenge) and redirects to frontend with reauth token.

Heartbeat (/api/nodes)

Used by ncclient (or other clients) to report node liveness.

MethodPathAuthDescription
POST/api/nodes/{node_id}/heartbeatYes (JWT)Updates last_seen and sets node status to active. Call periodically from enrolled nodes. Response: {"ok": true, "last_seen": "<iso>"}.

Networks (/api/networks)

Create and manage Nebula networks. Permissions are enforced per network (owner, member, and capability flags).

MethodPathAuthDescription
GET/api/networksYesList networks the user can access. Includes role, can_manage_nodes, can_invite_users, can_manage_firewall per network. System admins see all networks (with limited data).
POST/api/networksYesCreate a network. Body: name, subnet_cidr. Creator becomes owner. Returns full network object. 409 if name exists.
GET/api/networks/{network_id}YesGet a single network. System admins need an access grant to see CA path.
PATCH/api/networks/{network_id}YesUpdate network (owner only). Body: optional fields (currently no network-level firewall; use group firewall).
DELETE/api/networks/{network_id}YesDelete network (owner only; system admins can delete any). Body: reauth_token, confirmation (must match network name). 204 on success.
GET/api/networks/{network_id}/group-firewallYesList per-group firewall configs. Requires can_manage_firewall. Response: list of {group_name, inbound_rules}.
PUT/api/networks/{network_id}/group-firewall/{group_name}YesCreate or update inbound firewall rules for a group. Body: inbound_rules (each: allowed_group, protocol (any/tcp/udp/icmp), port_range, optional description).
DELETE/api/networks/{network_id}/group-firewall/{group_name}YesRemove group firewall config for that group. 204 on success.
GET/api/networks/{network_id}/check-ipYesCheck if an IP is available in the network. Query: ip. Response: {"available": true or false}. 400 if IP not in subnet.

Nodes (/api/nodes)

Manage Nebula nodes (hosts) within networks. Used by the Web UI and for manual cert/config workflows.

MethodPathAuthDescription
GET/api/nodesYesList nodes. Query: optional network_id. Returns list of node objects (id, network_id, hostname, ip_address, groups, is_lighthouse, is_relay, status, etc.).
GET/api/nodes/{node_id}YesGet a single node by ID.
PATCH/api/nodes/{node_id}YesUpdate node. Body (all optional): group, is_lighthouse, is_relay, public_endpoint, lighthouse_options, logging_options, punchy_options. 409 if removing the only lighthouse. Response: {"ok": true}.
DELETE/api/nodes/{node_id}YesDelete node: release IP, remove host cert/key files, delete related records. 204. 409 if node is the only lighthouse.
GET/api/nodes/{node_id}/configYesGenerate and return Nebula YAML config for the node (with inline PKI when key is stored). Response: application/yaml attachment.
GET/api/nodes/{node_id}/certsYesReturn a ZIP with ca.crt, host.crt, optional host.key, and README.txt.
POST/api/nodes/{node_id}/revoke-certificateYesRevoke the node’s certificate; node record is kept. Releases IP and removes cert/key files. Node can re-enroll later. Response: {"ok": true}.
POST/api/nodes/{node_id}/re-enrollYesRevoke existing cert (if any) and issue a new one for this node. Frontend typically creates an enrollment code afterward. Response: {"ok": true, "node_id": id}.

Certificates (/api/certificates)

Create or sign host certificates. Used when creating nodes from the Web UI or when using client-generated keys (e.g. betterkeys).

MethodPathAuthDescription
POST/api/certificates/signYesSign a host certificate (client sends public key). Body: network_id, name, public_key, optional group, suggested_ip, duration_days. Response: ip_address, certificate (PEM), optional ca_certificate. Creates or updates node record.
POST/api/certificates/createYesCreate a host certificate (server generates keypair). Body: network_id, name, optional group, suggested_ip, duration_days, is_lighthouse, is_relay, public_endpoint, lighthouse_options, punchy_options. Response: node_id, hostname, ip_address, certificate, private_key, optional ca_certificate. First node in network must be lighthouse. 409 if node name exists or suggested IP is taken.
GET/api/certificatesYesList issued certificates. Query: optional network_id. Response: list of {id, node_id, node_name, network_id, network_name, ip_address, issued_at, expires_at, revoked_at}.

Device (/api/device)

Used by ncclient for enrollment and for fetching config/certs with a device token. Flow: create enrollment code (admin) → device redeems code at POST /enroll → device uses returned token for GET /config and GET /certs.

MethodPathAuthDescription
POST/api/device/enrollment-codesYes (JWT)Create a one-time enrollment code for a node. Body: node_id, expires_in_hours (default 24). Response: code, expires_at, node_id, hostname. Node must already have a certificate.
POST/api/device/enrollNoPublic. Redeem a one-time code. Body: code. Response: device_token, node_id, hostname. Rate limited (e.g. 5 attempts per 15 min per IP). 404 if code invalid/expired, 400 if already used or expired.
GET/api/device/configDevice tokenReturn Nebula YAML config for the device (inline PKI). Header: Authorization: Bearer <device_token>. Optional If-None-Match: <etag> for 304 when unchanged.
GET/api/device/certsDevice tokenReturn ZIP with ca.crt, host.crt, optional host.key, README.txt for the device.

Users (/api/users)

System admin user management. All endpoints require system-admin role.

MethodPathAuthDescription
GET/api/usersSystem adminList all users. Response: list of {id, oidc_sub, email, system_role, created_at, network_count}.
GET/api/users/{user_id}System adminGet user details including networks (list of network id, name, role, permission flags).
PATCH/api/users/{user_id}System adminUpdate user. Body: optional system_role (system-admin or user).
DELETE/api/users/{user_id}System adminDelete user; removes all their network permissions. 204.

Node requests (/api/node-requests)

Request/approve workflow for node creation (e.g. when auto-approve is off).

MethodPathAuthDescription
POST/api/node-requestsYesCreate a node request. Body: network_id, hostname, optional groups, is_lighthouse, is_relay. If user has manage_nodes or network has auto_approve_nodes, request is approved immediately and node is created. Response includes status, created_node_id if approved.
GET/api/node-requestsYesList node requests. Query: optional network_id, status. Users see own requests; network owners/admins see requests for their networks; system admins see all.
POST/api/node-requests/{request_id}/approveYesApprove a pending request; creates the node and allocates IP. Body: empty object. Requires manage_nodes on the network.
POST/api/node-requests/{request_id}/rejectYesReject a pending request. Body: reason. Requires manage_nodes on the network.

Access grants (/api/access-grants)

Temporary access for system admins to a specific network or node (e.g. for support). Only network owners can create grants.

MethodPathAuthDescription
POST/api/access-grantsYesCreate an access grant. Body: admin_user_id, resource_type (network or node), resource_id, duration_hours, reason. Target user must be system-admin.
GET/api/access-grantsYesList grants. Query: active_only (default true). Network owners see grants they created; system admins see grants for them.
DELETE/api/access-grants/{grant_id}YesRevoke a grant. Only the user who created the grant can revoke. 204.

Invitations (/api/invitations)

Invite users to join a network by email. Requires can_invite_users (or owner) on the network.

MethodPathAuthDescription
POST/api/invitationsYesCreate invitation. Body: email, network_id, role (owner/member), can_manage_nodes, can_invite_users, can_manage_firewall, expires_in_days (default 7). Sends email if SMTP configured. 400 if user already member or pending invitation exists.
GET/api/invitationsYesList invitations. Query: optional network_id, status_filter. Owners see invitations for their networks; system admins see all.
GET/api/invitations/public/{token}NoPublic. Get invitation details by token (no auth). Returns network name, inviter, role, permissions, status, expires_at. 410 if expired.
POST/api/invitations/{token}/acceptYesAccept invitation; creates NetworkPermission for current user. Must be logged in. Email should match invitation (optional check).
POST/api/invitations/{invitation_id}/resendYesResend invitation email. Pending only.
DELETE/api/invitations/{invitation_id}YesRevoke invitation (inviter or network owner). Sets status to revoked. 204.

Network permissions (/api/networks)

Manage which users have access to a network and their roles/permissions. Owner-only for list/update/remove; can_invite_users for add.

MethodPathAuthDescription
GET/api/networks/{network_id}/usersYesList users with access to the network. Owner or system admin. Response: list of user_id, email, role, can_manage_, invited_by_, created_at.
POST/api/networks/{network_id}/usersYesAdd user to network. Body: user_id, role (owner/member), can_manage_nodes, can_invite_users, can_manage_firewall. Requires can_invite_users. 400 if already member.
PATCH/api/networks/{network_id}/users/{target_user_id}YesUpdate user’s permissions. Body: optional role, can_manage_nodes, can_invite_users, can_manage_firewall. Owner only. Cannot demote the last owner.
DELETE/api/networks/{network_id}/users/{target_user_id}YesRemove user from network. Owner only. Cannot remove the last owner. 204.

Audit (/api/audit)

Read-only audit log. System admins only.

MethodPathAuthDescription
GET/api/auditSystem adminList audit log entries. Query: limit (default 50, max 200), offset, optional action, resource_type, from_date, to_date. Ordered by occurred_at descending. Response: list of id, occurred_at, action, actor_*, resource_type, resource_id, result, details, client_ip.

Summary

  • /api — Root, health
  • /api/auth — Login, callback, dev-token, logout, reauth
  • /api/nodes — Heartbeat, and full node CRUD + config/certs/revoke/re-enroll
  • /api/networks — Networks CRUD, group firewall, check-ip, and network users (permissions)
  • /api/certificates — Sign host cert (client key), create host cert (server key), list certs
  • /api/device — Enrollment codes, enroll (public), config and certs (device token)
  • /api/users — User list/detail/update/delete (system admin)
  • /api/node-requests — Create/list/approve/reject node requests
  • /api/access-grants — Create/list/revoke temporary admin access
  • /api/invitations — Create/list/accept/resend/revoke invitations
  • /api/audit — List audit log (system admin)
Last modified February 27, 2026: Update API Documentation (211bbd5)