Skip to main content

MetaForge Gateway (0.1.0)

Download OpenAPI specification:Download

HTTP/WebSocket front door for the MetaForge platform

health

Health Check

Return the aggregated health of the gateway and its dependencies.

Responses

Response samples

Content type
application/json
{
  • "auth_mode": "off",
  • "components": [ ],
  • "status": "healthy",
  • "timestamp": "2019-08-24T14:15:22Z",
  • "uptime_seconds": 0,
  • "version": "0.1.0"
}

approvals

List Approvals

Every approval, normalized. status=decided and all are the audit views.

query Parameters
status
string (Status)
Default: "pending"
Enum: "pending" "decided" "all"
Project Id (string) or Project Id (null) (Project Id)
Kind (string) or Kind (null) (Kind)

Responses

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "unscoped_count": 0
}

Get Approval

path Parameters
approval_id
required
string (Approval Id)

Responses

Response samples

Content type
application/json
{
  • "allowed_decisions": [
    ],
  • "created_at": "string",
  • "deadline": "string",
  • "decidable": false,
  • "decision": {
    },
  • "detail": { },
  • "findings": [
    ],
  • "id": "string",
  • "kind": "gate",
  • "not_decidable_reason": "string",
  • "project_id": "string",
  • "reason_held": "string",
  • "reason_required_for": [
    ],
  • "requested_by": "string",
  • "rework_targets": [
    ],
  • "route": "dashboard",
  • "status": "pending",
  • "summary": "",
  • "title": "string"
}

Decide Approval

Decide an approval of any kind.

The deciding human is the authenticated principal for every kind. A reviewer or approved_by in the body is ignored and logged.

path Parameters
approval_id
required
string (Approval Id)
Request Body schema: application/json
required
decision
required
string (Decision)
Enum: "approve" "reject" "retry" "rework"
reason
string (Reason) <= 2000 characters
Default: ""
to_phase
string (To Phase) <= 200 characters
Default: ""
property name*
additional property
any

Responses

Request samples

Content type
application/json
{
  • "decision": "approve",
  • "reason": "",
  • "to_phase": ""
}

Response samples

Content type
application/json
{
  • "allowed_decisions": [
    ],
  • "created_at": "string",
  • "deadline": "string",
  • "decidable": false,
  • "decision": {
    },
  • "detail": { },
  • "findings": [
    ],
  • "id": "string",
  • "kind": "gate",
  • "not_decidable_reason": "string",
  • "project_id": "string",
  • "reason_held": "string",
  • "reason_required_for": [
    ],
  • "requested_by": "string",
  • "rework_targets": [
    ],
  • "route": "dashboard",
  • "status": "pending",
  • "summary": "",
  • "title": "string"
}

Decide Inline

Record a gate decision a person gave in the MCP client's chat (FORGE-582).

Gates only: a held tool call's inline answer has its own route (/v1/tool-approvals/{id}/resolve). The decision goes through the same service.decide as a dashboard click, so a gate that is not ready still cannot be approved, and retry and rework caps still apply.

path Parameters
approval_id
required
string (Approval Id)
Request Body schema: application/json
required
Approver (string) or Approver (null) (Approver)
approver_verified
boolean (Approver Verified)
Default: false
decision
required
string (Decision)
Enum: "approve" "reject" "retry" "rework"
reason
string (Reason) <= 2000 characters
Default: ""
to_phase
string (To Phase) <= 200 characters
Default: ""

Responses

Request samples

Content type
application/json
{
  • "approver": "string",
  • "approver_verified": false,
  • "decision": "approve",
  • "reason": "",
  • "to_phase": ""
}

Response samples

Content type
application/json
{
  • "allowed_decisions": [
    ],
  • "created_at": "string",
  • "deadline": "string",
  • "decidable": false,
  • "decision": {
    },
  • "detail": { },
  • "findings": [
    ],
  • "id": "string",
  • "kind": "gate",
  • "not_decidable_reason": "string",
  • "project_id": "string",
  • "reason_held": "string",
  • "reason_required_for": [
    ],
  • "requested_by": "string",
  • "rework_targets": [
    ],
  • "route": "dashboard",
  • "status": "pending",
  • "summary": "",
  • "title": "string"
}

assistant

List Proposals

List pending design-change proposals, optionally filtered by session/project.

query Parameters
Session Id (string) or Session Id (null) (Session Id)
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "proposals": [
    ],
  • "total": 0
}

Create Proposal

Create a design-change proposal directly from a human (MET-630).

Same underlying ApprovalWorkflow.propose_change an agent's twin.propose_change MCP call uses — a human (e.g. via a dashboard parameter panel) can submit one just as well, and it goes through the identical review/apply pipeline (decide → apply executor).

Request Body schema: application/json
required
agent_code
string (Agent Code) non-empty
Default: "human"

Code identifying who/what is proposing the change

description
required
string (Description) non-empty

What the change does

object (Diff)

Structured diff (e.g. {'action': 'regenerate_geometry'})

Project Id (string) or Project Id (null) (Project Id)
Session Id (string) or Session Id (null) (Session Id)
work_products_affected
Array of strings <uuid> (Work Products Affected) [ items <uuid > ]

Responses

Request samples

Content type
application/json
{
  • "agent_code": "human",
  • "description": "string",
  • "diff": { },
  • "project_id": "string",
  • "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
  • "work_products_affected": [
    ]
}

Response samples

Content type
application/json
{
  • "agent_code": "string",
  • "change_id": "53a22efb-209d-4639-a6e7-7072a755c213",
  • "created_at": "2019-08-24T14:15:22Z",
  • "decided_at": "2019-08-24T14:15:22Z",
  • "decision_agent": "string",
  • "decision_on_behalf_of": "string",
  • "decision_reason": "string",
  • "decision_surface": "string",
  • "description": "string",
  • "diff": { },
  • "project_id": "string",
  • "requires_approval": true,
  • "reviewer": "string",
  • "reviewer_verified": false,
  • "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
  • "status": "pending",
  • "work_products_affected": [
    ]
}

Get Proposal

Return a single design-change proposal.

path Parameters
change_id
required
string <uuid> (Change Id)

Responses

Response samples

Content type
application/json
{
  • "agent_code": "string",
  • "change_id": "53a22efb-209d-4639-a6e7-7072a755c213",
  • "created_at": "2019-08-24T14:15:22Z",
  • "decided_at": "2019-08-24T14:15:22Z",
  • "decision_agent": "string",
  • "decision_on_behalf_of": "string",
  • "decision_reason": "string",
  • "decision_surface": "string",
  • "description": "string",
  • "diff": { },
  • "project_id": "string",
  • "requires_approval": true,
  • "reviewer": "string",
  • "reviewer_verified": false,
  • "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
  • "status": "pending",
  • "work_products_affected": [
    ]
}

Decide Proposal

Approve or reject a pending design-change proposal.

On approval, run the proposal's diff via the apply executor (if wired) so the change is actually applied to the twin (HITL: propose → approve → apply).

path Parameters
change_id
required
string <uuid> (Change Id)
Request Body schema: application/json
required
change_id
required
string <uuid> (Change Id)

UUID of the proposal to decide on

decision
required
string (ApprovalDecisionType)
Enum: "approve" "reject"

Approve or reject

reason
required
string (Reason) non-empty

Human-written justification for the decision

reviewer
required
string (Reviewer) non-empty

Identifier of the human reviewer

Responses

Request samples

Content type
application/json
{
  • "change_id": "53a22efb-209d-4639-a6e7-7072a755c213",
  • "decision": "approve",
  • "reason": "string",
  • "reviewer": "string"
}

Response samples

Content type
application/json
{
  • "agent_code": "string",
  • "change_id": "53a22efb-209d-4639-a6e7-7072a755c213",
  • "created_at": "2019-08-24T14:15:22Z",
  • "decided_at": "2019-08-24T14:15:22Z",
  • "decision_agent": "string",
  • "decision_on_behalf_of": "string",
  • "decision_reason": "string",
  • "decision_surface": "string",
  • "description": "string",
  • "diff": { },
  • "project_id": "string",
  • "requires_approval": true,
  • "reviewer": "string",
  • "reviewer_verified": false,
  • "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
  • "status": "pending",
  • "work_products_affected": [
    ]
}

Submit Request

Submit a request to an agent via the orchestrator.

Looks up the workflow definition for body.action, creates a WorkflowRun, and dispatches it through the Scheduler.

Request Body schema: application/json
required
action
required
string (Action) non-empty

Agent action to perform (e.g. 'validate_stress', 'run_drc')

object (Parameters)

Action-specific parameters

project_id
required
string (Project Id) non-empty

Project this request belongs to

prompt
string (Prompt)
Default: ""

Free-text prompt or description for generative actions (e.g. generate_cad)

session_id
string <uuid> (Session Id)

Session ID for grouping related requests

Target Id (string) or Target Id (null) (Target Id)

UUID of the target work_product (optional for generative actions)

Responses

Request samples

Content type
application/json
{
  • "action": "string",
  • "parameters": { },
  • "project_id": "string",
  • "prompt": "",
  • "session_id": "1ffd059c-17ea-40a8-8aef-70fd0307db82",
  • "target_id": "d3bcdc92-4191-401b-ad0c-42056c6efab9"
}

Response samples

Content type
application/json
{
  • "errors": [
    ],
  • "request_id": "266ea41d-adf5-480b-af50-15b940c2b846",
  • "result": { },
  • "status": "string"
}

Get Run Status

Poll the status of a workflow run.

path Parameters
run_id
required
string (Run Id)

Responses

Response samples

Content type
application/json
{
  • "completed_at": "string",
  • "run_id": "string",
  • "status": "string",
  • "steps": { }
}

Session Events

SSE endpoint — streams real-time events for session_id.

path Parameters
session_id
required
string <uuid> (Session Id)

Responses

Response samples

Content type
application/json
null

bom

List Bom

List BOM components, optionally scoped to a project and/or filtered by category (case-insensitive exact match against BOMItem.specifications.category, e.g. category=fastener for a fastener list -- FORGE-294, gap G-H2).

Empty ({components: [], total: 0}) when the project has no BOM — not a 404, so the dashboard renders a clean empty state.

query Parameters
Project Id (string) or Project Id (null) (Project Id)
Category (string) or Category (null) (Category)

Responses

Response samples

Content type
application/json
{
  • "components": [
    ],
  • "total": 0
}

List Hierarchical Bom

Derive the hierarchical BOM (EBOM) -- FORGE-267, gap G-C3 -- from every "product"-kind HierarchyNode's CONTAINS tree in a project.

Empty (not an error) when the project has no product hierarchy yet (FORGE-260's tools haven't been used for it) -- matches the flat BOM's own convention.

query Parameters
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "lines": [
    ],
  • "total": 0
}

Get Bom Risk

query Parameters
project_id
required
string (Project Id)

Responses

Response samples

Content type
application/json
{ }

bringup

List Bringup Checklists

query Parameters
work_product_id
required
string (Work Product Id)

Responses

Response samples

Content type
application/json
{
  • "entries": [
    ]
}

Create Bringup Checklist

Request Body schema: application/json
required
Project Id (string) or Project Id (null) (Project Id)
work_product_id
required
string (Work Product Id)

Responses

Request samples

Content type
application/json
{
  • "project_id": "string",
  • "work_product_id": "string"
}

Response samples

Content type
application/json
{
  • "node_id": "string",
  • "statement": "string",
  • "steps": [
    ]
}

cad-export

Download Export File

path Parameters
export_id
required
string (Export Id)
filename
required
string (Filename)

Responses

Response samples

Content type
application/json
null

Generate Ros2 Launch

Request Body schema: application/json
required
default_urdf_path
required
string (Default Urdf Path) non-empty

Default 'urdf_path' launch argument — e.g. a just-exported URDF's download_url.

include_joint_state_publisher_gui
boolean (Include Joint State Publisher Gui)
Default: true
include_rviz
boolean (Include Rviz)
Default: true
robot_name
required
string (Robot Name) non-empty

Responses

Request samples

Content type
application/json
{
  • "default_urdf_path": "string",
  • "include_joint_state_publisher_gui": true,
  • "include_rviz": true,
  • "robot_name": "string"
}

Response samples

Content type
application/json
{
  • "default_urdf_path": "string",
  • "output_file": {
    },
  • "robot_name": "string"
}

Export Sdf

Request Body schema: application/json
required
Density Kg M3 (number) or Density Kg M3 (null) (Density Kg M3)
link_name
string (Link Name)
Default: "link"
Material (string) or Material (null) (Material)
mesh_format
string (Mesh Format)
Default: "stl"
Enum: "stl" "obj"
model_name
string (Model Name)
Default: "model"
node_id
required
string (Node Id) non-empty

Twin work-product node id (STEP file).

static
boolean (Static)
Default: false
World Name (string) or World Name (null) (World Name)

Responses

Request samples

Content type
application/json
{
  • "density_kg_m3": 0,
  • "link_name": "link",
  • "material": "string",
  • "mesh_format": "stl",
  • "model_name": "model",
  • "node_id": "string",
  • "static": false,
  • "world_name": "string"
}

Response samples

Content type
application/json
{
  • "center_of_mass_m": {
    },
  • "density_kg_m3": 0,
  • "inertia_kgm2": {
    },
  • "link_name": "string",
  • "mass_kg": 0,
  • "mesh_file": {
    },
  • "model_name": "string",
  • "output_file": {
    }
}

Export Sdf Assembly

Request Body schema: application/json
required
Array of objects (Joints)
mesh_format
string (Mesh Format)
Default: "stl"
Enum: "stl" "obj"
model_name
string (Model Name)
Default: "model"
required
Array of objects (Parts) non-empty
persist
boolean (Persist)
Default: true

Commit this export as a robot_description Twin work product (default on). Set false to keep the pre-MET-740 throwaway-only behavior.

Persist Name (string) or Persist Name (null) (Persist Name)

Work-product display name (default: ' robot description').

Project Id (string) or Project Id (null) (Project Id)

Project to link the persisted work product to.

static
boolean (Static)
Default: false
Update Node Id (string) or Update Node Id (null) (Update Node Id)

An existing robot_description node's id — when given, this export replaces that node's content and records a new version instead of creating a new node.

World Name (string) or World Name (null) (World Name)

Responses

Request samples

Content type
application/json
{
  • "joints": [
    ],
  • "mesh_format": "stl",
  • "model_name": "model",
  • "parts": [
    ],
  • "persist": true,
  • "persist_name": "string",
  • "project_id": "string",
  • "static": false,
  • "update_node_id": "string",
  • "world_name": "string"
}

Response samples

Content type
application/json
{
  • "joint_names": [
    ],
  • "joints": [ ],
  • "link_names": [
    ],
  • "mesh_files": [
    ],
  • "model_name": "string",
  • "output_file": {
    },
  • "robot_description_node_id": "string"
}

Get Session Summary

path Parameters
session_id
required
string (Session Id)

Responses

Response samples

Content type
application/json
{
  • "name": "string",
  • "object_count": 0,
  • "objects": [
    ],
  • "session_id": "string"
}

Get Session Joints

path Parameters
session_id
required
string (Session Id)

Responses

Response samples

Content type
application/json
{
  • "joints": [
    ]
}

Export Urdf

Request Body schema: application/json
required
Density Kg M3 (number) or Density Kg M3 (null) (Density Kg M3)
link_name
string (Link Name)
Default: "base_link"
Material (string) or Material (null) (Material)
mesh_format
string (Mesh Format)
Default: "stl"
Enum: "stl" "obj"
mesh_uri_prefix
string (Mesh Uri Prefix)
Default: ""
node_id
required
string (Node Id) non-empty

Twin work-product node id (STEP file).

xacro
boolean (Xacro)
Default: false

Responses

Request samples

Content type
application/json
{
  • "density_kg_m3": 0,
  • "link_name": "base_link",
  • "material": "string",
  • "mesh_format": "stl",
  • "mesh_uri_prefix": "",
  • "node_id": "string",
  • "xacro": false
}

Response samples

Content type
application/json
{
  • "center_of_mass_m": {
    },
  • "density_kg_m3": 0,
  • "inertia_kgm2": {
    },
  • "link_name": "string",
  • "mass_kg": 0,
  • "mesh_file": {
    },
  • "output_file": {
    }
}

Export Urdf Assembly

Request Body schema: application/json
required
Array of objects (Joints)
Mesh Angular Tolerance (number) or Mesh Angular Tolerance (null) (Mesh Angular Tolerance)

Max angle (radians) between adjacent facet normals. Omit for OCCT's default.

mesh_format
string (Mesh Format)
Default: "stl"
Enum: "stl" "obj"
Mesh Tolerance (number) or Mesh Tolerance (null) (Mesh Tolerance)

Max linear deviation (mm) between the tessellated mesh and the true CAD surface, applied to every part — smaller means more triangles on curves/fillets and less visible faceting. Omit to keep OCCT's default.

mesh_uri_prefix
string (Mesh Uri Prefix)
Default: ""
required
Array of objects (Parts) non-empty
persist
boolean (Persist)
Default: true

Commit this export as a robot_description Twin work product (default on). Set false to keep the pre-MET-740 throwaway-only behavior.

Persist Name (string) or Persist Name (null) (Persist Name)

Work-product display name (default: ' robot description').

Project Id (string) or Project Id (null) (Project Id)

Project to link the persisted work product to.

robot_name
string (Robot Name)
Default: "robot"
Update Node Id (string) or Update Node Id (null) (Update Node Id)

An existing robot_description node's id — when given, this export replaces that node's content and records a new version instead of creating a new node.

xacro
boolean (Xacro)
Default: false

Responses

Request samples

Content type
application/json
{
  • "joints": [
    ],
  • "mesh_angular_tolerance": 1,
  • "mesh_format": "stl",
  • "mesh_tolerance": 1,
  • "mesh_uri_prefix": "",
  • "parts": [
    ],
  • "persist": true,
  • "persist_name": "string",
  • "project_id": "string",
  • "robot_name": "robot",
  • "update_node_id": "string",
  • "xacro": false
}

Response samples

Content type
application/json
{
  • "joint_names": [
    ],
  • "joints": [ ],
  • "link_names": [
    ],
  • "mesh_files": [
    ],
  • "output_file": {
    },
  • "robot_description_node_id": "string",
  • "robot_name": "string"
}

Export Usd

Request Body schema: application/json
required
Density Kg M3 (number) or Density Kg M3 (null) (Density Kg M3)
Material (string) or Material (null) (Material)
node_id
required
string (Node Id) non-empty

Twin work-product node id (STEP file).

prim_name
string (Prim Name)
Default: "model"

Responses

Request samples

Content type
application/json
{
  • "density_kg_m3": 0,
  • "material": "string",
  • "node_id": "string",
  • "prim_name": "model"
}

Response samples

Content type
application/json
{
  • "center_of_mass_m": {
    },
  • "density_kg_m3": 0,
  • "inertia_kgm2": {
    },
  • "mass_kg": 0,
  • "mesh_file": {
    },
  • "output_file": {
    },
  • "prim_name": "string",
  • "triangle_count": 0
}

Export Usd Assembly

Request Body schema: application/json
required
Array of objects (Joints)
required
Array of objects (Parts) non-empty
persist
boolean (Persist)
Default: true

Commit this export as a robot_description Twin work product (default on). Set false to keep the pre-MET-740 throwaway-only behavior.

Persist Name (string) or Persist Name (null) (Persist Name)

Work-product display name (default: ' robot description').

Project Id (string) or Project Id (null) (Project Id)

Project to link the persisted work product to.

robot_name
string (Robot Name)
Default: "robot"
Update Node Id (string) or Update Node Id (null) (Update Node Id)

An existing robot_description node's id — when given, this export replaces that node's content and records a new version instead of creating a new node.

Responses

Request samples

Content type
application/json
{
  • "joints": [
    ],
  • "parts": [
    ],
  • "persist": true,
  • "persist_name": "string",
  • "project_id": "string",
  • "robot_name": "robot",
  • "update_node_id": "string"
}

Response samples

Content type
application/json
{
  • "joint_names": [
    ],
  • "joints": [ ],
  • "link_names": [
    ],
  • "mesh_files": [
    ],
  • "output_file": {
    },
  • "robot_description_node_id": "string",
  • "robot_name": "string"
}

cad

Create Assembly

Author + commit a multi-part assembly from a declarative spec.

Request Body schema: application/json
required
name
required
string (Name) non-empty

Assembly name.

required
Array of objects (Parts) non-empty

Parts to author + assemble.

Project Id (string) or Project Id (null) (Project Id)

Project to scope the cad_model to.

Responses

Request samples

Content type
application/json
{
  • "name": "string",
  • "parts": [
    ],
  • "project_id": "string"
}

Response samples

Content type
application/json
{
  • "content_hash": "string",
  • "minio_object_key": "string",
  • "model_url": "string",
  • "node_id": "string",
  • "part_count": 0
}

Compile Assembly

Compile a description into a spec and check it — but do NOT build (dry run).

Returns the spec for review plus any geometric-feasibility warnings, so the caller can tweak it (or save it and run /assembly) before committing.

Request Body schema: application/json
required
description
required
string (Description) non-empty

Plain-English description.

Model (string) or Model (null) (Model)

LLM model override.

Name (string) or Name (null) (Name)

Override the assembly name.

Provider (string) or Provider (null) (Provider)

LLM provider override.

Responses

Request samples

Content type
application/json
{
  • "description": "string",
  • "model": "string",
  • "name": "string",
  • "provider": "string"
}

Response samples

Content type
application/json
{
  • "buildable": true,
  • "errors": [
    ],
  • "spec": {
    }
}

Create Assembly From Text

Compile a plain-English description into a spec (LLM), then build it.

The LLM only produces the small declarative spec — the geometry itself is authored deterministically by the same builder as /assembly, so the output is reproducible and the spec is returned for review.

Request Body schema: application/json
required
description
required
string (Description) non-empty

Plain-English description of the part/assembly.

Model (string) or Model (null) (Model)

LLM model override for translation.

Name (string) or Name (null) (Name)

Override the assembly name (else the model chooses one).

Project Id (string) or Project Id (null) (Project Id)

Project to scope the cad_model to.

Provider (string) or Provider (null) (Provider)

LLM provider override for translation.

Responses

Request samples

Content type
application/json
{
  • "description": "string",
  • "model": "string",
  • "name": "string",
  • "project_id": "string",
  • "provider": "string"
}

Response samples

Content type
application/json
{
  • "content_hash": "string",
  • "minio_object_key": "string",
  • "model_url": "string",
  • "node_id": "string",
  • "part_count": 0,
  • "spec": {
    }
}

chat

List Channels

Return all available chat channels.

Responses

Response samples

Content type
application/json
{
  • "channels": [
    ]
}

List Threads

List threads with optional filtering and pagination.

query Parameters
Channel Id (string) or Channel Id (null) (Channel Id)

Filter by channel ID

Scope Kind (string) or Scope Kind (null) (Scope Kind)

Filter by scope kind

Entity Id (string) or Entity Id (null) (Entity Id)

Filter by scope entity ID

include_archived
boolean (Include Archived)
Default: false

Include archived threads

page
integer (Page) >= 1
Default: 1

Page number (1-indexed)

per_page
integer (Per Page) [ 1 .. 100 ]
Default: 20

Results per page

Responses

Response samples

Content type
application/json
{
  • "page": 0,
  • "per_page": 0,
  • "threads": [
    ],
  • "total": 0
}

Create Thread

Create a new thread, optionally with an initial message.

Request Body schema: application/json
required
Initial Message (string) or Initial Message (null) (Initial Message)

If provided, a first message is created automatically

scope_entity_id
required
string (Scope Entity Id)

ID of the scoped entity

scope_kind
required
string (Scope Kind)

Scope type (session, approval, bom-entry, ...)

Title (string) or Title (null) (Title)

Optional thread title

Responses

Request samples

Content type
application/json
{
  • "initial_message": "string",
  • "scope_entity_id": "string",
  • "scope_kind": "string",
  • "title": "string"
}

Response samples

Content type
application/json
{
  • "archived": true,
  • "channel_id": "string",
  • "created_at": "2019-08-24T14:15:22Z",
  • "id": "string",
  • "last_message_at": "2019-08-24T14:15:22Z",
  • "messages": [
    ],
  • "scope_entity_id": "string",
  • "scope_kind": "string",
  • "title": "string"
}

Get Thread

Return a single thread with all its messages.

path Parameters
thread_id
required
string (Thread Id)

Responses

Response samples

Content type
application/json
{
  • "archived": true,
  • "channel_id": "string",
  • "created_at": "2019-08-24T14:15:22Z",
  • "id": "string",
  • "last_message_at": "2019-08-24T14:15:22Z",
  • "messages": [
    ],
  • "scope_entity_id": "string",
  • "scope_kind": "string",
  • "title": "string"
}

Send Message

Append a message to an existing thread.

After persisting the user message, the handler routes it to the appropriate domain agent (when an LLM is configured). The agent's response is inserted into the thread automatically.

path Parameters
thread_id
required
string (Thread Id)
Request Body schema: application/json
required
actor_id
required
string (Actor Id)

ID of the actor sending the message

actor_kind
required
string (Actor Kind)

Actor type: user | agent | system

content
required
string (Content) non-empty

Message content

Graph Ref Label (string) or Graph Ref Label (null) (Graph Ref Label)

Digital-twin ref label

Graph Ref Node (string) or Graph Ref Node (null) (Graph Ref Node)

Digital-twin node reference

Graph Ref Type (string) or Graph Ref Type (null) (Graph Ref Type)

Digital-twin ref type

Model (string) or Model (null) (Model)

Override model for this turn

Provider (string) or Provider (null) (Provider)

Override provider id for this turn

Array of Tools (strings) or Tools (null) (Tools)

Enabled MCP tool ids for this turn (None = all available)

Responses

Request samples

Content type
application/json
{
  • "actor_id": "string",
  • "actor_kind": "string",
  • "content": "string",
  • "graph_ref_label": "string",
  • "graph_ref_node": "string",
  • "graph_ref_type": "string",
  • "model": "string",
  • "provider": "string",
  • "tools": [
    ]
}

Response samples

Content type
application/json
{
  • "actor_id": "string",
  • "actor_kind": "string",
  • "content": "string",
  • "created_at": "2019-08-24T14:15:22Z",
  • "graph_ref_label": "string",
  • "graph_ref_node": "string",
  • "graph_ref_type": "string",
  • "id": "string",
  • "status": "string",
  • "thread_id": "string",
  • "updated_at": "2019-08-24T14:15:22Z"
}

Update Thread Scope

Rescope an EXISTING thread in place (MET-580).

Unlike POST /threads, this preserves the conversation — the same thread continues, and its next turn's project brief (if scoped to a project) reflects the new scope. The agent-callable chat.set_project_scope native tool goes through the same apply_thread_scope helper, so a human hitting this endpoint and the agent switching scope mid-turn behave identically and both broadcast the same scope.changed SSE event.

path Parameters
thread_id
required
string (Thread Id)
Request Body schema: application/json
required
scope_entity_id
required
string (Scope Entity Id)

ID of the scoped entity

scope_kind
required
string (Scope Kind)

Scope type (session, approval, project, ...)

Responses

Request samples

Content type
application/json
{
  • "scope_entity_id": "string",
  • "scope_kind": "string"
}

Response samples

Content type
application/json
{
  • "archived": true,
  • "channel_id": "string",
  • "created_at": "2019-08-24T14:15:22Z",
  • "id": "string",
  • "last_message_at": "2019-08-24T14:15:22Z",
  • "messages": [
    ],
  • "scope_entity_id": "string",
  • "scope_kind": "string",
  • "title": "string"
}

Stream Thread Events

Stream real-time events for a chat thread via Server-Sent Events.

The client receives events as they occur:

  • message.created -- a new message was added
  • agent.typing -- an agent is processing
  • context.stats -- the turn's context-window snapshot: tokens used vs. the model's window, broken down by system prompt / project brief / history / tool schemas / message, with included-vs-available counts (harness turns)
  • agent.step -- one reasoning/tool-call step in the agent's trace
  • message.delta -- one token/chunk of the streaming answer
  • agent.done -- an agent finished
  • error -- an error occurred

The connection stays open until the client disconnects or the server closes the stream.

path Parameters
thread_id
required
string (Thread Id)

Responses

Response samples

Content type
application/json
null

chat-tool-approvals

List Pending Approvals

Tool-call approvals: the ones awaiting a decision, or every one.

Overdue holds are expired first, so nothing listed as pending is a call whose waiter has already given up (FORGE-466). status=all is the audit view (FORGE-473): every entry whichever route answered it, each carrying its route, outcome and approver.

project_id scopes the queue. Unscoped before, so a reviewer working on one project saw every project's held writes in one list -- and a held write names a tool and a caller, not a product, so there was no way to tell from the row which one it belonged to. Approvals whose tool call carried no project are counted rather than dropped: an approval that quietly disappears is the one nobody answers.

query Parameters
status
string (Status)
Default: "pending"
Enum: "pending" "all"
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "runs": [
    ],
  • "unscoped_count": 0
}

Hold Tool Call

Create a held approval and return it.

This exists because the approval store is process-level (an InMemoryRunStore in this process), and the MCP sidecar is a different process. Before FORGE-406 a sidecar could only hold calls in its own memory, where the dashboard — served from here — would never see them. So the sidecar parks them here instead, and there is exactly one ledger rather than one per process.

A second store would have been the more obvious fix and the wrong one: two queues means a reviewer clearing one while the other fills, and no page that shows both.

Request Body schema: application/json
required
object (Arguments)
caller
string (Caller)
Default: "untrusted"
Client (string) or Client (null) (Client)
Project (string) or Project (null) (Project)
reason
required
string (Reason)
route
string (Route)
Default: "dashboard"
Enum: "dashboard" "elicitation"
Session Id (string) or Session Id (null) (Session Id)
source
string (Source)
Default: "mcp"
Timeout Seconds (number) or Timeout Seconds (null) (Timeout Seconds)
tool
required
string (Tool)

Responses

Request samples

Content type
application/json
{
  • "arguments": { },
  • "caller": "untrusted",
  • "client": "string",
  • "project": "string",
  • "reason": "string",
  • "route": "dashboard",
  • "session_id": "string",
  • "source": "mcp",
  • "timeout_seconds": 1,
  • "tool": "string"
}

Response samples

Content type
application/json
{
  • "approval_deadline": 0,
  • "approval_reason": "string",
  • "approved_by": "string",
  • "approver_verified": false,
  • "created_at": 0,
  • "engine": "string",
  • "error": "string",
  • "flow_content_hash": "string",
  • "flow_version_id": "string",
  • "history": [
    ],
  • "id": "string",
  • "project_id": "string",
  • "request": { },
  • "result": { },
  • "status": "string",
  • "updated_at": 0,
  • "usage": { }
}

Get Approval

path Parameters
run_id
required
string (Run Id)

Responses

Response samples

Content type
application/json
{
  • "approval_deadline": 0,
  • "approval_reason": "string",
  • "approved_by": "string",
  • "approver_verified": false,
  • "created_at": 0,
  • "engine": "string",
  • "error": "string",
  • "flow_content_hash": "string",
  • "flow_version_id": "string",
  • "history": [
    ],
  • "id": "string",
  • "project_id": "string",
  • "request": { },
  • "result": { },
  • "status": "string",
  • "updated_at": 0,
  • "usage": { }
}

Submit Tool Approval

Record the decision, attributed to whoever made this request.

The identity comes from the request, not the body (FORGE-393). A client cannot nominate the approver, which is the whole point: some tools write the approver's name down as their result.

path Parameters
run_id
required
string (Run Id)
Request Body schema: application/json
required
decision
required
string (Decision)
Enum: "approve" "reject" "retry" "rework"
reason
string (Reason) <= 2000 characters
Default: ""
to_phase
string (To Phase) <= 200 characters
Default: ""

Responses

Request samples

Content type
application/json
{
  • "decision": "approve",
  • "reason": "",
  • "to_phase": ""
}

Response samples

Content type
application/json
{
  • "approval_deadline": 0,
  • "approval_reason": "string",
  • "approved_by": "string",
  • "approver_verified": false,
  • "created_at": 0,
  • "engine": "string",
  • "error": "string",
  • "flow_content_hash": "string",
  • "flow_version_id": "string",
  • "history": [
    ],
  • "id": "string",
  • "project_id": "string",
  • "request": { },
  • "result": { },
  • "status": "string",
  • "updated_at": 0,
  • "usage": { }
}

Resolve Unanswered Hold

The waiting side stopped waiting: close the hold so nobody answers it.

Idempotent. A hold already timed_out or canceled comes back as it is with 200, so a retry after a lost response is harmless. A hold a human already decided is 409: the waiter must read the decision back rather than overwrite it, because an approval that landed in the last instant is still an approval.

path Parameters
run_id
required
string (Run Id)
Request Body schema: application/json
required
Approver (string) or Approver (null) (Approver)
approver_verified
boolean (Approver Verified)
Default: false
outcome
required
string (Outcome)
Enum: "timed_out" "canceled" "approved" "rejected"
Reason (string) or Reason (null) (Reason)

Responses

Request samples

Content type
application/json
{
  • "approver": "string",
  • "approver_verified": false,
  • "outcome": "timed_out",
  • "reason": "string"
}

Response samples

Content type
application/json
{
  • "approval_deadline": 0,
  • "approval_reason": "string",
  • "approved_by": "string",
  • "approver_verified": false,
  • "created_at": 0,
  • "engine": "string",
  • "error": "string",
  • "flow_content_hash": "string",
  • "flow_version_id": "string",
  • "history": [
    ],
  • "id": "string",
  • "project_id": "string",
  • "request": { },
  • "result": { },
  • "status": "string",
  • "updated_at": 0,
  • "usage": { }
}

client-tasks

List Tasks

Tasks, open ones by default. status=all lists every state.

query Parameters
Status (string) or Status (null) (Status)
Default: "open"
Project Id (string) or Project Id (null) (Project Id)
Run Id (string) or Run Id (null) (Run Id)

Responses

Response samples

Content type
application/json
{ }

Open Task

Post a phase for the client. Idempotent on run:phase:attempt.

Request Body schema: application/json
required
attempt
integer (Attempt)
Default: 1
object (Brief)
phaseId
required
string (Phaseid)
Projectid (string) or Projectid (null) (Projectid)
runId
required
string (Runid)

Responses

Request samples

Content type
application/json
{
  • "attempt": 1,
  • "brief": { },
  • "phaseId": "string",
  • "projectId": "string",
  • "runId": "string"
}

Response samples

Content type
application/json
{ }

Get Task

path Parameters
task_id
required
string (Task Id)

Responses

Response samples

Content type
application/json
{ }

Cancel Task

Withdraw a task nobody will wait on any more (the worker's activity ended).

path Parameters
task_id
required
string (Task Id)
Request Body schema: application/json
required
reason
string (Reason)
Default: ""

Responses

Request samples

Content type
application/json
{
  • "reason": ""
}

Response samples

Content type
application/json
{ }

Claim Task

Take a task and get its full brief.

path Parameters
task_id
required
string (Task Id)
Request Body schema: application/json
required
client
string (Client)
Default: ""

Responses

Request samples

Content type
application/json
{
  • "client": ""
}

Response samples

Content type
application/json
{ }

Submit Task

Hand the phase back. The run's gate then checks the twin as usual.

path Parameters
task_id
required
string (Task Id)
Request Body schema: application/json
required
artifacts
Array of strings (Artifacts)
client
string (Client)
Default: ""
summary
required
string (Summary)

Responses

Request samples

Content type
application/json
{
  • "artifacts": [
    ],
  • "client": "",
  • "summary": "string"
}

Response samples

Content type
application/json
{ }

compliance

Get Checklist

Generate a compliance checklist for the given project and markets.

Markets are provided as a comma-separated query parameter, e.g. ?markets=UKCA,CE,FCC.

path Parameters
project_id
required
string (Project Id)
query Parameters
markets
string (Markets)
Default: "UKCA,CE"

Comma-separated regime codes

Responses

Response samples

Content type
application/json
{
  • "coverage_percent": 0,
  • "evidenced_items": 0,
  • "items": [
    ],
  • "project_id": "string",
  • "target_markets": [
    ],
  • "total_items": 0
}

Get Coverage

Get evidence coverage statistics for a project.

path Parameters
project_id
required
string (Project Id)

Responses

Response samples

Content type
application/json
{
  • "coverage_percent": 0,
  • "evidenced_items": 0,
  • "project_id": "string",
  • "total_items": 0
}

Link Evidence

Link a piece of evidence to a compliance checklist item.

path Parameters
project_id
required
string (Project Id)
Request Body schema: application/json
required
checklist_item_id
required
string (Checklist Item Id)

Checklist item ID to link to

description
string (Description)
Default: ""

Evidence description

evidence_type
required
string (EvidenceType)
Enum: "TEST_REPORT" "DECLARATION" "CERTIFICATE" "TECHNICAL_FILE" "RISK_ASSESSMENT"

Type of evidence

title
required
string (Title)

Evidence title

Work Product Id (string) or Work Product Id (null) (Work Product Id)

WorkProduct UUID

Responses

Request samples

Content type
application/json
{
  • "checklist_item_id": "string",
  • "description": "",
  • "evidence_type": "TEST_REPORT",
  • "title": "string",
  • "work_product_id": "224aa6cf-be77-49ce-9c79-b3b38dfd40f4"
}

Response samples

Content type
application/json
{
  • "checklist_item_id": "string",
  • "description": "string",
  • "evidence_type": "string",
  • "id": "string",
  • "status": "string",
  • "title": "string",
  • "uploaded_at": "string"
}

Get Evidence

Retrieve all evidence records for a checklist item.

path Parameters
project_id
required
string (Project Id)
item_id
required
string (Item Id)

Responses

Response samples

Content type
application/json
[
  • {
    }
]

component-selection

Select Component

Request Body schema: application/json
required
required
Array of objects (Candidates)
category
required
string (Category)
Projectid (string) or Projectid (null) (Projectid)
purchaseUnit
required
string (Purchaseunit)
quantity
integer (Quantity)
Default: 1
rationale
required
string (Rationale)
required
object (Requiredspecs)
Array of Requirementids (strings) or Requirementids (null) (Requirementids)
selectedMpn
required
string (Selectedmpn)
title
required
string (Title)

Responses

Request samples

Content type
application/json
{
  • "candidates": [
    ],
  • "category": "string",
  • "projectId": "string",
  • "purchaseUnit": "string",
  • "quantity": 1,
  • "rationale": "string",
  • "requiredSpecs": {
    },
  • "requirementIds": [
    ],
  • "selectedMpn": "string",
  • "title": "string"
}

Response samples

Content type
application/json
{ }

constraint

Synthesize Constraint

Turn a drag delta into a parametric constraint, and — when the dragged group maps to a live FreeCAD session object (session_id + obj_id) — bind it into the model so Apply re-parameterizes and re-solves (MET-531).

Without a session/object it stays a suggestion-only stub (MET-519). Binding is best-effort: an adapter error leaves the suggestion intact with bound=False and a binding_error.

Request Body schema: application/json
required
required
object (DeltaTransform)

Delta of a dragged group: translation (mm), or — additively, MET-611 — a single-axis rotation or scale. Exactly one kind is populated per request, matching whichever gizmo mode produced it on the client.

group_name
required
string (Group Name) non-empty
Obj Id (string) or Obj Id (null) (Obj Id)
Property Path (string) or Property Path (null) (Property Path)
Session Id (string) or Session Id (null) (Session Id)

Responses

Request samples

Content type
application/json
{
  • "delta": {
    },
  • "group_name": "string",
  • "obj_id": "string",
  • "property_path": "string",
  • "session_id": "string"
}

Response samples

Content type
application/json
{
  • "binding_error": "string",
  • "bound": false,
  • "conflict_reason": "string",
  • "constraint": {
    },
  • "expression": "string",
  • "status": "ok",
  • "suggestion": "string"
}

controls

Get Repeatability Estimate

query Parameters
work_product_id
required
string (Work Product Id)
requirement_mm
number (Requirement Mm)
Default: 0.5
End Effector Part (string) or End Effector Part (null) (End Effector Part)

Responses

Response samples

Content type
application/json
{
  • "contributions": [
    ],
  • "passes": true,
  • "requirement_mm": 0,
  • "target_part": "string",
  • "warnings": [
    ],
  • "work_product_id": "string",
  • "worst_case_repeatability_mm": 0
}

convert

Upload And Convert

Upload a STEP/IGES file and convert to GLB.

Returns the conversion result with a URL to the GLB file and metadata. Results are cached by content hash — re-uploading the same file is instant.

query Parameters
quality
string (Quality) ^(preview|standard|fine)$
Default: "standard"
Request Body schema: multipart/form-data
required
file
required
string <application/octet-stream> (File)

STEP or IGES CAD file

Responses

Response samples

Content type
application/json
{
  • "cached": true,
  • "glb_url": "string",
  • "hash": "string",
  • "metadata": { }
}

Get Conversion

Retrieve a cached conversion result by content hash.

path Parameters
file_hash
required
string (File Hash)
query Parameters
quality
string (Quality) ^(preview|standard|fine)$
Default: "standard"

Responses

Response samples

Content type
application/json
{
  • "cached": true,
  • "glb_url": "string",
  • "hash": "string",
  • "metadata": { }
}

Get Glb

Download the converted GLB file.

path Parameters
file_hash
required
string (File Hash)
query Parameters
quality
string (Quality) ^(preview|standard|fine)$
Default: "standard"

Responses

Response samples

Content type
application/json
null

Get Metadata

Retrieve conversion metadata (part tree, stats, materials).

path Parameters
file_hash
required
string (File Hash)
query Parameters
quality
string (Quality) ^(preview|standard|fine)$
Default: "standard"

Responses

Response samples

Content type
application/json
{ }

decisions

design-flows

List Design Flows

Every launchable flow, as the gateway will actually run it.

Responses

Response samples

Content type
application/json
{
  • "defaultFlowId": "string",
  • "flows": [
    ]
}

Compile Flow Intent

Compile an intent into its structured model. Stores nothing, starts nothing.

Deterministic: no model call, and no value the person did not state. Use it before proposing to see what was understood and what is still unknown.

Request Body schema: application/json
required
Budget (string) or Budget (null) (Budget)
CallerBody (object) or null
intent
required
string (Intent)
Loadsanduse (string) or Loadsanduse (null) (Loadsanduse)
ManufacturingContextBody (object) or null
Model (string) or Model (null) (Model)
Array of Operations (objects) or Operations (null) (Operations)
Projectid (string) or Projectid (null) (Projectid)
Provider (string) or Provider (null) (Provider)
requirements
Array of strings (Requirements)
TargetMaturity (string) or null
Template (string) or Template (null) (Template)

Responses

Request samples

Content type
application/json
{
  • "budget": "string",
  • "caller": {
    },
  • "intent": "string",
  • "loadsAndUse": "string",
  • "manufacturingContext": {
    },
  • "model": "string",
  • "operations": [
    ],
  • "projectId": "string",
  • "provider": "string",
  • "requirements": [
    ],
  • "targetMaturity": "concept",
  • "template": "string"
}

Response samples

Content type
application/json
{
  • "intent": { },
  • "missingInputs": [
    ]
}

Propose Flow

Tailor a template to a project's intent, and hold it for a human.

The response carries an approvalId, not a run. FORGE-398's rule is that nothing starts before approval, and the way to make that true is for the endpoint that generates a flow to have no ability to start one.

If the manufacturing route, target maturity or loads are missing, the answer is 200 with status: "needs_input" and the questions to answer -- no flow, no stored version, no held approval (FORGE-463). A generator that guesses those produces a flow that reads as tailored and is not.

Request Body schema: application/json
required
Budget (string) or Budget (null) (Budget)
CallerBody (object) or null
intent
required
string (Intent)
Loadsanduse (string) or Loadsanduse (null) (Loadsanduse)
ManufacturingContextBody (object) or null
Model (string) or Model (null) (Model)
Array of Operations (objects) or Operations (null) (Operations)
Projectid (string) or Projectid (null) (Projectid)
Provider (string) or Provider (null) (Provider)
requirements
Array of strings (Requirements)
TargetMaturity (string) or null
Template (string) or Template (null) (Template)

Responses

Request samples

Content type
application/json
{
  • "budget": "string",
  • "caller": {
    },
  • "intent": "string",
  • "loadsAndUse": "string",
  • "manufacturingContext": {
    },
  • "model": "string",
  • "operations": [
    ],
  • "projectId": "string",
  • "provider": "string",
  • "requirements": [
    ],
  • "targetMaturity": "concept",
  • "template": "string"
}

Response samples

Content type
application/json
{
  • "intent": "string",
  • "message": "string",
  • "notes": [
    ],
  • "questions": [
    ],
  • "status": "needs_input"
}

Validate Edited Flow

Check an edit without saving it.

The editor calls this as the canvas changes, so a person sees a rule break while they are looking at the thing that broke it -- rather than at save, by which point they have made five more changes and have to work out which one the message is about.

Request Body schema: application/json
required
baseTemplateId
required
string (Basetemplateid)
Name (string) or Name (null) (Name)
required
Array of objects (Phases)

Responses

Request samples

Content type
application/json
{
  • "baseTemplateId": "string",
  • "name": "string",
  • "phases": [
    ]
}

Response samples

Content type
application/json
{
  • "valid": true,
  • "violations": [
    ]
}

Save Edited Flow

Save an edit as a new version, held for approval.

Never mutates an existing version. A run pins the version it started on, so a version changing underneath would make a completed run's provenance a lie -- and an approval that can be edited afterwards is not an approval.

Request Body schema: application/json
required
baseTemplateId
required
string (Basetemplateid)
Name (string) or Name (null) (Name)
required
Array of objects (Phases)

Responses

Request samples

Content type
application/json
{
  • "baseTemplateId": "string",
  • "name": "string",
  • "phases": [
    ]
}

Response samples

Content type
application/json
{
  • "approvalId": "string",
  • "baseTemplateId": "string",
  • "baseVersion": "string",
  • "changes": [
    ],
  • "context": "",
  • "flow": {
    },
  • "origin": "string",
  • "status": "string",
  • "valid": true,
  • "versionId": "string",
  • "violations": [
    ]
}

Get Flow Version

path Parameters
version_id
required
string (Version Id)

Responses

Response samples

Content type
application/json
{
  • "approvalId": "string",
  • "baseTemplateId": "string",
  • "baseVersion": "string",
  • "changes": [
    ],
  • "context": "",
  • "flow": {
    },
  • "origin": "string",
  • "status": "string",
  • "valid": true,
  • "versionId": "string",
  • "violations": [
    ]
}

Version Capabilities

The same assessment for a saved (tailored or edited) flow version.

path Parameters
version_id
required
string (Version Id)
query Parameters
Profile (string) or Profile (null) (Profile)

Responses

Response samples

Content type
application/json
{
  • "flowId": "string",
  • "profile": "string",
  • "report": { },
  • "versionId": "string"
}

Get Design Flow

One flow, for the run detail view and the plan canvas.

path Parameters
flow_id
required
string (Flow Id)

Responses

Response samples

Content type
application/json
{
  • "description": "string",
  • "graph": { },
  • "id": "string",
  • "isDefault": false,
  • "label": "string",
  • "name": "string",
  • "phases": [
    ],
  • "valid": true,
  • "version": "string",
  • "violations": [
    ]
}

Flow Capabilities

Can this template be run with the tools that exist and answer right now?

profile narrows coverage to the tools a client connected with that MCP profile is served.

path Parameters
flow_id
required
string (Flow Id)
query Parameters
Profile (string) or Profile (null) (Profile)

Responses

Response samples

Content type
application/json
{
  • "flowId": "string",
  • "profile": "string",
  • "report": { },
  • "versionId": "string"
}

design-loop

Start Design Loop

Request Body schema: application/json
required
deflectionLimitMm
required
number (Deflectionlimitmm)
loadN
required
number (Loadn)
material
string (Material)
Default: "aluminum_6061"
maxIterations
integer (Maxiterations)
Default: 60
Projectid (string) or Projectid (null) (Projectid)
Array of Requirementids (strings) or Requirementids (null) (Requirementids)
sfLimit
number (Sflimit)
Default: 2
Wallmaxmm (number) or Wallmaxmm (null) (Wallmaxmm)
wallMinMm
number (Wallminmm)
Default: 0.5
workProductId
required
string (Workproductid)

Responses

Request samples

Content type
application/json
{
  • "deflectionLimitMm": 0,
  • "loadN": 0,
  • "material": "aluminum_6061",
  • "maxIterations": 60,
  • "projectId": "string",
  • "requirementIds": [
    ],
  • "sfLimit": 2,
  • "wallMaxMm": 0,
  • "wallMinMm": 0.5,
  • "workProductId": "string"
}

Response samples

Content type
application/json
{ }

Get Design Loop

path Parameters
loop_id
required
string (Loop Id)

Responses

Response samples

Content type
application/json
{ }

Approve Design Loop

path Parameters
loop_id
required
string (Loop Id)
Request Body schema: application/json
required
approvedBy
required
string (Approvedby)

Responses

Request samples

Content type
application/json
{
  • "approvedBy": "string"
}

Response samples

Content type
application/json
{ }

dfm

Run Overhang Check

Request Body schema: application/json
required
Array of Build Axis (numbers) or Build Axis (null) (Build Axis)
mesh_file
required
string (Mesh File)
Project Id (string) or Project Id (null) (Project Id)
Threshold Deg (number) or Threshold Deg (null) (Threshold Deg)
work_product_id
required
string (Work Product Id)

Responses

Request samples

Content type
application/json
{
  • "build_axis": [
    ],
  • "mesh_file": "string",
  • "project_id": "string",
  • "threshold_deg": 0,
  • "work_product_id": "string"
}

Response samples

Content type
application/json
{
  • "build_axis": [
    ],
  • "dfm_pass": true,
  • "evidence_node_id": "string",
  • "faces": [
    ],
  • "flagged_count": 0,
  • "threshold_deg": 0,
  • "total_faces": 0
}

evals

Get Evals

Responses

Response samples

Content type
application/json
{ }

features

Generate Feature

Request Body schema: application/json
required
adapter
string (Adapter)
Default: "freecad"
commit
boolean (Commit)
Default: true
required
object (Feature)
material
string (Material)
Default: "aluminum_6061"
name
required
string (Name)
Projectid (string) or Projectid (null) (Projectid)
Workproductid (string) or Workproductid (null) (Workproductid)

Responses

Request samples

Content type
application/json
{
  • "adapter": "freecad",
  • "commit": true,
  • "feature": { },
  • "material": "aluminum_6061",
  • "name": "string",
  • "projectId": "string",
  • "workProductId": "string"
}

Response samples

Content type
application/json
{ }

Get Feature Diff

path Parameters
work_product_id
required
string (Work Product Id)

Responses

Response samples

Content type
application/json
{
  • "added": { },
  • "changed": {
    },
  • "currentWorkProductId": "string",
  • "previousWorkProductId": "string",
  • "removed": { }
}

firmware

Create Firmware Scaffold

Request Body schema: application/json
required
Project Id (string) or Project Id (null) (Project Id)
work_product_id
required
string (Work Product Id)

Responses

Request samples

Content type
application/json
{
  • "project_id": "string",
  • "work_product_id": "string"
}

Response samples

Content type
application/json
{
  • "firmware_source_node_id": "string",
  • "joints": [
    ],
  • "pinmap_node_id": "string"
}

harness

Set Credential

Store a provider credential so the runtime uses it (no restart).

api_key → the gateway auth store; oauth → the Codex auth.json the codex adapter reads. Validates the provider against the registry.

header Parameters
X-Metaforge-Admin (string) or X-Metaforge-Admin (null) (X-Metaforge-Admin)
Request Body schema: application/json
required
Api Key (string) or Api Key (null) (Api Key)

Raw API key (method=api_key).

Base Url (string) or Base Url (null) (Base Url)

Optional base_url override.

method
string (Method)
Default: "api_key"

'api_key' or 'oauth'.

provider
required
string (Provider)

Registry provider id (e.g. openai, openai-codex).

Tokens (object) or Tokens (null) (Tokens)

OAuth token blob in auth.json shape (method=oauth).

Responses

Request samples

Content type
application/json
{
  • "api_key": "string",
  • "base_url": "string",
  • "method": "api_key",
  • "provider": "string",
  • "tokens": { }
}

Response samples

Content type
application/json
{
  • "method": "string",
  • "ok": true,
  • "provider": "string"
}

Delete Credential

Forget a provider's stored API key (and clear the selection if it pointed there).

path Parameters
provider
required
string (Provider)
header Parameters
X-Metaforge-Admin (string) or X-Metaforge-Admin (null) (X-Metaforge-Admin)

Responses

Response samples

Content type
application/json
{
  • "method": "string",
  • "ok": true,
  • "provider": "string"
}

List Models

Models for a provider. OpenAI-compatible + configured → live-fetched; else empty.

query Parameters
provider
required
string (Provider)

Provider id

Responses

Response samples

Content type
application/json
{
  • "models": [
    ],
  • "provider": "string",
  • "source": "string"
}

List Providers

List registered providers (configured ones first) + the active selection.

Responses

Response samples

Content type
application/json
{
  • "active_model": "string",
  • "active_provider": "string",
  • "fallback_count": 0,
  • "last_fallback": {
    },
  • "providers": [
    ]
}

Get Routing

Which provider and model each role is routed to.

A role absent from roles is served by the durable harness selection (default_provider / default_model).

query Parameters
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "default_model": "string",
  • "default_provider": "string",
  • "effective_for_project": {
    },
  • "problems": [
    ],
  • "projects": {
    },
  • "roles": {
    }
}

Set Selection

Set the durable active provider/model (overrides the METAFORGE_LLM_* env).

header Parameters
X-Metaforge-Admin (string) or X-Metaforge-Admin (null) (X-Metaforge-Admin)
Request Body schema: application/json
required
Model (string) or Model (null) (Model)

Optional model id.

provider
required
string (Provider)

Registry provider id to make active.

Responses

Request samples

Content type
application/json
{
  • "model": "string",
  • "provider": "string"
}

Response samples

Content type
application/json
{
  • "method": "string",
  • "ok": true,
  • "provider": "string"
}

List Tools

MCP tools/connectors reachable via the gateway's bridge (empty if none wired).

Responses

Response samples

Content type
application/json
[
  • {
    }
]

knowledge

Ingest Document

Ingest a document (markdown / plain text) via the L1 KnowledgeService.

Backs the forge ingest <path> CLI (MET-336). Heading-aware chunking, dedup, and citation metadata are handled by the underlying provider — the route is a thin pass-through.

Request Body schema: application/json
required
content
required
string (Content) non-empty
knowledgeType
required
string (KnowledgeType)
Enum: "design_decision" "component" "failure" "constraint" "session"

Categories of knowledge stored in the knowledge layer.

object (Metadata)
Projectid (string) or Projectid (null) (Projectid)
sourcePath
required
string (Sourcepath) non-empty
Sourceworkproductid (string) or Sourceworkproductid (null) (Sourceworkproductid)

Responses

Request samples

Content type
application/json
{
  • "content": "string",
  • "knowledgeType": "design_decision",
  • "metadata": { },
  • "projectId": "5a8591dd-4039-49df-9202-96385ba3eff8",
  • "sourcePath": "string",
  • "sourceWorkProductId": "c83b8d43-b0ff-4427-847b-87295ebb87a8"
}

Response samples

Content type
application/json
{
  • "chunksIndexed": 0,
  • "entryIds": [
    ],
  • "sourcePath": "string"
}

Ingest Knowledge

Manually ingest a knowledge entry.

Routes through KnowledgeService when available so the chunk pipeline, dedup, and citation-field round-trip apply consistently with /documents and /search (MET-390).

Request Body schema: application/json
required
content
required
string (Content) non-empty
knowledgeType
required
string (KnowledgeType)
Enum: "design_decision" "component" "failure" "constraint" "session"

Categories of knowledge stored in the knowledge layer.

object (Metadata)
Projectid (string) or Projectid (null) (Projectid)
Sourcepath (string) or Sourcepath (null) (Sourcepath)
Sourceworkproductid (string) or Sourceworkproductid (null) (Sourceworkproductid)

Responses

Request samples

Content type
application/json
{
  • "content": "string",
  • "knowledgeType": "design_decision",
  • "metadata": { },
  • "projectId": "5a8591dd-4039-49df-9202-96385ba3eff8",
  • "sourcePath": "string",
  • "sourceWorkProductId": "c83b8d43-b0ff-4427-847b-87295ebb87a8"
}

Response samples

Content type
application/json
{
  • "embedded": true,
  • "entryId": "09a8b554-45ca-4bab-a638-265db4b3e828"
}

Search Knowledge

Semantic search over indexed knowledge.

Routes through KnowledgeService when available so it shares the same backend as /ingest and /documents (MET-390).

project_id (MET-670) mirrors the projectId filter already on /sources and /ingest: without it, KnowledgeService.search falls back to the default tenant, so a project-scoped ingest was never searchable from a project-scoped UI — the search box silently returned whatever unrelated content happened to live under default instead of the active project's own sources.

query Parameters
query
required
string (Query) non-empty

Search query

KnowledgeType (string) or Knowledgetype (null) (Knowledgetype)

Filter by knowledge type

Projectid (string) or Projectid (null) (Projectid)

Scope search to a project UUID

limit
integer (Limit) [ 1 .. 50 ]
Default: 5

Max results

Responses

Response samples

Content type
application/json
{
  • "query": "string",
  • "results": [
    ],
  • "totalFound": 0
}

List Knowledge Sources

List ingested knowledge sources via KnowledgeService.list_sources().

Backs the forge sources list CLI (MET-411). Mirrors the schema surfaced by the metaforge://knowledge/sources MCP resource.

query Parameters
KnowledgeType (string) or Knowledgetype (null) (Knowledgetype)

Filter by knowledge type

Projectid (string) or Projectid (null) (Projectid)

Filter by project UUID

limit
integer (Limit) [ 1 .. 1000 ]
Default: 100

Max sources to return

offset
integer (Offset) >= 0
Default: 0

Pagination offset

Responses

Response samples

Content type
application/json
{
  • "sources": [
    ],
  • "total": 0
}

Delete Knowledge Source

Delete every chunk for a source via KnowledgeService.delete_by_source().

Backs the forge sources delete CLI (MET-411). Returns the chunk count the backend removed; 0 when the source was already absent — callers treat that as a no-op rather than an error.

path Parameters
source_path
required
string (Source Path)

Responses

Response samples

Content type
application/json
{
  • "deletedChunks": 0,
  • "sourcePath": "string"
}

Get Knowledge Source

Per-source detail — looks up by exact source_path match.

No dedicated single-source accessor exists in the KnowledgeService contract, so we list and find — fine for CLI usage where the user has already picked a known path. Returns 404 when the source isn't registered.

path Parameters
source_path
required
string (Source Path)
query Parameters
Projectid (string) or Projectid (null) (Projectid)

Filter by project UUID

Responses

Response samples

Content type
application/json
{
  • "chunks": [
    ],
  • "fragmentCount": 0,
  • "indexedAt": "2019-08-24T14:15:22Z",
  • "knowledgeType": "string",
  • "metadata": { },
  • "sourcePath": "string"
}

Get Knowledge Entry

Retrieve a single knowledge entry by ID.

path Parameters
entry_id
required
string <uuid> (Entry Id)

Responses

Response samples

Content type
application/json
{
  • "chunkIndex": 0,
  • "content": "string",
  • "createdAt": "2019-08-24T14:15:22Z",
  • "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
  • "knowledgeType": "design_decision",
  • "metadata": { },
  • "sourcePath": "string",
  • "sourceWorkProductId": "c83b8d43-b0ff-4427-847b-87295ebb87a8",
  • "totalChunks": 0
}

manufacture

Release For Manufacture

query Parameters
work_product_id
required
string (Work Product Id)
process
required
string (Process)

'3d_print' (-> STL) or 'cnc' (-> STEP)

Responses

Response samples

Content type
application/json
{
  • "content_base64": "string",
  • "file_size_bytes": 0,
  • "filename": "string",
  • "format": "string",
  • "process": "string",
  • "work_product_id": "string"
}

memory

Get Component Context

Component usage / relationship knowledge for name (MET-471).

Wraps MemoryClient.get_component_context: a typed convenience over the L1 knowledge base keyed off KnowledgeType.COMPONENT. Empty / whitespace name returns 422 — that's a client bug, not a backend gap.

path Parameters
name
required
string (Name)
query Parameters
limit
integer (Limit) [ 1 .. 50 ]
Default: 5
Projectid (string) or Projectid (null) (Projectid)

Responses

Response samples

Content type
application/json
{
  • "hits": [
    ],
  • "query": "string",
  • "totalFound": 0
}

Trigger Consolidation

Trigger one consolidation pass synchronously.

Defaults to on_demand mode (manual triage with the importance floor relaxed). Pass mode=background to run the standard pass or mode=janitor to re-validate previously-stored insights without synthesizing new ones.

Request Body schema: application/json
required
Fetchlimit (integer) or Fetchlimit (null) (Fetchlimit)
Minimportance (number) or Minimportance (null) (Minimportance)
mode
string (ConsolidationMode)
Default: "on_demand"
Enum: "background" "on_demand" "proactive" "janitor"

Consolidation mode. Defaults to on_demand since the REST endpoint is a manual trigger; the Temporal worker handles background.

Projectid (string) or Projectid (null) (Projectid)
Since (string) or Since (null) (Since)
ConsolidationTheme (string) or null
Until (string) or Until (null) (Until)

Responses

Request samples

Content type
application/json
{
  • "fetchLimit": 1,
  • "minImportance": 0,
  • "mode": "background",
  • "projectId": "5a8591dd-4039-49df-9202-96385ba3eff8",
  • "since": "2019-08-24T14:15:22Z",
  • "theme": "mechanical_validation",
  • "until": "2019-08-24T14:15:22Z"
}

Response samples

Content type
application/json
{
  • "acceptedCount": 0,
  • "fetchedCount": 0,
  • "groupCount": 0,
  • "mode": "background",
  • "newlyFailedCount": 0,
  • "rejectedCount": 0,
  • "rejectedReasons": [
    ],
  • "revalidatedCount": 0,
  • "synthesizedCount": 0
}

List Insights

List consolidated insights, newest first.

Excludes STALE_WARN insights by default — agents should act on fresh lessons. Pass includeStale=true for an audit / review view that includes faded insights. Optional theme narrows to one consolidation theme.

query Parameters
ConsolidationTheme (string) or Theme (null) (Theme)
includeStale
boolean (Includestale)
Default: false
limit
integer (Limit) [ 1 .. 500 ]
Default: 50

Responses

Response samples

Content type
application/json
{
  • "includeStale": true,
  • "insights": [
    ],
  • "theme": "mechanical_validation",
  • "total": 0
}

Retrieve Similar Experience

Return experiences most similar to the supplied goal.

Body shape matches MemoryRetrieveRequest. The response carries hits sorted by descending similarity, plus the echoed query and total_found so callers can paginate without re-derivation.

Request Body schema: application/json
required
Agentcode (string) or Agentcode (null) (Agentcode)

Optional filter to a specific agent.

goal
required
string (Goal) non-empty

Natural-language description of the task.

limit
integer (Limit) [ 1 .. 50 ]
Default: 5

Maximum number of experiences to return.

Minsimilarity (number) or Minsimilarity (null) (Minsimilarity)

Optional retrieval-confidence floor: drop hits whose cosine similarity is below this value. None = no floor.

Onlysuccess (boolean) or Onlysuccess (null) (Onlysuccess)

True = success-only, False = failures-only, None = no filter.

Projectid (string) or Projectid (null) (Projectid)

Optional project scope.

Responses

Request samples

Content type
application/json
{
  • "agentCode": "string",
  • "goal": "string",
  • "limit": 5,
  • "minSimilarity": -1,
  • "onlySuccess": true,
  • "projectId": "5a8591dd-4039-49df-9202-96385ba3eff8"
}

Response samples

Content type
application/json
{
  • "hits": [
    ],
  • "query": "string",
  • "totalFound": 0
}

Search Design Rationale

Semantic search over design-decision knowledge (MET-471).

Wraps MemoryClient.search_design_rationale: a typed convenience over the L1 knowledge base that asks "why was X decided?" and returns ranked hits keyed off KnowledgeType.DESIGN_DECISION. Requires the gateway to have wired a knowledge_service on app.state.knowledge_service; the 503 from _get_client covers the case where the service hasn't initialised.

Request Body schema: application/json
required
limit
integer (Limit) [ 1 .. 50 ]
Default: 5

Maximum number of hits to return.

Projectid (string) or Projectid (null) (Projectid)

Optional project scope.

query
required
string (Query) non-empty

Natural-language query against design-decision knowledge.

Responses

Request samples

Content type
application/json
{
  • "limit": 5,
  • "projectId": "5a8591dd-4039-49df-9202-96385ba3eff8",
  • "query": "string"
}

Response samples

Content type
application/json
{
  • "hits": [
    ],
  • "query": "string",
  • "totalFound": 0
}

projects

List Projects

List all hardware projects.

Responses

Response samples

Content type
application/json
{
  • "projects": [
    ],
  • "total": 0
}

Create Project

Create a new hardware project (starts with no work products).

Request Body schema: application/json
required
description
string (Description) <= 2000 characters
Default: ""

Project description

name
required
string (Name) [ 1 .. 200 ] characters

Project name

status
string (Status)
Default: "draft"

Initial project status

Responses

Request samples

Content type
application/json
{
  • "description": "",
  • "name": "string",
  • "status": "draft"
}

Response samples

Content type
application/json
{
  • "agent_count": 0,
  • "created_at": "string",
  • "description": "string",
  • "id": "string",
  • "last_updated": "string",
  • "name": "string",
  • "status": "string",
  • "work_products": [
    ]
}

Delete Project

Delete a project by ID.

path Parameters
project_id
required
string (Project Id)

Responses

Response samples

Content type
application/json
{
  • "detail": [
    ]
}

Get Project

Get a single project by ID.

path Parameters
project_id
required
string (Project Id)

Responses

Response samples

Content type
application/json
{
  • "agent_count": 0,
  • "created_at": "string",
  • "description": "string",
  • "id": "string",
  • "last_updated": "string",
  • "name": "string",
  • "status": "string",
  • "work_products": [
    ]
}

Update Project

Rename, redescribe, or change the status of an existing project.

path Parameters
project_id
required
string (Project Id)
Request Body schema: application/json
required
Description (string) or Description (null) (Description)
Name (string) or Name (null) (Name)
Status (string) or Status (null) (Status)

Responses

Request samples

Content type
application/json
{
  • "description": "string",
  • "name": "string",
  • "status": "string"
}

Response samples

Content type
application/json
{
  • "agent_count": 0,
  • "created_at": "string",
  • "description": "string",
  • "id": "string",
  • "last_updated": "string",
  • "name": "string",
  • "status": "string",
  • "work_products": [
    ]
}

promotion

List Promotions

query Parameters
project_id
required
string (Project Id)

Responses

Response samples

Content type
application/json
{
  • "gates": [
    ]
}

Attempt Promotion Route

Promote (or veto), attributed to whoever made this request.

A dashboard click is a human act, so this route needs no separate approval hop the way the MCP path does — but the authority is still read off the request rather than the body (FORGE-393).

Request Body schema: application/json
required
Comment (string) or Comment (null) (Comment)
k
number (K)
Default: 1
level
required
string (Level)
projectId
required
string (Projectid)
reject
boolean (Reject)
Default: false
requiredClaimIds
required
Array of strings (Requiredclaimids)

Responses

Request samples

Content type
application/json
{
  • "comment": "string",
  • "k": 1,
  • "level": "string",
  • "projectId": "string",
  • "reject": false,
  • "requiredClaimIds": [
    ]
}

Response samples

Content type
application/json
{
  • "blockedReason": "string",
  • "comment": "string",
  • "decidedBy": "string",
  • "gateId": "string",
  • "level": "string",
  • "promoted": true,
  • "results": [
    ]
}

releases

List Releases

query Parameters
project_id
required
string (Project Id)

Responses

Response samples

Content type
application/json
{
  • "releases": [
    ]
}

Create Release

Request Body schema: application/json
required
Notes (string) or Notes (null) (Notes)
project_id
required
string (Project Id)

Responses

Request samples

Content type
application/json
{
  • "notes": "string",
  • "project_id": "string"
}

Response samples

Content type
application/json
{
  • "created_at": "string",
  • "diff_from_previous": {
    },
  • "gate_status": "string",
  • "node_id": "string",
  • "snapshot": {
    },
  • "statement": "string",
  • "title": "string"
}

requirements

Create Constraint

FORGE-259: create one structured constraint (metric/operator/limit/ unit/target_node_type) from the dashboard's constraint editor. Live pass/fail/no_data status for it then comes from the existing GET /v1/requirements/matrix, computed from real Claim/Evidence data -- this route only ever records the requirement's own declaration.

Request Body schema: application/json
required
expectedEvidence
string (Expectedevidence)
Default: ""
limit
required
number (Limit)
message
string (Message)
Default: ""
metric
required
string (Metric)
name
required
string (Name)
operator
string (Operator)
Default: "<="
projectId
required
string (Projectid)
severity
string (Severity)
Default: "error"
targetNodeType
string (Targetnodetype)
Default: ""
unit
string (Unit)
Default: ""
verificationMethod
string (Verificationmethod)
Default: ""

Responses

Request samples

Content type
application/json
{
  • "expectedEvidence": "",
  • "limit": 0,
  • "message": "",
  • "metric": "string",
  • "name": "string",
  • "operator": "<=",
  • "projectId": "string",
  • "severity": "error",
  • "targetNodeType": "",
  • "unit": "",
  • "verificationMethod": ""
}

Response samples

Content type
application/json
{
  • "constraintId": "string",
  • "setWorkProductId": "string"
}

Get Requirement Coverage

FORGE-297 (gap G-I1): the 5 traceability coverage percentages (needs->requirements, requirements->architecture, requirements-> verification, verification->evidence, critical_requirements->evidence), computed live by TraceabilityAgent (FORGE-56/73) -- previously real, tested code with no gateway route exposing it at all.

query Parameters
project_id
required
string (Project Id)

Responses

Response samples

Content type
application/json
{
  • "critical_requirements_to_evidence": 0,
  • "needs_to_requirements": 0,
  • "requirements_to_architecture": 0,
  • "requirements_to_verification": 0,
  • "verification_to_evidence": 0
}

Get Requirement Matrix

FORGE-318: requirements x claims x evidence, one row per real requirement -- status (pass/uncertain/fail/no_data/stale) derived live from current claim + evidence staleness state, never cached.

query Parameters
project_id
required
string (Project Id)

Responses

Response samples

Content type
application/json
{
  • "revisionRefs": [ ],
  • "rows": [
    ]
}

Get Requirement Quality

query Parameters
project_id
required
string (Project Id)
product_type
string (Product Type)
Default: "generic"

Responses

Response samples

Content type
application/json
{
  • "completeness": {
    },
  • "conflicts": [
    ],
  • "requirements": [
    ]
}

Propose Requirement Fix

Generate a proposed rewrite for one flawed requirement -- diagnoses with the same deterministic linter the quality report already used, then asks the Requirement Author agent for a corrected version linked back to the original via REFINES. Never writes anything itself; the caller applies the resulting patch through the normal review path.

path Parameters
requirement_id
required
string (Requirement Id)

Responses

Response samples

Content type
application/json
{
  • "conclusions": [
    ],
  • "proposedText": "string",
  • "rationale": "string"
}

robot-loads

Compute Joint Loads

Request Body schema: application/json
required
required
Array of objects (Joints)
required
Array of objects (Links)
payload_mass_kg
number (Payload Mass Kg)
Default: 0
Array of Payload Position World Mm (items) or Payload Position World Mm (null) (Payload Position World Mm)

Responses

Request samples

Content type
application/json
{
  • "joints": [
    ],
  • "links": [
    ],
  • "payload_mass_kg": 0,
  • "payload_position_world_mm": [
    ]
}

Response samples

Content type
application/json
{
  • "loads": [
    ],
  • "worst_joint": {
    }
}

runs

List Runs

Every run, or one project's.

Unfiltered before: /runs showed every project's work in one list, and the project a run belonged to was only inside its request blob. Passing project_id scopes it; the response says how many runs were left out for having no project, so they do not simply vanish.

query Parameters
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "runs": [
    ],
  • "unscoped_count": 0
}

Create Run

Request Body schema: application/json
required
object (Request)

Opaque run input (goal, spec, config) handed to the harness.

start
boolean (Start)
Default: true

Transition queued -> running immediately after creation.

Responses

Request samples

Content type
application/json
{
  • "request": { },
  • "start": true
}

Response samples

Content type
application/json
{
  • "approval_deadline": 0,
  • "approval_reason": "string",
  • "approved_by": "string",
  • "approver_verified": false,
  • "created_at": 0,
  • "engine": "string",
  • "error": "string",
  • "flow_content_hash": "string",
  • "flow_version_id": "string",
  • "history": [
    ],
  • "id": "string",
  • "project_id": "string",
  • "request": { },
  • "result": { },
  • "status": "string",
  • "updated_at": 0,
  • "usage": { }
}

Get Usage Summary

LLM tokens and cost across all runs for the trailing window (FORGE-476).

query Parameters
window_hours
number (Window Hours)
Default: 24

Responses

Response samples

Content type
application/json
{ }

Get Run

path Parameters
run_id
required
string (Run Id)

Responses

Response samples

Content type
application/json
{
  • "approval_deadline": 0,
  • "approval_reason": "string",
  • "approved_by": "string",
  • "approver_verified": false,
  • "created_at": 0,
  • "engine": "string",
  • "error": "string",
  • "flow_content_hash": "string",
  • "flow_version_id": "string",
  • "history": [
    ],
  • "id": "string",
  • "project_id": "string",
  • "request": { },
  • "result": { },
  • "status": "string",
  • "updated_at": 0,
  • "usage": { }
}

Submit Approval

Answer the gate this run is parked at.

Async so the store transition — which resolves the in-process executor's gate future via the coordinator — runs on the event-loop thread (future resolution is not thread-safe from FastAPI's sync worker pool).

On Temporal the decision is also signalled into the workflow, which is what actually resumes it (FORGE-401). The store transition stays, because the run list, the SSE stream and the ledger all read from it.

The deciding human comes from the request, never the body (FORGE-393).

path Parameters
run_id
required
string (Run Id)
Request Body schema: application/json
required
decision
required
string (Decision)
Enum: "approve" "reject" "retry" "rework"
reason
string (Reason) <= 2000 characters
Default: ""
to_phase
string (To Phase) <= 200 characters
Default: ""

Responses

Request samples

Content type
application/json
{
  • "decision": "approve",
  • "reason": "",
  • "to_phase": ""
}

Response samples

Content type
application/json
{
  • "approval_deadline": 0,
  • "approval_reason": "string",
  • "approved_by": "string",
  • "approver_verified": false,
  • "created_at": 0,
  • "engine": "string",
  • "error": "string",
  • "flow_content_hash": "string",
  • "flow_version_id": "string",
  • "history": [
    ],
  • "id": "string",
  • "project_id": "string",
  • "request": { },
  • "result": { },
  • "status": "string",
  • "updated_at": 0,
  • "usage": { }
}

Stream Run Events

SSE stream of a run's status transitions until it reaches a terminal state.

path Parameters
run_id
required
string (Run Id)

Responses

Response samples

Content type
application/json
null

Get Flow State

Phase-by-phase state of a design-flow run.

Queries the Temporal workflow. A workflow query is answered by a worker, so with none running there is nobody to answer -- which is reported as live: false with a reason rather than as an empty flow, because an empty flow and a flow nobody can see render identically and mean opposite things.

path Parameters
run_id
required
string (Run Id)

Responses

Response samples

Content type
application/json
{
  • "attempt": 1,
  • "awaitingGate": "string",
  • "currentPhase": "string",
  • "detail": "",
  • "error": "string",
  • "events": [
    ],
  • "flow": "string",
  • "flowContentHash": "string",
  • "flowVersion": "string",
  • "flowVersionId": "string",
  • "gateFindings": [
    ],
  • "gateReady": true,
  • "live": true,
  • "maxReworkCycles": 0,
  • "phases": [
    ],
  • "retriesLeft": 0,
  • "reworkCycles": 0,
  • "reworksLeft": 0,
  • "runId": "string",
  • "status": "string",
  • "usage": { }
}

Gate Opened

Record that a run's workflow has opened a gate (FORGE-489).

Called by the design-flow worker's announcer. The workflow is the authority on whether a gate is open, so this first re-reads it (_reconcile_run). Only when the workflow cannot be asked does it fall back to the worker's word. Either way it moves the record to awaiting_approval, which is what lists the run on the Approvals page and publishes the change on its SSE stream. It never approves: a decision still has to come through /approval, and the workflow ignores one for a gate that is not open.

path Parameters
run_id
required
string (Run Id)
Request Body schema: application/json
required
gate
required
string (Gate) non-empty
reason
string (Reason)
Default: ""

Responses

Request samples

Content type
application/json
{
  • "gate": "string",
  • "reason": ""
}

Response samples

Content type
application/json
{
  • "approval_deadline": 0,
  • "approval_reason": "string",
  • "approved_by": "string",
  • "approver_verified": false,
  • "created_at": 0,
  • "engine": "string",
  • "error": "string",
  • "flow_content_hash": "string",
  • "flow_version_id": "string",
  • "history": [
    ],
  • "id": "string",
  • "project_id": "string",
  • "request": { },
  • "result": { },
  • "status": "string",
  • "updated_at": 0,
  • "usage": { }
}

Get Run Lifecycle

The lifecycle view of one design run, with its completion verdict.

path Parameters
run_id
required
string (Run Id)

Responses

Response samples

Content type
application/json
{
  • "lifecycle": { },
  • "limits": [
    ],
  • "live": true,
  • "nextStep": "",
  • "runId": "string"
}

Propose Run Patch

Plan a change to a running flow and hold it for a person.

Nothing changes until somebody approves the approval this returns, and then POST /v1/runs/{run_id}/patches/{version_id}/apply applies it at the run's next gate. Only the phases the change touches re-run.

path Parameters
run_id
required
string (Run Id)
Request Body schema: application/json
required
expectedContentHash
required
string (Expectedcontenthash)
invalidate
Array of strings (Invalidate)
Array of objects (Operations)
reason
required
string (Reason)

Responses

Request samples

Content type
application/json
{
  • "expectedContentHash": "string",
  • "invalidate": [
    ],
  • "operations": [
    ],
  • "reason": "string"
}

Response samples

Content type
application/json
{
  • "added": [
    ],
  • "approvalId": "string",
  • "changes": [
    ],
  • "nextStep": "string",
  • "notes": [
    ],
  • "preserved": [
    ],
  • "removed": [
    ],
  • "rerun": [
    ],
  • "runId": "string",
  • "versionId": "string"
}

Apply Run Patch

Apply an approved patch. Refused unless approved and still current.

path Parameters
run_id
required
string (Run Id)
version_id
required
string (Version Id)

Responses

Response samples

Content type
application/json
{
  • "nextStep": "string",
  • "rerun": [
    ],
  • "runId": "string",
  • "versionId": "string"
}

sessions

List Sessions

List all agent sessions.

Merges internal Temporal WorkflowRuns with externally-recorded agent sessions (MET-493) so MCP/CLI-driven work shows up alongside autonomous runs. Most-recent-first.

project_id scopes to one project (MET-516). Internal Temporal runs carry no project, so they're excluded when a project filter is set.

query Parameters
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "sessions": [
    ],
  • "total": 0,
  • "unscoped_count": 0
}

Create Session

Open a new externally-recorded agent session.

Request Body schema: application/json
required
agent_code
required
string (Agent Code)
Project Id (string) or Project Id (null) (Project Id)
task_type
required
string (Task Type)
Title (string) or Title (null) (Title)

Responses

Request samples

Content type
application/json
{
  • "agent_code": "string",
  • "project_id": "string",
  • "task_type": "string",
  • "title": "string"
}

Response samples

Content type
application/json
{
  • "agent_code": "string",
  • "completed_at": "string",
  • "events": [
    ],
  • "id": "string",
  • "project_id": "string",
  • "run_id": "string",
  • "source": "string",
  • "started_at": "string",
  • "status": "string",
  • "summary": "string",
  • "task_type": "string"
}

Get Session

Get a single session by ID (store first, then workflow engine).

path Parameters
session_id
required
string (Session Id)

Responses

Response samples

Content type
application/json
{
  • "agent_code": "string",
  • "completed_at": "string",
  • "events": [
    ],
  • "id": "string",
  • "project_id": "string",
  • "run_id": "string",
  • "source": "string",
  • "started_at": "string",
  • "status": "string",
  • "summary": "string",
  • "task_type": "string"
}

Update Session

Complete a session (set terminal status + optional summary).

path Parameters
session_id
required
string (Session Id)
Request Body schema: application/json
required
status
required
string (Status)
Summary (string) or Summary (null) (Summary)

Responses

Request samples

Content type
application/json
{
  • "status": "string",
  • "summary": "string"
}

Response samples

Content type
application/json
{
  • "agent_code": "string",
  • "completed_at": "string",
  • "events": [
    ],
  • "id": "string",
  • "project_id": "string",
  • "run_id": "string",
  • "source": "string",
  • "started_at": "string",
  • "status": "string",
  • "summary": "string",
  • "task_type": "string"
}

Append Session Event

Append one event (thought / action / decision / …) to a session.

path Parameters
session_id
required
string (Session Id)
Request Body schema: application/json
required
object (Data)
message
required
string (Message)
type
required
string (Type)

Responses

Request samples

Content type
application/json
{
  • "data": { },
  • "message": "string",
  • "type": "string"
}

Response samples

Content type
application/json
{
  • "event_id": "string",
  • "seq": 0
}

simulation

List Load Cases

List load cases, optionally scoped to a project.

Empty (not a 404) when the project has none yet, matching /v1/bom.

query Parameters
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "loadCases": [
    ],
  • "total": 0
}

Create Load Case

Create a load case, via the same document-recorder path twin.record_document(document_type='load_case') uses (see module docstring) so a dashboard-authored and agent-authored case are indistinguishable on the twin.

Request Body schema: application/json
required
fixedNodeSet
required
string (Fixednodeset) non-empty
loadForceN
required
Array of numbers (Loadforcen) = 3 items
loadNodeSet
required
string (Loadnodeset) non-empty
required
object (Material) non-empty
name
required
string (Name) [ 1 .. 200 ] characters
projectId
required
string (Projectid) non-empty
Sourceofloads (string) or Sourceofloads (null) (Sourceofloads)
Array of Sourcepartnodeids (strings) or Sourcepartnodeids (null) (Sourcepartnodeids)

Responses

Request samples

Content type
application/json
{
  • "fixedNodeSet": "string",
  • "loadForceN": [
    ],
  • "loadNodeSet": "string",
  • "material": { },
  • "name": "string",
  • "projectId": "string",
  • "sourceOfLoads": "string",
  • "sourcePartNodeIds": [
    ]
}

Response samples

Content type
application/json
{
  • "createdAt": "string",
  • "fixedNodeSet": "string",
  • "id": "string",
  • "loadForceN": [
    ],
  • "loadNodeSet": "string",
  • "material": { },
  • "name": "string",
  • "projectId": "string",
  • "sourceOfLoads": "string",
  • "updatedAt": "string"
}

List Named Faces

Named-face geometry for an already-generated mesh (FORGE-277).

Backs the dashboard's geometric boundary-condition face picker: given a mesh file path (from an earlier freecad.generate_mesh call, e.g. surfaced in a forge chat turn), returns each named surface group's real centroid/normal/area/bbox so the dashboard can render pickable face patches instead of a blind "type the gmsh group name" text field.

Request Body schema: application/json
required
meshFile
required
string (Meshfile) non-empty

Responses

Request samples

Content type
application/json
{
  • "meshFile": "string"
}

Response samples

Content type
application/json
{
  • "faces": [
    ],
  • "meshFile": "string"
}

List Simulation Results

List FEA results, optionally scoped to a project (FORGE-279).

Empty (not a 404) when the project has none yet, matching list_load_cases. Creation is agent-driven only (see module docstring) — there is no corresponding POST.

query Parameters
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "results": [
    ],
  • "total": 0
}

Get Simulation Result Field

Serve a simulation_result's 3D result field (FORGE-532).

404 field not stored for a result recorded without one (every result before FORGE-532, or one whose MinIO write failed); the dashboard treats that as "show the numbers only".

path Parameters
result_id
required
string (Result Id)

Responses

Response samples

Content type
application/json
{
  • "detail": [
    ]
}

technical-drawings

List Technical Drawings

query Parameters
work_product_id
required
string (Work Product Id)

Responses

Response samples

Content type
application/json
{
  • "drawings": [
    ]
}

testplans

List Test Plan

query Parameters
project_id
required
string (Project Id)

Responses

Response samples

Content type
application/json
{
  • "entries": [
    ]
}

Generate Test Plan

Request Body schema: application/json
required
project_id
required
string (Project Id)

Responses

Request samples

Content type
application/json
{
  • "project_id": "string"
}

Response samples

Content type
application/json
{
  • "entries": [
    ],
  • "project_id": "string"
}

trade-study

List Concept Options

query Parameters
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{ }

Add Concept Option

Request Body schema: application/json
required
required
object (Criteriascores)
evidenceBackedCriteria
Array of strings (Evidencebackedcriteria)
Default: []
Projectid (string) or Projectid (null) (Projectid)
title
required
string (Title)

Responses

Request samples

Content type
application/json
{
  • "criteriaScores": {
    },
  • "evidenceBackedCriteria": [ ],
  • "projectId": "string",
  • "title": "string"
}

Response samples

Content type
application/json
{ }

Select Concept

Request Body schema: application/json
required
optionIds
required
Array of strings (Optionids)
Projectid (string) or Projectid (null) (Projectid)
rationale
required
string (Rationale)
Array of Requirementids (strings) or Requirementids (null) (Requirementids)
selectedOptionId
required
string (Selectedoptionid)
title
required
string (Title)
required
object (Weights)

Responses

Request samples

Content type
application/json
{
  • "optionIds": [
    ],
  • "projectId": "string",
  • "rationale": "string",
  • "requirementIds": [
    ],
  • "selectedOptionId": "string",
  • "title": "string",
  • "weights": {
    }
}

Response samples

Content type
application/json
{ }

twin

List Baselines

A project's baselines, newest first.

query Parameters
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "baselines": [
    ],
  • "total": 0
}

Diff Baselines Route

Per item: unchanged, changed (@x -> @y), added or removed between a and b.

query Parameters
a
required
string (A)

Baseline id

b
required
string (B)

Baseline id, or 'current' for the project's current items

Responses

Response samples

Content type
application/json
{
  • "a": {
    },
  • "b": {
    },
  • "b_is_current": false,
  • "counts": {
    },
  • "items": [
    ]
}

Get Baseline

One baseline with its item pins and constraint/entity members.

path Parameters
baseline_id
required
string (Baseline Id)

Responses

Response samples

Content type
application/json
{
  • "approved_by": [
    ],
  • "created_at": "string",
  • "gate_id": "string",
  • "id": "string",
  • "item_count": 0,
  • "items": [
    ],
  • "member_count": 0,
  • "members": [
    ],
  • "name": "string",
  • "project_id": "string",
  • "reason": "",
  • "run_id": "string",
  • "source": "manual"
}

Get Current View

The project's current items, records, counts and readiness (current items only).

query Parameters
project_id
required
string (Project Id)

Responses

Response samples

Content type
application/json
{
  • "counts": { },
  • "groups": [
    ],
  • "items": [
    ],
  • "latest_baseline": {
    },
  • "other": [
    ],
  • "project_id": "string",
  • "readiness": 0,
  • "records": [
    ]
}

Get Hierarchy Tree

List a project's hierarchy nodes, each with its parent link and its own rolled-up mass/cost.

Empty (not a 404) when the project has none yet, matching /v1/bom. Note: computes one rollup per node (each its own subtree walk) -- fine at the scale a hand-built product hierarchy actually reaches, not optimized for a tree of thousands of nodes.

query Parameters
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "malformedBudgets": [ ],
  • "nodes": [
    ]
}

Realize Hierarchy Node

"Replace placeholder with part": attach or replace node_id's REALIZED_BY (a cad_model work product, e.g. from POST /v1/twin/import) and/or INSTANCE_OF (a BOMItem) geometry -- the dashboard's own action reuses the SAME bound callable twin.realize_hierarchy_node uses.

path Parameters
node_id
required
string (Node Id)
Request Body schema: application/json
required
Bomitemid (string) or Bomitemid (null) (Bomitemid)
Workproductid (string) or Workproductid (null) (Workproductid)

Responses

Request samples

Content type
application/json
{
  • "bomItemId": "string",
  • "workProductId": "string"
}

Response samples

Content type
application/json
{
  • "instanceOfBomItemId": "string",
  • "nodeId": "string",
  • "realizedByWorkProductId": "string"
}

Import Work Product

Upload a design file and register it as a work product in the Twin.

Accepts STEP, IGES, KiCad (.kicad_sch, .kicad_pcb), and FreeCAD (.FCStd) files. Metadata is extracted automatically based on file type.

Request Body schema: multipart/form-data
required
description
string (Description)
Default: ""

Work product description

Domain (string) or Domain (null) (Domain)

Domain (mechanical, electronics)

file
required
string <application/octet-stream> (File)

Design file to import

Project Id (string) or Project Id (null) (Project Id)

Project to link to

Wp Type (string) or Wp Type (null) (Wp Type)

Work product type

Responses

Response samples

Content type
application/json
{
  • "content_hash": "string",
  • "created_at": "string",
  • "domain": "string",
  • "file_path": "string",
  • "format": "string",
  • "id": "string",
  • "metadata": { },
  • "name": "string",
  • "project_id": "string",
  • "wp_type": "string"
}

Check Interference

Real boolean-intersection clearance/interference check between two named parts' committed STEP geometry (FORGE-272, gap G-D4).

Deliberately a pairwise check on two caller-named parts, not an all-pairs sweep across an entire assembly, and deliberately not an ISO 286 tolerance-grade/fit classification -- see api_gateway.twin.interference_check's module docstring for why both are out of scope here.

query Parameters
work_product_id_a
required
string (Work Product Id A)
work_product_id_b
required
string (Work Product Id B)

Responses

Response samples

Content type
application/json
{
  • "interference_area_mm2": 0,
  • "interference_volume_mm3": 0,
  • "interferes": true,
  • "work_product_id_a": "string",
  • "work_product_id_b": "string"
}

List Twin Items

Versioned definitions, each at its current head.

query Parameters
Project Id (string) or Project Id (null) (Project Id)
Item Type (string) or Item Type (null) (Item Type)

e.g. cad_model, constraint_set

Responses

Response samples

Content type
application/json
{
  • "items": [
    ],
  • "total": 0
}

Get Item Diff

Geometry delta, parameter, requirement and field changes between two revisions.

path Parameters
key
required
string (Key)
query Parameters
A (string) or A (null) (A)

Older revision, e.g. 2 or @2

B (string) or B (null) (B)

Newer revision; defaults to the current one

Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "a": { },
  • "a_ref": "string",
  • "b": { },
  • "b_ref": "string",
  • "dependents": [
    ],
  • "fields": [
    ],
  • "geometry": { },
  • "item_type": "string",
  • "key": "string",
  • "name": "string",
  • "parameters": [
    ],
  • "requirements": [
    ],
  • "warnings": [
    ]
}

Get Item Prd

One prd prose revision (KEY or KEY@n) with the current requirements.

path Parameters
key
required
string (Key)
query Parameters
Project Id (string) or Project Id (null) (Project Id)
Run Id (string) or Run Id (null) (Run Id)

Read as this design-flow run: include its open drafts

Responses

Response samples

Content type
application/json
{
  • "markdown": "string",
  • "project_id": "string",
  • "prose_ref": "string",
  • "refs": [
    ],
  • "requirement_count": 0,
  • "requirement_refs": [
    ],
  • "sources": [
    ],
  • "title": "string"
}

Get Item Revisions

Every revision of one item, oldest first. key may carry an @n suffix.

path Parameters
key
required
string (Key)
query Parameters
Project Id (string) or Project Id (null) (Project Id)
Run Id (string) or Run Id (null) (Run Id)

Read as this design-flow run: include its open drafts

Responses

Response samples

Content type
application/json
{
  • "current": {
    },
  • "item": {
    },
  • "lessons": [ ],
  • "revisions": [
    ]
}

List Twin Nodes

List work-product nodes in the Digital Twin.

project_id scopes the view to a single project (MET-491). Omitted or empty returns every node (including unscoped legacy nodes) — preserving the prior global behaviour. A specific project_id returns only that project's nodes; unscoped nodes are excluded.

FORGE-525: a design-flow run's drafts are left out until its gate approves them (and for good if it never does); include_drafts=true lists them too.

query Parameters
Domain (string) or Domain (null) (Domain)
Project Id (string) or Project Id (null) (Project Id)
include_drafts
boolean (Include Drafts)
Default: false

Responses

Response samples

Content type
application/json
{
  • "nodes": [
    ],
  • "total": 0
}

Boolean Cut Nodes

Real CSG boolean-cut between two committed STEP work products (MET-612).

A direct-commit endpoint, not the twin.propose_change/apply HITL pipeline — a human cutting their own open model is not meaningfully different from clicking Save (same rationale as twin.record_document, whose apply executor doesn't fit this action either). Drives the containerized CadQuery adapter via the shared MCP bridge, then commits the result through the geometry recorder with provenance edges to both inputs.

Request Body schema: application/json
required
cutter_node_id
required
string (Cutter Node Id) non-empty
operation
string (Operation)
Default: "subtract"
Enum: "subtract" "union" "intersect"
Result Name (string) or Result Name (null) (Result Name)
target_node_id
required
string (Target Node Id) non-empty

Responses

Request samples

Content type
application/json
{
  • "cutter_node_id": "string",
  • "operation": "subtract",
  • "result_name": "string",
  • "target_node_id": "string"
}

Response samples

Content type
application/json
{
  • "node": {
    },
  • "operation": "string",
  • "result_area_mm2": 0,
  • "result_volume_mm3": 0
}

Delete Node

Delete a work-product node, its project links, and its MinIO blob (MET-484).

Without cascade a delete that would orphan dependents returns 409. Best-effort on the blob (a storage failure doesn't block the delete).

path Parameters
node_id
required
string (Node Id)
query Parameters
cascade
boolean (Cascade)
Default: false

Also delete dependents that would orphan

Responses

Response samples

Content type
application/json
{
  • "detail": [
    ]
}

Get Twin Node

Get a single work-product node by ID.

path Parameters
node_id
required
string (Node Id)

Responses

Response samples

Content type
application/json
{
  • "assembly": { },
  • "assemblyParts": [
    ],
  • "dependsOn": [
    ],
  • "domain": "string",
  • "geometryParameters": { },
  • "hasScript": false,
  • "id": "string",
  • "meshStats": { },
  • "name": "string",
  • "poses": {
    },
  • "projectId": "string",
  • "properties": {
    },
  • "staleness": {
    },
  • "status": "string",
  • "technicalDrawing": { },
  • "type": "string",
  • "updatedAt": "string"
}

Approve Design Sketch

Human sign-off on a design_sketch work product (follow-up to MET-740/747).

The forge/agent side creates a sketch as unapproved (twin.commit_design_sketch); this is the dashboard's side of the gate — a human explicitly approving it before the calling agent is expected to proceed to real CAD/build work.

path Parameters
node_id
required
string <uuid> (Node Id)
Request Body schema: application/json
required
Approved By (string) or Approved By (null) (Approved By)

Identifier of the human approving this sketch.

Any of
string (Approved By)

Identifier of the human approving this sketch.

Responses

Request samples

Content type
application/json
{
  • "approved_by": "string"
}

Response samples

Content type
application/json
{
  • "approved": true,
  • "approved_at": "string",
  • "node_id": "string"
}

Approve Technical Drawing

Human sign-off on a technical_drawing work product (FORGE-293, gap G-H1).

Mirrors approve_design_sketch above -- a real work product, a real approval gate, not a dashboard-local checkbox.

path Parameters
node_id
required
string <uuid> (Node Id)
Request Body schema: application/json
required
Approved By (string) or Approved By (null) (Approved By)

Identifier of the human approving this drawing.

Any of
string (Approved By)

Identifier of the human approving this drawing.

Responses

Request samples

Content type
application/json
{
  • "approved_by": "string"
}

Response samples

Content type
application/json
{
  • "approved": true,
  • "approved_at": "string",
  • "node_id": "string"
}

Update Assembly Joints

Add/edit/delete mates+joints on an already-committed assembly node (FORGE-271).

Whole-list replace -- matches how the URDF/SDF/USD export panel's own manual joint-list form already works (FORGE-245/MET-740). Persisted directly onto metadata.assembly.joints: a joint is a logical annotation, not new geometry, so this deliberately skips the full VersionService revision machinery /nodes/{id}/iterate uses for an actual re-export -- editing joints here never touches the underlying committed blob.

Unlike the export panel, this does NOT require a live FreeCAD session or re-running an export -- it works on any already-committed node, any time, which is the whole point (FORGE-245's own fix only got joints persisted onto the node at commit time; this is what makes them editable afterward).

path Parameters
node_id
required
string <uuid> (Node Id)
Request Body schema: application/json
required
required
Array of objects (Joints)
Array
Array of items (Anchor) = 3 items
Default: [0,0,0]
Array of items (Axis) = 3 items
Default: [0,0,1]
base
required
string (Base) non-empty
follower
required
string (Follower) non-empty
Limits (object) or Limits (null) (Limits)
name
required
string (Name) non-empty
type
required
string (Type)

Responses

Request samples

Content type
application/json
{
  • "joints": [
    ]
}

Response samples

Content type
application/json
{
  • "assembly": { },
  • "nodeId": "string"
}

Diff Versions

Return a metadata diff between two revisions (1-indexed).

path Parameters
node_id
required
string <uuid> (Node Id)
query Parameters
v1
required
integer (V1)
v2
required
integer (V2)

Responses

Response samples

Content type
application/json
{
  • "added": { },
  • "changed": {
    },
  • "removed": { },
  • "revision_a": 0,
  • "revision_b": 0,
  • "work_product_id": "string"
}

Download Node File

Stream a work product's stored file for download / open / preview.

download=false (default) returns the blob inline with a preview content-type so the dashboard can render PDFs, images, text, and BOMs in place; download=true forces a Content-Disposition: attachment.

path Parameters
node_id
required
string (Node Id)
query Parameters
download
boolean (Download)
Default: false

Force attachment download vs inline preview

Responses

Response samples

Content type
application/json
null

Download Node Named File

Stream one of a work product's NAMED blobs (MET-740 follow-up).

GET /nodes/{id}/file only ever serves the primary blob. A robot_description node stores N additional mesh blobs (one per URDF link) under metadata["mesh_files"] (link filename -> MinIO object key) — this resolves any of THOSE by filename, or falls back to the primary blob if filename matches it, so the dashboard's existing URDF preview (which expects every mesh reachable at {some_base_url}/{filename}, exactly like a fresh export's _cad_exports/{export_id}/ directory) can point straight at a persisted node with zero re-export round trip.

path Parameters
node_id
required
string (Node Id)
filename
required
string (Filename)

Responses

Response samples

Content type
application/json
null

Diff Geometry

Diff a work product's real geometry against its SUPERSEDES predecessor.

Unlike /diff above (a metadata-revision diff on the SAME node -- /iterate never changes the underlying blob, so no two revisions of one node ever have different geometry), this walks the real SUPERSEDES edge a re-committed, same-named CAD_MODEL gets (api_gateway.twin.geometry_ recorder) and compares the two NODES' actual STEP files.

path Parameters
node_id
required
string (Node Id)

Responses

Response samples

Content type
application/json
{
  • "area_delta_mm2": 0,
  • "current_area_mm2": 0,
  • "current_bounding_box": { },
  • "current_volume_mm3": 0,
  • "current_work_product_id": "string",
  • "previous_area_mm2": 0,
  • "previous_bounding_box": { },
  • "previous_volume_mm3": 0,
  • "previous_work_product_id": "string",
  • "volume_delta_mm3": 0
}

Iterate Work Product

Record a new revision and apply metadata updates to a work product.

path Parameters
node_id
required
string <uuid> (Node Id)
Request Body schema: application/json
required
change_description
required
string (Change Description)
object (Metadata Updates)
Default: {}

Responses

Request samples

Content type
application/json
{
  • "change_description": "string",
  • "metadata_updates": { }
}

Response samples

Content type
application/json
{
  • "change_description": "string",
  • "content_hash": "string",
  • "created_at": "string",
  • "metadata_snapshot": { },
  • "revision": 0
}

Create File Link

Link a work product to an external source file.

The source file must exist on the gateway's filesystem. Once linked, you can call POST /sync to re-import changes, or enable watch for automatic detection.

path Parameters
node_id
required
string (Node Id)
Request Body schema: application/json
required
source_path
required
string (Source Path)

Absolute path to the source file

tool
string (Tool)
Default: ""

Tool identifier (kicad, freecad, cadquery)

watch
boolean (Watch)
Default: true

Enable file watching

Responses

Request samples

Content type
application/json
{
  • "source_path": "string",
  • "tool": "",
  • "watch": true
}

Response samples

Content type
application/json
{
  • "created_at": "string",
  • "last_synced_at": "string",
  • "source_hash": "string",
  • "source_path": "string",
  • "sync_status": "string",
  • "tool": "string",
  • "watch": true,
  • "work_product_id": "string"
}

Get Node Model

Convert a CAD work-product's STEP file to GLB and return the URL.

Reads the STEP file from the shared adapter workspace, converts it via the OCCT converter, and returns the GLB URL + metadata.

path Parameters
node_id
required
string (Node Id)
query Parameters
quality
string (Quality) ^(preview|standard|fine)$
Default: "standard"

Responses

Response samples

Content type
application/json
{ }

Get Node Script

The current git-versioned generation script for a CAD_MODEL node (MET-630).

Lets a dashboard parameter panel seed a regeneration proposal with the script as it stands today, rather than the user retyping it from scratch. 404 when the node has no linked script (imported geometry, or the git backend isn't configured).

path Parameters
node_id
required
string <uuid> (Node Id)

Responses

Response samples

Content type
application/json
{
  • "git_commit_sha": "string",
  • "git_path": "string",
  • "node_id": "string",
  • "script_node_id": "string",
  • "script_source": "string"
}

Sync File Link

Manually trigger a sync for a linked work product.

Re-reads the source file, extracts metadata, and updates the Twin node if the file has changed.

path Parameters
node_id
required
string (Node Id)

Responses

Response samples

Content type
application/json
{ }

Get Version History

Return the full revision history for a work product.

path Parameters
node_id
required
string <uuid> (Node Id)

Responses

Response samples

Content type
application/json
{
  • "revisions": [
    ],
  • "total": 0,
  • "work_product_id": "string"
}

Apply Item Migration

Apply a reviewed plan. Requires approve: true; refused when the twin changed.

path Parameters
project_id
required
string (Project Id)
Request Body schema: application/json
required
approve
boolean (Approve)
Default: false

Must be true: applying the plan writes to the twin.

required
object (MigrationPlan-Input)

The plan exactly as the dry run returned it.

reason
string (Reason)
Default: ""

Why this plan is approved (kept in the log).

Responses

Request samples

Content type
application/json
{
  • "approve": false,
  • "plan": {
    },
  • "reason": ""
}

Response samples

Content type
application/json
{
  • "approved_by": "string",
  • "approver_verified": true,
  • "result": {
    }
}

Plan Item Migration

Dry run: how the project's legacy nodes would become items. Writes nothing.

path Parameters
project_id
required
string (Project Id)

Responses

Response samples

Content type
application/json
{
  • "empty": true,
  • "plan": {
    },
  • "report": "string"
}

Get Project Prd

The project's prd, rendered from its current prose and requirements.

path Parameters
project_id
required
string (Project Id)
query Parameters
Run Id (string) or Run Id (null) (Run Id)

Read as this design-flow run: include its open drafts

Responses

Response samples

Content type
application/json
{
  • "markdown": "string",
  • "project_id": "string",
  • "prose_ref": "string",
  • "refs": [
    ],
  • "requirement_count": 0,
  • "requirement_refs": [
    ],
  • "sources": [
    ],
  • "title": "string"
}

List Twin Relationships

List edges in the Digital Twin graph.

project_id scopes the view to a single project (MET-491), matching list_twin_nodes. Omitted or empty returns every edge (including unscoped legacy nodes) — preserving the prior global behaviour.

query Parameters
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "relationships": [
    ],
  • "total": 0
}

Get Revision Index

Node id -> KEY@n for every revision (and constraint-set constraint) of the project.

query Parameters
project_id
required
string (Project Id)

Responses

Response samples

Content type
application/json
{
  • "nodes": {
    },
  • "project_id": "string"
}

Get Run Changes

Revisions a design-flow run produced, and the baselines its gates recorded.

path Parameters
run_id
required
string (Run Id)
query Parameters
Project Id (string) or Project Id (null) (Project Id)

Responses

Response samples

Content type
application/json
{
  • "baselines": [
    ],
  • "revisions": [
    ],
  • "run_id": "string"
}

wiring

Get Harness Estimate

query Parameters
work_product_id
required
string (Work Product Id)

Responses

Response samples

Content type
application/json
{
  • "joints": [
    ],
  • "work_product_id": "string"
}