API Endpoints Reference
Detailed documentation of the Wiretastix RESTful API endpoints.
Wiretastix exposes a comprehensive RESTful API that allows for programmatic interaction with the daemon. The wiretastix-cli tool is a direct wrapper around these APIs, providing a convenient command-line interface.
All API endpoints are prefixed with the base path configured in wiretastix.yaml (default: /wiretastix/api/v1/). By default, the API server binds to 127.0.0.1, meaning it is only accessible from the local machine and not from external networks. This can be changed in the wiretastix.yaml configuration file if external access is required.
Authentication
All API requests must be authenticated using a Bearer token in the Authorization header:
Authorization: Bearer YOUR_API_TOKEN
Endpoints
Tokens
Manage API authentication tokens.
GET /tokens/- Description: Retrieve a list of all API tokens.
- Response:
200 OKwith a list ofAPIKeyobjects. - Response Model (
APIKey):[ { "token": "some-generated-token-1", "name": "admin-token", "created-ts": "2025-01-01T12:00:00Z", "description": "Administrator access token" }, { "token": "some-generated-token-2", "name": "cli-token", "created-ts": "2025-01-02T10:30:00Z" } ] - CURL Example:
curl -k -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/apitokens/
PUT /apitokens/:token- Description: Create a new API token. The token string itself is provided in the path and must match the
namein the request body.namemust be 1-16 characters: letters, numbers, dots, dashes, and underscores – the same rule the CLI enforces client-side, now also enforced here, so a name that would pass the CLI can no longer be silently rejected (or a name the CLI would never allow silently accepted) when this endpoint is called directly. - Parameters:
:token(path): The new API token string.
- Request Body: Optional
APIKeyobject to setnameanddescription. - Request Body Example:
{ "name": "my-new-token-name", "description": "Token for my application" } - Response:
201 Createdwith the createdAPIKeyobject. - Response Model (
APIKey):{ "token": "my-new-token-name", "name": "my-new-token-name", "created-ts": "2025-01-03T09:00:00Z", "description": "Token for my application" } - CURL Example:
curl -k -X PUT \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"name": "my-new-token-name", "description": "Token for my application"}' \ https://127.0.0.1:8095/wiretastix/api/v1/apitokens/my-new-token-name
- Description: Create a new API token. The token string itself is provided in the path and must match the
DELETE /tokens/:token- Description: Delete an existing API token.
- Parameters:
:token(path): The API token to delete.
- Response:
204 No Contenton success. - CURL Example:
curl -k -X DELETE \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/apitokens/token-to-delete-string
Configurations
Manage global Wiretastix configurations.
GET /configs/- Description: Retrieve all configuration parameters.
- Response:
200 OKwith a list ofConfigItemobjects. - Response Model (
ConfigItem):[ { "param": "default_keepalive_seconds", "value": "25" }, { "param": "default_mtu", "value": "1280" } ] - CURL Example:
curl -k -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/configs/
PUT /configs/:param- Description: Set a specific configuration parameter. The
paramproperty in the request body must match the:paramin the URL. - Parameters:
:param(path): The name of the configuration parameter. Allowed values are:default_keepalive_secondsmax_devicesdefault_groupdefault_mtudefault_dnsdefault_searchdefault_endpointnew_users_enablednew_tunnels_enableddefault_allowed_ipsauto_disable_on_auth_errorreauthenticate_everyadditional_ports
- Request Body: JSON object with the
paramand newvalue. - Request Body Example:
{ "param": "default_keepalive_seconds", "value": "30" } - Response:
200 OKwith the updatedConfigItemobject. - Response Model (
ConfigItem):{ "param": "default_keepalive_seconds", "value": "30" } - CURL Example:
curl -k -X PUT \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"param": "default_keepalive_seconds", "value": "30"}' \ https://127.0.0.1:8095/wiretastix/api/v1/configs/default_keepalive_seconds
- Description: Set a specific configuration parameter. The
DELETE /configs/:param- Description: Delete a specific configuration parameter.
- Parameters:
:param(path): The name of the configuration parameter to delete.
- Response:
204 No Contenton success. - CURL Example:
curl -k -X DELETE \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/configs/default_keepalive_seconds
Peers
Manage static WireGuard peers. These are VPN endpoints not linked to any OIDC user account, typically used to connect other machines or services. Each OIDC user, on the other hand, can self-provision one or more dynamic VPN tunnels through the web interface.
GET /peers/- Description: Retrieve a list of all WireGuard peers. For peers not linked to an OIDC user, the
user_idfield will benull. - Response:
200 OKwith a list ofPeerobjects. - Response Model (
Peer):[ { "id": 1, "user_id": null, "name": "static-server", "public_key": "PUBLIC_KEY_STRING_1", "preshared_key": "PRESHARED_KEY_STRING_1", "ipv4": "10.0.0.2", "ipv6": "fd00::2", "keepalive": 25, "dns": "1.1.1.1", "search": "example.com", "allowed_ips": "0.0.0.0/0,::/0", "active": true, "created_at": "2025-01-01T12:00:00Z", "updated_at": "2025-01-01T12:00:00Z" }, { "id": 2, "user_id": "user123", "name": "laptop-john", "public_key": "PUBLIC_KEY_STRING_2", "preshared_key": "PRESHARED_KEY_STRING_2", "ipv4": "10.0.0.3", "ipv6": "fd00::3", "keepalive": 25, "dns": "1.1.1.1", "search": "example.com", "allowed_ips": "0.0.0.0/0,::/0", "active": true, "created_at": "2025-01-02T10:00:00Z", "updated_at": "2025-01-02T10:00:00Z" } ] - CURL Example:
curl -k -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/peers/
- Description: Retrieve a list of all WireGuard peers. For peers not linked to an OIDC user, the
GET /peers/status- Description: Retrieve real-time status and statistics for active peers.
- Response:
200 OKwith a list ofPeerStatsobjects. - Response Model (
PeerStats):[ { "id": 1, "user-id": "user123", "key": "PUBLIC_KEY_STRING_1", "name": "laptop-john", "endpoint": "192.168.1.100:12345", "last-handshake": 1672531200, "rx": 102400, "tx": 51200, "user": { "id": "user123", "nick": "John Doe", "name": "john.doe", "email": "john.doe@example.com", "enabled": true, "active": true, "created-ts": "2025-01-01T12:00:00Z", "updated-ts": "2025-01-01T12:00:00Z", "last-sign-in-ts": "2025-01-01T12:00:00Z", "max-devices": 5, "groups": ["vpn-users"] } } ] - CURL Example:
curl -k -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/peers/status
POST /peers/- Description: Create a new WireGuard peer. This endpoint only ever
creates an unmanaged peer –
nameis the only field it binds; there is nouser_id(or any other) parameter to associate it with a user, and one in the request body is silently ignored rather than rejected. Peers get a user association only through that user’s own OIDC self-service login flow, never through this endpoint. Names aren’t unique either – there’s no duplicate check, since a peer’s name is just a human-friendly label, not an identifier (idandpublic_keyare what actually identify it). All of this is intentional, not an oversight. - Request Body Example:
{ "name": "my-new-peer" } - Response:
200 OKwith a JSON object containing the generated WireGuard configuration. - Response Model:
{ "config": "[Interface]\nPrivateKey = 6M+ThPORyqqP+MRlibyoQg7LSsD+Qqdeb12umntp0E4=\nAddress = fd41:34e9:dead:beef::d\nDNS = 1.1.1.1,8.8.8.8, localdomain\nMTU = 1280\n\n[Peer]\nPublicKey = PCh7zzur2voTBLamwwUghcQcZ8tjLH27ZOjwVQeC0g8=\nPresharedKey = 02Ajv7tNsM6huTbp4XydQZC7P63hWpPYMWnS5ZTN8oc=\nAllowedIPs = 192.168.1.0/24\nEndpoint = 192.168.0.1:51820\nPersistentKeepalive = 25\n" } - Example WireGuard Configuration Output (Plain Text):
[Interface] PrivateKey = 6M+ThPORyqqP+MRlibyoQg7LSsD+Qqdeb12umntp0E4= Address = fd41:34e9:dead:beef::d DNS = 1.1.1.1,8.8.8.8, localdomain MTU = 1280 [Peer] PublicKey = PCh7zzur2voTBLamwwUghcQcZ8tjLH27ZOjwVQeC0g8= PresharedKey = 02Ajv7tNsM6huTbp4XydQZC7P63hWpPYMWnS5ZTN8oc= AllowedIPs = 192.168.1.0/24 Endpoint = 192.168.0.1:51820 PersistentKeepalive = 25 - CURL Example:
curl -k -X POST \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"name": "my-new-peer"}' \ https://127.0.0.1:8095/wiretastix/api/v1/peers/
- Description: Create a new WireGuard peer. This endpoint only ever
creates an unmanaged peer –
DELETE /peers/:peer-id- Description: Delete a WireGuard peer. The
:peer-idis theidproperty obtained when listing peers. - Parameters:
:peer-id(path): The ID of the peer to delete.
- Response:
200 OKwith a success message. - Response Model (
ApiMessage):{ "detail": "", "message": "Peer 11 deleted", "status": 200 } - CURL Example:
curl -k -X DELETE \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/peers/11
- Description: Delete a WireGuard peer. The
Users
Manage users.
GET /users/- Description: Retrieve a list of all users.
- Response:
200 OKwith a list ofUserobjects. - Response Model (
User):[ { "id": "user123", "nick": "John Doe", "name": "john.doe", "email": "john.doe@example.com", "enabled": true, "active": true, "created-ts": "2025-01-01T12:00:00Z", "updated-ts": "2025-01-01T12:00:00Z", "last-sign-in-ts": "2025-01-01T12:00:00Z", "max-devices": 5, "jwt-token-type": "Bearer", "jwt-token": "JWT_TOKEN_STRING", "jwt-refresh": "JWT_REFRESH_TOKEN_STRING", "jwt-expire-ts": "2025-01-01T13:00:00Z", "last-refreshed-at": "2025-01-01T12:30:00Z", "groups": ["vpn-users", "developers"] } ] - CURL Example:
curl -k -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/users/
GET /users/:user- Description: Retrieve details of a specific user.
- Parameters:
:user(path): The ID or name of the user.
- Response:
200 OKwith a singleUserobject. - Response Model (
User):{ "id": "user123", "nick": "John Doe", "name": "john.doe", "email": "john.doe@example.com", "enabled": true, "active": true, "created-ts": "2025-01-01T12:00:00Z", "updated-ts": "2025-01-01T12:00:00Z", "last-sign-in-ts": "2025-01-01T12:00:00Z", "max-devices": 5, "jwt-token-type": "Bearer", "jwt-token": "JWT_TOKEN_STRING", "jwt-refresh": "JWT_REFRESH_TOKEN_STRING", "jwt-expire-ts": "2025-01-01T13:00:00Z", "last-refreshed-at": "2025-01-01T12:30:00Z", "groups": ["vpn-users", "developers"] } - CURL Example:
curl -k -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/users/user123
PUT /users/:user- Description: Update a user. The user ID is provided in the path.
Only two properties are actually settable:
enabledandmax-devices. Everything else on theUserobject –nick,name,email,groups,active, and all session/token internals – is silently ignored if included in the request body, not rejected. This is deliberate:nick/name/email/groupsare owned by the OIDC provider’s claims and get overwritten on the user’s next login/refresh regardless (see OIDC Integration), andactive/session state are internal bookkeeping an admin-facing endpoint must never accept from a caller – an earlier version of this endpoint bound the request directly onto the fullUserstruct and let a caller forge a stored session token this way; it’s now a small allowlisted DTO instead. Both fields are optional and nullable, so a request touching only one of them leaves the other untouched (a genuine partial update, not a full replace). A negativemax-devicesis rejected. - Parameters:
:user(path): The ID of the user to update.
- Request Body Example:
{ "enabled": false, "max-devices": 5 } - Response:
200 OKwith the updatedUserobject. - Response Model (
User):{ "id": "user123", "nick": "Johnny D.", "name": "john.doe", "email": "john.doe@example.com", "enabled": false, "active": true, "created-ts": "2025-01-01T12:00:00Z", "updated-ts": "2025-01-03T11:00:00Z", "last-sign-in-ts": "2025-01-01T12:00:00Z", "max-devices": 5, "groups": ["vpn-users"] } - CURL Example:
curl -k -X PUT \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"enabled": false, "max-devices": 5}' \ https://127.0.0.1:8095/wiretastix/api/v1/users/user123
- Description: Update a user. The user ID is provided in the path.
Only two properties are actually settable:
DELETE /users/:user- Description: Delete a user and all their associated peers.
- Parameters:
:user(path): The ID or name of the user to delete.
- Response:
204 No Contenton success. - CURL Example:
curl -k -X DELETE \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/users/user123
Groups
Manage groups.
GET /groups/- Description: Retrieve a list of all groups.
- Response:
200 OKwith a list ofGroupobjects. - Response Model (
Group):[ { "oidc": "my-oidc-provider", "name": "developers", "priority": 100, "policy": "accept", "enabled": true, "allowed-ips": "10.0.1.0/24", "default-dns": "8.8.8.8", "default-search": "dev.local", "max-devices": 5 } ] - CURL Example:
curl -k -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/groups/
GET /groups/:group- Description: Retrieve details of a specific group.
- Parameters:
:group(path): The ID or name of the group.
- Response:
200 OKwith a singleGroupobject. - Response Model (
Group):{ "oidc": "my-oidc-provider", "name": "developers", "priority": 100, "policy": "accept", "enabled": true, "allowed-ips": "10.0.1.0/24", "default-dns": "8.8.8.8", "default-search": "dev.local", "max-devices": 5 } - CURL Example:
curl -k -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/groups/developers
PUT /groups/- Description: Create a new group.
oidcandpolicyare both required – an empty or missingpolicyis rejected (must beaccept,drop, ornone).policyis enforced as the group’s catch-all for anything its own rules don’t match, including when the group has no rules at all yet – see NFTables Integration. When a peer belongs to more than one group,priority(lower first) decides which group’spolicywins – see Multiple Group Membership and Priority Order. - Request Body: JSON object with
Groupdetails. - Request Body Example:
{ "oidc": "my-oidc-provider", "name": "marketing", "priority": 200, "policy": "drop", "enabled": true, "allowed-ips": "10.0.2.0/24", "default-dns": "1.1.1.1", "max-devices": 2 } - Response:
200 OKwith the details of the newGroupobject. - Response Model (
Group):{ "oidc": "my-oidc-provider", "name": "marketing", "priority": 200, "policy": "drop", "enabled": true, "allowed-ips": "10.0.2.0/24", "default-dns": "1.1.1.1", "max-devices": 2 } - CURL Example:
curl -k -X PUT \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "oidc": "my-oidc-provider", "name": "marketing", "priority": 200, "policy": "drop", ""enabled": true, "allowed-ips": "10.0.2.0/24", "default-dns": "1.1.1.1", "max-devices": 2 }' \ https://127.0.0.1:8095/wiretastix/api/v1/groups/
- Description: Create a new group.
POST /groups/:group- Description: Update an existing group. The group ID is provided in the path. The
oidcproperty cannot be changed; if provided in the request body, its value must be identical to the:groupparameter in the URL. - Parameters:
:group(path): The ID or name of the group to update.
- Request Body: JSON object with updated
Groupdetails. - Request Body Example:
{ "oidc": "my-oidc-provider", "policy": "accept", "default-dns": "9.9.9.9" } - Response:
200 OKwith the updatedGroupobject. - Response Model (
Group):{ "oidc": "my-oidc-provider", "name": "developers", "priority": 100, "policy": "accept", "enabled": true, "allowed-ips": "10.0.1.0/24", "default-dns": "9.9.9.9", "default-search": "dev.local", "max-devices": 5 } - CURL Example:
curl -k -X POST \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"oidc": "my-oidc-provider", "policy": "accept", "default-dns": "9.9.9.9"}' \ https://127.0.0.1:8095/wiretastix/api/v1/groups/developers
- Description: Update an existing group. The group ID is provided in the path. The
DELETE /groups/:group- Description: Delete a group.
- Parameters:
:group(path): The ID or name of the group to delete.
- Response:
204 No Contenton success. - CURL Example:
curl -k -X DELETE \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/groups/marketing
Rules
Manage network rules.
GET /rules/- Description: Retrieve a list of all network rules.
- Response:
200 OKwith a list ofRuleobjects. - Response Model (
Rule):[ { "rule-id": 1, "group-id": "developers", "nf-proto": 4, "l4-proto": "tcp", "src": "10.0.1.0/24", "srcport": null, "dst": "0.0.0.0/0", "dst-port": 80, "action": "accept" } ] - CURL Example:
curl -k -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/rules/
PUT /rules/- Description: Create a new network rule.
group-idandaction(accept,drop, ornone) are required;nf-protomust be4or6;l4-protomust betcp,udp,icmp, or empty;srcport/dst-portrequirel4-prototo betcporudp;src/dstmust be valid CIDR notation (not a bare IP – include the mask, e.g.10.0.1.0/24) whose address family matchesnf-proto. All of this is validated at creation time – a malformed rule that previously only failed silently when rules were next applied is now rejected immediately with an error. - Request Body: JSON object with
Ruledetails. - Request Body Example:
{ "group-id": "developers", "nf-proto": 4, "l4-proto": "tcp", "dst-port": 22, "action": "drop" } - Response:
200 OKwith the details of the newRuleobject. - Response Model (
Rule):{ "rule-id": 2, "group-id": "developers", "nf-proto": 4, "l4-proto": "tcp", "src": null, "srcport": null, "dst": null, "dst-port": 22, "action": "drop" } - CURL Example:
curl -k -X PUT \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "group-id": "developers", "nf-proto": 4, "l4-proto": "tcp", "dst-port": 22, "action": "drop" }' \ https://127.0.0.1:8095/wiretastix/api/v1/rules/
- Description: Create a new network rule.
POST /rules/apply- Description: Apply all configured network rules to the
nftablesfirewall. This method atomically recreates the entirenftablesruleset based on the current configuration in Wiretastix, ensuring consistency after rules are added or deleted. - Response:
200 OKon success. - CURL Example:
curl -k -X POST \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/rules/apply
- Description: Apply all configured network rules to the
DELETE /rules/:rule- Description: Delete a network rule.
- Parameters:
:rule(path): The ID of the rule to delete.
- Response:
200 OKon success,404 Not Foundif no rule with that ID exists. - CURL Example:
curl -k -X DELETE \ -H "Authorization: Bearer ${WIRETASTIX_TOKEN}" \ https://127.0.0.1:8095/wiretastix/api/v1/rules/1