|
Important
|
flowkit itself makes zero network calls. This document does not describe an API the
kit requires — it specifies the API surface a backend should expose to drive a
full-featured builder, and how each endpoint maps to a config hook. Everything here is
implemented consumer-side through the |
| Endpoint | Required | Feeds config hook | Purpose |
|---|---|---|---|
|
yes |
|
The node registry: all palette entries as |
|
no |
|
Node icon images (SVG/PNG). Alternative: ship icons inline in schemas or render React nodes. |
|
no |
|
Dynamic option lists for |
|
no |
|
Flow document persistence. localStorage or files work too. |
|
no |
consumer save flow |
Optimistic-concurrency check before overwrite. |
|
no |
|
Credential records for the |
A minimal backend is exactly one endpoint (GET /nodes) — or zero, if schemas are
static (see the playground demos). Everything else layers on as needed.
The single most important endpoint: it defines what users can build.
GET /api/v1/nodes?client=agentflowv2Query parameters (consumer-defined; Flowise’s):
| Param | Meaning |
|---|---|
|
Which builder generation the schemas target ( |
[
{
"name": "llmAgentflow",
"label": "LLM",
"version": 1,
"category": "Agent Flows",
"description": "Large language model node",
"badge": "NEW",
"color": "#64B5F6",
"icon": "https://cdn.example.com/icons/llm.svg",
"baseClasses": ["LLMAgentflow"],
"inputs": [
{ "label": "Model", "name": "llmModel", "type": "asyncOptions", "loadMethod": "listModels" },
{ "label": "Messages", "name": "llmMessages", "type": "array",
"array": [
{ "label": "Role", "name": "role", "type": "options",
"options": [ { "label": "System", "name": "system" }, { "label": "User", "name": "user" } ] },
{ "label": "Content", "name": "content", "type": "string", "rows": 3, "acceptVariable": true }
]
},
{ "label": "Enable Memory", "name": "llmEnableMemory", "type": "boolean", "default": true, "optional": true },
{ "label": "Memory Type", "name": "llmMemoryType", "type": "options", "optional": true,
"options": [ { "label": "All Messages", "name": "allMessages" } ],
"show": { "llmEnableMemory": true } }
],
"credential": { "label": "Credential", "name": "credential", "type": "credential",
"credentialNames": ["openAIApi", "azureOpenAIApi"] },
"outputs": [ { "name": "0", "label": "Output" } ]
}
]Field-by-field rules for the schema: see BuilderNodeSchema spec. Backend notes:
-
version— bump it when the schema changes incompatibly; the UI can then flag outdated canvas nodes (config.resolveNodeWarning) and offer a sync. -
badge—NEW/DEPRECATINGrender as palette chips;DEPRECATINGplusdeprecateMessagedrives the node warning badge. -
type(not shown above) — reserved hint for the canvas node type. Flowise usesIteration(group node) andStickyNote(annotation). Map it viaconfig.resolveNodeType. -
Keep the payload JSON-serializable and self-contained — the UI stores a snapshot of the schema inside the saved flow document.
GET /api/v1/node-icon/{name} → image/svg+xml | image/png-
Consumed by
registry.renderIcon()(palette rows, node cards, summary chips). -
Return 404 for unknown names; the UI falls back to a colored dot.
-
Alternatives that need no endpoint: put a URL in
schema.icon, or return JSX fromregistry.renderIcon(e.g. an emoji span or an icon-font component — the pipeline demo does exactly this).
Params typed asyncOptions / asyncMultiOptions declare a loadMethod; the UI asks
the backend to resolve them at render time (e.g. "list available models for this
credential"). Kit side: config.asyncOptionsFetcher wraps this endpoint.
POST /api/v1/node-load-method/{nodeName}
Content-Type: application/json{nodeName} is the schema name (e.g. llmAgentflow). Body:
{
"name": "llmAgentflow",
"label": "LLM 0",
"id": "llmAgentflow_0",
"inputs": { "llmEnableMemory": true, "credential": "c9f1..." },
"credential": "c9f1...",
"loadMethod": "listModels",
"previousNodes": [
{ "id": "startAgentflow_0", "name": "startAgentflow", "label": "Start", "inputs": {} }
],
"currentNode": { "id": "llmAgentflow_0", "name": "llmAgentflow", "label": "LLM 0", "inputs": { } }
}| Field | Meaning |
|---|---|
|
The full canvas node data (schema snapshot + current input values) — lets the backend tailor options to the node’s current configuration. |
|
The method the param asked for ( |
|
Resolved credential id, if the node has one (from |
|
Upstream nodes reachable from this node (id/name/label/inputs) — needed for options like "pick a variable from an earlier node". |
|
This node’s id/name/label/inputs. |
[
{ "label": "gpt-4o", "name": "gpt-4o", "description": "Flagship, most capable" },
{ "label": "gpt-4o-mini", "name": "gpt-4o-mini", "description": "Fast and cheap", "imageSrc": "https://.../openai.svg" }
]Option fields: label (display), name (stored value), optional description,
optional imageSrc (rewritten by the consumer’s resolveImageSrc, e.g. to the
node-icon endpoint). An empty array means "no options" — the UI shows the empty list;
fetch failures should also resolve to [] (the field surfaces an error state).
A flow document is the JSON produced by config.serialize — by default React Flow’s
toObject(): { nodes, edges, viewport } where each node embeds its full
BuilderNodeData (schema snapshot + inputs value map). Spec:
FlowDocument.
GET /api/v1/flows/{id} → 200 { "id": "...", "name": "...", "flowData": "<json string>", "updatedDate": "..." }
POST /api/v1/flows → 201 { "id": "..." } body: { "name": "...", "flowData": "<json string>", ... }
PUT /api/v1/flows/{id} → 200 body: { "name": "...", "flowData": "<json string>" }Backend/consumer contract points:
-
flowDatais stored opaque — the backend never parses it. Treat it as a blob (Flowise stores the JSON string in a text column). -
The consumer typically loads on mount (
initialFlowvialoadFlow) and saves viauseFlowBuilder().saveFlow()→config.onSave(doc). -
Flowise’s reference adds metadata columns (
type,deployed,isPublic,workspaceId,apikeyid) — all outside the kit’s concern.
GET /api/v1/flows/{id}/has-changed/{lastUpdatedDateTime} → 200 { "hasChanged": true | false }Called before overwriting a flow the user has had open for a while. If hasChanged,
the consumer shows a confirm ("overwrite changes made elsewhere?"). Kit angle: none —
this lives entirely in the consumer’s save orchestration (the Flowise adapter’s
handleSaveFlow).
Flowise’s credential param type renders a select of stored credentials and stores
the chosen id in data.credential (hoisted out of inputs at serialize time). Its
endpoints are purely domain: GET /credentials, GET /credentials-by-name/{name}, etc.
The kit ships no credential UI — consumers register a fieldRenderers.credential
renderer (the Flowise adapter wraps its CredentialInputHandler).
For comparison, the Flowise server (packages/server) implements:
| This spec | Flowise endpoint |
|---|---|
Node registry |
|
Node detail |
|
Nodes by category |
|
Icons |
|
Async options |
|
Custom JS eval (expand dialog "Execute") |
|
Flow CRUD |
|
Concurrency |
|
AI flow generation |
|
-
❏ Registry returns valid
BuilderNodeSchema[](validate against node-model). -
❏ Unknown/legacy schema fields allowed — the UI tolerates extras (schemas carry an index signature).
-
❏ Options endpoints return
[](not 4xx/5xx) for empty results where possible; the UI degrades gracefully. -
❏ Version bumps on incompatible schema changes;
DEPRECATINGbadge +deprecateMessagewhen sunsetting a node. -
❏ Persist
flowDataopaque; returnupdatedDatefor concurrency checks. -
❏ CORS/credentials: the UI client sends cookies (
withCredentials) in the Flowise adapter — mirror if your builder is session-based.