Files
p2ns/docs/RESTAPI.md
T

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 with domains-list).
  • Server → client messages:

    • stats-snapshot — Full stats page payload (stats, historical, health, status, minutes). Includes stats.core (invite RPC diagnostics) and stats.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 after subscribe-log: { "type": "log-snapshot", "channel": "core", "lines": ["..."] }.
    • logLegacy; may still map to core. Prefer file-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 name
    • hash (string): Holesail hash or "internal" for internal domains
    • isLocal (boolean): Whether the local writer has a claim for this domain
    • isOwner (boolean): Whether the local writer is the resolved claimant (owner) of this domain
    • consensusState (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 won
    • services (array): Array of service objects with serviceName, key, port, and protocol fields
  • 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) and value (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) and ip (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 with index (number), name (string), type (string), ttl (number), class (string, usually "IN"), and type-specific fields (e.g., data for A, preference and exchange for MX).
    • conflicts: Array of objects with domain (string), version (p2p/public), and publicIP (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 p2p or public.
  • 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), and peersCount (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), and info (object including state: 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), and info (object including state: 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, and INITIAL_IP_INDEX are managed separately via the subnet configurator (see /api/subnets).
  • Response: JSON object with settings (object mapping whitelisted keys to values) and metadata (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 from plugin-sites/{domain}/config.json files, including p2ns.admin) cannot be claimed and will return an error.
  • Request Body: JSON with domain (string), hash (string, e.g., hs://<hash>), and optionally ssl (boolean). The ssl field indicates if the Holesail connection uses SSL/TLS. When true, proxy connections will use HTTPS/WSS instead of HTTP/WS. Defaults to false if not provided.
  • Response: Plain text OK on 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-domain
    
    OK
    

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.removeDomain RPC to trigger other peers to clean up
    • Conflict Claim: Removes only your own claim and votes, broadcasts removeConflictDomainClaim: notification (other peers preserve their claims)
  • Request Body: JSON with domain (string).
  • Response: Plain text OK on 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-domain
    
    OK
    

18. POST /api/regenerate-ca

  • Description: Regenerates the root CA certificate.
  • Request Body: None.
  • Response: Plain text OK on 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-ca
    
    OK
    

19. POST /api/install-ca

  • Description: Installs the root CA to the system trust store.
  • Request Body: None.
  • Response: Plain text OK on success, error message on failure.
  • Status Codes:
    • 200: Success.
    • 500: Failed to install CA.
  • Example:
    curl -X POST \
         https://p2ns.admin/api/install-ca
    
    OK
    

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 OK on 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-cert
    
    OK
    

21. POST /api/delete-cert

  • Description: Deletes the certificate for a specified domain.
  • Request Body: JSON with domain (string).
  • Response: Plain text OK on 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-cert
    
    OK
    

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 OK on 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-cert
    
    OK
    

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 OK on 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-interfaces
    
    OK
    

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., data for A, preference and exchange for MX).
  • Response: Plain text OK on 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-dns
    
    OK
    
  • 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-dns
    
    OK
    

25. POST /api/update-local-dns

  • Description: Updates an existing custom DNS record in local_dns.json by index. Supports all DNS record types.
  • Request Body: JSON object with index (number) and record (object with name, type, ttl, class (optional), and type-specific fields).
  • Response: Plain text OK on 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-dns
    
    OK
    

26. POST /api/delete-local-dns

  • Description: Deletes a custom DNS record from local_dns.json by index.
  • Request Body: JSON with index (number).
  • Response: Plain text OK on 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-dns
    
    OK
    

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) and version (string: p2p or public).
  • Response: Plain text OK on 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-preference
    
    OK
    

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 conflicts array containing objects with:
    • domain (string): Domain name
    • localHash (string): User's local claim hash
    • resolvedHash (string): Consensus-resolved hash
    • resolvedClaimant (string): Public key of consensus winner
    • localClaimant (string): User's public key
    • consensusStatus (string): Current consensus status
    • hashPreference (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) and preference (string: local or resolved).
  • Response: Plain text OK on 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-preference
    
    OK
    

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 OK on 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-cache
    
    OK
    

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 OK on 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-domain
    
    OK
    

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 OK on 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-delete
    
    OK
    

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 OK on 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-restart
    
    OK
    

35. POST /api/holesail-client-create

  • Description: Creates a new Holesail client for a domain and port. Persists to holesail_clients.json. If serviceName is provided, the client ID will be domain_servicename; otherwise, a generated ID is used. The client is also added to the domain's claim record clients array.
  • 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 number
    • serviceName (string, optional): Service name for naming the client (format: domain_servicename)
    • protocol (string, optional): Protocol type (tcp or udp, 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 OK on 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-delete
    
    OK
    

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 OK on 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-restart
    
    OK
    

38. POST /api/update-settings

  • Description: Updates environment settings (whitelisted variables) and persists them to .env. Note: SUBNETS can be updated here, but it's recommended to use /api/subnets for subnet management. SUBNET_BASE and INITIAL_IP_INDEX are deprecated in favor of the subnet configurator.
  • Request Body: JSON with settings (object mapping whitelisted keys to values). For SUBNETS, provide a JSON array string.
  • Response: JSON object with message (string), restartRequired (boolean), and optionally restartRequiredSettings (array of strings).
  • Status Codes:
    • 200: Success.
    • 400: Validation failed (includes errors array).
    • 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_BASE if 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/description
    • index (number): Subnet index in array
    • available (number): Total available IPs in subnet
    • used (number): Currently used IPs
    • remaining (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) and restartRequired (boolean, always true).
  • Status Codes:
    • 200: Success.
    • 400: Validation failed (includes error string and errors array).
    • 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:
    • base must be a valid IPv4 address (e.g., "192.168.3.0")
    • cidr must be between 1 and 32
    • startIndex must 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 (liveness or readiness, default: liveness).
  • Response: JSON object with status (healthy/degraded/not_ready), timestamp, uptime, probe, services (object with DNS, proxy, swarm status), and dependencies (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-snapshot over WebSocket). The admin UI loads this once, then uses subscribe-stats for 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)
    • pluginRpc and peerChannels — Per-plugin protomux-rpc protocol stats (transport: 'rpc', methods, rpcOpen counts)
    • 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: channelcore, proxy, httpProxy, dns, plugins, or holesail
  • Query: lines — max lines (default 500, max 5000)
  • 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, and fileCount.
  • 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) and path (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) and message (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-000000 or backup-20240101-000000.tar.gz).
  • Response: JSON object with success (boolean) and message (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) and type (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), and responseTime (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), and stream (boolean, optional, default: false).
  • Response:
    • Non-streaming: JSON object with success, target, count, output, error, and responseTime.
    • Streaming: NDJSON stream with type (output/error/complete), data, timestamp, and completion status.
  • 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) and stream (boolean, optional, default: false).
  • Response:
    • Non-streaming: JSON object with success, target, output, error, and responseTime.
    • Streaming: NDJSON stream with type (output/error/complete), data, timestamp, and completion status.
  • 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) and port (number, required).
  • Response: JSON object with success (boolean), domain, ip (resolved IP), port, latency (if successful), error (if failed), and responseTime.
  • 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, optional note, 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 of domains, 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.ico
    
    Not 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 is resolved, otherwise null.
    • resolvedClaimant (string|null): Public key of the winning claimant if resolved, otherwise null.
    • 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, or null if 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 with domain, resolved count, and failed count.
    • sidecar (object): Same fields as GET /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) and message (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) and message (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 identifier
    • key (string): Holesail connection hash
    • port (number): Port number
    • protocol (string): Protocol type (tcp or udp)
  • 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 name
    • serviceName (string): Service identifier
    • key (string): Holesail connection hash
    • port (number): Port number
    • protocol (string): Protocol type (tcp or udp)
  • 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_servicename and persists the subscription to subscriptions.json.
  • Request Body: JSON with:
    • domain (string, required): Domain name
    • serviceName (string, required): Service identifier
    • key (string, required): Holesail connection hash
    • port (number, required): Port number
    • protocol (string, optional): Protocol type (tcp or udp, 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 name
    • serviceName (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 name
    • name (string): Plugin name from config.json
    • version (string): Plugin version
    • description (string): Plugin description
    • author (string): Plugin author
    • homepage (string): Plugin homepage URL
    • license (string): Plugin license
    • status (string): Plugin status (loaded, stopped, or static)
    • hasHandler (boolean): Whether plugin has a handler function
    • hasWww (boolean): Whether plugin has a www directory
    • hasDatabase (boolean): Whether plugin has HyperDB configured
    • actions (array): Array of registered action objects
    • settings (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), and domain (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), and domain (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), and domain (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) and result (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}.json and 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) and message (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), and peerId (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-Token header 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 peer
  • timestamp: 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, and subscriptions.json should have restricted permissions to prevent unauthorized modifications.

Testing

  • Use tools like curl or 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-log per channel) or GET /api/logs/:channel; plugin logs use plugin-log WebSocket messages.