REST API
The Infinia backend is a headless Spring Boot application that exposes a REST + SSE API over loopback (server.address=127.0.0.1). The default port is 24056; if it is taken the launcher falls back to an OS-assigned port and announces it as FENGYU_PORT=<n> on stdout. See Backend.
Authentication
Every request passes through TokenAuthFilter, which compares the X-FengYu-Token header to the value supplied via --token at launch. Three path prefixes bypass the filter so the system can bootstrap without a credential:
/api/health— liveness probe./api/setup/*— first-launch wizard (the token may not exist yet)./plugin-runtime/{id}/**— static plugin UI assets, served under a strict CSP.
All other endpoints require a matching token. In the tables below, the Auth column is token (header required), — (no token, bypassed), ticket (a one-time ?ticket= from the matching stream-ticket endpoint — for SSE, which cannot set headers), or a permission name (token plus a plugin permission).
TIP
The SSE streams do not accept the token as a ?token= query parameter. Mint a one-time ticket first (POST /api/ai/stream-ticket, /api/agent/stream-ticket, or /api/notifications/stream-ticket), then open the stream with ?ticket= (plus ?streamId= or ?runId= where applicable). See SSE Events.
Health
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/health | — | Liveness probe. Returns { "status": "ok" }. |
Plugin categories
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/plugin-categories | token | The category vocabulary (id, labelKey, icon) used by the marketplace UI. |
Plugin runtime
Descriptor access and worker invocation for installed plugins.
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/plugin-runtime | token | Enabled plugins as InstalledPluginDescriptor[]. |
POST | /api/plugin-runtime/{id}/invoke | token | Invoke a worker method. Body {callId, method, params} → JSON-RPC result. callId is the protocol correlation id. See Worker. |
POST | /api/plugin-runtime/{id}/invoke/{callId}/cancel | token | Interrupt a tracked invocation. Returns {cancelled}; cancelling a Worker call tears down that Worker so a stuck handler cannot continue. |
GET | /api/plugin-runtime/{id}/logs | token | Recent Worker events as {timestamp, level, logger, thread, message, sequence}; legacy stderr has null logger/thread. |
GET | /api/plugin-runtime/{id}/logs/stream | token | Replay recent Worker events, then stream new events over SSE. |
GET | /plugin-runtime/{id}/** | — | Plugin UI static assets (entry HTML + JS), served under a strict CSP. |
Plugin files
File grant endpoints for sandboxed plugins. All live under base /api/plugin-runtime/{id}/files. Each is gated by a permission declared in the plugin manifest. See File I/O.
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST | /api/plugin-runtime/{id}/files/upload | token + files.read | Upload a single file (multipart file) → FileRef snapshotted into temp. |
POST | /api/plugin-runtime/{id}/files/upload-directory | token + files.read (+ files.write for read-write) | Upload a tree (multipart files + paths[], optional access=read-write) → directory FileRef. |
POST | /api/plugin-runtime/{id}/files/native | token + files.read and/or files.write | Wrap a native OS path (body {path, kind, access}) as a FileRef. Desktop only. |
POST | /api/plugin-runtime/{id}/files/output | token + files.write | Allocate a fresh writable output directory → FileRef. |
GET | /api/plugin-runtime/{id}/files/export/{ref} | token + files.write | Stream a zip of the granted directory for download. |
Marketplace
Plugin registry and lifecycle. Base /api/plugin-market. See Marketplace.
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/plugin-market | token | Browse the catalog → MarketplacePlugin[]. |
POST | /api/plugin-market/upload | token | Install from an uploaded .fyp (multipart). Same id as an installed plugin → replaces it (update). |
POST | /api/plugin-market/upload-native | token | Install from a local filesystem path (body {path}). Desktop only. |
POST | /api/plugin-market/inspect | token | Read an uploaded .fyp's manifest without installing → PackageInspection (install-vs-update + version step). |
POST | /api/plugin-market/inspect-native | token | Path-based twin of /inspect (body {path}). Desktop only. |
POST | /api/plugin-market/{id}/install | token | Install a catalog plugin by id. |
POST | /api/plugin-market/{id}/update | token | Update an installed plugin to the catalog's latest. |
PATCH | /api/plugin-market/{id}/enabled | token | Toggle enabled. Body {enabled}. Disabling stops the worker immediately. |
DELETE | /api/plugin-market/{id}?deleteData=<boolean> | token | Uninstall with an explicit runtime-data retain/delete policy. Retain also preserves the provisioned DB namespace. |
Settings
User-facing preferences. See Configuration — User settings.
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/settings | token | Read {theme, language, sidebarCollapsed, logLevel, computerUseEnabled, computerUse}. |
PUT | /api/settings | token | Partial update of user settings; logLevel applies live to the host and Java Workers, computerUseEnabled toggles the desktop computer_* tools. |
POST | /api/settings/database/reset | token | Back up datasource.properties, clear it, restart into SETUP mode. |
AI
Chat invocation and the streaming endpoint. See AI Chat.
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST | /api/ai/chat | token | Start a chat turn. Body {messages:[{role, content}], permissionMode?, workflowId?} → {streamId}. A workflowId binds the turn to that flow (draft or published): the model receives it as the run_current_flow tool inside the ordinary chat tool-call loop. |
GET | /api/ai/stream?streamId= | token | SSE stream for the chat turn. See SSE Events — Chat. |
AI config
Backend selection and API keys, with hot-swap. See Configuration — AI config.
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/ai/config | token | Masked config snapshot (API keys masked with ***). |
PUT | /api/ai/config | token | Partial update; hot-swaps the active backend without restart. |
POST | /api/ai/config/test | token | Probe a connection without saving. Body {mode, endpoint, apiKey, model, baseUrl}. |
Conversations
Persisted chat history. See AI Chat — Conversations.
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/ai/conversations | token | Conversation summaries, newest first. |
GET | /api/ai/conversations/{id} | token | A single conversation (title + messages). |
POST | /api/ai/conversations | token | Create. Body {title, messages} → created conversation with id. |
PUT | /api/ai/conversations/{id} | token | Full replace of title + messages. Body {title, messages}. |
DELETE | /api/ai/conversations/{id} | token | Remove a conversation. |
Agent
The plan-and-execute agent. See AI Agent.
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST | /api/agent/run | token | Start a run. Body {goal, config} → {runId}. |
POST | /api/agent/batch | token | Start 1–8 independent runs concurrently. Body {goals, config} → {runIds}. |
GET | /api/agent/stream?runId= | token | SSE stream for the run. See SSE Events — Agent. |
POST | /api/agent/{runId}/approve | token | Release an approval gate. Optional edited AgentPlan body. |
POST | /api/agent/{runId}/cancel | token | Cooperatively cancel the run. |
GET | /api/agent/tools | token | Orchestrable tool list (host-aggregated ToolCallback[]). |
GET | /api/agent/runs | token | Persisted run summaries, newest first. |
GET | /api/agent/runs/{runId} | token | Persisted plan, executions, and ordered audit events. |
POST | /api/agent/runs/{runId}/resume | token | Resume unfinished steps from a failed/cancelled run and require plan review. |
GET | /api/mcp/status | token | Configured MCP connections and discovered tool count. |
GET | /api/mcp/servers | token | List dynamically managed MCP servers, connection state, and discovered tool names. |
POST | /api/mcp/servers | token | Add a STDIO, SSE, or STREAMABLE_HTTP server and connect immediately. Credentials are accepted in env/headers and are never returned by the API. |
PUT | /api/mcp/servers/{id} | token | Replace a server definition, close the old session, reconnect, and refresh the live AI tool catalog. |
DELETE | /api/mcp/servers/{id} | token | Disconnect and remove a dynamically managed server. |
POST | /api/mcp/servers/{id}/test | token | Reconnect and perform MCP initialization plus tools/list. |
POST | /api/mcp/servers/{id}/call | token | Directly call a discovered MCP tool. Body {tool, arguments}. |
GET | /api/mcp/servers/{id}/prompts | token | List prompts exposed by the live MCP session. |
GET | /api/mcp/servers/{id}/resources | token | List resources exposed by the live MCP session. |
Workflows
Reusable workflow definitions use the same AgentPlan DAG as the agent runner. inputSchema is a JSON Schema object; runtime inputs bind to {{inputs.name}} placeholders. layout maps compiled step indexes to canvas positions, and graph (optional) stores the authored canvas graph verbatim — {nodes, edges} with sticky-note nodes included — so the flow builder reopens the exact arrangement (definitions without graph reconstruct from plan + layout). Published definitions are added to the live AI tool catalog.
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/workflows | token | List the current user's workflow definitions. |
GET | /api/workflows/{workflowId} | token | Read one definition. |
POST | /api/workflows | token | Create from {name, description, inputSchema, plan, layout?, graph?}. |
PUT | /api/workflows/{workflowId} | token | Replace the editable definition and increment its revision. |
POST | /api/workflows/{workflowId}/publish | token | Set publication with {published}; published workflows become AI tools. |
DELETE | /api/workflows/{workflowId} | token | Delete a definition. |
POST | /api/workflows/{workflowId}/run | token | Manually run with {inputs, config} → {runId}; observe the normal agent SSE stream. |
Notifications
The unified host notification center — persisted rows plus a live SSE fan-out. Producers POST one row; every connected shell receives it live (see SSE Events — Notification stream) and shows an in-app toast or a native OS notification depending on window visibility. Known producers: the plugin notify host bridge and agent run termination. History is kept newest-first with a 200-row retention window per install.
| Method | Path | Auth | Purpose |
|---|---|---|---|
POST | /api/notifications | token | Create + broadcast. Body {source, level, title, body?, link?} → the created view. level is info\|success\|warning\|error; source names the originator (host, agent, plugin:<id>). |
GET | /api/notifications?limit=&unreadOnly= | token | Newest-first history (capped at 100 per call). |
GET | /api/notifications/unread-count | token | Badge counter. |
POST | /api/notifications/{id}/read | token | Acknowledge one (idempotent). |
POST | /api/notifications/read-all | token | Acknowledge everything. |
DELETE | /api/notifications/{id} | token | Remove one from the center. |
POST | /api/notifications/stream-ticket | token | Mint the one-time ticket the SSE stream redeems. |
GET | /api/notifications/stream?ticket= | ticket | Live notification events to every connected shell. |
Setup
First-launch wizard. All endpoints bypass the token filter and exist only in SETUP mode. See Database — Setup endpoints.
| Method | Path | Auth | Purpose |
|---|---|---|---|
GET | /api/setup/status | — | {initialized, supportedTypes[], embeddedTypes[]}. |
GET | /api/setup/types | — | Per-backend form metadata for the wizard. |
POST | /api/setup/test-connection | — | Probe a connection without persisting. Body {type, params}. |
POST | /api/setup/initialize | — | Re-test, persist config, signal restart into APP mode. Body {type, params}. |
DELETE | /api/setup/config | — | Back up config, clear it, restart into SETUP mode. |
Conventions
- Content type for JSON bodies is
application/json; file uploads usemultipart/form-data. - Errors use standard HTTP status codes. A
403from a file endpoint means a missing permission; a401/403elsewhere means a missing or mismatched token. - SSE frames are named after their event type and carry a JSON
datapayload. Both stream endpoints emit a:connectedcomment heartbeat as the first frame.
Next steps
- SSE Events — the full chat and agent stream taxonomy.
- Architecture — Backend — the launcher, port announcement, and SETUP vs APP mode.
- Guide — Configuration — worked examples for settings and AI config.