API and MCP
API keys
Long-lived tokens for scripts and AI agents, separate from user accounts — a machine cannot do one-time passwords, and it should not borrow someone's password.
Format is walis_<prefix>_<secret>; only a PBKDF2 hash is stored and the plaintext is returned once. Keys carry a role (admin, operator, viewer) and cannot create other keys — a leaked key should not be able to breed more.
curl -H "Authorization: Bearer walis_..." http://127.0.0.1:11120/api/jobsMCP
The API speaks MCP directly at /mcp, so an agent needs a URL and a key — nothing to install:
# Claude Code
claude mcp add --transport http walis http://127.0.0.1:11120/mcp \
--header "Authorization: Bearer walis_..."
# Codex CLI — reads the token from an environment variable
codex mcp add walis --url http://127.0.0.1:11120/mcp --bearer-token-env-var WALIS_API_KEYTools: list_jobs, get_job, trigger_build, wait_for_build, get_build, get_build_log, list_builds. Jobs can be named rather than referenced by id.
Settings, accounts and key management are deliberately not exposed. Those are irreversible or credential-bearing, and belong to a human in the admin UI; a leaked key stays limited to triggering builds and reading logs.
/mcp goes through the same authentication as /api — it can trigger builds, so it is not left open just because it sits outside the /api prefix.
Metrics
GET /metrics returns Prometheus text: job counts, queue depth, builds by status, average duration and queue time, runners by state. It sits outside /api and needs no key, because a scraper on the same machine should not need one and the numbers are aggregates.
Portability
GET /api/portability/export exports every job and custom action without ids, statistics or timestamps — those describe this machine, not the definition. Import matches by name: existing jobs are skipped unless you ask to overwrite, and overwriting updates them in place so build history survives.