{
  "openapi": "3.1.1",
  "info": {
    "title": "Twinworks Line Balancing API",
    "version": "1.0.0",
    "summary": "Assign assembly tasks to stations for a takt time: efficiency, balance delay and smoothness index.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://twinworkslinebalance.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Assign assembly tasks to stations for a takt time: efficiency, balance delay and smoothness index.",
        "description": "Solves the simple assembly line balancing problem (type 1) with the Ranked Positional Weight (Helgeson–Birnie) and Largest Candidate rules: tasks with times and precedence relations are assigned to as few stations as possible without exceeding the takt time. Returns the station assignment, line efficiency, balance delay, smoothness index and a ready-to-simulate Twinworks model of the balanced line.\n\nMethodology:\n- Takt time = available production time ÷ demand (or as given). Theoretical minimum stations = ⌈Σ task times ÷ takt⌉.\n- RPW: positional weight = own time + times of all direct and indirect successors; LCR: task time. Stations are filled one by one with the highest-priority task whose predecessors are all assigned and that still fits into the remaining takt time.\n- Efficiency = Σ task times ÷ (stations × takt); balance delay = 1 − efficiency; smoothness index = √Σ(max station time − station time)².\n- The result includes a Twinworks model (one constant-time machine per station, single-place buffers) so the balance can be simulated or opened in the app.\n\nHeuristics give good but not always optimal balances. Zoning constraints, operator skills and task variability are not considered.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "twinworks_line_balance",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TwinworksLineBalanceInput"
              },
              "examples": {
                "example1": {
                  "summary": "Wheelbarrow-style example: 8 tasks, 450 min shift, demand 270",
                  "value": {
                    "tasks": [
                      {
                        "id": "A",
                        "name": "Fit frame",
                        "time": 60,
                        "predecessors": ""
                      },
                      {
                        "id": "B",
                        "name": "Mount axle",
                        "time": 40,
                        "predecessors": "A"
                      },
                      {
                        "id": "C",
                        "name": "Fit wheel",
                        "time": 55,
                        "predecessors": "B"
                      },
                      {
                        "id": "D",
                        "name": "Attach tray",
                        "time": 50,
                        "predecessors": "A"
                      },
                      {
                        "id": "E",
                        "name": "Fit legs",
                        "time": 30,
                        "predecessors": "D"
                      },
                      {
                        "id": "F",
                        "name": "Attach handles",
                        "time": 45,
                        "predecessors": "D"
                      },
                      {
                        "id": "G",
                        "name": "Grips",
                        "time": 20,
                        "predecessors": "F"
                      },
                      {
                        "id": "H",
                        "name": "Final check",
                        "time": 35,
                        "predecessors": "C,E,G"
                      }
                    ],
                    "availableMinutes": 450,
                    "demand": 270,
                    "method": "best"
                  }
                },
                "example2": {
                  "summary": "Six tasks with a fixed takt time of 10 s",
                  "value": {
                    "tasks": [
                      {
                        "id": "1",
                        "time": 4,
                        "predecessors": ""
                      },
                      {
                        "id": "2",
                        "time": 3,
                        "predecessors": "1"
                      },
                      {
                        "id": "3",
                        "time": 5,
                        "predecessors": "1"
                      },
                      {
                        "id": "4",
                        "time": 6,
                        "predecessors": "2"
                      },
                      {
                        "id": "5",
                        "time": 2,
                        "predecessors": "3"
                      },
                      {
                        "id": "6",
                        "time": 4,
                        "predecessors": "4,5"
                      }
                    ],
                    "taktTime": 10,
                    "method": "rpw"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TwinworksLineBalanceResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "TwinworksLineBalanceInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "tasks": {
            "title": "Tasks",
            "type": "array",
            "minItems": 1,
            "maxItems": 200,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "id": {
                  "title": "Task id",
                  "type": "string",
                  "maxLength": 20
                },
                "name": {
                  "title": "Description",
                  "type": "string",
                  "maxLength": 80
                },
                "time": {
                  "title": "Time (s)",
                  "type": "number",
                  "minimum": 0,
                  "maximum": 100000
                },
                "predecessors": {
                  "title": "Predecessors (comma-separated ids)",
                  "type": "string",
                  "maxLength": 400
                }
              },
              "required": [
                "id",
                "time"
              ]
            }
          },
          "taktTime": {
            "title": "Takt time",
            "description": "Leave empty to compute it from available time ÷ demand.",
            "type": "number",
            "minimum": 0.001,
            "maximum": 10000000,
            "x-unit": "s"
          },
          "availableMinutes": {
            "title": "Available production time",
            "description": "Per period, e.g. 450 min per shift.",
            "type": "number",
            "minimum": 1,
            "maximum": 1000000,
            "x-unit": "min"
          },
          "demand": {
            "title": "Demand in that period",
            "type": "number",
            "minimum": 1,
            "maximum": 1000000000,
            "x-unit": "units"
          },
          "method": {
            "title": "Heuristic",
            "type": "string",
            "enum": [
              "best",
              "rpw",
              "lcr"
            ],
            "default": "best"
          }
        },
        "required": [
          "tasks"
        ]
      },
      "TwinworksLineBalanceResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "required": [
              "method",
              "taktTime",
              "totalWork",
              "theoreticalMin",
              "stationCount",
              "stations",
              "efficiency",
              "balanceDelay",
              "smoothnessIndex",
              "cycleTime",
              "maxThroughputPerHour",
              "model"
            ],
            "properties": {
              "method": {
                "type": "string"
              },
              "taktTime": {
                "type": "number"
              },
              "totalWork": {
                "type": "number"
              },
              "theoreticalMin": {
                "type": "integer"
              },
              "stationCount": {
                "type": "integer"
              },
              "stations": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "station",
                    "tasks",
                    "time",
                    "idle",
                    "utilization"
                  ],
                  "properties": {
                    "station": {
                      "type": "integer"
                    },
                    "tasks": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "time": {
                      "type": "number"
                    },
                    "idle": {
                      "type": "number"
                    },
                    "utilization": {
                      "type": "number"
                    }
                  }
                }
              },
              "efficiency": {
                "type": "number"
              },
              "balanceDelay": {
                "type": "number"
              },
              "smoothnessIndex": {
                "type": "number"
              },
              "cycleTime": {
                "type": "number"
              },
              "maxThroughputPerHour": {
                "type": "number"
              },
              "positionalWeights": {
                "type": "object",
                "additionalProperties": {
                  "type": "number"
                }
              },
              "alternative": {
                "type": [
                  "object",
                  "null"
                ]
              },
              "model": {
                "type": "object"
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}