Base URL: http://
Most endpoints require one of:
POST /login)X-Grove-Secret: header (for peer-to-peer APIs)Public endpoints (no auth): /login, /api/version, /api/pubkey, /api/source, /invite/, /manifest.json, /sw.js
GET /api/versionReturns build info. Public (no auth).
{"build": "abc123", "build_time": "2026-03-28T...", "started": "2026-03-28T...", "grove_py": 255707, "web_py": 575495}
GET /api/healthCell health check. Requires peer secret.
{"ok": true, "disk_free_gb": 333.2, "chunks": 142, "peers": 5}
GET /api/pubkeyReturns cell's public signing key. Public.
{"signing_pubkey": "1ChOy...", "x25519_pubkey": "abc..."}
GET /api/statusCell status overview. Requires auth.
{"chunks": 142, "peers": 5, "manifests": 47, "bounty": 1250.5}
POST /uploadUpload files to GROVE_HOME. Session auth. Multipart form with files field.
POST /download/Download a file by manifest name. Session auth. Returns file content.
GET /view/Inline view of a file (for images, video, audio preview). Session auth.
GET /preview?path=Serve a file from GROVE_HOME for inline preview. Session auth.
POST /syncManually sync a specific file to peers. Form: path=. Session auth.
POST /sync-allTrigger sync of all files to peers. Session auth.
POST /archive-by-pathRemove local copy of a file (keep on peers). Form: path=. Session auth.
POST /restore/Restore a file from peers (download chunks back). Session auth.
These are called between cells during sync. All require X-Grove-Secret header.
GET /api/chunk-inventoryReturns list of all chunk hashes this cell holds.
{"chunks": ["abc123...", "def456..."]}
POST /api/receive-chunksPush chunks to this cell. Multipart form: each field is {hash}: (hash, data, "application/octet-stream").
GET /api/serve-chunk-peer/Download a specific chunk by hash.
POST /api/delete-chunksDelete chunks from this cell. JSON body: {"hashes": ["abc...", "def..."]}.
GET /api/manifest-inventoryReturns list of all manifest filenames.
{"manifests": ["photo.jpg.a1b2c3d4.json", ...]}
POST /api/receive-manifestsPush manifests to this cell. JSON body with manifest data.
GET /api/serve-manifest/Download a specific manifest file.
POST /api/receive-grantPush a share grant to this cell. JSON body with grant data.
GET /api/grants-for/Get grants created by a specific pubkey (for sync).
POST /api/revoke-grantRevoke a previously sent grant.
POST /shareShare file(s) with peers. Form: manifest=, peers=. Session auth.
POST /unshareRevoke sharing. Form: manifest=, peers=. Session auth.
POST /reshareRe-share updated version of a file. Form: manifest=. Session auth.
POST /api/shared-foldersGet/set auto-share folder configuration. Session auth.
GET /feedHTML feed page showing files shared with you. Session auth.
GET /api/replication-statusReplication health for all peers.
{"peers": [{"user": "nookman", "status": "online", "chunks": 89, ...}], "total_chunks": 142}
GET /api/route-speedsAll routes to all peers with recorded speeds and selected route.
{"peers": [{"user": "nookman", "routes": [...], "selected_route": "100.96.243.69"}], "last_benchmark": "..."}
POST /api/benchmarkTrigger manual route benchmark (pushes/pulls test chunks to all peers).
GET /api/opp-sync-statusBackground sync status.
{"active": false, "interval_seconds": 300}
GET /api/relay/statusRelay connection status.
{"connected": true, "relay_url": "ws://...", "peers_online": ["pubkey1", ...]}
GET /api/peer-speedsRaw peer speed measurements.
GET /api/peer-healthPeer uptime/reliability data.
POST /peers/addAdd a peer. Form: host=, port=5678, user=. Session auth.
POST /peers/removeRemove a peer. Form: host=, mode=list-only|and-files. Returns JSON.
POST /peers/favoriteToggle favorite status. Form: user=. Session auth.
POST /friends/addPromote peer to friend. Form: host=. Session auth.
POST /friends/removeDemote friend to peer. Form: host=. Session auth.
POST /api/invite/createCreate an invite link. JSON body: {"message": "Welcome!", "name": "...", "bounty": 0}.
{"ok": true, "token_id": "abc...", "url": "https://grove.nook.website/invite/abc..."}
GET /api/invite/listList all invites with status.
GET /invite/Invite landing page (browser) or install script (curl/wget).
POST /invite//download Download install script with user's chosen name baked in.
POST /api/invite//accept Accept an invite (called by install script). JSON: {"pubkey": "...", "self_name": "..."}.
GET /api/ai/statusLocal AI availability, hardware, model info.
{"available": true, "model": "nemotron-3-nano-4b-q4_k_m.gguf", "hardware": {"chip": "Apple M4", "gpu": "metal"}, "status": "idle"}
POST /api/ai/chatSend a message to local AI. JSON: {"message": "Hello", "system": "optional system prompt"}. Returns streaming response.
GET /api/ai/networkFind AI-capable peers in the fleet.
POST /api/ai/proxyProxy a chat request to a peer's AI.
GET /api/settingsCurrent cell settings.
POST /api/settingsUpdate settings. JSON body with fields to change.
POST /api/settings/passwordChange dashboard password. JSON: {"current": "...", "new": "..."}.
GET /api/chatGet chat conversations and messages.
POST /api/chat-messageSend an encrypted chat message. JSON: {"peer": "pubkey", "message": "..."}.
POST /api/chat/deleteDelete a chat message.
POST /api/gcRun garbage collection (remove orphaned chunks).
POST /api/prune-excessRemove over-replicated chunks from peers.
GET /api/prune-previewPreview what pruning would remove.
GET /api/backup-keysDownload encryption keys as ZIP (for backup).
POST /api/restore-keysRestore keys from backup ZIP.