{
  "openapi": "3.1.1",
  "info": {
    "title": "Kerfwise Cabinet Builder API",
    "version": "1.0.0",
    "summary": "Parametric cabinet → every part with cut sizes, edge banding, drilling and hardware.",
    "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://kerfwisecabinetbuilder.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Parametric cabinet → every part with cut sizes, edge banding, drilling and hardware.",
        "description": "Give a cabinet type (base, wall, tall, drawer bank, blind corner, open shelf, wardrobe, bookshelf, desk, table, bed frame) with its size, back panel, doors, drawers, shelves and joinery, and get the complete parts list with finished and cut sizes, grain direction, edge banding per edge, hinge and shelf-pin drilling, hardware and a front view. The same engine powers the Kerfwise app.\n\nMethodology:\n- Carcass: sides run full height, so side height = cabinet height − plinth height; top, bottom and fixed shelves sit between the sides (length = inner width = width − 2 × panel thickness), plus 2 × dado depth (T/3) for dado joints or 2 × rabbet depth (T/2) for rabbets.\n- Back panels: grooved = (inner width + 2 × groove depth) × (inner height + 2 × groove depth) and the shelves lose groove set-back + back thickness of depth; inset = inner width × inner height; nailed = outer size − 2 mm, and the carcass depth includes the back.\n- Doors: full overlay = width / n − gap by carcass height − gap (gap 3 mm = 1.5 mm reveal per edge); inset = (opening − (n + 1) × gap) / n. Hinges per door by height: ≤ 900 mm → 2, ≤ 1600 → 3, ≤ 2000 → 4, else 5, placed 100 mm from the ends; Ø35 × 13 mm cup 22.5 mm from the edge with two Ø8 dowel holes 45 mm apart, mounting plates on the side 37 mm from the front.\n- Drawers: slide length = largest standard length ≤ inner depth − 10 mm; box length = nominal slide length; box width = opening − 25.4 mm (side-mount, 12.7 mm per side) or opening − 42 mm + 2 × side thickness (undermount); box height = front height − 40 mm (side) / − 47 mm (undermount). Front/back length: butt or dowel = box width − 2t, dado = + t, dovetail = full box width.\n- Adjustable shelves: inner width − 2 mm, 20 mm set back, on Ø5 holes at 32 mm pitch in two rows (37 mm from the front, rear row on the 32 mm grid). Fasteners: 50 mm from each end, ≤ 150 mm apart (dowels, confirmat, screws, pocket screws), cams 2–3 per joint.\n- Cut size = finished size − edge-banding thickness on each banded edge (L1/L2 run along the length and reduce the width; W1/W2 reduce the length) when deduction is on.\n\nDimensions follow common European frameless practice and the stated rules. Always check hardware manufacturers’ planning data for the exact hinges and slides you buy, and verify critical sizes before cutting expensive material.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "kerfwise_cabinet_builder",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KerfwiseCabinetBuilderInput"
              },
              "examples": {
                "example1": {
                  "summary": "Kitchen base cabinet 600, grooved back, legs, 1 door",
                  "value": {
                    "type": "base",
                    "width": 600,
                    "height": 870,
                    "depth": 560,
                    "backType": "groove",
                    "grooveDepth": 8,
                    "plinthType": "legs",
                    "plinthHeight": 150,
                    "doorCount": 1,
                    "shelfCount": 1,
                    "carcassJoint": "dowel",
                    "topType": "rails"
                  }
                },
                "example2": {
                  "summary": "Drawer bank 800 with undermount slides and dovetails",
                  "value": {
                    "type": "drawer",
                    "width": 800,
                    "height": 870,
                    "depth": 560,
                    "drawerCount": 4,
                    "slideType": "under",
                    "drawerJoint": "dovetail",
                    "carcassJoint": "confirmat"
                  }
                },
                "example3": {
                  "summary": "Wardrobe 1000 × 2200, cam joints, 2 doors",
                  "value": {
                    "type": "wardrobe",
                    "width": 1000,
                    "height": 2200,
                    "depth": 600,
                    "carcassJoint": "cam",
                    "plinthType": "board",
                    "plinthHeight": 80
                  }
                },
                "example4": {
                  "summary": "Dining table 1600 × 900 with mortise & tenon aprons",
                  "value": {
                    "type": "table",
                    "width": 1600,
                    "depth": 900,
                    "height": 750,
                    "materialId": "oakpanel-27",
                    "frameJoint": "mortise-tenon"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KerfwiseCabinetBuilderResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "KerfwiseCabinetBuilderInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "type": {
            "title": "Cabinet type",
            "type": "string",
            "enum": [
              "base",
              "wall",
              "tall",
              "drawer",
              "corner",
              "open",
              "wardrobe",
              "bookshelf",
              "desk",
              "table",
              "bed"
            ],
            "default": "base"
          },
          "width": {
            "title": "Width",
            "description": "Outer width (table/desk: top length).",
            "type": "number",
            "minimum": 150,
            "maximum": 4000,
            "default": 600,
            "x-unit": "mm"
          },
          "height": {
            "title": "Height",
            "description": "Outer height incl. plinth, without worktop. Empty = type default.",
            "type": "number",
            "minimum": 150,
            "maximum": 3000,
            "x-unit": "mm"
          },
          "depth": {
            "title": "Depth",
            "description": "Outer depth. Empty = type default.",
            "type": "number",
            "minimum": 100,
            "maximum": 2500,
            "x-unit": "mm"
          },
          "materialId": {
            "title": "Carcass material",
            "type": "string",
            "enum": [
              "mel-18",
              "oak-18",
              "birch-15",
              "mdf-19",
              "walnut-19",
              "oakpanel-27",
              "hdf-8",
              "hdf-3"
            ],
            "default": "mel-18"
          },
          "frontMaterialId": {
            "title": "Front material",
            "type": "string",
            "enum": [
              "mel-18",
              "oak-18",
              "birch-15",
              "mdf-19",
              "walnut-19",
              "oakpanel-27",
              "hdf-8",
              "hdf-3"
            ],
            "default": "oak-18"
          },
          "backType": {
            "title": "Back panel",
            "type": "string",
            "enum": [
              "groove",
              "inset",
              "nailed",
              "none"
            ],
            "default": "groove"
          },
          "grooveDepth": {
            "title": "Groove depth",
            "type": "number",
            "minimum": 0,
            "maximum": 20,
            "default": 8,
            "x-unit": "mm"
          },
          "topType": {
            "title": "Top",
            "type": "string",
            "enum": [
              "full",
              "rails"
            ],
            "default": "full"
          },
          "plinthType": {
            "title": "Plinth / toe kick",
            "type": "string",
            "enum": [
              "legs",
              "board",
              "none"
            ],
            "default": "legs"
          },
          "plinthHeight": {
            "title": "Plinth height",
            "type": "number",
            "minimum": 0,
            "maximum": 300,
            "default": 150,
            "x-unit": "mm"
          },
          "doorCount": {
            "title": "Doors",
            "description": "Empty = type default.",
            "type": "integer",
            "minimum": 0,
            "maximum": 4
          },
          "doorStyle": {
            "title": "Door style",
            "type": "string",
            "enum": [
              "overlay",
              "inset"
            ],
            "default": "overlay"
          },
          "drawerCount": {
            "title": "Drawers",
            "description": "Empty = type default. With doors, drawers go on top (150 mm each).",
            "type": "integer",
            "minimum": 0,
            "maximum": 8
          },
          "slideType": {
            "title": "Drawer slides",
            "type": "string",
            "enum": [
              "side",
              "under"
            ],
            "default": "side"
          },
          "shelfCount": {
            "title": "Shelves",
            "description": "Empty = type default.",
            "type": "integer",
            "minimum": 0,
            "maximum": 12
          },
          "adjustableShelves": {
            "title": "Adjustable shelves (32 mm system holes)",
            "type": "boolean",
            "default": true
          },
          "faceFrame": {
            "title": "Face frame",
            "type": "boolean",
            "default": false
          },
          "carcassJoint": {
            "title": "Carcass joinery",
            "type": "string",
            "enum": [
              "butt",
              "dowel",
              "confirmat",
              "pocket",
              "cam",
              "dado",
              "rabbet"
            ],
            "default": "dowel"
          },
          "frameJoint": {
            "title": "Frame / apron joinery",
            "type": "string",
            "enum": [
              "pocket",
              "dowel",
              "mortise-tenon",
              "butt"
            ],
            "default": "pocket"
          },
          "drawerJoint": {
            "title": "Drawer box joinery",
            "type": "string",
            "enum": [
              "butt",
              "dado",
              "dovetail",
              "dowel"
            ],
            "default": "dado"
          },
          "handle": {
            "title": "Handles",
            "type": "string",
            "enum": [
              "bar128",
              "bar160",
              "knob",
              "none"
            ],
            "default": "bar128"
          },
          "bandingDeduct": {
            "title": "Deduct edge-banding thickness from cut sizes",
            "type": "boolean",
            "default": true
          }
        },
        "required": [
          "width"
        ]
      },
      "KerfwiseCabinetBuilderResult": {
        "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": [
              "type",
              "size",
              "dimensions",
              "parts",
              "hardware",
              "totals",
              "warnings",
              "project",
              "openInApp"
            ],
            "properties": {
              "type": {
                "type": "string"
              },
              "size": {
                "type": "object",
                "properties": {
                  "w": {
                    "type": "number"
                  },
                  "h": {
                    "type": "number"
                  },
                  "d": {
                    "type": "number"
                  }
                }
              },
              "dimensions": {
                "type": "object",
                "description": "Key derived dimensions (carcass height, inner sizes, door/back sizes, slide length …)."
              },
              "parts": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "label",
                    "name",
                    "L",
                    "W",
                    "T",
                    "cutL",
                    "cutW",
                    "material",
                    "grain",
                    "edges",
                    "holes"
                  ],
                  "properties": {
                    "label": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "group": {
                      "type": "string"
                    },
                    "L": {
                      "type": "number"
                    },
                    "W": {
                      "type": "number"
                    },
                    "T": {
                      "type": "number"
                    },
                    "cutL": {
                      "type": "number"
                    },
                    "cutW": {
                      "type": "number"
                    },
                    "material": {
                      "type": "string"
                    },
                    "grain": {
                      "type": "boolean"
                    },
                    "edges": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    },
                    "holes": {
                      "type": "integer"
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              },
              "hardware": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "qty": {
                      "type": "number"
                    },
                    "unit": {
                      "type": "string"
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              },
              "totals": {
                "type": "object",
                "properties": {
                  "parts": {
                    "type": "integer"
                  },
                  "holes": {
                    "type": "integer"
                  },
                  "areaM2": {
                    "type": "number"
                  },
                  "bandingM": {
                    "type": "number"
                  }
                }
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "project": {
                "type": "object",
                "description": "Kerfwise project JSON containing this cabinet (open it in the app or pass it to kerfwise-cut-list)."
              },
              "openInApp": {
                "type": "string"
              }
            }
          },
          "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"
              }
            }
          }
        }
      }
    }
  }
}