Skip to main content

Core API & WebSocket proxy

The Supervisor proxies Core API traffic so that apps can talk to the Core runtime without knowing its address or holding a Core token. The canonical prefix is /core; the v1 tree also mirrors every route at the legacy /apexos prefix.

MethodPathDescription
GET/core/websocketWebSocket proxy to the Core WebSocket API
GET/core/api/websocketSame handler, alternate path
GET/core/api/streamProxy the Core event stream (long-lived)
GET / POST / DELETE/core/api/{path}Proxy an arbitrary Core REST call
GET/core/api/Proxy the Core API root

Only GET, POST, and DELETE are registered for the REST proxy — PUT and PATCH are not proxied.

Authentication

On the v1 tree these paths are exempt from the Supervisor's token middleware; the proxy performs its own check instead:

  • REST/stream: the token is taken from Authorization: Bearer ... (or a legacy access header) and must belong to an installed app that declares Core API access (apexos_api). Anything else gets 401.
  • On the /v2 tree the paths are not exempt: the standard middleware requires a token whose role grants /core/* (role apexos or higher) before the proxy's own check runs.

/core/api/supervisor/* (and the /apexos equivalent) is blocked outright with 403 — the proxy cannot be used to reach a Supervisor passthrough on the Core side.

All proxy calls fail with 502 Bad Gateway when the Core API is not up.

REST proxying details

  • Request query string, body, and content type are forwarded; only a small header allowlist is passed through (Accept, Last-Event-ID, Mcp-Session-Id, MCP-Protocol-Version, X-Speech-Content).
  • Responses with content type text/event-stream (e.g. SSE endpoints) are streamed back unbuffered, preserving Cache-Control and Mcp-Session-Id.
  • Other responses are relayed with their upstream status and content type.
  • The default upstream timeout is 300 seconds; /core/api/stream has no timeout.

WebSocket proxy

GET /core/websocket performs a Core-style auth handshake with the connecting app, then bridges frames in both directions:

  1. Server sends {"type": "auth_required", "apexos_version": "<core version>"}.
  2. Client must reply within 10 seconds with a message containing its Supervisor token in access_token (or the legacy api_password field).
  3. The token must belong to an installed app with Core API access; otherwise the server sends {"type": "auth_invalid", "message": "Invalid access"} and closes.
  4. On success the server sends {"type": "auth_ok", "apexos_version": "<core version>"} and opens a client connection to the Core WebSocket API.

After the handshake, text and binary frames are forwarded verbatim in both directions with a 30-second heartbeat; when either side closes, the other side is closed too.

:::info Legacy field The frames also carry ha_version, a deprecated duplicate of apexos_version kept for older client libraries. :::