Skip to content

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

MethodPathAuthPurpose
GET/api/healthLiveness probe. Returns { "status": "ok" }.

Plugin categories

MethodPathAuthPurpose
GET/api/plugin-categoriestokenThe category vocabulary (id, labelKey, icon) used by the marketplace UI.

Plugin runtime

Descriptor access and worker invocation for installed plugins.

MethodPathAuthPurpose
GET/api/plugin-runtimetokenEnabled plugins as InstalledPluginDescriptor[].
POST/api/plugin-runtime/{id}/invoketokenInvoke 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}/canceltokenInterrupt a tracked invocation. Returns {cancelled}; cancelling a Worker call tears down that Worker so a stuck handler cannot continue.
GET/api/plugin-runtime/{id}/logstokenRecent Worker events as {timestamp, level, logger, thread, message, sequence}; legacy stderr has null logger/thread.
GET/api/plugin-runtime/{id}/logs/streamtokenReplay 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.

MethodPathAuthPurpose
POST/api/plugin-runtime/{id}/files/uploadtoken + files.readUpload a single file (multipart file) → FileRef snapshotted into temp.
POST/api/plugin-runtime/{id}/files/upload-directorytoken + 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/nativetoken + files.read and/or files.writeWrap a native OS path (body {path, kind, access}) as a FileRef. Desktop only.
POST/api/plugin-runtime/{id}/files/outputtoken + files.writeAllocate a fresh writable output directory → FileRef.
GET/api/plugin-runtime/{id}/files/export/{ref}token + files.writeStream a zip of the granted directory for download.

Marketplace

Plugin registry and lifecycle. Base /api/plugin-market. See Marketplace.

MethodPathAuthPurpose
GET/api/plugin-markettokenBrowse the catalog → MarketplacePlugin[].
POST/api/plugin-market/uploadtokenInstall from an uploaded .fyp (multipart). Same id as an installed plugin → replaces it (update).
POST/api/plugin-market/upload-nativetokenInstall from a local filesystem path (body {path}). Desktop only.
POST/api/plugin-market/inspecttokenRead an uploaded .fyp's manifest without installing → PackageInspection (install-vs-update + version step).
POST/api/plugin-market/inspect-nativetokenPath-based twin of /inspect (body {path}). Desktop only.
POST/api/plugin-market/{id}/installtokenInstall a catalog plugin by id.
POST/api/plugin-market/{id}/updatetokenUpdate an installed plugin to the catalog's latest.
PATCH/api/plugin-market/{id}/enabledtokenToggle enabled. Body {enabled}. Disabling stops the worker immediately.
DELETE/api/plugin-market/{id}?deleteData=<boolean>tokenUninstall with an explicit runtime-data retain/delete policy. Retain also preserves the provisioned DB namespace.

Settings

User-facing preferences. See Configuration — User settings.

MethodPathAuthPurpose
GET/api/settingstokenRead {theme, language, sidebarCollapsed, logLevel, computerUseEnabled, computerUse}.
PUT/api/settingstokenPartial update of user settings; logLevel applies live to the host and Java Workers, computerUseEnabled toggles the desktop computer_* tools.
POST/api/settings/database/resettokenBack up datasource.properties, clear it, restart into SETUP mode.

AI

Chat invocation and the streaming endpoint. See AI Chat.

MethodPathAuthPurpose
POST/api/ai/chattokenStart 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=tokenSSE stream for the chat turn. See SSE Events — Chat.

AI config

Backend selection and API keys, with hot-swap. See Configuration — AI config.

MethodPathAuthPurpose
GET/api/ai/configtokenMasked config snapshot (API keys masked with ***).
PUT/api/ai/configtokenPartial update; hot-swaps the active backend without restart.
POST/api/ai/config/testtokenProbe a connection without saving. Body {mode, endpoint, apiKey, model, baseUrl}.

Conversations

Persisted chat history. See AI Chat — Conversations.

MethodPathAuthPurpose
GET/api/ai/conversationstokenConversation summaries, newest first.
GET/api/ai/conversations/{id}tokenA single conversation (title + messages).
POST/api/ai/conversationstokenCreate. Body {title, messages} → created conversation with id.
PUT/api/ai/conversations/{id}tokenFull replace of title + messages. Body {title, messages}.
DELETE/api/ai/conversations/{id}tokenRemove a conversation.

Agent

The plan-and-execute agent. See AI Agent.

MethodPathAuthPurpose
POST/api/agent/runtokenStart a run. Body {goal, config}{runId}.
POST/api/agent/batchtokenStart 1–8 independent runs concurrently. Body {goals, config}{runIds}.
GET/api/agent/stream?runId=tokenSSE stream for the run. See SSE Events — Agent.
POST/api/agent/{runId}/approvetokenRelease an approval gate. Optional edited AgentPlan body.
POST/api/agent/{runId}/canceltokenCooperatively cancel the run.
GET/api/agent/toolstokenOrchestrable tool list (host-aggregated ToolCallback[]).
GET/api/agent/runstokenPersisted run summaries, newest first.
GET/api/agent/runs/{runId}tokenPersisted plan, executions, and ordered audit events.
POST/api/agent/runs/{runId}/resumetokenResume unfinished steps from a failed/cancelled run and require plan review.
GET/api/mcp/statustokenConfigured MCP connections and discovered tool count.
GET/api/mcp/serverstokenList dynamically managed MCP servers, connection state, and discovered tool names.
POST/api/mcp/serverstokenAdd 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}tokenReplace a server definition, close the old session, reconnect, and refresh the live AI tool catalog.
DELETE/api/mcp/servers/{id}tokenDisconnect and remove a dynamically managed server.
POST/api/mcp/servers/{id}/testtokenReconnect and perform MCP initialization plus tools/list.
POST/api/mcp/servers/{id}/calltokenDirectly call a discovered MCP tool. Body {tool, arguments}.
GET/api/mcp/servers/{id}/promptstokenList prompts exposed by the live MCP session.
GET/api/mcp/servers/{id}/resourcestokenList 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.

MethodPathAuthPurpose
GET/api/workflowstokenList the current user's workflow definitions.
GET/api/workflows/{workflowId}tokenRead one definition.
POST/api/workflowstokenCreate from {name, description, inputSchema, plan, layout?, graph?}.
PUT/api/workflows/{workflowId}tokenReplace the editable definition and increment its revision.
POST/api/workflows/{workflowId}/publishtokenSet publication with {published}; published workflows become AI tools.
DELETE/api/workflows/{workflowId}tokenDelete a definition.
POST/api/workflows/{workflowId}/runtokenManually 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.

MethodPathAuthPurpose
POST/api/notificationstokenCreate + 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=tokenNewest-first history (capped at 100 per call).
GET/api/notifications/unread-counttokenBadge counter.
POST/api/notifications/{id}/readtokenAcknowledge one (idempotent).
POST/api/notifications/read-alltokenAcknowledge everything.
DELETE/api/notifications/{id}tokenRemove one from the center.
POST/api/notifications/stream-tickettokenMint the one-time ticket the SSE stream redeems.
GET/api/notifications/stream?ticket=ticketLive 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.

MethodPathAuthPurpose
GET/api/setup/status{initialized, supportedTypes[], embeddedTypes[]}.
GET/api/setup/typesPer-backend form metadata for the wizard.
POST/api/setup/test-connectionProbe a connection without persisting. Body {type, params}.
POST/api/setup/initializeRe-test, persist config, signal restart into APP mode. Body {type, params}.
DELETE/api/setup/configBack up config, clear it, restart into SETUP mode.

Conventions

  • Content type for JSON bodies is application/json; file uploads use multipart/form-data.
  • Errors use standard HTTP status codes. A 403 from a file endpoint means a missing permission; a 401/403 elsewhere means a missing or mismatched token.
  • SSE frames are named after their event type and carry a JSON data payload. Both stream endpoints emit a :connected comment heartbeat as the first frame.

Next steps

Released under the GPL-3.0 License.