Skip to main content

API Reference

Complete reference for the Wirety REST API.

Overview

Base URL

All endpoints are relative to:

/api/v1

Authentication

Most endpoints require authentication. Three mechanisms are accepted and may be combined:

MechanismHeader / CookieValue
Session hashAuthorization: Session <hash>Obtained from login or OIDC token exchange
API tokenAuthorization: Bearer wirety_<hex>Long-lived personal access token
Session cookiewirety_session (HttpOnly cookie)Set automatically by the server on login

Session cookies are set automatically when using the login or token exchange endpoints.

Roles

RoleDescription
administratorFull access to all resources across all networks
userAccess limited to authorized networks and own peers

Endpoints marked [admin] require the administrator role and return 403 Forbidden otherwise.

Error Format

All error responses use:

{ "error": "human-readable error message" }

Pagination

Paginated endpoints accept page (default 1) and page_size (default 20) query parameters and return:

{
"data": [...],
"total": 100,
"page": 1,
"page_size": 20
}

Health

Health Check

Check if the API server is running. No authentication required.

GET /health

Response 200

{ "status": "ok" }

Authentication

Get Auth Config

Returns the public authentication configuration. No credentials required.

GET /auth/config

Response 200

{
"enabled": true,
"issuer_url": "https://accounts.example.com",
"client_id": "wirety-app",
"simple_auth": false
}
FieldDescription
enabledWhether OIDC authentication is enabled
issuer_urlOIDC issuer URL (empty when OIDC is disabled)
client_idOIDC client ID for the frontend
simple_authtrue when AUTH_ENABLED=false — admin/password login is used instead

Exchange OIDC Token

Exchange an OIDC authorization code for a server-side session. Only available when OIDC is enabled (enabled: true in auth config).

POST /auth/token

Request Body

{
"code": "authorization_code_from_oidc",
"redirect_uri": "https://app.example.com/callback"
}

Response 200

{
"session_hash": "abc123...",
"expires_in": 3600
}

The server also sets a wirety_session HttpOnly cookie. Subsequent requests can use either the session_hash value in the Authorization: Session header or the cookie.


Login (Simple Auth)

Authenticate with username/password. Only available when OIDC is disabled (simple_auth: true in auth config).

POST /auth/login

Request Body

{
"username": "admin",
"password": "your-admin-password"
}

Response 200

{
"session_hash": "abc123...",
"expires_in": 2592000
}

The server also sets a wirety_session HttpOnly cookie.


Logout

Invalidate the current session.

POST /auth/logout

Request Body (optional — the session is preferably resolved from the cookie or Authorization header)

{
"session_hash": "abc123..."
}

Response 200

{ "message": "Logged out successfully" }

Users

Get Current User

Returns the authenticated user's profile.

GET /users/me

Response 200

{
"id": "user-sub-from-oidc",
"email": "alice@example.com",
"name": "Alice",
"role": "user",
"authorized_networks": ["net-id-1", "net-id-2"],
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-10T12:00:00Z",
"last_login_at": "2024-04-10T08:00:00Z"
}

List Users [admin]

Returns all registered users.

GET /users

Response 200 — array of User objects (same shape as above).


Get User [admin]

GET /users/:userId

Path Parameters

ParameterDescription
userIdUser ID

Response 200 — User object.


Update User [admin]

Update a user's name, role, or authorized networks.

PUT /users/:userId

Request Body

{
"name": "Alice Smith",
"role": "administrator",
"authorized_networks": ["net-id-1"]
}

All fields are optional. Response 200 — updated User object.


Delete User [admin]

DELETE /users/:userId

Response 204 No Content


Get Default Permissions [admin]

Get the default role and network list applied to newly created users.

GET /users/defaults

Response 200

{
"default_role": "user",
"default_authorized_networks": ["net-id-1"]
}

Update Default Permissions [admin]

PUT /users/defaults

Request Body

{
"default_role": "user",
"default_authorized_networks": ["net-id-1"]
}

Response 200 — updated DefaultNetworkPermissions object.


API Tokens

Tokens belong to the authenticated user and use the wirety_ prefix.

List API Tokens

GET /users/me/tokens

Response 200 — array of token objects (raw token is not included in listing).

[
{
"id": "token-uuid",
"name": "ci-bot",
"created_at": "2024-01-01T00:00:00Z",
"expires_at": null,
"last_used_at": "2024-04-10T08:00:00Z"
}
]

Create API Token

POST /users/me/tokens

Request Body

{
"name": "ci-bot",
"expires_at": "2025-01-01T00:00:00Z"
}

expires_at is optional — omit for a non-expiring token.

Response 201

{
"id": "token-uuid",
"name": "ci-bot",
"token": "wirety_deadbeef...",
"created_at": "2024-04-13T00:00:00Z",
"expires_at": "2025-01-01T00:00:00Z",
"last_used_at": null
}

The token field is shown exactly once. Store it securely — it cannot be retrieved again.


Delete API Token

DELETE /users/me/tokens/:tokenId

Response 204 No Content


Networks

List Networks

Returns networks accessible to the authenticated user, with pagination and optional filtering.

GET /networks

Query Parameters

ParameterDefaultDescription
page1Page number
page_size20Items per page (max 200)
filterCase-insensitive substring filter on name, CIDR, or ID

Response 200

{
"data": [
{
"id": "net-uuid",
"name": "office",
"cidr": "10.10.0.0/16",
"peer_count": 12,
"dns": ["1.1.1.1"],
"domain_suffix": "internal",
"default_group_ids": [],
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-04-01T00:00:00Z"
}
],
"total": 1,
"page": 1,
"page_size": 20
}
FieldDescription
peer_countNumber of peers (computed, lightweight)
dnsAdditional DNS servers pushed to peers
domain_suffixInternal DNS domain suffix (default: internal)
default_group_idsGroups automatically assigned to non-admin peers

Create Network [admin]

POST /networks

Request Body

{
"name": "office",
"cidr": "10.10.0.0/16",
"dns": ["1.1.1.1", "8.8.8.8"],
"domain_suffix": "internal"
}

dns and domain_suffix are optional. Response 201 — Network object.


Get Network

GET /networks/:networkId

Response 200 — Network object.


Update Network [admin]

PUT /networks/:networkId

Request Body (all fields optional)

{
"name": "office-v2",
"cidr": "10.20.0.0/16",
"dns": ["1.1.1.1"],
"domain_suffix": "corp",
"default_group_ids": ["group-uuid"]
}

Response 200 — updated Network object.


Delete Network [admin]

DELETE /networks/:networkId

Response 204 No Content


Peers

List Peers

GET /networks/:networkId/peers

Non-admin users only see peers they own. Supports pagination and filtering.

Query Parameters

ParameterDefaultDescription
page1Page number
page_size20Items per page (max 500)
filterSubstring filter on name, IP address, or ID

Response 200

{
"data": [
{
"id": "peer-uuid",
"name": "laptop-alice",
"public_key": "base64pubkey=",
"address": "10.10.0.2",
"endpoint": "203.0.113.5:51820",
"listen_port": 51820,
"additional_allowed_ips": ["192.168.1.0/24"],
"token": "enroll-token-value",
"is_jump": false,
"use_agent": true,
"owner_id": "user-sub-123",
"group_ids": ["group-uuid"],
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-04-01T00:00:00Z"
}
],
"total": 1,
"page": 1,
"page_size": 20
}
FieldDescription
endpointExternal IP:port (mainly for jump peers)
listen_portWireGuard listen port (mainly for jump peers)
additional_allowed_ipsExtra CIDRs this peer can route
tokenAgent enrollment token (secret, handle with care)
is_jumpWhether this peer acts as a hub/jump server
use_agentWhether the dynamic agent manages this peer
owner_idUser ID of the peer owner (empty for admin-created peers)
group_idsGroups this peer belongs to

Create Peer

POST /networks/:networkId/peers

Non-admin users automatically become the peer owner.

Request Body

{
"name": "laptop-alice",
"endpoint": "203.0.113.5:51820",
"listen_port": 51820,
"is_jump": false,
"use_agent": true,
"additional_allowed_ips": ["192.168.1.0/24"]
}

All fields except name are optional. Response 201 — Peer object.


Get Peer

GET /networks/:networkId/peers/:peerId

Non-admin users can only retrieve their own peers.

Response 200 — Peer object.


Update Peer

PUT /networks/:networkId/peers/:peerId

Non-admin users can only update their own peers. Only admins can change owner_id.

Request Body (all fields optional)

{
"name": "laptop-alice-v2",
"endpoint": "203.0.113.10:51820",
"listen_port": 51820,
"additional_allowed_ips": ["192.168.2.0/24"],
"owner_id": "another-user-id"
}

Response 200 — updated Peer object.


Delete Peer

DELETE /networks/:networkId/peers/:peerId

Non-admin users can only delete their own peers.

Response 204 No Content


Get Peer Config

Returns the WireGuard configuration file for a peer.

GET /networks/:networkId/peers/:peerId/config

Non-admin users can only retrieve their own peer config.

Response 200

{ "config": "[Interface]\nPrivateKey = ...\n..." }

Get Peer Session Status

Returns the security session status for a peer (active agent sessions, endpoint changes, suspicious activity).

GET /networks/:networkId/peers/:peerId/session

Response 200

{
"peer_id": "peer-uuid",
"has_active_agent": true,
"current_session": {
"peer_id": "peer-uuid",
"hostname": "laptop-alice",
"system_uptime": 86400,
"wireguard_uptime": 3600,
"reported_endpoint": "203.0.113.5:51820",
"last_seen": "2024-04-13T10:00:00Z",
"first_seen": "2024-04-12T09:00:00Z",
"session_id": "sess-uuid"
},
"conflicting_sessions": [],
"recent_endpoint_changes": [],
"suspicious_activity": false,
"last_checked": "2024-04-13T10:05:00Z"
}

Get Peer Reachability

Computes which peers, policy rules, and external routes are reachable from a given peer, based on ACL and group/policy configuration.

GET /networks/:networkId/peers/:peerId/reachability

Response 200

{
"peer_id": "peer-uuid",
"peer_name": "laptop-alice",
"peer_address": "10.10.0.2",
"is_jump": false,
"peer_access": [
{
"peer_id": "peer-uuid-2",
"peer_name": "server-bob",
"address": "10.10.0.3",
"is_jump": false,
"allowed": true,
"reason": "default_allow"
}
],
"rules": [
{
"direction": "output",
"action": "allow",
"target_type": "cidr",
"target": "192.168.1.0/24",
"addresses": ["192.168.1.0/24"],
"policy_name": "allow-office",
"group_name": "engineering",
"description": "Allow office subnet"
}
],
"routes": [
{
"route_id": "route-uuid",
"route_name": "office-lan",
"destination_cidr": "192.168.1.0/24",
"jump_peer_id": "jump-uuid",
"jump_peer_name": "jump-server-1",
"group_name": "engineering"
}
]
}

reason values for peer_access:

ValueMeaning
acl_disabledACL is disabled — all peers can communicate
allow_ruleMatched an explicit allow rule
deny_ruleMatched an explicit deny rule
blockedPeer is in the blocked list
default_allowNo rule matched — default is allow

Groups

Groups require DB_ENABLED=true. All group endpoints are [admin] only.

List Groups [admin]

GET /networks/:networkId/groups

Response 200 — array of Group objects.

[
{
"id": "group-uuid",
"network_id": "net-uuid",
"name": "engineering",
"description": "Engineering team",
"priority": 100,
"peer_ids": ["peer-uuid"],
"policy_ids": ["policy-uuid"],
"route_ids": ["route-uuid"],
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-04-01T00:00:00Z"
}
]
FieldDescription
priorityPolicy application order — lower value = higher priority (range 1–999)

Create Group [admin]

POST /networks/:networkId/groups

Request Body

{
"name": "engineering",
"description": "Engineering team",
"priority": 100
}

description and priority are optional (default priority: 100). Response 201 — Group object.


Get Group [admin]

GET /networks/:networkId/groups/:groupId

Response 200 — Group object.


Update Group [admin]

PUT /networks/:networkId/groups/:groupId

Request Body (all fields optional)

{
"name": "engineering-v2",
"description": "Updated description",
"priority": 50
}

Response 200 — updated Group object.


Delete Group [admin]

DELETE /networks/:networkId/groups/:groupId

Response 204 No Content


Add Peer to Group [admin]

POST /networks/:networkId/groups/:groupId/peers/:peerId

Response 200

Returns 400 Bad Request with details if adding the peer would create a circular routing dependency.


Remove Peer from Group [admin]

DELETE /networks/:networkId/groups/:groupId/peers/:peerId

Response 204 No Content


Get Group Routes [admin]

GET /networks/:networkId/groups/:groupId/routes

Response 200 — array of Route objects attached to the group.


Policies

Policies require DB_ENABLED=true. All policy endpoints are [admin] only.

List Policies [admin]

GET /networks/:networkId/policies

Response 200 — array of Policy objects.

[
{
"id": "policy-uuid",
"network_id": "net-uuid",
"name": "allow-office",
"description": "Allow access to office subnet",
"rules": [
{
"id": "rule-uuid",
"direction": "output",
"action": "allow",
"target": "192.168.1.0/24",
"target_type": "cidr",
"description": "Office LAN"
}
],
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-04-01T00:00:00Z"
}
]

PolicyRule fields

FieldValues
direction"input" or "output"
action"allow" or "deny"
target_type"cidr", "peer", or "group"
targetCIDR string, peer ID, or group ID depending on target_type

Create Policy [admin]

POST /networks/:networkId/policies

Request Body

{
"name": "allow-office",
"description": "Allow access to office subnet",
"rules": [
{
"direction": "output",
"action": "allow",
"target": "192.168.1.0/24",
"target_type": "cidr",
"description": "Office LAN"
}
]
}

description and rules are optional. Response 201 — Policy object.


Get Policy [admin]

GET /networks/:networkId/policies/:policyId

Response 200 — Policy object.


Update Policy [admin]

PUT /networks/:networkId/policies/:policyId

Request Body (all fields optional)

{
"name": "allow-office-v2",
"description": "Updated description"
}

Response 200 — updated Policy object.


Delete Policy [admin]

DELETE /networks/:networkId/policies/:policyId

Response 204 No Content


Add Rule to Policy [admin]

POST /networks/:networkId/policies/:policyId/rules

Request Body

{
"direction": "output",
"action": "allow",
"target": "192.168.1.0/24",
"target_type": "cidr",
"description": "Office LAN"
}

Response 201 — PolicyRule object.


Remove Rule from Policy [admin]

DELETE /networks/:networkId/policies/:policyId/rules/:ruleId

Response 204 No Content


Attach Policy to Group [admin]

POST /networks/:networkId/groups/:groupId/policies/:policyId

Response 200


Detach Policy from Group [admin]

DELETE /networks/:networkId/groups/:groupId/policies/:policyId

Response 204 No Content


Get Group Policies [admin]

GET /networks/:networkId/groups/:groupId/policies

Response 200 — array of Policy objects attached to the group.


Reorder Group Policies [admin]

Set the evaluation order of policies within a group. The array must contain all policy IDs currently attached to the group.

PUT /networks/:networkId/groups/:groupId/policies/order

Request Body

{
"policy_ids": ["policy-uuid-1", "policy-uuid-2"]
}

Response 200

{ "message": "Policies reordered successfully" }

Routes

Routes require DB_ENABLED=true. All route endpoints are [admin] only.

List Routes [admin]

GET /networks/:networkId/routes

Response 200 — array of Route objects.

[
{
"id": "route-uuid",
"network_id": "net-uuid",
"name": "office-lan",
"description": "Office internal network",
"destination_cidr": "192.168.1.0/24",
"jump_peer_id": "jump-uuid",
"domain_suffix": "office.internal",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-04-01T00:00:00Z"
}
]

Create Route [admin]

POST /networks/:networkId/routes

Request Body

{
"name": "office-lan",
"description": "Office internal network",
"destination_cidr": "192.168.1.0/24",
"jump_peer_id": "jump-uuid",
"domain_suffix": "office.internal"
}

description and domain_suffix are optional. Response 201 — Route object.


Get Route [admin]

GET /networks/:networkId/routes/:routeId

Response 200 — Route object.


Update Route [admin]

PUT /networks/:networkId/routes/:routeId

Request Body (all fields optional)

{
"name": "office-lan-v2",
"description": "Updated description",
"destination_cidr": "192.168.2.0/24",
"jump_peer_id": "jump-uuid-2",
"domain_suffix": "corp.internal"
}

Response 200 — updated Route object.


Delete Route [admin]

DELETE /networks/:networkId/routes/:routeId

Response 204 No Content


Attach Route to Group [admin]

POST /networks/:networkId/groups/:groupId/routes/:routeId

Response 200

Returns 400 Bad Request with details if attaching would create a circular routing dependency.


Detach Route from Group [admin]

DELETE /networks/:networkId/groups/:groupId/routes/:routeId

Response 204 No Content


DNS Mappings

DNS mappings require DB_ENABLED=true. All DNS endpoints are [admin] only.

DNS mappings resolve hostnames within a route's CIDR to specific IP addresses. The FQDN format is <name>.<route_name>.<domain_suffix>.

List DNS Mappings [admin]

GET /networks/:networkId/routes/:routeId/dns

Response 200 — array of DNSMapping objects.

[
{
"id": "dns-uuid",
"route_id": "route-uuid",
"name": "server1",
"ip_address": "192.168.1.10",
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-04-01T00:00:00Z"
}
]

Create DNS Mapping [admin]

POST /networks/:networkId/routes/:routeId/dns

Request Body

{
"name": "server1",
"ip_address": "192.168.1.10"
}

The name field must follow DNS label rules (alphanumeric + hyphens, max 63 characters). Response 201 — DNSMapping object.


Update DNS Mapping [admin]

PUT /networks/:networkId/routes/:routeId/dns/:dnsId

Request Body (all fields optional)

{
"name": "server1-new",
"ip_address": "192.168.1.11"
}

Response 200 — updated DNSMapping object.


Delete DNS Mapping [admin]

DELETE /networks/:networkId/routes/:routeId/dns/:dnsId

Response 204 No Content


Get Network DNS Records [admin]

Returns all DNS records for a network (both peer-based and route mapping-based).

GET /networks/:networkId/dns

Response 200 — array of DNS record objects.

[
{
"name": "laptop-alice",
"ip_address": "10.10.0.2",
"fqdn": "laptop-alice.office.internal",
"type": "peer"
},
{
"name": "server1",
"ip_address": "192.168.1.10",
"fqdn": "server1.office-lan.office.internal",
"type": "route"
}
]
typeSource
"peer"Peer in the network
"route"DNS mapping attached to a route

ACL

ACL endpoints are [admin] only.

The ACL is a lightweight allow/deny layer operating at the peer-to-peer level. It complements group policies. When disabled, all peers can communicate freely.

Get ACL [admin]

GET /networks/:networkId/acl

Response 200

{
"id": "acl-uuid",
"name": "default",
"enabled": true,
"blocked_peers": {
"peer-uuid-bad": true
},
"rules": [
{
"id": "rule-uuid",
"source_peer": "*",
"target_peer": "peer-uuid-3",
"action": "deny",
"description": "Block access to server"
}
]
}
FieldDescription
enabledWhen false, ACL is bypassed and all peers can communicate
blocked_peersMap of peer IDs that are unconditionally blocked
rulesOrdered list of rules; first match wins; default is allow
source_peer / target_peerPeer ID or "*" for all peers

Update ACL [admin]

Replaces the entire ACL configuration.

PUT /networks/:networkId/acl

Request Body — full ACL object (same structure as GET response).

Response 200 — updated ACL object. Notifies connected agents via WebSocket.


Security / Incidents

List Security Incidents

Returns security incidents. Non-admin users only see incidents for their own peers.

GET /security/incidents

Query Parameters

ParameterDescription
resolvedtrue or false to filter by resolved status; omit for all

Response 200 — array of SecurityIncident objects.

[
{
"id": "incident-uuid",
"peer_id": "peer-uuid",
"peer_name": "laptop-alice",
"network_id": "net-uuid",
"network_name": "office",
"incident_type": "session_conflict",
"detected_at": "2024-04-13T08:00:00Z",
"public_key": "base64pubkey=",
"endpoints": ["203.0.113.5:51820", "198.51.100.1:51820"],
"details": "Multiple active agents detected for the same peer",
"resolved": false,
"resolved_at": null,
"resolved_by": null
}
]

incident_type values:

ValueDescription
shared_configSame WireGuard key used from multiple IPs
session_conflictMultiple active agents for the same peer
suspicious_activityRapid endpoint changes detected

List Network Security Incidents

GET /networks/:networkId/security/incidents

Same behavior as the global endpoint but scoped to one network. Accepts the same resolved query parameter.

Response 200 — array of SecurityIncident objects.


Get Security Incident

GET /security/incidents/:incidentId

Non-admin users can only retrieve incidents for their own peers.

Response 200 — SecurityIncident object.


Resolve Security Incident [admin]

POST /security/incidents/:incidentId/resolve

Response 200

{ "message": "Incident resolved successfully" }

Get Network Security Config [admin]

GET /networks/:networkId/security/config

Response 200

{
"id": "cfg-uuid",
"network_id": "net-uuid",
"enabled": true,
"session_conflict_threshold_minutes": 5,
"endpoint_change_threshold_minutes": 5,
"max_endpoint_changes_per_day": 10,
"port_change_threshold_minutes": 5,
"max_port_changes_per_window": 5,
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-04-13T00:00:00Z"
}

All threshold values are in minutes.


Update Network Security Config [admin]

PUT /networks/:networkId/security/config

Request Body (all fields optional)

{
"enabled": true,
"session_conflict_threshold_minutes": 5,
"endpoint_change_threshold_minutes": 10,
"max_endpoint_changes_per_day": 20,
"port_change_threshold_minutes": 5,
"max_port_changes_per_window": 10
}

Validation: all threshold values must be ≥ 1. max_endpoint_changes_per_day and max_port_changes_per_window must be between 1 and 1000.

Response 200 — updated SecurityConfigResponse.


IPAM

Suggest Available CIDRs

Suggests one or more CIDRs of the right size for a target number of peers, carved from a base CIDR. Useful when planning a new network.

GET /ipam/available-cidrs

Query Parameters

ParameterRequiredDefaultDescription
max_peersYesMinimum number of usable host addresses needed
countNo1Number of CIDRs to return (max 20)
base_cidrNo10.0.0.0/8Root CIDR to carve from

Response 200

{
"base_cidr": "10.0.0.0/8",
"requested_max_peers": 50,
"suggested_prefix": 26,
"usable_hosts": 62,
"cidrs": ["10.0.0.0/26", "10.0.0.64/26"]
}

List IPAM Allocations

Returns all IP allocations across accessible networks, with pagination and filtering.

GET /ipam

Non-admin users only see peers they own.

Query Parameters

ParameterDefaultDescription
page1Page number
page_size20Items per page (max 100)
filterSubstring filter on network name, IP, or peer name

Response 200

{
"data": [
{
"network_id": "net-uuid",
"network_name": "office",
"network_cidr": "10.10.0.0/16",
"ip": "10.10.0.2",
"peer_id": "peer-uuid",
"peer_name": "laptop-alice",
"allocated": true
}
],
"total": 1,
"page": 1,
"page_size": 20
}

Get Network IPAM Allocations

GET /ipam/networks/:networkId

Response 200 — array of IPAMAllocation objects for the specified network.


Sessions

List Network Sessions

Returns active agent sessions in a network.

GET /networks/:networkId/sessions

Response 200 — array of AgentSession objects.

[
{
"peer_id": "peer-uuid",
"hostname": "laptop-alice",
"system_uptime": 86400,
"wireguard_uptime": 3600,
"reported_endpoint": "203.0.113.5:51820",
"last_seen": "2024-04-13T10:00:00Z",
"first_seen": "2024-04-12T09:00:00Z",
"session_id": "sess-uuid"
}
]

Agent Enrollment

Resolve Agent Token

Exchange a peer enrollment token for the peer's identifiers and WireGuard configuration. This endpoint is unauthenticated (uses the token itself as authentication via Authorization: Bearer).

GET /agent/resolve

Headers

Authorization: Bearer <enrollment-token>

Response 200

{
"network_id": "net-uuid",
"peer_id": "peer-uuid",
"peer_name": "laptop-alice",
"config": "[Interface]\nPrivateKey = ...\n..."
}

Returns 404 Not Found if the token is invalid or expired.


MCP Server

Wirety exposes a Model Context Protocol (MCP) server at /api/v1/mcp using the SSE transport. Both GET (stream) and POST (messages) at the same path are supported. Authentication is required (same session/token mechanisms as other endpoints).

See the MCP documentation for the list of available tools.


WebSocket

WebSocket (Token-based)

GET /ws

Connect with a short-lived WebSocket token. Delivers real-time peer configuration updates.

WebSocket (Legacy)

GET /ws/:networkId/:peerId

Peer-specific WebSocket connection using network and peer IDs directly.


Captive Portal

Create Captive Portal Token

Called by a jump peer agent (authenticated via enrollment token) when a new peer connects and needs to authenticate.

POST /captive-portal/token

Headers

Authorization: Bearer <jump-peer-enrollment-token>

Request Body

{ "peer_ip": "10.10.0.5" }

Response 201 — captive portal token object.

Requires OIDC authentication to be enabled (AUTH_ENABLED=true).


Authenticate Captive Portal

Validates the captive portal token against the current user session and whitelists the peer.

POST /captive-portal/authenticate

Requires the wirety_session cookie to be present (set during login).

Request Body

{ "captive_token": "captive-token-value" }

Response 200

{
"peer_ip": "10.10.0.5",
"network_id": "net-uuid",
"whitelisted": true
}