homeio
PublikFork dari doctor-io/homeio
api-reference.md
This reference is generated from the current app/api/**/route.ts tree and verified against route exports. Auth means the route is protected by the shared requireApiSession() helper or an auth-specific session check. There is no central middleware.
Response Conventions
- Preferred success shape for new routes:
{ "data": ... }. - Preferred error shape:
{ "error": string, "code"?: string, "details"?: unknown }. - Current code is inconsistent. Examples:
app/api/v1/files/route.tsreturns{ data, meta };app/api/v1/scheduled-tasks/route.tsreturns{ tasks }; auth routes use auth-specific shapes. - Routes that parse JSON generally return
400for invalid JSON or validation failure. - Protected routes return
401when session authentication fails. POST /api/auth/loginreturns429with{ "error": "Too many login attempts" }after 5 failed attempts per 15 minutes for the same normalized username/client IP.
Auth Routes
| Method | Path | Auth | Request | Response |
|---|---|---|---|---|
POST | /api/auth/login | N | JSON username/password | session cookie + user/session payload or error |
POST | /api/auth/logout | N | session cookie | clears cookie |
GET | /api/auth/me | Y | session cookie | current user/session |
POST | /api/auth/register | N | JSON username/password | creates first user/session |
GET | /api/auth/status | N | none | registration/status payload |
POST | /api/auth/unlock | N | JSON password | unlock result |
GET | /api/health | N | none | health payload |
Apps And Store
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/v1/apps | Y | List installed apps |
POST | /api/v1/apps/[appId]/start | Y | Start app stack |
POST | /api/v1/apps/[appId]/stop | Y | Stop app stack |
POST | /api/v1/apps/[appId]/restart | Y | Restart app stack |
POST | /api/v1/apps/[appId]/check-updates | Y | Check one app for updates |
GET | /api/v1/apps/[appId]/logs/stream | Y | SSE container logs |
GET | /api/v1/store/apps | Y | List catalog apps |
GET | /api/v1/store/apps/[appId] | Y | App detail |
GET | /api/v1/store/apps/[appId]/compose | Y | Compose for catalog/installed app |
PATCH | /api/v1/store/apps/[appId]/settings | Y | Update stored app settings |
POST | /api/v1/store/apps/[appId]/install | Y | Start install operation |
POST | /api/v1/store/apps/[appId]/update | Y | Start update operation |
POST | /api/v1/store/apps/[appId]/redeploy | Y | Start redeploy operation |
POST | /api/v1/store/apps/[appId]/uninstall | Y | Start uninstall operation |
GET | /api/v1/store/operations/[operationId] | Y | Operation snapshot |
GET | /api/v1/store/operations/[operationId]/stream | Y | SSE operation progress |
POST | /api/v1/store/check-updates | Y | Check catalog/installed updates |
POST | /api/v1/store/custom-apps/install | Y | Install custom app |
GET | /api/v1/store/sources | Y | List catalog sources |
POST | /api/v1/store/sources | Y | Create catalog source |
PATCH | /api/v1/store/sources/[sourceId] | Y | Update catalog source |
DELETE | /api/v1/store/sources/[sourceId] | Y | Delete catalog source |
POST | /api/v1/store/sources/[sourceId]/refresh | Y | Refresh catalog source |
Contracts: lib/shared/contracts/apps.ts, lib/shared/contracts/docker.ts. Operation SSE events: operation.step, operation.completed, operation.failed, heartbeat.
Store operation mutation routes can return 409 with code: "operation_conflict" when the same app already has an active operation, or 429 with code: "operation_limit_reached" when serverEnv.STORE_MAX_CONCURRENT_OPERATIONS is reached.
Docker
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/v1/docker/info | Y | Docker daemon info |
GET | /api/v1/docker/stats | Y | Container stats snapshot |
GET | /api/v1/docker/stats/stream | Y | SSE stats stream |
POST | /api/v1/docker/prune/images | Y | Prune Docker images |
POST | /api/v1/docker/prune/volumes | Y | Prune Docker volumes |
Docker stats SSE events: stats.updated, heartbeat.
Files
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/v1/files | Y | List directory |
GET | /api/v1/files/root | Y | File root info |
GET | /api/v1/files/content | Y | Read file content |
PUT | /api/v1/files/content | Y | Write text file |
GET | /api/v1/files/asset | Y | Stream asset content |
GET | /api/v1/files/download | Y | Download file |
POST | /api/v1/files/upload | Y | Upload files |
POST | /api/v1/files/ops | Y | Create/rename/paste/info/star operations |
GET | /api/v1/files/search | Y | Search files |
GET | /api/v1/files/starred | Y | List starred files |
GET | /api/v1/files/zip | Y | Download folder zip |
POST | /api/v1/files/trash/move | Y | Move entry to trash |
POST | /api/v1/files/trash/restore | Y | Restore trash entry |
POST | /api/v1/files/trash/delete | Y | Delete trash entry |
POST | /api/v1/files/trash/empty | Y | Empty trash |
GET | /api/v1/files/network/discover/servers | Y | Discover SMB servers |
POST | /api/v1/files/network/discover/shares | Y | Discover SMB shares |
GET | /api/v1/files/network/shares | Y | List SMB shares |
POST | /api/v1/files/network/shares | Y | Add SMB share |
DELETE | /api/v1/files/network/shares/[shareId] | Y | Remove SMB share |
POST | /api/v1/files/network/shares/[shareId]/mount | Y | Mount SMB share |
POST | /api/v1/files/network/shares/[shareId]/unmount | Y | Unmount SMB share |
GET | /api/v1/files/shared/folders | Y | List local folder shares |
POST | /api/v1/files/shared/folders | Y | Add local folder share |
DELETE | /api/v1/files/shared/folders/[shareId] | Y | Remove local folder share |
GET | /api/v1/files/usb | Y | List USB drives |
GET | /api/v1/files/usb/stream | Y | SSE USB events |
POST | /api/v1/files/usb/[driveId]/mount | Y | Mount USB drive |
POST | /api/v1/files/usb/[driveId]/unmount | Y | Unmount USB drive |
POST | /api/v1/files/usb/[driveId]/eject | Y | Eject USB drive |
GET | /api/v1/files/google-drive/auth | N | Start Google Drive OAuth |
GET | /api/v1/files/google-drive/callback | N | OAuth callback |
GET | /api/v1/files/google-drive/connections | Y | List Drive connections |
DELETE | /api/v1/files/google-drive/connections/[id] | Y | Delete Drive connection |
GET | /api/v1/files/google-drive/[id]/browse | Y | Browse Drive folder |
GET | /api/v1/files/google-drive/[id]/download | Y | Download Drive file |
POST | /api/v1/files/google-drive/[id]/upload | Y | Upload Drive file |
POST | /api/v1/files/google-drive/[id]/folders | Y | Create Drive folder |
PATCH | /api/v1/files/google-drive/[id]/files/[fileId] | Y | Move/rename Drive file |
DELETE | /api/v1/files/google-drive/[id]/files/[fileId] | Y | Delete Drive file |
Contracts: lib/shared/contracts/files.ts, lib/shared/contracts/usb.ts, lib/shared/contracts/google-drive.ts. File service errors use FileServiceErrorCode.
POST /api/v1/files/upload accepts multipart FormData with path, optional includeHidden, and repeated file parts. The route stream-parses multipart content with busboy, passes each file stream to the file service, and avoids holding whole uploads in memory. The client upload helper uses XMLHttpRequest for progress and supports AbortSignal cancellation. Next's route-handler proxy upload limit is configured by experimental.proxyClientMaxBodySize in next.config.mjs; external reverse proxies may still enforce their own limit.
POST /api/v1/files/ops also supports action: "unzip" for archive extraction beside create/rename/paste/info/star operations.
Network
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/v1/network/status | Y | Network status |
GET | /api/v1/network/networks | Y | WiFi scan |
POST | /api/v1/network/connect | Y | Connect WiFi |
POST | /api/v1/network/disconnect | Y | Disconnect WiFi |
GET | /api/v1/network/events/stream | Y | SSE network events |
Contract: lib/shared/contracts/network.ts.
Notifications
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/v1/notifications | Y | List notifications |
DELETE | /api/v1/notifications | Y | Clear notifications |
POST | /api/v1/notifications/read-all | Y | Mark all read |
GET | /api/v1/notifications/stream | Y | SSE notification events |
Contract: lib/shared/contracts/notifications.ts.
Scheduled Tasks
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/v1/scheduled-tasks | Y | List tasks |
POST | /api/v1/scheduled-tasks | Y | Create task |
GET | /api/v1/scheduled-tasks/[taskId] | Y | Task detail |
PATCH | /api/v1/scheduled-tasks/[taskId] | Y | Update task |
DELETE | /api/v1/scheduled-tasks/[taskId] | Y | Delete task |
POST | /api/v1/scheduled-tasks/[taskId]/run | Y | Run task now |
Contract: lib/shared/contracts/scheduled-tasks.ts.
Settings And System
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/v1/settings/appearance | Y | Appearance settings |
PUT | /api/v1/settings/appearance | Y | Save appearance settings |
GET | /api/v1/settings/telemetry | Y | Anonymous usage stats setting |
PUT | /api/v1/settings/telemetry | Y | Turn anonymous usage stats on or off ({ "enabled": boolean }) |
GET | /api/v1/settings/google-oauth | Y | Public Google OAuth config status |
PUT | /api/v1/settings/google-oauth | Y | Save Google OAuth client credentials |
DELETE | /api/v1/settings/google-oauth | Y | Clear Google OAuth client credentials |
GET | /api/v1/system/info | Y | Server info |
GET | /api/v1/system/metrics | Y | Metrics snapshot |
GET | /api/v1/system/stream | Y | SSE metrics stream |
GET | /api/v1/system/preferences | Y | System preferences |
PUT | /api/v1/system/preferences | Y | Save system preferences |
GET | /api/v1/system/security | Y | Security settings |
PUT | /api/v1/system/security | Y | Save security settings |
GET | /api/v1/system/updates | Y | Update status |
POST | /api/v1/system/updates/check | Y | Check for updates |
POST | /api/v1/system/updates/apply | Y | Apply update |
GET | /api/v1/system/backups | Y | List backups |
POST | /api/v1/system/backups/run | Y | Run backup |
PUT | /api/v1/system/backups/settings | Y | Save backup settings |
POST | /api/v1/system/backups/[backupId]/restore | Y | Restore backup |
GET | /api/v1/system/power/capabilities | Y | Power capabilities |
GET | /api/v1/system/power/schedule | Y | Reboot schedule |
PUT | /api/v1/system/power/schedule | Y | Save reboot schedule |
POST | /api/v1/system/power/shutdown | Y | Shutdown host |
POST | /api/v1/system/power/reboot | Y | Reboot host |
POST | /api/v1/system/power/factory-reset | Y | Schedule factory reset |
GET | /api/v1/system/disks | Y | List disks |
POST | /api/v1/system/disks/format | Y | Format partition |
POST | /api/v1/system/disks/mount | Y | Mount partition |
POST | /api/v1/system/disks/unmount | Y | Unmount partition |
POST | /api/v1/system/disks/create-partition | Y | Create partition |
POST | /api/v1/system/disks/delete-partition | Y | Delete partition |
POST | /api/v1/system/disks/wipe | Y | Wipe disk |
GET | /api/v1/logs | Y | Read logs |
Contracts: lib/shared/contracts/system.ts, lib/shared/contracts/disks.ts, lib/shared/contracts/server-info.ts.
Terminal
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST | /api/v1/terminal/execute | Y | Execute allowlisted command |
WS | /api/terminal | Configured by TERMINAL_WS_REQUIRE_AUTH | Full PTY terminal |
WebSocket client-to-server messages in lib/server/modules/terminal/websocket-server.ts:
| Message | Shape | Effect |
|---|---|---|
input | { "type": "input", "data": string } | Writes data to PTY |
resize | { "type": "resize", "cols"?: number, "rows"?: number } | Resizes PTY |
attach | { "type": "attach", "target": string } | Switches to docker exec -it <target> bash, fallback sh |
ping | { "type": "ping" } | Sends { "type": "pong" } |
Server-to-client terminal output is mostly raw PTY bytes as WebSocket text. Error messages can be JSON: { "type": "error", "code": string, "message": string }.
Known Auth Gaps
Current /api/v1/** routes are protected by the shared requireApiSession() helper except the Google Drive OAuth bootstrap/callback routes listed above. See security.md for remaining risks.