68 KiB
P2NS Admin Backend API
The P2NS (Peer-to-Peer Name System) admin backend API, hosted at https://p2ns.admin, provides endpoints for managing the decentralized DNS system programmatically. These endpoints, implemented in admin.js, allow interaction with domains, Holesail servers and clients, local DNS records, certificates, virtual interfaces, logs, settings, and system status. All endpoints are accessible via HTTP/HTTPS and do not require authentication (since the domain is local). Responses are typically JSON or plain text, with errors returned as plain text messages. Real-time updates are broadcast via WebSocket at wss://p2ns.admin/ws.
Base URL
https://p2ns.admin
WebSocket Endpoint
-
URL:
wss://p2ns.admin/ws -
Description: Establishes a WebSocket connection for real-time updates from the server.
-
Client → server messages:
subscribe-stats/unsubscribe-stats/request-stats-snapshot— Stats tab live data.subscribe-log—{ "type": "subscribe-log", "channel": "core", "lines": 1000 }(channels:core,proxy,httpProxy,dns,plugins,holesail).unsubscribe-log— Stop log tail.request-domains— Refresh domains list (server replies withdomains-list).
-
Server → client messages:
stats-snapshot— Full stats page payload (stats,historical,health,status,minutes). Includesstats.core(invite RPC diagnostics) andstats.pluginRpc/stats.peerChannels(plugin RPC metrics).update-stats— Notifies stats subscribers to apply their latest snapshot (does not embed metrics itself).update-health— Health payload for Diagnostics tab subscribers.file-log—{ "type": "file-log", "channel": "dns", "level": "info", "message": "<line>" }(live log tail).log-snapshot— Initial tail aftersubscribe-log:{ "type": "log-snapshot", "channel": "core", "lines": ["..."] }.log— Legacy; may still map to core. Preferfile-log+subscribe-log.holesail-log— Holesail child process logs (id,level,message).plugin-log— Per-plugin logs (domain,level,component,message).domains-list— Resolved domains array.update-database,update-peers,update-certs,update-interfaces,update-local-dns,update-holesail,update-holesail-clients,update-settings,update-plugins,update-plugin-settings— Tab refresh hints.system-reset— Client should reload.
-
Example (
file-log):{ "type": "file-log", "channel": "core", "level": "info", "message": "2026-05-28T12:00:00.000Z [INFO] [Main] Starting..." }
Endpoints
1. GET /
- Description: Serves the admin panel HTML (
includes/admin/admin-frontend/index.html). - Response: HTML content.
- Status Codes:
200: Success.500: Failed to load admin panel.
- Example:
curl -X GET \ https://p2ns.admin/
2. GET /styles.css
- Description: Serves the admin panel stylesheet (
includes/admin/admin-frontend/styles.css). - Response: CSS content.
- Status Codes:
200: Success.500: Failed to load styles.
- Example:
curl -X GET \ https://p2ns.admin/styles.css
3. GET /admin.js
- Description: Serves the admin panel JavaScript (
includes/admin/admin-frontend/admin.js). - Response: JavaScript content.
- Status Codes:
200: Success.500: Failed to load script.
- Example:
curl -X GET \ https://p2ns.admin/admin.js
4. GET /api/resolved-domains
- Description: Retrieves a list of resolved domains with their hashes, local status, ownership, consensus information, and available services.
- Response: JSON array of objects with:
domain(string): Domain namehash(string): Holesail hash or"internal"for internal domainsisLocal(boolean): Whether the local writer has a claim for this domainisOwner(boolean): Whether the local writer is the resolved claimant (owner) of this domainconsensusState(object): Detailed consensus information including status, vote counts, quorum status, etc.consensusStatus(string): Simplified status that may include"conflict"for domains where local peer has a claim but another claimant wonservices(array): Array of service objects withserviceName,key,port, andprotocolfields
- Status Codes:
200: Success.500: Failed to fetch domains.
- Example:
curl -X GET \ https://p2ns.admin/api/resolved-domains[ { "domain": "example.tld", "hash": "hs://s00084bf...", "isLocal": true, "isOwner": true, "consensusState": { "status": "resolved", "hash": "hs://s00084bf...", "resolvedClaimant": "a6a6d7ebcc1df8f33410067bf96ad2cc30d5276516f758bb0f34195e914c451f", "voteCounts": { "a6a6d7ebcc1df8f33410067bf96ad2cc30d5276516f758bb0f34195e914c451f": 8 }, "activePeers": 5, "quorumMet": true, "minVotes": 2, "totalVotes": 8, "lastResolution": 1766780982538 }, "consensusStatus": "resolved", "services": [ { "serviceName": "web", "key": "hs://s00084bf...", "port": 8080, "protocol": "tcp" } ] }, { "domain": "bm.git", "hash": "hs://s000f44fb5cfe3fa7f37e9070ea14975a8dbf1e2156689638bc92458118df7a4987b", "isLocal": true, "isOwner": false, "consensusState": { "status": "resolved", "hash": "hs://s000f44fb5cfe3fa7f37e9070ea14975a8dbf1e2156689638bc92458118df7a4987b", "resolvedClaimant": "acbb3b69ee810f4fbe54927a5742530e4cf76b7b462a4c37ddfe27ba5c3060b6", "voteCounts": { "a6a6d7ebcc1df8f33410067bf96ad2cc30d5276516f758bb0f34195e914c451f": 1, "acbb3b69ee810f4fbe54927a5742530e4cf76b7b462a4c37ddfe27ba5c3060b6": 7 }, "activePeers": 5, "quorumMet": true, "minVotes": 2, "totalVotes": 8, "lastResolution": 1766780982538 }, "consensusStatus": "conflict", "services": [] }, { "domain": "peer.directory", "hash": "internal", "isLocal": true, "isOwner": true, "consensusStatus": "internal", "services": [] } ]
5. GET /api/entries
- Description: Retrieves all Autopass ledger entries (claims and votes).
- Response: JSON array of objects with
key(string) andvalue(string). - Status Codes:
200: Success.500: Failed to fetch entries.
- Example:
curl -X GET \ https://p2ns.admin/api/entries[ { "key": "claim:example.tld:abc123", "value": "hs://s00084bf..." }, { "key": "vote:example.tld:abc123:def456", "value": "1" } ]
6. GET /api/peers
- Description: Lists connected peers (public keys).
- Response: JSON array of peer public keys (strings).
- Status Codes:
200: Success.500: Failed to fetch peers.
- Example:
curl -X GET \ https://p2ns.admin/api/peers["def456", "ghi789"]
7. GET /api/certs
- Description: Lists domains with generated certificates.
- Response: JSON array of domain names (strings).
- Status Codes:
200: Success.500: Failed to fetch certs.
- Example:
curl -X GET \ https://p2ns.admin/api/certs["example.tld", "peer.directory"]
8. GET /api/cert-details?domain=
- Description: Retrieves the certificate content for a specified domain.
- Query Parameters:
domain: The domain name (e.g.,example.tld).
- Response: Plain text certificate content (PEM format).
- Status Codes:
200: Success.500: Failed to fetch cert details.
- Example:
curl -X GET \ https://p2ns.admin/api/cert-details?domain=example.tld-----BEGIN CERTIFICATE----- MIID... -----END CERTIFICATE-----
9. GET /api/interfaces
- Description: Lists virtual interfaces with domain-to-IP mappings.
- Response: JSON array of objects with
domain(string) andip(string). - Status Codes:
200: Success.500: Failed to fetch interfaces.
- Example:
curl -X GET \ https://p2ns.admin/api/interfaces[ { "domain": "example.tld", "ip": "192.168.3.2" }, { "domain": "peer.directory", "ip": "192.168.3.3" } ]
10. GET /api/local-dns
- Description: Retrieves custom local DNS records and conflicting domains (domains with both P2P and public records).
- Response: JSON object with:
records: Array of DNS records withindex(number),name(string),type(string),ttl(number),class(string, usually "IN"), and type-specific fields (e.g.,datafor A,preferenceandexchangefor MX).conflicts: Array of objects withdomain(string),version(p2p/public), andpublicIP(string).
- Status Codes:
200: Success.500: Failed to fetch local DNS and conflicts.
- Example:
curl -X GET \ https://p2ns.admin/api/local-dns{ "records": [ { "index": 0, "name": "local.example", "type": "A", "class": "IN", "ttl": 3600, "data": "192.168.1.100" }, { "index": 1, "name": "mail.example", "type": "MX", "class": "IN", "ttl": 3600, "preference": 10, "exchange": "mx.example.com" }, { "index": 2, "name": "_service._tcp.example", "type": "SRV", "class": "IN", "ttl": 3600, "priority": 0, "weight": 5, "port": 8080, "target": "server.example.com" } ], "conflicts": [ { "domain": "myspace.com", "version": "public", "publicIP": "151.101.1.195" }, { "domain": "example.com", "version": "p2p", "publicIP": "93.184.216.34" } ] }
11. GET /api/selector-cache
- Description: Retrieves DNS version preferences for domains with both P2P and public records.
- Response: JSON object mapping domains to
p2porpublic. - Status Codes:
200: Success.500: Failed to fetch selector cache.
- Example:
curl -X GET \ https://p2ns.admin/api/selector-cache{ "myspace.com": "public", "example.com": "p2p" }
12. GET /api/status
- Description: Retrieves system status, including master/joiner mode and peer count.
- Response: JSON object with
isMaster(boolean),isConnected(boolean), andpeersCount(number). - Status Codes:
200: Success.500: Failed to fetch status.
- Example:
curl -X GET \ https://p2ns.admin/api/status{ "isMaster": true, "isConnected": true, "peersCount": 5 }
13. GET /api/holesail-servers
- Description: Lists all Holesail servers with their configurations and status.
- Response: JSON array of objects with
id(string),opts(configuration object), andinfo(object includingstate: running/stopped). - Status Codes:
200: Success.500: Failed to fetch Holesail servers.
- Example:
curl -X GET \ https://p2ns.admin/api/holesail-servers[ { "id": "abc123", "opts": { "name": "server1", "port": 8080, "host": "0.0.0.0", "secure": true, "log": 1 }, "info": { "state": "running", "url": "hs://s00084bf..." } } ]
14. GET /api/holesail-clients
- Description: Lists all Holesail clients with their configurations and status.
- Response: JSON array of objects with
id(string),opts(configuration object), andinfo(object includingstate: running/starting/stopped/error). - Status Codes:
200: Success.500: Failed to fetch Holesail clients.
- Example:
curl -X GET \ https://p2ns.admin/api/holesail-clients[ { "id": "def456", "opts": { "domain": "example.tld", "key": "hs://s00084bf...", "port": 8080, "protocol": "tcp" }, "info": { "state": "running" } } ]
15. GET /api/settings
- Description: Retrieves environment settings (whitelisted variables). Note:
SUBNETS,SUBNET_BASE, andINITIAL_IP_INDEXare managed separately via the subnet configurator (see/api/subnets). - Response: JSON object with
settings(object mapping whitelisted keys to values) andmetadata(object with setting metadata including types, descriptions, and categories). - Status Codes:
200: Success.500: Failed to fetch settings.
- Example:
curl -X GET \ https://p2ns.admin/api/settings{ "settings": { "LOG_LEVEL": "1", "INTERNAL_DOMAINS": "Note: Internal domains are now automatically discovered from plugin-sites/{domain}/config.json files" }, "metadata": { "LOG_LEVEL": { "type": "number", "category": "Logging & Debugging", "label": "Log Level", "description": "...", "default": "0" } } }
16. POST /api/add-domain
- Description: Adds a domain with its Holesail hash to the P2P network and
domains.json. Assigns an IP if needed and triggers auto-voting. Note: Internal domains (automatically discovered fromplugin-sites/{domain}/config.jsonfiles, includingp2ns.admin) cannot be claimed and will return an error. - Request Body: JSON with
domain(string),hash(string, e.g.,hs://<hash>), and optionallyssl(boolean). Thesslfield indicates if the Holesail connection uses SSL/TLS. Whentrue, proxy connections will use HTTPS/WSS instead of HTTP/WS. Defaults tofalseif not provided. - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to add domain.
- WebSocket Broadcast:
update-database. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.tld","hash":"hs://s00084bf...","ssl":true}' \ https://p2ns.admin/api/add-domainOK
17. POST /api/remove-domain
- Description: Removes a domain. Behavior depends on consensus status:
- Resolved Claimant: Performs full cleanup removing all claims and votes for the domain, broadcasts
consensus.removeDomainRPC to trigger other peers to clean up - Conflict Claim: Removes only your own claim and votes, broadcasts
removeConflictDomainClaim:notification (other peers preserve their claims)
- Resolved Claimant: Performs full cleanup removing all claims and votes for the domain, broadcasts
- Request Body: JSON with
domain(string). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.403: No claim found for domain or peer not initialized.500: Failed to remove domain.
- WebSocket Broadcast:
update-database,update-holesail-clients,update-local-dns. - Note: Only the peer that created a claim can remove it. Ownership is strictly validated before removal.
- Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.tld"}' \ https://p2ns.admin/api/remove-domainOK
18. POST /api/regenerate-ca
- Description: Regenerates the root CA certificate.
- Request Body: None.
- Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to regenerate CA.
- WebSocket Broadcast:
update-certs. - Example:
curl -X POST \ https://p2ns.admin/api/regenerate-caOK
19. POST /api/install-ca
- Description: Installs the root CA to the system trust store.
- Request Body: None.
- Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to install CA.
- Example:
curl -X POST \ https://p2ns.admin/api/install-caOK
20. POST /api/generate-cert
- Description: Generates a certificate for a specified domain, assigning an IP if needed.
- Request Body: JSON with
domain(string). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to generate cert.
- WebSocket Broadcast:
update-certs. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.tld"}' \ https://p2ns.admin/api/generate-certOK
21. POST /api/delete-cert
- Description: Deletes the certificate for a specified domain.
- Request Body: JSON with
domain(string). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to delete cert.
- WebSocket Broadcast:
update-certs. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.tld"}' \ https://p2ns.admin/api/delete-certOK
22. POST /api/regenerate-cert
- Description: Regenerates the certificate for a specified domain, assigning an IP if needed.
- Request Body: JSON with
domain(string). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to regenerate cert.
- WebSocket Broadcast:
update-certs. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.tld"}' \ https://p2ns.admin/api/regenerate-certOK
23. POST /api/cleanup-interfaces
- Description: Cleans up unused virtual interfaces.
- Note: This endpoint is available via the API but is not exposed in the admin UI interface.
- Request Body: None.
- Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to cleanup interfaces.
- WebSocket Broadcast:
update-interfaces. - Example:
curl -X POST \ https://p2ns.admin/api/cleanup-interfacesOK
24. POST /api/add-local-dns
- Description: Adds a custom DNS record to
local_dns.json. Supports all DNS record types (e.g., A, AAAA, CNAME, MX, TXT, SRV, SOA, CAA, NS, PTR, OTHER) with flexible fields. - Request Body: JSON object with
name(string),type(string),ttl(number),class(string, optional, defaults to "IN"), and type-specific fields (e.g.,datafor A,preferenceandexchangefor MX). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to add local DNS record.
- WebSocket Broadcast:
update-local-dns. - Example (A record):
curl -X POST \ -H "Content-Type: application/json" \ -d '{"name":"local.example","type":"A","ttl":3600,"data":"192.168.1.100"}' \ https://p2ns.admin/api/add-local-dnsOK - Example (SRV record):
curl -X POST \ -H "Content-Type: application/json" \ -d '{"name":"_service._tcp.example","type":"SRV","ttl":3600,"priority":0,"weight":5,"port":8080,"target":"server.example.com"}' \ https://p2ns.admin/api/add-local-dnsOK
25. POST /api/update-local-dns
- Description: Updates an existing custom DNS record in
local_dns.jsonby index. Supports all DNS record types. - Request Body: JSON object with
index(number) andrecord(object withname,type,ttl,class(optional), and type-specific fields). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.400: Invalid index.500: Failed to update local DNS record.
- WebSocket Broadcast:
update-local-dns. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"index":0,"record":{"name":"local.example","type":"A","ttl":7200,"data":"192.168.1.101"}}' \ https://p2ns.admin/api/update-local-dnsOK
26. POST /api/delete-local-dns
- Description: Deletes a custom DNS record from
local_dns.jsonby index. - Request Body: JSON with
index(number). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.400: Invalid index.500: Failed to delete local DNS record.
- WebSocket Broadcast:
update-local-dns. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"index":0}' \ https://p2ns.admin/api/delete-local-dnsOK
27. POST /api/update-version-preference
- Description: Updates the DNS version preference (p2p or public) for a domain with both P2P and public records, stored in
selector_cache.json. - Request Body: JSON with
domain(string) andversion(string:p2porpublic). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.400: Invalid version.500: Failed to update version preference.
- WebSocket Broadcast:
update-local-dns. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"myspace.com","version":"public"}' \ https://p2ns.admin/api/update-version-preferenceOK
28. GET /api/p2p-domain-conflicts
- Description: Retrieves domains with P2P consensus conflicts where the user has a local claim but another claimant won consensus. Used for the P2P Domain Conflicts management interface.
- Response: JSON object with
conflictsarray containing objects with:domain(string): Domain namelocalHash(string): User's local claim hashresolvedHash(string): Consensus-resolved hashresolvedClaimant(string): Public key of consensus winnerlocalClaimant(string): User's public keyconsensusStatus(string): Current consensus statushashPreference(string): User's hash preference ('local' or 'resolved')
- Status Codes:
200: Success.500: Failed to fetch P2P domain conflicts.
- WebSocket Broadcast: None.
- Example:
curl -X GET \ https://p2ns.admin/api/p2p-domain-conflicts{ "conflicts": [ { "domain": "example.com", "localHash": "hs://s0001abc...", "resolvedHash": "hs://s0001def...", "resolvedClaimant": "abc123...", "localClaimant": "def456...", "consensusStatus": "resolved", "hashPreference": "resolved" } ] }
29. POST /api/update-hash-preference
- Description: Updates the hash preference ('local' or 'resolved') for a domain with P2P consensus conflicts, stored in
selector_cache.json. When changed, automatically restarts any active Holesail clients for the domain to use the new hash. - Request Body: JSON with
domain(string) andpreference(string:localorresolved). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.400: Invalid preference.500: Failed to update hash preference.
- WebSocket Broadcast:
update-local-dns. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.com","preference":"local"}' \ https://p2ns.admin/api/update-hash-preferenceOK
30. POST /api/clear-dns-cache
- Description: Clears DNS resolution cache entries for a specific domain to force fresh hash resolution on next DNS query.
- Request Body: JSON with
domain(string). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to clear DNS cache.
- WebSocket Broadcast: None.
- Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.com"}' \ https://p2ns.admin/api/clear-dns-cacheOK
31. POST /api/restart-holesail-clients-for-domain
- Description: Restarts all Holesail clients (both admin-managed and DNS-triggered) for a specific domain to use updated hash preferences. Closes existing connections and creates new ones with correct hashes. Ensures IP assignment exists before creating clients.
- Request Body: JSON with
domain(string). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to restart clients or resolve hash.500: Failed to restart Holesail clients.
- WebSocket Broadcast:
update-holesail-clients. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.com"}' \ https://p2ns.admin/api/restart-holesail-clients-for-domainOK
32. POST /api/holesail-create
- Description: Creates a new Holesail server, optionally assigning it to a domain. Persists to
holesail_servers.json. - Request Body: JSON with
name(string, optional),port(number),host(string, optional),key(string, optional),domain(string, optional),secure(boolean),udp(boolean),log(number). - Response: JSON with
id(string) on success, error message on failure. - Status Codes:
200: Success.500: Failed to create Holesail server.
- WebSocket Broadcast:
update-holesail,update-database(if domain assigned). - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"name":"server1","port":8080,"host":"0.0.0.0","secure":true,"udp":false,"log":1,"domain":"example.tld"}' \ https://p2ns.admin/api/holesail-create{"id":"abc123"}
33. POST /api/holesail-delete
- Description: Deletes a Holesail server by ID and removes it from
holesail_servers.json. - Request Body: JSON with
id(string). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to delete Holesail server.
- WebSocket Broadcast:
update-holesail. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"id":"abc123"}' \ https://p2ns.admin/api/holesail-deleteOK
34. POST /api/holesail-restart
- Description: Restarts a Holesail server by ID, optionally reassigning its domain. Persists to
holesail_servers.json. - Request Body: JSON with
id(string). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to restart Holesail server.
- WebSocket Broadcast:
update-holesail,update-database(if domain assigned). - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"id":"abc123"}' \ https://p2ns.admin/api/holesail-restartOK
35. POST /api/holesail-client-create
- Description: Creates a new Holesail client for a domain and port. Persists to
holesail_clients.json. IfserviceNameis provided, the client ID will bedomain_servicename; otherwise, a generated ID is used. The client is also added to the domain's claim recordclientsarray. - Request Body: JSON with:
domain(string, required): Domain name (must be owned by local writer)key(string, required): Holesail connection hash (e.g.,hs://s00084bf...)port(number, required): Port numberserviceName(string, optional): Service name for naming the client (format:domain_servicename)protocol(string, optional): Protocol type (tcporudp, default:tcp)
- Response: JSON with
id(string) on success, error message on failure. - Status Codes:
200: Success.400: Invalid request (missing required fields or domain not owned).500: Failed to create Holesail client.
- WebSocket Broadcast:
update-holesail-clients. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.tld","key":"hs://s00084bf...","port":8080,"serviceName":"web","protocol":"tcp"}' \ https://p2ns.admin/api/holesail-client-create{"id":"example.tld_web"}
36. POST /api/holesail-client-delete
- Description: Deletes a Holesail client by ID, closing connections and removing it from
holesail_clients.json. - Request Body: JSON with
id(string). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to delete Holesail client.
- WebSocket Broadcast:
update-holesail-clients. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"id":"def456"}' \ https://p2ns.admin/api/holesail-client-deleteOK
37. POST /api/holesail-client-restart
- Description: Restarts a Holesail client by ID, ensuring the port is free and connections are closed.
- Request Body: JSON with
id(string). - Response: Plain text
OKon success, error message on failure. - Status Codes:
200: Success.500: Failed to restart Holesail client.
- WebSocket Broadcast:
update-holesail-clients. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"id":"def456"}' \ https://p2ns.admin/api/holesail-client-restartOK
38. POST /api/update-settings
- Description: Updates environment settings (whitelisted variables) and persists them to
.env. Note:SUBNETScan be updated here, but it's recommended to use/api/subnetsfor subnet management.SUBNET_BASEandINITIAL_IP_INDEXare deprecated in favor of the subnet configurator. - Request Body: JSON with
settings(object mapping whitelisted keys to values). ForSUBNETS, provide a JSON array string. - Response: JSON object with
message(string),restartRequired(boolean), and optionallyrestartRequiredSettings(array of strings). - Status Codes:
200: Success.400: Validation failed (includeserrorsarray).500: Failed to update settings.
- WebSocket Broadcast:
update-settings. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"settings":{"LOG_LEVEL":"1"}}' \ https://p2ns.admin/api/update-settings{ "message": "Settings saved and applied successfully.", "restartRequired": false }
39. GET /api/network-interfaces
- Description: Retrieves a list of available network interfaces on the system. Used by the admin interface to populate the Subnet Interface Name dropdown setting.
- Response: JSON object with
interfaces(array of interface objects). Each interface object contains:value(string): Interface name (e.g., "lo0", "lo", "eth0")label(string): Display label for the interface (may include "(default)" for OS default)
- Status Codes:
200: Success.500: Failed to fetch network interfaces.
- Example:
curl -X GET \ https://p2ns.admin/api/network-interfaces{ "interfaces": [ { "value": "lo0", "label": "lo0" }, { "value": "en0", "label": "en0" }, { "value": "eth0", "label": "eth0" } ] } - Note: Interfaces are sorted with loopback interfaces (lo, lo0) and OS-specific defaults (lo0 on macOS, lo on Linux, Loopback Pseudo-Interface 1 on Windows) prioritized first.
40. GET /api/subnets
- Description: Retrieves all configured subnets with capacity information. Returns default subnet from
SUBNET_BASEif no subnets are configured. - Response: JSON object with
subnets(array of subnet objects). Each subnet object contains:base(string): Network base IP address (e.g., "192.168.3.0")cidr(number): CIDR notation (1-32, e.g., 24)startIndex(number): First usable IP index (1-254)name(string): Subnet name/descriptionindex(number): Subnet index in arrayavailable(number): Total available IPs in subnetused(number): Currently used IPsremaining(number): Remaining available IPs
- Status Codes:
200: Success.500: Failed to fetch subnets.
- Example:
curl -X GET \ https://p2ns.admin/api/subnets{ "subnets": [ { "base": "192.168.3.0", "cidr": 24, "startIndex": 2, "name": "Primary Subnet", "index": 0, "available": 253, "used": 5, "remaining": 248 }, { "base": "10.0.0.0", "cidr": 24, "startIndex": 2, "name": "Secondary Subnet", "index": 1, "available": 253, "used": 0, "remaining": 253 } ] }
41. POST /api/subnets
- Description: Updates subnet configuration. Replaces all existing subnets with the provided array. Changes require a system restart to fully take effect.
- Request Body: JSON object with
subnets(array of subnet objects). Each subnet object must contain:base(string, required): Network base IP address (e.g., "192.168.3.0")cidr(number, required): CIDR notation (1-32, typically 24)startIndex(number, required): First usable IP index (1-254, typically 2)name(string, optional): Subnet name/description (defaults to "Subnet N" if not provided)
- Response: JSON object with
message(string) andrestartRequired(boolean, always true). - Status Codes:
200: Success.400: Validation failed (includeserrorstring anderrorsarray).500: Failed to update subnets.
- WebSocket Broadcast:
update-settings. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"subnets":[{"base":"192.168.3.0","cidr":24,"startIndex":2,"name":"Primary Subnet"},{"base":"10.0.0.0","cidr":24,"startIndex":2,"name":"Secondary Subnet"}]}' \ https://p2ns.admin/api/subnets{ "message": "Subnets updated. Restart required to fully apply changes.", "restartRequired": true } - Validation Rules:
basemust be a valid IPv4 address (e.g., "192.168.3.0")cidrmust be between 1 and 32startIndexmust be between 1 and 254 (or up to subnet size - 2)- Subnets must not overlap with each other
42. GET /api/health
- Description: Health check endpoint supporting liveness and readiness probes.
- Query Parameters:
probe: Type of health probe (livenessorreadiness, default:liveness).
- Response: JSON object with
status(healthy/degraded/not_ready),timestamp,uptime,probe,services(object with DNS, proxy, swarm status), anddependencies(object with corestore, hyperswarm status). - Status Codes:
200: System is healthy.503: System is degraded or not ready.
- Example:
curl -X GET \ https://p2ns.admin/api/health{ "status": "healthy", "timestamp": "2024-01-01T00:00:00.000Z", "uptime": 3600000, "probe": "liveness", "services": { "dns": { "enabled": true, "healthy": true, "initialized": true }, "proxy": { "enabled": true, "healthy": true }, "swarm": { "healthy": true } }, "dependencies": { "corestore": { "healthy": true }, "hyperswarm": { "healthy": true } } }
43. GET /api/stats
- Description: Retrieves a one-shot system metrics snapshot (same data shape as
stats-snapshotover WebSocket). The admin UI loads this once, then usessubscribe-statsfor live updates. - Response: JSON object including:
- Request statistics (total, success rate, average response time, failed requests)
- Holesail children (servers, clients, P2P domain connections) with status, PID, uptime, CPU/memory usage
core— Core control-plane / invite RPC diagnostics (diagnoseInviteIssues)pluginRpcandpeerChannels— Per-plugin protomux-rpc protocol stats (transport: 'rpc', methods,rpcOpencounts)- HyperDB / Hyperdrive sections when available
- Status Codes:
200: Success.500: Failed to fetch stats.
- Example:
curl -X GET \ https://p2ns.admin/api/stats{ "requests": { "total": 1000, "successful": 950, "failed": 50, "successRate": 0.95, "avgResponseTime": 45 }, "holesailChildren": [ { "id": "abc123", "type": "server", "status": "running", "pid": 12345, "uptime": 3600000, "cpuUsage": { "percentage": 2.5 }, "memoryUsage": { "rss": 52428800 } } ] }
44. GET /api/logs
- Description: Lists available split log channels written under
LOG_DIR(default./logs/). - Response:
{ "channels": [ { "id": "core", "label": "Core", "file": "core.log" }, ... ] } - Status Codes:
200,500 - Example:
curl -k https://p2ns.admin/api/logs
45. GET /api/logs/:channel
- Description: Returns the tail of a log file (in-memory buffer with file fallback).
- Path:
channel—core,proxy,httpProxy,dns,plugins, orholesail - Query:
lines— max lines (default500, max5000) - Response:
{ "channel": "dns", "lines": ["..."] } - Example:
curl -k "https://p2ns.admin/api/logs/dns?lines=200"
46. GET /api/stats/historical
- Description: Retrieves historical metrics data for a specified time range.
- Query Parameters:
minutes: Time range in minutes (1-1440, default: 60).
- Response: JSON object with historical metrics data including request trends, connection statistics, and system performance over time.
- Status Codes:
200: Success.500: Failed to fetch historical data.
- Example:
curl -X GET \ "https://p2ns.admin/api/stats/historical?minutes=1440"
47. GET /api/backups
- Description: Lists all available backups with metadata including name, timestamp, size, and file count.
- Response: JSON array of backup objects with
name,timestamp,size,sizeFormatted, andfileCount. - Status Codes:
200: Success.500: Failed to list backups.
- Example:
curl -X GET \ https://p2ns.admin/api/backups[ { "name": "backup-20240101-000000", "timestamp": "2024-01-01T00:00:00.000Z", "size": 1048576, "sizeFormatted": "1.00 MB", "fileCount": 15 } ]
48. POST /api/backups/create
- Description: Creates a manual backup of configuration files, certificates, and cache data. Automatic cleanup of old backups is performed before creation.
- Request Body: None.
- Response: JSON object with
success(boolean) andpath(string, backup file path). - Status Codes:
200: Success.500: Failed to create backup.
- Example:
curl -X POST \ https://p2ns.admin/api/backups/create{ "success": true, "path": "./backups/backup-20240101-000000.tar.gz" }
49. POST /api/backups/restore
- Description: Restores system configuration from a backup. Replaces current configuration files and certificates.
- Request Body: JSON with
backupName(string, backup name to restore). - Response: JSON object with
success(boolean) andmessage(string). - Status Codes:
200: Success.400: Invalid request (missing backupName).500: Failed to restore backup.
- Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"backupName":"backup-20240101-000000"}' \ https://p2ns.admin/api/backups/restore{ "success": true, "message": "Backup restored successfully" }
50. DELETE /api/backups/:id
- Description: Deletes a backup by name. Supports both directory and tar.gz formats.
- Path Parameters:
id: Backup name (e.g.,backup-20240101-000000orbackup-20240101-000000.tar.gz).
- Response: JSON object with
success(boolean) andmessage(string). - Status Codes:
200: Success.400: Invalid backup name.500: Failed to delete backup.
- Example:
curl -X DELETE \ https://p2ns.admin/api/backups/backup-20240101-000000
51. GET /api/backups/:id/metadata
- Description: Retrieves detailed metadata for a backup including file list, sizes, and timestamps.
- Path Parameters:
id: Backup name.
- Response: JSON object with backup metadata including
timestamp,files(array with name, size, sizeFormatted, modified), and other metadata. - Status Codes:
200: Success.404: Backup not found.500: Failed to get backup metadata.
- Example:
curl -X GET \ https://p2ns.admin/api/backups/backup-20240101-000000/metadata
52. POST /api/diagnostics/dns-lookup
- Description: Performs DNS lookup for a domain with specified record type.
- Request Body: JSON with
domain(string, required) andtype(string, optional, default:A). Supported types: A, AAAA, MX, TXT, NS, CNAME, SRV, PTR, SOA. - Response: JSON object with
success(boolean),domain,type,results(array), andresponseTime(number). - Status Codes:
200: Success (includes both successful and failed lookups).400: Invalid request (missing domain).500: Server error.
- Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.com","type":"A"}' \ https://p2ns.admin/api/diagnostics/dns-lookup{ "success": true, "domain": "example.com", "type": "A", "results": ["93.184.216.34"], "responseTime": 25 }
53. POST /api/diagnostics/ping
- Description: Tests network connectivity using ping. Supports both streaming and non-streaming modes.
- Request Body: JSON with
target(string, required),count(number, optional, default: 4), andstream(boolean, optional, default: false). - Response:
- Non-streaming: JSON object with
success,target,count,output,error, andresponseTime. - Streaming: NDJSON stream with
type(output/error/complete),data,timestamp, and completion status.
- Non-streaming: JSON object with
- Status Codes:
200: Success.400: Invalid request (missing target).500: Server error.
- Example (non-streaming):
curl -X POST \ -H "Content-Type: application/json" \ -d '{"target":"8.8.8.8","count":4}' \ https://p2ns.admin/api/diagnostics/ping - Example (streaming):
curl -X POST \ -H "Content-Type: application/json" \ -d '{"target":"8.8.8.8","count":4,"stream":true}' \ https://p2ns.admin/api/diagnostics/ping
54. POST /api/diagnostics/traceroute
- Description: Traces network path to a target. Supports both streaming and non-streaming modes.
- Request Body: JSON with
target(string, required) andstream(boolean, optional, default: false). - Response:
- Non-streaming: JSON object with
success,target,output,error, andresponseTime. - Streaming: NDJSON stream with
type(output/error/complete),data,timestamp, and completion status.
- Non-streaming: JSON object with
- Status Codes:
200: Success.400: Invalid request (missing target).500: Server error.
- Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"target":"8.8.8.8","stream":true}' \ https://p2ns.admin/api/diagnostics/traceroute
55. POST /api/diagnostics/connection-test
- Description: Tests TCP connectivity to a domain and port combination.
- Request Body: JSON with
domain(string, required) andport(number, required). - Response: JSON object with
success(boolean),domain,ip(resolved IP),port,latency(if successful),error(if failed), andresponseTime. - Status Codes:
200: Success (includes both successful and failed tests).400: Invalid request (missing domain or port).500: Server error.
- Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.com","port":443}' \ https://p2ns.admin/api/diagnostics/connection-test{ "success": true, "domain": "example.com", "ip": "93.184.216.34", "port": 443, "latency": 45, "responseTime": 50 }
56. GET /api/diagnostics/bandwidth
- Description: Network interface information and configuration. Real-time throughput stats are not available via Node.js; response is interface layout only.
- Response: JSON with
interfaces, optionalnote,responseTime. - Status Codes:
200,500 - Example:
curl -k https://p2ns.admin/api/diagnostics/bandwidth
57. GET /api/diagnostics/invites
- Description: Core invite / control-plane diagnostics over
p2ns.core-request-rpc(invite.request,invite.deliver,invite.ack,core.status). Used by the Stats Core section and Invite Diagnostics UI. - Response: JSON with
summary(dnsPass, rpcOpen, requestChannelOpen, failed peers, …),peers,recommendations,connectionIssues, etc. - Status Codes:
200,503(still initializing),500 - Example:
curl -k https://p2ns.admin/api/diagnostics/invites
58. GET /
- Description: Redirects to the admin panel with the specified tab (e.g.,
/domains,/host,/local-dns) open. - Path Parameters:
tab: One ofdomains,host,local-dns,entries,peers,certs,interfaces,logs,settings.
- Response: HTTP redirect to
/#<tab>. - Status Codes:
302: Redirect.
- Example:
curl -X GET \ -L \ https://p2ns.admin/domains
59. GET /favicon.ico
- Description: Returns a 404 response (favicon not implemented).
- Response: Plain text
Not Found. - Status Codes:
404: Not found.
- Example:
curl -X GET \ https://p2ns.admin/favicon.icoNot Found
Consensus Endpoints
60. GET /api/consensus/:domain
- Description: Retrieves the consensus state for a specific domain, including vote counts, quorum status, and resolution information.
- Path Parameters:
domain: The domain name (e.g.,example.tld).
- Response: JSON object with:
status(string): Consensus status (resolved,insufficient_quorum,tie,no_claims,error).hash(string|null): Resolved Holesail hash if status isresolved, otherwisenull.resolvedClaimant(string|null): Public key of the winning claimant if resolved, otherwisenull.voteCounts(object): Mapping of claimant public keys to their vote counts.activePeers(number): Number of active peers in the network (including local node).quorumMet(boolean): Whether the quorum threshold has been met.minVotes(number): Minimum votes required to meet quorum.totalVotes(number): Total number of votes cast for all claimants.lastResolution(number|null): Timestamp of last resolution, ornullif never resolved.
- Status Codes:
200: Success.500: Failed to get consensus state.
- Example:
curl -X GET \ https://p2ns.admin/api/consensus/example.tld{ "status": "resolved", "hash": "hs://s00084bf87dfa89a3048fb081c0e6207eb5a", "resolvedClaimant": "abc123def456...", "voteCounts": { "abc123def456...": 3, "ghi789jkl012...": 1 }, "activePeers": 5, "quorumMet": true, "minVotes": 3, "totalVotes": 4, "lastResolution": 1704067200000 }
GET /api/consensus/status
- Description: Returns health and progress of the consensus Autobase sidecar (the sole read path for
getConsensusState). - Response: JSON object with:
open(boolean): Whether the sidecar Autobase instance is open.ready(boolean): Whether the sidecar has completed opening.writable(boolean): Whether this node can append sidecar events.bootstrapComplete(boolean): Whether bootstrap or hydration from dnsPass has finished.eventCount(number): Total events applied to the in-memory view.domainCount(number): Domains present in the apply view.lastApplyAt(number|null): Timestamp of the last applied event.indexedLength(number): Autobase indexed length.length(number): Autobase length.key(string|null): Sidecar public key (hex).
- Status Codes:
200: Success.500: Failed to get consensus status.
- Example:
curl -X GET \ https://p2ns.admin/api/consensus/status{ "open": true, "ready": true, "writable": true, "bootstrapComplete": true, "eventCount": 142, "domainCount": 12, "lastApplyAt": 1704067200000, "indexedLength": 142, "length": 142, "key": "a1b2c3..." }
61. GET /api/consensus/metrics
- Description: Retrieves overall consensus metrics including resolution statistics, quorum failures, ties, validation failures, and sidecar health.
- Response: JSON object with:
resolutions(number): Total number of successful domain resolutions.quorumFailures(number): Number of times quorum was not met.ties(number): Number of ties that required tie-breaking.validationFailures(number): Number of invalid votes that were rejected.totalVotes(number): Total number of votes cast across all domains.avgVotesPerDomain(number): Average number of votes per domain.domainResolutions(array): Per-domain resolution statistics withdomain,resolvedcount, andfailedcount.sidecar(object): Same fields asGET /api/consensus/status.bootstrapComplete(boolean): Whether sidecar bootstrap/hydration is complete.
- Status Codes:
200: Success.500: Failed to get consensus metrics.
- Example:
curl -X GET \ https://p2ns.admin/api/consensus/metrics{ "resolutions": 42, "quorumFailures": 3, "ties": 2, "validationFailures": 1, "totalVotes": 156, "avgVotesPerDomain": 3.71, "domainResolutions": [ { "domain": "example.tld", "resolved": 5, "failed": 0 }, { "domain": "another.tld", "resolved": 3, "failed": 1 } ], "sidecar": { "open": true, "ready": true, "writable": true, "bootstrapComplete": true, "eventCount": 142, "domainCount": 12, "lastApplyAt": 1704067200000, "indexedLength": 142, "length": 142, "key": "a1b2c3..." }, "bootstrapComplete": true }
62. POST /api/consensus/recalculate
- Description: Forces a consensus recalculation for all domains. Invalidates the consensus cache and triggers auto-voting checks.
- Request Body: None.
- Response: JSON object with
success(boolean) andmessage(string). - Status Codes:
200: Success.500: Failed to recalculate consensus.
- WebSocket Broadcast:
update-database(triggers refresh of domains and entries). - Example:
curl -X POST \ https://p2ns.admin/api/consensus/recalculate{ "success": true, "message": "Consensus recalculation triggered" }
63. POST /api/consensus/recalculate/:domain
- Description: Forces a consensus recalculation for a specific domain. Invalidates the consensus cache for that domain and triggers auto-voting.
- Path Parameters:
domain: The domain name (e.g.,example.tld).
- Request Body: None.
- Response: JSON object with
success(boolean) andmessage(string). - Status Codes:
200: Success.500: Failed to recalculate consensus for domain.
- WebSocket Broadcast:
update-database(triggers refresh of domains and entries). - Example:
curl -X POST \ https://p2ns.admin/api/consensus/recalculate/example.tld{ "success": true, "message": "Consensus recalculation triggered for example.tld" }
Service Subscription Endpoints
64. GET /api/domain-services
- Description: Retrieves all services configured for a specific domain from its claim record.
- Query Parameters:
domain(string, required): The domain name to query services for.
- Response: JSON array of service objects, each containing:
serviceName(string): Service identifierkey(string): Holesail connection hashport(number): Port numberprotocol(string): Protocol type (tcporudp)
- Status Codes:
200: Success (returns empty array if domain has no services or is not resolved).400: Missing domain parameter.500: Failed to fetch domain services.
- Example:
curl -X GET \ "https://p2ns.admin/api/domain-services?domain=example.tld"[ { "serviceName": "web", "key": "hs://s00084bf87dfa89a3048fb081c0e6207eb5a", "port": 8080, "protocol": "tcp" }, { "serviceName": "api", "key": "hs://s000bcc379b38f6d3a5cb4cfde23fa52392d", "port": 9090, "protocol": "tcp" } ]
65. GET /api/service-subscriptions
- Description: Lists all service subscriptions configured on this node.
- Response: JSON array of subscription objects, each containing:
domain(string): Domain nameserviceName(string): Service identifierkey(string): Holesail connection hashport(number): Port numberprotocol(string): Protocol type (tcporudp)
- Status Codes:
200: Success.500: Failed to fetch subscriptions.
- Example:
curl -X GET \ https://p2ns.admin/api/service-subscriptions[ { "domain": "example.tld", "serviceName": "web", "key": "hs://s00084bf87dfa89a3048fb081c0e6207eb5a", "port": 8080, "protocol": "tcp" } ]
66. GET /api/subscribe-all-domains
- Description: Lists all domains for which "subscribe all" is enabled. When enabled, the system automatically subscribes to all services for that domain, including newly added services.
- Response: JSON array of domain names (strings).
- Status Codes:
200: Success.500: Failed to fetch subscribe-all domains.
- Example:
curl -X GET \ https://p2ns.admin/api/subscribe-all-domains["example.tld", "another.tld"]
67. POST /api/service-subscribe
- Description: Subscribes to a specific service from a domain. Creates a Holesail client automatically with ID
domain_servicenameand persists the subscription tosubscriptions.json. - Request Body: JSON with:
domain(string, required): Domain nameserviceName(string, required): Service identifierkey(string, required): Holesail connection hashport(number, required): Port numberprotocol(string, optional): Protocol type (tcporudp, default:tcp)
- Response: JSON with
success(boolean) on success, error message on failure. - Status Codes:
200: Success.400: Missing required fields.409: Already subscribed to this service.500: Failed to subscribe.
- WebSocket Broadcast:
update-holesail-clients. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.tld","serviceName":"web","key":"hs://s00084bf...","port":8080,"protocol":"tcp"}' \ https://p2ns.admin/api/service-subscribe{"success": true}
68. POST /api/service-unsubscribe
- Description: Unsubscribes from a specific service. Deletes the associated Holesail client and removes the subscription from
subscriptions.json. - Request Body: JSON with:
domain(string, required): Domain nameserviceName(string, required): Service identifier
- Response: JSON with
success(boolean) on success, error message on failure. - Status Codes:
200: Success.400: Missing required fields.404: Subscription not found.500: Failed to unsubscribe.
- WebSocket Broadcast:
update-holesail-clients. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.tld","serviceName":"web"}' \ https://p2ns.admin/api/service-unsubscribe{"success": true}
69. POST /api/subscribe-all
- Description: Enables "subscribe all" for a domain. This automatically subscribes to all current services for that domain and will automatically subscribe to any new services added in the future. Creates Holesail clients for all existing services.
- Request Body: JSON with:
domain(string, required): Domain name
- Response: JSON with
success(boolean) on success, error message on failure. - Status Codes:
200: Success.400: Missing domain field.500: Failed to set subscribe-all.
- WebSocket Broadcast:
update-holesail-clients. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.tld"}' \ https://p2ns.admin/api/subscribe-all{"success": true}
70. POST /api/unsubscribe-all
- Description: Disables "subscribe all" for a domain and unsubscribes from all services for that domain. Deletes all associated Holesail clients.
- Request Body: JSON with:
domain(string, required): Domain name
- Response: JSON with
success(boolean) on success, error message on failure. - Status Codes:
200: Success.400: Missing domain field.500: Failed to clear subscribe-all.
- WebSocket Broadcast:
update-holesail-clients. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"domain":"example.tld"}' \ https://p2ns.admin/api/unsubscribe-all{"success": true}
Plugin Management Endpoints
Note: For detailed information about the plugin system, see plugins/README.md and plugins/PLUGIN_SDK.md.
71. GET /api/plugins
- Description: Lists all plugins with their information, status, actions, and settings. Includes both loaded and stopped plugins.
- Response: JSON object with
plugins(array of plugin objects). Each plugin object contains:domain(string): Plugin domain namename(string): Plugin name from config.jsonversion(string): Plugin versiondescription(string): Plugin descriptionauthor(string): Plugin authorhomepage(string): Plugin homepage URLlicense(string): Plugin licensestatus(string): Plugin status (loaded,stopped, orstatic)hasHandler(boolean): Whether plugin has a handler functionhasWww(boolean): Whether plugin has a www directoryhasDatabase(boolean): Whether plugin has HyperDB configuredactions(array): Array of registered action objectssettings(object): Map of registered settings with their current values
- Status Codes:
200: Success.500: Failed to list plugins.
- Example:
curl -X GET \ https://p2ns.admin/api/plugins{ "plugins": [ { "domain": "example.plugin", "name": "Example Plugin", "version": "1.0.0", "description": "A template plugin", "author": "P2NS", "homepage": "https://example.com", "license": "MIT", "status": "loaded", "hasHandler": true, "hasWww": true, "hasDatabase": false, "actions": [ { "name": "testAction", "label": "Test Action", "description": "A test action", "icon": "🧪" } ], "settings": { "maxItems": { "type": "number", "label": "Maximum Items", "description": "Maximum number of items", "default": 100, "value": 100 } } } ] }
72. GET /api/plugins/:domain
- Description: Retrieves detailed information for a specific plugin.
- Path Parameters:
domain: The plugin domain name (e.g.,example.plugin).
- Response: JSON object with plugin information (same structure as plugin object in GET /api/plugins).
- Status Codes:
200: Success.404: Plugin not found.500: Failed to get plugin info.
- Example:
curl -X GET \ https://p2ns.admin/api/plugins/example.plugin
73. POST /api/plugins/:domain/start
- Description: Starts a stopped plugin. Loads the plugin handler and initializes resources.
- Path Parameters:
domain: The plugin domain name (e.g.,example.plugin).
- Request Body: None.
- Response: JSON object with
success(boolean),message(string), anddomain(string). - Status Codes:
200: Success.400: Invalid domain parameter.500: Failed to start plugin.
- WebSocket Broadcast:
update-plugins. - Example:
curl -X POST \ https://p2ns.admin/api/plugins/example.plugin/start{ "success": true, "message": "Plugin example.plugin started successfully", "domain": "example.plugin" }
74. POST /api/plugins/:domain/stop
- Description: Stops a running plugin. Unloads the plugin handler and cleans up resources.
- Path Parameters:
domain: The plugin domain name (e.g.,example.plugin).
- Request Body: None.
- Response: JSON object with
success(boolean),message(string), anddomain(string). - Status Codes:
200: Success.400: Invalid domain parameter.500: Failed to stop plugin.
- WebSocket Broadcast:
update-plugins. - Example:
curl -X POST \ https://p2ns.admin/api/plugins/example.plugin/stop{ "success": true, "message": "Plugin example.plugin stopped successfully", "domain": "example.plugin" }
75. POST /api/plugins/:domain/reload
- Description: Reloads a plugin. Stops the plugin, clears the module cache, and starts it again. Useful for applying code changes without restarting P2NS.
- Path Parameters:
domain: The plugin domain name (e.g.,example.plugin).
- Request Body: None.
- Response: JSON object with
success(boolean),message(string), anddomain(string). - Status Codes:
200: Success.400: Invalid domain parameter.500: Failed to reload plugin.
- WebSocket Broadcast:
update-plugins. - Example:
curl -X POST \ https://p2ns.admin/api/plugins/example.plugin/reload{ "success": true, "message": "Plugin example.plugin reloaded successfully", "domain": "example.plugin" }
76. POST /api/plugins/:domain/actions/:actionName
- Description: Executes a registered plugin action. The action handler is called with the provided parameters.
- Path Parameters:
domain: The plugin domain name (e.g.,example.plugin).actionName: The action name (e.g.,testAction).
- Request Body: JSON object with action parameters (optional).
- Response: JSON object with
success(boolean) andresult(any) containing the action handler's return value. - Status Codes:
200: Success.400: Invalid request path.404: Plugin or action not found.500: Action execution failed.
- Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"value": 10}' \ https://p2ns.admin/api/plugins/example.plugin/actions/testAction{ "success": true, "result": { "success": true, "message": "Test action executed successfully!", "timestamp": "2025-12-12T10:00:00.000Z" } }
77. POST /api/plugins/:domain/settings
- Description: Updates plugin settings. Saves settings to
cache/plugin-settings/{domain}.jsonand persists them across plugin restarts. - Path Parameters:
domain: The plugin domain name (e.g.,example.plugin).
- Request Body: JSON object mapping setting keys to values.
- Response: JSON object with
success(boolean) andmessage(string). - Status Codes:
200: Success.400: Invalid domain parameter.500: Failed to update settings.
- WebSocket Broadcast:
update-plugin-settings. - Example:
curl -X POST \ -H "Content-Type: application/json" \ -d '{"maxItems": 200, "enableFeature": true}' \ https://p2ns.admin/api/plugins/example.plugin/settings{ "success": true, "message": "Settings updated for plugin example.plugin" }
78. GET /api/token
- Description: Generates a signed Ed25519 authentication token for plugin authentication. Available to all plugins globally.
- Request Headers: None required.
- Response: JSON object with
token(string),expiresAt(number), andpeerId(string). - Status Codes:
200: Success.500: Failed to generate token.
- Example:
curl -X GET \ https://global.profile/api/token{ "token": "eyJwZWVySWQiOiIxMjM0NTY3ODkwYWJjZGVmZ2hpamsuLi4iLCJ0aW1lc3RhbXAiOjE2ODk...", "expiresAt": 1689123456789, "peerId": "1234567890abcdef..." } - Notes:
- Tokens expire after 1 hour (3600 seconds) by default.
- Tokens are signed with Ed25519 using the local peer's private key.
- Use the token in the
Authorization: Bearer <token>header for authenticated requests. - The
X-Auth-Tokenheader is also supported as an alternative.
Authentication
Plugin write operations (POST, PUT, DELETE, PATCH) require authentication using Ed25519-signed tokens.
Authentication Headers
Authorization Header (Preferred):
Authorization: Bearer <token>
Alternative Header:
X-Auth-Token: <token>
Error Responses
401 Unauthorized:
{
"error": "Authentication required",
"message": "Invalid or missing authentication token"
}
403 Forbidden:
{
"error": "Forbidden",
"message": "Only the local peer can perform this operation"
}
Token Format
Tokens are base64-encoded JSON objects containing:
peerId: The public key (hex string) of the authenticated peertimestamp: Token creation timestamp (milliseconds)expiresAt: Token expiration timestamp (milliseconds)signature: Ed25519 signature (hex string) of the token payload
Frontend Integration
Include the authentication utilities script:
<script src="/auth-utils.js"></script>
Use authenticatedFetch() for write operations:
const response = await authenticatedFetch('/api/data', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ data: 'value' })
});
See plugins/PLUGIN_SDK.md for complete authentication API documentation.
Security Notes
- Plugin Authentication: Write operations in plugins require Ed25519-signed tokens. See Authentication section above.
- No Authentication: Admin endpoints are unauthenticated, so restrict access to trusted networks or users in production.
- HTTPS: Use HTTPS to protect data in transit.
- Input Validation: Ensure inputs (e.g., domain names, DNS record fields) are sanitized to prevent injection attacks.
- Permissions:
selector_cache.json,domains.json,local_dns.json,holesail_servers.json,holesail_clients.json, andsubscriptions.jsonshould have restricted permissions to prevent unauthorized modifications.
Testing
- Use tools like
curlor Postman to test endpoints. - Verify WebSocket updates using a WebSocket client (e.g.,
wscat). - Test DNS record creation with various types (e.g., SRV, SOA) and check
local_dns.json. - Monitor logs in the admin Logs tab (
subscribe-logper channel) orGET /api/logs/:channel; plugin logs useplugin-logWebSocket messages.