Arrange canvas nodes
import { FloraClient } from '@flora-ai/flora';
const client = new FloraClient({ apiKey: process.env['FLORA_API_KEY'] });
const canva = await client.projects.canvas.arrangeNodes({ workspaceId: '<workspaceId>', projectId: '<projectId>', node_ids: [ 'n7', ],});console.log(canva);curl -X POST 'https://app.flora.ai/api/v1/workspaces/<workspaceId>/projects/<projectId>/canvas/arrange' \ -H 'Authorization: Bearer $FLORA_API_KEY' \ -H 'Content-Type: application/json' \ -d '{ "node_ids": [ "n7" ]}'Lays out nodes with the canvas’s own layout engine — the same Tidy the editor offers — so a caller never has to compute positions by hand. The layout follows edges (sources left of the nodes they feed), stacks unconnected nodes below the flow, and keeps group members inside their frame; a frame’s own size is left as it is. Pass node_ids for the nodes to arrange, or all:true to reorganize the entire canvas, which moves work the user positioned by hand and so should only follow an explicit request; a request with neither is rejected. For an explicit row, column or grid layout without an origin, the block is translated clear of relevant untouched nodes: top-level work for a top-level set, or sibling members for a set inside a field. An explicit origin is authoritative and may collide with untouched work. Tidy retains its flow-layout behavior. Inspect the returned overlaps and choose a clear origin or arrange the relevant work when needed. Unknown ids reject the whole request with a machine-readable ref_not_found per id and nothing moves. Positions are written as one atomic transaction. The revision returned is the same change-detection marker the project graph endpoint reports. Mutating public API requests support an optional Idempotency-Key header for client retries; duplicate keys within two hours return idempotency_duplicate.
Error responses use the standard error body.
Authorizations
Section titled “Authorizations ”Parameters
Section titled “ Parameters ”Path Parameters
Section titled “Path Parameters ”Workspace identifier
Workspace identifier
Project identifier
Project identifier
Request Body required
Section titled “Request Body required ”object
Nodes to lay out, addressed by the short id or node UUID the project graph endpoint reports. Up to 500 per request. With layout, this is also the placement order.
Place the nodes in a row, a column, or a grid instead of the edge-following Tidy layout. Each cell is as wide as the widest node in its column and as tall as the tallest node in its row, so mixed sizes stay aligned and never overlap each other. The nodes must all sit at the top level of the canvas or all be direct members of the same group; a mixed set is rejected, and so is a label pinned to a node, which follows its host. Members are laid out from their frame’s padded corner and the frame is refit around all of its members in the same write (an explicit origin inside the frame only grows it; the exact frame anchor aliases its padded content corner; any other origin above or left of the padded corner is rejected). Nodes outside the set are not moved and are not obstacles, so the response’s overlaps still names anything the block landed on.
object
How to place the nodes: row lays them left to right, column top to bottom, grid row-major with columns per row. Every mode keeps the order of node_ids, so the first id is the leading node.
Nodes per row for mode grid; defaults to the square root of the count, rounded up. Ignored on row and column, which determine it from the mode.
Space between neighbouring nodes in canvas units, between columns and between rows alike. Defaults to 64, the canvas’s own Autoformat grid gap.
Absolute canvas position of the block’s visual top-left corner — where the first node’s box starts painting, not its anchor. Omit to keep the block where the nodes already are (the top-left corner of their current bounding box) or, for group members, to start at the frame’s padded corner. For members of one frame, the exact frame anchor (both coordinates equal its graph position) is an alias for that padded corner; every other explicit origin stays literal.
object
Absolute horizontal canvas coordinate
Absolute vertical canvas coordinate
object
Lay out every node on the canvas. Moves work the user positioned by hand, so pass it only when the user asked for the whole canvas to be reorganized.
Responses
Section titled “ Responses ”Nodes arranged.
object
Project identifier
Project canvas URL
Nodes the layout considered
Nodes whose position changed. Zero means the set was already laid out.
Pairs left too close together: an arranged node and something that cannot move out of its way — a node outside the set, or another created node pinned to a caller-chosen position. WHAT COUNTS AS TOO CLOSE DEPENDS ON THE PASS. A layout reports true geometric intersection — it plans in isolation, so nodes outside it are not obstacles. The collision rescue instead reports anything inside the canvas’s node spacing (320px horizontal, 40px vertical), the same clearance the placer keeps, so a pair it names may still have visible air between them. Either way an empty array is the only clean result, and it is always empty for all:true, which leaves nothing outside the layout.
object
Arranged node’s short id
Short id of the node it conflicts with, which cannot move out of the way: one outside the arranged set, or another created node pinned to a caller-chosen position
How to resolve the collisions. Present only when overlaps is non-empty.
Absolute visual bounding box of the arranged nodes after the layout — painted edges, not anchors — so a follow-up batch can be placed beside or below it (for example at origin y = bounds.y + bounds.height + gap). Reported by the arrange endpoint; absent from the collision rescue a canvas write runs on what it created.
object
Absolute left edge of the arranged block
Absolute top edge of the arranged block
Width of the arranged block
Height of the arranged block
Change-detection marker of the canvas after the layout, identical to the value the project graph endpoint reports
Example
{ "project_id": "prj_abc123", "overlaps": [ { "node_id": "n3", "overlaps_with": "n7" } ], "revision": "4f2c8ab19e3d7c05"}