Identity & Device Pool API
Identity
GET /api/identity/nickname
Get the current node's nickname.
PUT /api/identity/nickname
Set a nickname. Body: {"nickname": "my-node"}
DELETE /api/identity/nickname
Clear the nickname.
GET /api/identity/leaderboard
Network-wide leaderboard. Ranks by shards hosted, not by credits — the credit economy is dormant and no surface publishes a balance (docs/CREDITS_DESIGN.md).
GET /api/identity/peers
Peer identity directory (nicknames, regions, tiers).
Device Pools ("My Devices")
Link multiple devices owned by the same user, so they serve each other privately and the owner can pin models to them. Credit forwarding to the owner's balance still runs underneath, but credits are dormant and nothing shows a balance (docs/CREDITS_DESIGN.md).
Terminology: "My Devices" in the UI (More → My Devices). This is different from connecting to the SwarmLLM network — linking devices groups your own hardware, while the network connects you with other people.
Quick Start (CLI)
# On your main device:
swarmllm pool create --name "My Devices"
swarmllm pool invite-code
# → swarmpool://… (a long code)
# On each other device:
swarmllm pool join 'swarmpool://…'
# Check status:
swarmllm pool status
Invite Code System
Instead of exchanging raw 64-character node IDs, device pools use an invite code: a swarmpool://… link that carries the main device's reachable addresses and a short join token, so the joining device can dial it directly. (A bare 8-character code such as A3F7K2M9 — the token on its own — is still accepted, but only joins when both devices already share a swarm.)
- Owner generates a code →
POST /api/pool/generate-code - Code shared verbally, via QR, or copy-paste
- Member enters code →
POST /api/pool/join→ broadcasts join request over gossip - Owner's node auto-validates code and creates invitation
- Member auto-accepts → pool established
Security: Codes use a 32-character alphabet (no 0/O/1/I), are one-time use, expire in 24h, and the code itself is never transmitted over the network — only its BLAKE3 hash.
API Endpoints
GET /api/pool/state
Current pool membership state. Returns in_pool and this node's own node_id; in a pool, also is_owner, the member list with device names, online status, per-device stats, and the credit split percentage.
POST /api/pool/create
Create a new device pool. Body: {"name": "My Devices"}
POST /api/pool/generate-code
Generate an invite code (owner only). Returns {"status": "ok", "code": "swarmpool://…"} — the whole link the other device pastes, not the short token inside it. Max 5 active codes.
POST /api/pool/join
Join a pool using an invite code. Body: {"code": "A3F7K2M9"}
POST /api/pool/invite
Invite a specific node by ID (advanced). Body: {"node_id": "abc123..."}
POST /api/pool/accept
Accept a pool invitation. Body: {"invitation_id": "..."}
POST /api/pool/remove
Remove a member (owner only). Body: {"node_id": "..."}
POST /api/pool/leave
Leave the current pool.
POST /api/pool/device-name
Set this device's nickname. Body: {"name": "Gaming PC"}
PUT /api/pool/credit-split
Set credit split percentage (owner only). Body: {"pct": 20} (0-100, the share the member keeps; default 0 = everything is forwarded)
PUT /api/pool/contribution
Set per-member contribution level override. Body: {"node_id": "...", "level": 75} (integer 0–100)
GET /api/pool/invitations
List pending invitations for this node.
GET /api/pool/leaderboard
Pool member contribution rankings.
GET/PUT /api/admin/pools/:id/rates
Per-pool credit rate overrides.
Private Mode
Keep your OWN requests on your device group. By default this also admits other SwarmLLM computers on your local network (pool.private_mode_allow_lan = true); set it to false to keep requests on your own devices only. It does not stop your node serving the swarm.
GET /api/pool/private-mode
Current state + coverage summary. Returns enabled, allow_lan, offline_mode, and coverage object.
PUT /api/pool/private-mode
Toggle private mode. Body: {"enabled": true} or {"enabled": true, "offline_mode": true}.
Returns coverage summary so the UI can show trade-offs immediately.
GET /api/pool/coverage
Per-model coverage breakdown: total_shards, pool_shards, coverage_pct, missing indices, est_download_mb. Also returns disk_budget_mb and disk_used_mb.
Shard Pinning
GET /api/pool/pins
List current shard pins.
POST /api/pool/pin
Pin a model to a specific device (owner only). Body: {"model_id": "...", "target_node_id": "hex..."}.
Optional shard_indices array for specific shards (empty = all shards).
DELETE /api/pool/pin
Remove a shard pin. Same body format as POST.
Pool Features
- Device nicknames: Name each device for easy identification
- Online/offline status: Tracked via health pings, displayed with last-seen timestamps
- Per-device stats: VRAM, shards hosted, forwards served, uptime, models hosted
- Combined VRAM: Aggregate GPU memory across all linked devices
- Credit split: Owner configures what percentage (0-100%, default 0) members keep vs forward
- Private Mode: Restrict inference to pool devices only. Toggle via UI or API
- Shard Pinning: Assign specific models to specific devices. Auto-manage respects pins
- Offline Mode: Air-gapped LAN operation with mDNS-only discovery
- Coverage Dashboard: Per-model availability bars showing pool shard coverage
- Max 10 devices per pool (configurable), 10 pool operations per hour rate limit
Pool Security
- Invite codes: 32^8 ≈ 1.1 trillion combos, one-time use, 24h expiry
- Join requests signed with Ed25519 (transport-layer sender authentication)
- Credit forwarding uses dual-signed
PoolCreditForward(member + owner) - Member removal requires Ed25519-signed removal notice with replay protection
- Pool state gossip verifies each member's acceptance signature
- Blinded invitation broadcast (SEC-M18): network observers can't see who's invited