Kolbo.AIKolbo.AI Docs
Developer API

Flow Builder

Read, edit, estimate and run Flow Builder canvases through the API.

A Flow is a Flow Builder canvas: nodes (inputs, generation steps, editing steps, notes, groups) connected by edges. The API reads and edits the same saved canvas the app shows, and runs it on the server with a credit ceiling you set. Open editor_url from any response to see the canvas in the app.

Endpoints

GET   /api/v1/flows/schema                         node catalog, writable fields and limits (?node_type=)
GET   /api/v1/flows?project_id=...                 list Flows in a project
POST  /api/v1/flows                                create a Flow
GET   /api/v1/flows/:flowId                        read a Flow
PATCH /api/v1/flows/:flowId                        apply edit operations
POST  /api/v1/flows/:flowId/validate               validate the saved graph
POST  /api/v1/flows/:flowId/undo                   undo one of your edits
POST  /api/v1/flows/:flowId/duplicate              copy a Flow
POST  /api/v1/flows/:flowId/move                   move to another project
POST  /api/v1/flows/:flowId/trash                  move to trash
POST  /api/v1/flows/:flowId/restore                restore from trash
POST  /api/v1/flows/:flowId/snapshot               replace the whole graph (canvas save)
POST  /api/v1/flows/:flowId/estimate               free credit quote
POST  /api/v1/flows/:flowId/runs                   start a run
GET   /api/v1/flows/:flowId/runs                   list runs
GET   /api/v1/flows/:flowId/runs/:runId            read a run
POST  /api/v1/flows/:flowId/runs/:runId/cancel     cancel a run
POST  /api/v1/flows/:flowId/runs/:runId/retry      retry failed nodes of a run

Responses use { "status": true, "data": { ... } }. Errors use { "status": false, "code": "...", "message": "..." } (some add details) and default to HTTP 400. Every write and every run action (create, edit, snapshot, undo, duplicate, move, trash, restore, start, cancel and retry a run) needs a write-enabled API key — a key without write, including an older grandfathered one, gets 403 FORBIDDEN. Reads, validate and estimate work with any key. The routes share a limit of 180 requests per minute per account, counting every request; a limited request receives the plain-text body Too many requests, please try again later. Access follows the Flow's project: reading needs view access, editing needs edit access, and removing nodes, undoing, trashing or moving needs delete access. A request body may not exceed 2 MB.

The Flow object

Reads and writes return:

FieldNotes
flow_session_id, project_id, nameIdentity
revisionString. Send it back as expected_revision on every write and run
schema_versionGraph schema version
instructionsSession instructions (up to 10,000 characters)
flow_data{ nodes, edges }. Omitted in list results. Each node keeps only its latest run unless you read with include_history=true
isPinned, isArchived, isLocked, deletedState flags
editor_urlOpens the canvas in the Kolbo web app
updated_atTimestamp

Writes also return operation_id (keep it to undo), created_node_ids, deleted_node_ids, changed_node_ids and changed.

List, read and create

  • GET /api/v1/flows requires project_id. Optional: limit (1–100, default 25), offset, query (name search), include_archived, is_archived, include_trashed. Returns data: { sessions, has_more, offset, limit }.
  • GET /api/v1/flows/:flowId accepts include_history=true, include_trashed=true, node_ids=a,b (only those nodes and their edges) and project_id (returns 403 PROJECT_MISMATCH if the Flow lives elsewhere).
  • POST /api/v1/flows takes project_id and idempotency_key (required), plus optional name (1–200 characters, default New Flow), instructions and flow_data. Repeating the key with the same body returns the existing Flow with replayed: true; a different body returns 409 IDEMPOTENCY_CONFLICT.

Read GET /api/v1/flows/schema before building nodes. It lists every node type with its handles and default config, the allowed node and config fields, and the limits: 500 nodes, 2,500 edges, 200 operations per request and a 2 MB graph.

Edit

Every write takes expected_revision (the revision you last read) and an idempotency_key of 8–100 letters, digits, hyphens or underscores. A stale revision returns 409 REVISION_CONFLICT: read the Flow again and reapply the edit. A locked Flow returns 409 SESSION_LOCKED.

PATCH /api/v1/flows/:flowId

{
  "expected_revision": "7",
  "idempotency_key": "edit-0001",
  "operations": [
    { "op": "node.add", "node_id": "text1", "type": "text-input", "fields": { "position": { "x": 0, "y": 0 }, "text": "A red bicycle on a beach" } },
    { "op": "node.add", "node_id": "img1", "type": "image-generation", "fields": { "position": { "x": 420, "y": 0 } } },
    { "op": "edge.add", "source": "text1", "target": "img1", "source_handle": "text-output", "target_handle": "text-input" }
  ]
}

Send 1–200 operations, applied in order as one change. Add "dry_run": true to validate without saving.

opFields
node.addtype, optional node_id, fields
node.update, group.updatenode_id, fields, optional unset (field names to remove)
node.removenode_id (also removes its edges)
edge.addsource, target, source_handle, target_handle, optional edge_id
edge.updateedge_id, fields (source, target, sourceHandle, targetHandle, label)
edge.removeedge_id
nodes.duplicatenode_ids, optional offset { x, y } (default 80, 80)
input.reordernode_id, handle, edge_ids (every edge into that handle, once each)
group.createoptional node_id, node_ids, fields
group.set_membersnode_id, node_ids
group.removenode_id (members stay)
layout.applyoptional node_ids (default all)
session.updatefields: name, instructions, isPinned, isArchived
output.selectnode_id, run_id, index, optional handle: choose which completed output a node passes on

fields patch a node: omitted fields stay, config keys merge and arrays replace. Unknown fields, incompatible connections (INCOMPATIBLE_PORT), cycles (GRAPH_CYCLE) and unknown models (MODEL_NOT_FOUND) are rejected. Media referenced by URL must be http(s), and media-library items must be accessible to you (MEDIA_FORBIDDEN, MEDIA_NOT_FOUND).

Other writes:

RouteBody
undoexpected_revision, idempotency_key, operation_id of your own most recent edit. Fails with 409 REVISION_CONFLICT if later edits exist, 404 UNDO_UNAVAILABLE if the receipt is gone. Runtime results are kept
duplicateidempotency_key, optional project_id and name (default <name> (copy)). Run results are not copied
moveexpected_revision, idempotency_key, project_id (you need create access there)
trash, restoreexpected_revision, idempotency_key
snapshotexpected_revision, idempotency_key, flow_data, optional name. Replaces the whole editable graph

Moving or trashing a Flow with an active run returns 409 RUN_STATE_CONFLICT. validate returns data: { valid, node_count, edge_count, warnings, revision }.

Estimate and run

POST /api/v1/flows/:flowId/estimate is free:

FieldNotes
expected_revisionRequired
scopeall (default), selected or downstream (the selected nodes plus everything after them)
node_idsThe nodes for selected / downstream
prerequisitesreuse (default: use upstream outputs already selected) or run_missing (also run upstream nodes that have no output yet)

It returns data: { total_credits, known_credits, provisional, requires_max_credits, nodes }. Each entry in nodes has node_id, credits and provisional. total_credits is null when a node is only priced at admission (Smart Select, token-priced assistant steps, or steps priced by a source's length).

POST /api/v1/flows/:flowId/runs takes the same fields plus:

FieldNotes
idempotency_keyRequired. 8–128 characters of letters, digits, _, ., : or -. The same key and body returns the original run; a different body returns 409 IDEMPOTENCY_CONFLICT
max_creditsThe most the run may spend. Required (positive, up to 1,000,000) whenever any selected node costs credits (400 MAX_CREDITS_REQUIRED). A quote above it returns 402 FLOW_CREDIT_CEILING

A run snapshots the graph at expected_revision, so later edits do not change it. A node type that cannot run on the server returns NODE_EXECUTION_UNSUPPORTED; an upstream node with no output returns INPUT_MISSING (use prerequisites: "run_missing"). A locked Flow returns 409 FLOW_LOCKED.

The run object

FieldNotes
run_id, flow_session_id, project_id, actor_id, revision, parent_run_idIdentity
statusqueued, running, cancel_requested, completed, failed, cancelled or needs_attention
max_credits, admitted_creditsCeiling and credits admitted so far
nodesPer node: node_id, status, attempt, outputs (keyed by output handle), error, generation_id, progress, cancellation, started_at, finished_at
created_at, finished_atTimestamps

Poll GET /api/v1/flows/:flowId/runs/:runId until status is completed, failed, cancelled or needs_attention. GET /api/v1/flows/:flowId/runs lists runs with limit (1–100, default 20), offset and before (a date); it returns runs, offset, limit, has_more and next_offset.

  • Cancel (.../cancel): optional node_ids (default all). Only the user who started the run can cancel it. Returns the run with status: "cancel_requested".
  • Retry (.../retry): a new idempotency_key, optional node_ids (only failed, cancelled or blocked nodes) and max_credits (defaults to the original run's). Only terminal runs can be retried (409 RUN_STATE_CONFLICT), and only while the Flow is still at the run's revision (409 REVISION_CONFLICT); to run edited nodes, start a new run.

MCP

get_flow_schema, list_flow_sessions, create_flow_session, get_flow_session, update_flow_session, validate_flow_session, duplicate_flow_session, undo_flow_edit, move_flow_session, trash_flow_session, restore_flow_session, estimate_flow_run, run_flow_session, get_flow_run, list_flow_runs, cancel_flow_run and retry_flow_run.