guide #050

API Key Management (Dashboard KEYS Page)

Problem
Changing API keys requires SSH access and manual env file editing.

Solution
Full KEYS page: view (masked), inline edit, one-tap test (hits provider API), add new keys.

Context

PocketClaw uses multiple API keys: AI providers (Kimi, Groq, OpenAI), messaging (Telegram bot token), and optional services. Initially, changing a key required: SSH into the phone, edit ~/.openclaw/env with vi, save, restart the gateway. This multi-step process was error-prone and inaccessible to anyone who can't use a terminal.

The KEYS page provides a web interface for full API key lifecycle management, accessible from any browser on the same WiFi network.

Implementation

Each provider has a specific test endpoint:

// Test endpoints per provider type:
const testEndpoints = {
  // AI providers — GET /v1/models
  'MOONSHOT_API_KEY': 'https://api.kimi.com/coding/v1/models',
  'OPENAI_API_KEY': 'https://api.openai.com/v1/models',
  'GROQ_API_KEY': 'https://api.groq.com/openai/v1/models',

  // Telegram — GET /botXXX/getMe
  'TELEGRAM_BOT_TOKEN': (key) => `https://api.telegram.org/bot${key}/getMe`,

  // Discord — GET /users/@me
  'DISCORD_BOT_TOKEN': 'https://discord.com/api/v10/users/@me',
};

Key operations:

// GET /api/keys — list all keys (masked)
// Returns: [{ name: "MOONSHOT_API_KEY", value: "sk-...x4f2", set: true }]

// POST /api/keys — save a key
// Body: { name: "MOONSHOT_API_KEY", value: "sk-kimi-full-key-here" }
// Writes to ~/.openclaw/env AND updates process.env (no restart needed)

// POST /api/keys/test — test a key
// Body: { name: "MOONSHOT_API_KEY" }
// Hits the provider's health endpoint, returns { ok: true/false, error?: "..." }

Keys are stored in ~/.openclaw/env with mode 0600:

# ~/.openclaw/env format:
MOONSHOT_API_KEY=sk-kimi-xxx
TELEGRAM_BOT_TOKEN=8360:AAH...
GROQ_API_KEY=gsk_xxx

Verification

# Access KEYS page:
curl -s http://localhost:9000/keys | grep "MOONSHOT"
# Expected: HTML showing MOONSHOT_API_KEY (masked)

# Test a key via API:
curl -s -X POST http://localhost:9000/api/keys/test \
  -H "Content-Type: application/json" \
  -d '{"name":"MOONSHOT_API_KEY"}'
# Expected: {"ok":true} or {"ok":false,"error":"..."}

# Verify env file permissions:
ls -la ~/.openclaw/env
# Expected: -rw------- (mode 600)

Gotchas

  • Keys are masked in the GET response (showing only last 4 characters). This prevents casual shoulder-surfing on the local network
  • The POST /api/keys endpoint writes to disk AND updates process.env in the running process — no gateway restart needed
  • There's no authentication on the KEYS page. It's only accessible on the local network, but anyone on the same WiFi can access it. Consider adding basic auth for shared networks
  • Telegram bot tokens have a special format (number:hash) — the test endpoint constructs the URL differently than AI providers

Result

MetricBeforeAfter
Key change methodSSH + viWeb browser
Key testingManual curlOne-tap button
Gateway restart neededYesNo (live update)
Time to change a key2-3 min10 seconds
Continue reading
guide
Pocket AI complete guide
Running self-hosted AI on portable hardware
guide
Edge AI hardware buyer's guide 2026
Pi 5 vs Mini PC vs Mac Mini
report
Self-hosted AI landscape 2026
Quarterly state of the ecosystem
section
Pocket AI hardware hub
All portable hosts reviewed
section
Agent tracker
Live stats on every agent
newsletter
Thursday digest
Weekly summary in your inbox