Skip to content

REST API Reference

siamakerlab edited this page May 23, 2026 · 24 revisions

REST API Reference

Complete endpoint catalog as of v0.10.0. All routes are defined as constants in shared/.../ApiPath.kt; copy them into your client to stay wire-compatible.

Authentication

All /api/* routes (except /api/auth/setup, /api/auth/setup/status, /api/auth/login, and /health) require Bearer authentication:

Authorization: Bearer <token>

Obtain a token with POST /api/auth/login. The same token works with both the header and the vibe_session cookie path.

Base URL

http://<host>:17880

For LAN deployments. HTTPS is the operator's responsibility (reverse proxy recommended for non-LAN exposure).


Auth

POST /api/auth/setup/status

Check whether an admin user exists. Used by clients to decide between login and setup screen.

curl http://localhost:17880/api/auth/setup/status
# → {"adminExists": true}

POST /api/auth/setup

Create the first admin user (only when no admin exists). Returns 409 Conflict if one already exists.

curl -X POST http://localhost:17880/api/auth/setup \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"ChangeMe123","deviceName":"my-laptop"}'
# → {"token":"...","deviceId":"...","serverName":"...","username":"admin"}

POST /api/auth/login

curl -X POST http://localhost:17880/api/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"ChangeMe123","deviceName":"my-android"}'
# → {"token":"...","deviceId":"...","serverName":"...","username":"admin"}

10 consecutive failures lock the account for 15 minutes (timing-safe).

POST /api/auth/password

Change password. Requires Bearer auth.

curl -X POST http://localhost:17880/api/auth/password \
  -H 'Authorization: Bearer $TOKEN' \
  -H 'Content-Type: application/json' \
  -d '{"currentPassword":"old","newPassword":"new"}'
# → 204 No Content

Server status

GET /api/server/status

High-level summary.

curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:17880/api/server/status
{
  "serverName": "Vibe Coder Server",
  "serverVersion": "0.10.0",
  "osName": "Linux 6.x",
  "javaVersion": "17.0.19",
  "workspaceRoot": "/workspace",
  "projectCount": 3,
  "runningTaskCount": 0,
  "claudeAvailable": true,
  "androidSdkAvailable": true,
  "gitAvailable": true,
  "freeDiskSpaceBytes": 102400000000
}

GET /api/server/environment / GET /api/server/environment/check

Detailed per-component diagnostics.


Projects

GET /api/projects

curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:17880/api/projects
# → [{"id":"my-app","name":"My App","packageName":"...", ...}]

POST /api/projects/register

Empty project:

curl -X POST http://localhost:17880/api/projects/register \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{
    "projectId": "my-app",
    "appName": "My App",
    "packageName": "com.siamakerlab.myapp"
  }'

Clone from git:

curl -X POST http://localhost:17880/api/projects/register \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{
    "projectId": "my-app",
    "appName": "My App",
    "packageName": "com.siamakerlab.myapp",
    "sourceType": "clone",
    "cloneUrl": "https://github.com/owner/repo.git",
    "cloneBranch": "main"
  }'

Private SSH URL — first register a PAT or generate an SSH key via the Git integrations endpoints below.


Builds

POST /api/projects/{id}/build/debug

Queue a debug build. Returns immediately with a BuildDto; stream live output via /ws/projects/{id}/builds/{buildId}/logs.

GET /api/projects/{id}/builds

List recent builds.

POST /api/projects/{id}/builds/{buildId}/cancel

Send SIGTERM (then SIGKILL after 5 s) to the build subprocess.

GET /api/projects/{id}/artifacts/{artifactId}/download

Stream the produced APK.


Claude Console (per-project persistent session)

POST /api/projects/{id}/claude/console/prompt

curl -X POST http://localhost:17880/api/projects/my-app/claude/console/prompt \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"text":"Add a settings screen with a dark mode toggle"}'
# → 202 Accepted (response streamed over WebSocket)

POST /api/projects/{id}/claude/console/new

Tear down the current session and start fresh (--resume <id> is dropped).

GET /api/projects/{id}/claude/status

Model, plan, quota remaining (cached 60 s).


Environment setup (v0.10.0)

GET /api/env-setup/components

curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:17880/api/env-setup/components
{
  "components": [
    {"id":"java","displayName":"JDK 17","status":"INSTALLED","installable":false, ...},
    {"id":"android-sdk","displayName":"Android SDK","status":"MISSING","installable":true, ...},
    {"id":"claude-auth","displayName":"Claude 로그인","status":"INSTALLED","installable":false, ...}
  ]
}

POST /api/env-setup/install-all

Trigger sequential install of every installable component. Returns {"taskId":"..."}. Subscribe to /ws/env-setup/{taskId}/logs for live output.

POST /api/env-setup/{componentId}/install

Install a specific component (e.g. android-sdk).


Claude authentication (v0.10.0)

POST /api/env-setup/claude-auth/upload (multipart)

Upload .credentials.json obtained on another machine.

curl -X POST http://localhost:17880/api/env-setup/claude-auth/upload \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@$HOME/.claude/.credentials.json"
# → {"targetPath":"/home/vibe/.claude/.credentials.json", ...}

POST /api/env-setup/claude-auth/api-key

curl -X POST http://localhost:17880/api/env-setup/claude-auth/api-key \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"apiKey":"sk-ant-..."}'
# → 204 No Content

DELETE /api/env-setup/claude-auth/api-key/delete

Remove the API key (also accepts POST for clients that lack DELETE).


Claude semi-automatic web OAuth (v0.10.0)

POST /api/env-setup/claude-login/start

Spawn claude auth login wrapped in script -q. Returns the initial state.

curl -X POST http://localhost:17880/api/env-setup/claude-login/start \
  -H "Authorization: Bearer $TOKEN"
{
  "id":"task-...",
  "state":"STARTING",
  "url":null,
  "startedAt":"2026-05-23T12:00:00Z",
  "updatedAt":"2026-05-23T12:00:00Z",
  "errorMessage":null,
  "lastLines":[]
}

Poll /api/env-setup/claude-login/status every 1 s until state becomes AWAITING_CODE (and url is set).

GET /api/env-setup/claude-login/status

Same shape as above. Returns 204 if no session active.

POST /api/env-setup/claude-login/submit

curl -X POST http://localhost:17880/api/env-setup/claude-login/submit \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"code":"abc...#xyz"}'

State → VERIFYING, then DONE or FAILED.

POST /api/env-setup/claude-login/cancel

Destroy the child process. State → CANCELED.


MCP catalog (v0.10.0)

GET /api/env-setup/mcp

curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:17880/api/env-setup/mcp
{
  "entries": [
    {
      "id":"github",
      "displayName":"GitHub",
      "pkg":"@modelcontextprotocol/server-github",
      "description":"...",
      "category":"Git 호스팅 (GitHub / GitLab / Gitea / Bitbucket)",
      "trust":"VERIFIED",
      "recommended":true,
      "homepage":null,
      "configFields":[
        {"key":"GITHUB_PERSONAL_ACCESS_TOKEN","label":"GitHub PAT","placeholder":"ghp_...","isSecret":true,"required":true,"help":"..."}
      ],
      "status":"NOT_INSTALLED",
      "configValues":{}
    },
    ...
  ]
}

POST /api/env-setup/mcp/install

curl -X POST http://localhost:17880/api/env-setup/mcp/install \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{
    "selections": {
      "filesystem": {},
      "github": {"GITHUB_PERSONAL_ACCESS_TOKEN":"ghp_..."},
      "context7": {}
    }
  }'
# → {"taskId":"..."}    (subscribe to /ws/env-setup/{taskId}/logs)

POST /api/env-setup/mcp/unregister

Removes entries from .mcp.json. The npm package itself stays on disk.

curl -X POST http://localhost:17880/api/env-setup/mcp/unregister \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"ids":["github","slack"]}'
# → 204 No Content

POST /api/env-setup/mcp/{mcpId}/file/{fieldKey} (multipart, v0.11.0+)

Upload a secret file (Service Account JSON, Apple .p8, OAuth client.json) for an MCP entry whose configFields[].isFile is true.

curl -X POST http://localhost:17880/api/env-setup/mcp/google-play-publisher/file/GOOGLE_PLAY_SERVICE_ACCOUNT_JSON \
  -H "Authorization: Bearer $TOKEN" \
  -F "file=@./play-sa.json"
# → {"path":"/home/vibe/.config/mcp-secrets/google-play-publisher-GOOGLE_PLAY_SERVICE_ACCOUNT_JSON.json"}

Then pass the returned path as the value for that config key in the subsequent POST /api/env-setup/mcp/install:

curl -X POST http://localhost:17880/api/env-setup/mcp/install \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{
    "selections": {
      "google-play-publisher": {
        "GOOGLE_PLAY_SERVICE_ACCOUNT_JSON": "/home/vibe/.config/mcp-secrets/google-play-publisher-GOOGLE_PLAY_SERVICE_ACCOUNT_JSON.json",
        "GOOGLE_PLAY_PACKAGE_NAME": "com.siamakerlab.myapp"
      }
    }
  }'
  • File saved with 0600 permissions in ${CLAUDE_CONFIG_DIR}/mcp-secrets/.
  • 128 KB size cap (normal Service Account / .p8 is a few KB).
  • Filename sanitized — only [A-Za-z0-9._-] in the stored name.
  • Re-upload to replace (atomic move).

Git integrations (v0.10.0)

GET /api/settings/git-integrations

List registered PATs (masked) + SSH public key.

curl -H "Authorization: Bearer $TOKEN" \
  http://localhost:17880/api/settings/git-integrations
{
  "tokens": [
    {"provider":"github","host":"github.com","username":"x-access-token","tokenMasked":"••••••••wxyz","createdAt":"2026-05-23T12:00:00Z","note":null}
  ],
  "sshPublicKey": "ssh-ed25519 AAAA... vibe-coder"
}

POST /api/settings/git-integrations

curl -X POST http://localhost:17880/api/settings/git-integrations \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{
    "provider":"github",
    "host":"github.com",
    "username":"x-access-token",
    "token":"ghp_...",
    "note":"vibe-coder PAT, expires 2026-12"
  }'
# → 204 No Content

POST /api/settings/git-integrations/delete

curl -X POST http://localhost:17880/api/settings/git-integrations/delete \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"host":"github.com"}'

POST /api/settings/git-integrations/ssh-keygen

Generate ed25519 key pair if missing. Returns the full state including the public key for the user to copy.


Error response shape

{
  "code": "missing_clone_url",
  "message": "sourceType=clone 일 때 cloneUrl 이 필수입니다.",
  "detail": null
}

HTTP status codes: 400 bad input, 401 no/invalid token, 403 insufficient permission, 404 not found, 409 conflict, 413 payload too large, 502 upstream failed (git clone, npm install), 504 timeout.

Clone this wiki locally