The Hoody Code Orchestrator endpoints power the VS Code web interface served inside a Hoody container. Use them to load the editor, manage password-based authentication, serve static assets and manifests, and proxy HTTP/WebSocket traffic to local ports running inside the container.
All endpoints live on the container-scoped subdomain:
https://{projectId}-{containerId}-code-1.{server}.containers.hoody.icu
VS Code Interface
Section titled “VS Code Interface”GET /api/v1/code
Section titled “GET /api/v1/code”Returns the main VS Code web interface.
If authentication is enabled and the user is not logged in, the server redirects to /login. The session is managed via cookies. When no folder or workspace parameter is supplied, the last opened folder (or the CLI argument) is reused, and the query parameters are stored in settings for the next session.
Add ?extension=PUBLISHER.NAME to open the editor in extension-only mode (file explorer is hidden and the extension’s UI takes focus). The --external-js and --external-css flags inject external resources — JavaScript files are loaded in <head> and CSS files are linked as stylesheets. The Content-Security-Policy header is automatically updated to allow the external domains.
curl -X GET "https://acme-prod-cnt42-code-1.us-east.containers.hoody.icu/api/v1/code?folder=%2Fhome%2Fuser%2Fproject&locale=en" \ -H "Cookie: session=<session_token>"import { HoodyClient } from "hoody-sdk";
const client = new HoodyClient({ token: process.env.HOODY_TOKEN });
await client.code.vscode.getVSCode({ folder: "/home/user/project", locale: "en",});Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
folder | query | string | No | Absolute path to folder to open in VS Code. Takes precedence over workspace. Stored in settings for next session. |
workspace | query | string | No | Absolute path to VS Code workspace file (.code-workspace). Used when folder is not provided. Stored in settings for next session. |
extension | query | string | No | Extension identifier to open in extension-only mode. Format: PUBLISHER.NAME (e.g. ms-python.python, ms-toolsai.jupyter). |
ew | query | boolean | No | ”Empty Window” flag — when present, clears the last opened folder/workspace from settings. |
locale | query | string | No | Display language for VS Code UI. IETF language tag (e.g. en, fr, de, ja, zh-CN). |
Response
Section titled “Response”<!DOCTYPE html><html><head> <title>VS Code</title> <meta charset="utf-8"></head><body> <!-- VS Code web interface --></body></html>| Header | Description |
|---|---|
Content-Type | text/html; charset=utf-8 |
Content-Security-Policy | CSP header with appropriate directives. Automatically updated when --external-js or --external-css is used. |
Redirects to the login page when authentication is required.
| Header | Example |
|---|---|
Location | /login?to=%2F%3Ffolder%3D%2Fhome%2Fuser%2Fproject |
GET /api/v1/code/manifest.json
Section titled “GET /api/v1/code/manifest.json”Returns the Progressive Web App manifest used to install Hoody Code as an installable web app. The manifest exposes the app name (configurable via --app-name), icon set, fullscreen display mode with the window-controls-overlay override, and start URL.
curl -X GET "https://acme-prod-cnt42-code-1.us-east.containers.hoody.icu/api/v1/code/manifest.json"import { HoodyClient } from "hoody-sdk";
const client = new HoodyClient({ token: process.env.HOODY_TOKEN });
await client.code.vscode.getManifest();This endpoint takes no parameters.
Response
Section titled “Response”{ "name": "hoody-code", "short_name": "hoody-code", "start_url": ".", "display": "fullscreen", "display_override": ["window-controls-overlay"], "description": "Run Code on a remote server.", "icons": [ { "src": "/_static/out/browser/media/pwa-icon-192.png", "type": "image/png", "sizes": "192x192", "purpose": "any" }, { "src": "/_static/out/browser/media/pwa-icon-512.png", "type": "image/png", "sizes": "512x512", "purpose": "any" }, { "src": "/_static/out/browser/media/pwa-icon-maskable-512.png", "type": "image/png", "sizes": "512x512", "purpose": "maskable" } ]}POST /api/v1/code/mint-key
Section titled “POST /api/v1/code/mint-key”Generates or retrieves the server’s 256-bit (32-byte) web key half used by VS Code for secure communications. The key is stored at user-data-dir/serve-web-key-half and is created once and reused across restarts. The response body is binary (32 bytes).
curl -X POST "https://acme-prod-cnt42-code-1.us-east.containers.hoody.icu/api/v1/code/mint-key"import { HoodyClient } from "hoody-sdk";
const client = new HoodyClient({ token: process.env.HOODY_TOKEN });
await client.code.vscode.mintKey();This endpoint takes no parameters.
Response
Section titled “Response”Returns the 32-byte server key as application/octet-stream in the response body.
Authentication
Section titled “Authentication”The login endpoints are only available when authentication is enabled. Sessions are managed via the cookie returned on successful login.
GET /api/v1/code/login
Section titled “GET /api/v1/code/login”Returns the login page HTML. If the user is already authenticated, redirects to the target page.
curl -X GET "https://acme-prod-cnt42-code-1.us-east.containers.hoody.icu/api/v1/code/login?to=%2Fprojects%2Fhoody"import { HoodyClient } from "hoody-sdk";
const client = new HoodyClient({ token: process.env.HOODY_TOKEN });
await client.code.auth.getLoginPage({ to: "/projects/hoody" });Parameters
Section titled “Parameters”| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
to | query | string | No | / | URL to redirect to after successful login. |
Response
Section titled “Response”<!DOCTYPE html><html><head><title>Login — Hoody Code</title></head><body> <form method="POST" action="/api/v1/code/login"> <input type="password" name="password" autofocus> <button type="submit">Sign in</button> </form></body></html>Redirects to the destination when the user is already authenticated.
| Header | Description |
|---|---|
Location | The destination URL. |
POST /api/v1/code/login
Section titled “POST /api/v1/code/login”Authenticates with the configured password and sets the session cookie on success.
Rate limits apply: 2 attempts per minute and 12 attempts per hour. Passwords configured with --hashed-password are compared against argon2 hashes; passwords configured with --password are compared against SHA-256 hashes. Failed attempts are logged with the IP and user agent.
curl -X POST "https://acme-prod-cnt42-code-1.us-east.containers.hoody.icu/api/v1/code/login?to=%2Fprojects%2Fhoody" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "password=s3cureP%40ss%21"import { HoodyClient } from "hoody-sdk";
const client = new HoodyClient({ token: process.env.HOODY_TOKEN });
await client.code.auth.login({ to: "/projects/hoody" });
// or, to log in without specifying a redirect target:await client.code.auth.login();Parameters
Section titled “Parameters”| Name | In | Type | Required | Default | Description |
|---|---|---|---|---|---|
to | query | string | No | / | URL to redirect to after successful login. |
Request Body
Section titled “Request Body”Content-Type: application/x-www-form-urlencoded
| Field | Type | Required | Description |
|---|---|---|---|
password | string (format: password) | Yes | Password to authenticate with. |
Response
Section titled “Response”Re-renders the login page with an error message.
<!DOCTYPE html><html><head><title>Login — Hoody Code</title></head><body> <form method="POST" action="/api/v1/code/login"> <p class="error">Invalid password. Please try again.</p> <input type="password" name="password" autofocus> <button type="submit">Sign in</button> </form></body></html>| Error Code | Title | Description | Resolution |
|---|---|---|---|
INVALID_PASSWORD | Invalid password | The password provided is incorrect | Check your password and try again |
RATE_LIMITED | Too many login attempts | Rate limit exceeded (2 attempts/min or 12 attempts/hour) | Wait a few minutes before trying again |
Redirects to the destination on success, or back to the login page on failure.
| Header | Description |
|---|---|
Location | Destination URL on success, or login URL on failure. |
Set-Cookie | Session cookie (set on success). |
GET /api/v1/code/logout
Section titled “GET /api/v1/code/logout”Clears the session cookie and redirects to the home page. Only available when authentication is enabled.
curl -X GET "https://acme-prod-cnt42-code-1.us-east.containers.hoody.icu/api/v1/code/logout" \ -H "Cookie: session=<session_token>"import { HoodyClient } from "hoody-sdk";
const client = new HoodyClient({ token: process.env.HOODY_TOKEN });
await client.code.auth.logout();This endpoint takes no parameters.
Response
Section titled “Response”| Header | Example | Description |
|---|---|---|
Location | / | Home page. |
Set-Cookie | session=; Path=/; Expires=Thu, 01 Jan 1970 00:00:00 GMT | Expired session cookie. |
Static Assets and Policy Files
Section titled “Static Assets and Policy Files”GET /_static/{path}
Section titled “GET /_static/{path}”Serves static files from the build directory — bundled JavaScript/CSS, images, icons, and the service worker. Long cache headers are emitted in production (keyed on the git commit); no cache headers are emitted in development. The service worker at /_static/out/browser/serviceWorker.js is returned with the special header Service-Worker-Allowed: / to allow it to register at root scope.
curl -X GET "https://acme-prod-cnt42-code-1.us-east.containers.hoody.icu/_static/out/browser/workbench.js"import { HoodyClient } from "hoody-sdk";
const client = new HoodyClient({ token: process.env.HOODY_TOKEN });
await client.code.static.get("out/browser/workbench.js");Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
path | path | string | Yes | Path to static file relative to the build root. |
Response
Section titled “Response”Returns the requested static file.
| Header | Description |
|---|---|
Cache-Control | Cache control header. Long-lived in production, no-cache in development. |
Service-Worker-Allowed | Set to / for service worker files only. |
File not found.
GET /hoody-code/injected/{script}
Section titled “GET /hoody-code/injected/{script}”Serves injected JavaScript files from the extra/injected/ directory. These scripts are loaded automatically when the --hoody-code flag is enabled: they run sequentially after the window load event, are applied to all VS Code pages, and can customize behavior and branding. The same files are also available under /vscode/hoody-code/injected/{script}.
curl -X GET "https://acme-prod-cnt42-code-1.us-east.containers.hoody.icu/hoody-code/injected/branding.js"import { HoodyClient } from "hoody-sdk";
const client = new HoodyClient({ token: process.env.HOODY_TOKEN });
await client.code.static.getInjectedScript("branding.js");Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
script | path | string | Yes | Script filename. |
Response
Section titled “Response”Returns the JavaScript file with Content-Type: application/javascript.
Script not found.
GET /robots.txt
Section titled “GET /robots.txt”Returns the robots.txt file used by web crawlers.
curl -X GET "https://acme-prod-cnt42-code-1.us-east.containers.hoody.icu/robots.txt"import { HoodyClient } from "hoody-sdk";
const client = new HoodyClient({ token: process.env.HOODY_TOKEN });
await client.code.static.getRobots();This endpoint takes no parameters.
Response
Section titled “Response”Returns the robots.txt body as text/plain.
GET /security.txt
Section titled “GET /security.txt”Returns the security.txt file used for vulnerability disclosure. Also available at /.well-known/security.txt.
curl -X GET "https://acme-prod-cnt42-code-1.us-east.containers.hoody.icu/security.txt"import { HoodyClient } from "hoody-sdk";
const client = new HoodyClient({ token: process.env.HOODY_TOKEN });
await client.code.static.getSecurityPolicy();This endpoint takes no parameters.
Response
Section titled “Response”Returns the security.txt body as text/plain.
Port Proxying
Section titled “Port Proxying”The proxy endpoints forward traffic from the public VS Code URL to applications running on local container ports. Both endpoints support any HTTP method and WebSocket upgrades, and both require authentication (OPTIONS preflight can be skipped via --skip-auth-preflight).
Use /proxy/{port}/{path} when the proxied application should see the request at its root path (the /proxy/{port} prefix is stripped before forwarding). Use /absproxy/{port}/{path} when the proxied application is aware of the subpath and must be configured to serve from /absproxy/{port}/. The base path for the absolute proxy can be customized with --abs-proxy-base-path.
GET /api/v1/code/proxy/{port}/{path}
Section titled “GET /api/v1/code/proxy/{port}/{path}”Forwards the request to http://localhost:{port}{path}, stripping the /proxy/{port} prefix.
For example, an app on port 3000 reachable at http://localhost:3000/api/users becomes https://{projectId}-{containerId}-code-1.{server}.containers.hoody.icu/proxy/3000/api/users.
curl -X GET "https://acme-prod-cnt42-code-1.us-east.containers.hoody.icu/api/v1/code/proxy/3000/api/users" \ -H "Cookie: session=<session_token>"import { HoodyClient } from "hoody-sdk";
const client = new HoodyClient({ token: process.env.HOODY_TOKEN });
await client.code.proxy.resolve(3000, "api/users");Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
port | path | integer | Yes | Local port to proxy to. Must be in the range 1024–65535. |
path | path | string | Yes | Path to append to the proxied request. The /proxy/{port} prefix is stripped before forwarding. |
Response
Section titled “Response”Returns the proxied response from the upstream application, with headers and body forwarded as-is.
Returned when the request is not authenticated.
| Error Code | Title | Description | Resolution |
|---|---|---|---|
AUTHENTICATION_REQUIRED | Authentication required | You must be logged in to access proxied ports | Log in with your password first |
Returned when the upstream port is not reachable.
| Error Code | Title | Description | Resolution |
|---|---|---|---|
PORT_UNREACHABLE | Cannot connect to local port | The specified port is not accessible or no service is running | Verify the application is running on the specified port |
GET /api/v1/code/absproxy/{port}/{path}
Section titled “GET /api/v1/code/absproxy/{port}/{path}”Forwards the request to http://localhost:{port} while preserving the full incoming path, including /absproxy/{port}/. Use this when the proxied application is aware of the subpath and is configured to serve from /absproxy/{port}/.
curl -X GET "https://acme-prod-cnt42-code-1.us-east.containers.hoody.icu/api/v1/code/absproxy/8080/dashboard/overview" \ -H "Cookie: session=<session_token>"import { HoodyClient } from "hoody-sdk";
const client = new HoodyClient({ token: process.env.HOODY_TOKEN });
await client.code.proxy.resolveAbsolute(8080, "dashboard/overview");Parameters
Section titled “Parameters”| Name | In | Type | Required | Description |
|---|---|---|---|---|
port | path | integer | Yes | Local port to proxy to. |
path | path | string | Yes | Path (preserved in forwarded request). |
Response
Section titled “Response”Returns the proxied response from the upstream application, with the full /absproxy/{port}/{path} URL preserved.
Unauthorized. The request is missing or has an invalid session cookie.
Bad gateway. The upstream port is not reachable or no service is listening on it.