{
  "openapi": "3.1.1",
  "info": {
    "title": "Room Areas, Paint, Tiles \u0026 Heat Loss Calculator API",
    "version": "1.0.0",
    "summary": "Floor areas, paint, tiles, skirting, volumes, daylight and heat loss from a plan of walls.",
    "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://kerfwiseroomquantities.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Floor areas, paint, tiles, skirting, volumes, daylight and heat loss from a plan of walls.",
        "description": "Draw rooms as centre-line walls with thickness, doors and windows. Get the rooms the walls enclose with net floor area, gross and construction area (DIN 277 / ISO 9836 style), wall surfaces net of openings for paint, floor tiles with waste, skirting length, room volumes, an approximate average daylight factor and an approximate room heat load, plus furniture collision and clearance checks.\n\nMethodology:\n- Walls are centre-line polylines with a thickness (or layers). Segments are split where walls meet (T and X junctions); at every node the offset lines of neighbouring walls are intersected, which gives mitred L corners and clean T/X joins. Rooms are the bounded faces of this planar graph, traced on the wall faces, so a stub wall inside a room is deducted correctly.\n- Areas follow the DIN 277:2021 / ISO 9836 structure: net room area NRF = sum of the room areas measured to the wall faces (NUF usable, TF technical, VF circulation by the use you assign), gross floor area BGF = area inside the outer wall faces, construction area KGF = BGF − NRF (= the wall footprints), gross volume BRI = BGF × storey height. Simplified: plaster is part of the wall thickness, door reveals and niches are not added, no separate area under low ceilings.\n- Wall surfaces = room perimeter × clear height, minus doors and windows (each side of an internal opening counts for the room on that side; optionally only openings above a size limit). Paint = (net walls + ceiling) × coats ÷ coverage. Tiles = floor area × (1 + waste) ÷ (tile + joint) area, rounded up. Skirting = perimeter minus door widths.\n- Daylight: BRE average daylight factor ADF = T·Aw·θ·M / (A·(1 − R²)) with the glazed area Aw = window area × glazed fraction, θ = 90° − obstruction angle and A = floor + ceiling + walls. Heat load: EN 12831-1 simplified — Σ A·U·ΔT per wall, window, door, floor and ceiling (internal dimensions, U + a thermal-bridge allowance for elements to the outside or ground) plus ventilation 0.34·n·V·ΔT. U-values of layered walls after EN ISO 6946.\n- Furniture (Kerfwise cabinets and appliances as bounding boxes): collisions with wall footprints, door swings and passages, other items at the same height, windows below the item top, and the clear depth in front of each floor item (bisection to 1 mm).\n\nApproximate planning quantities, not certified: not for building permits, energy certificates, heat load sizing of a heating system or contractual area statements. Method: areas in the DIN 277 / ISO 9836 structure from wall centre lines, the BRE average daylight factor and a simplified EN 12831-1 transmission heat load (Σ A·U·ΔT). An architect or engineer would additionally measure the built rooms, apply the rules for your purpose (for example the full EN 12831-1 with ventilation and thermal bridges for heating design, or the local living-area rules for rentals) and check every number against the approved plans.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "kerfwise_room_quantities",
        "x-owner-app": "kerfwise",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KerfwiseRoomQuantitiesInput"
              },
              "examples": {
                "example1": {
                  "summary": "L-shaped flat: living room, kitchen and bathroom",
                  "value": {
                    "room": "{\n \"format\": \"kerfwise-room\",\n \"version\": 1,\n \"name\": \"L-shaped flat with kitchen and bathroom\",\n \"storeys\": [\n  {\n   \"id\": \"og1\",\n   \"name\": \"Flat\",\n   \"elevationMm\": 0,\n   \"heightMm\": 2800,\n   \"clearHeightMm\": 2500,\n   \"floor\": {\n    \"thicknessMm\": 200,\n    \"uValue\": null,\n    \"boundary\": \"heated\"\n   },\n   \"ceiling\": {\n    \"thicknessMm\": 200,\n    \"uValue\": null,\n    \"boundary\": \"heated\"\n   },\n   \"walls\": [\n    {\n     \"id\": \"ext\",\n     \"name\": \"External wall\",\n     \"points\": [\n      [\n       0,\n       0\n      ],\n      [\n       7000,\n       0\n      ],\n      [\n       7000,\n       4000\n      ],\n      [\n       4000,\n       4000\n      ],\n      [\n       4000,\n       7000\n      ],\n      [\n       0,\n       7000\n      ]\n     ],\n     \"closed\": true,\n     \"thicknessMm\": 405,\n     \"heightMm\": null,\n     \"layers\": [\n      {\n       \"name\": \"Lime plaster\",\n       \"thicknessMm\": 15,\n       \"lambda\": 0.87\n      },\n      {\n       \"name\": \"Clay brick\",\n       \"thicknessMm\": 240,\n       \"lambda\": 0.58\n      },\n      {\n       \"name\": \"Mineral wool insulation\",\n       \"thicknessMm\": 140,\n       \"lambda\": 0.035\n      },\n      {\n       \"name\": \"External render\",\n       \"thicknessMm\": 10,\n       \"lambda\": 0.87\n      }\n     ],\n     \"uValue\": null\n    },\n    {\n     \"id\": \"p1\",\n     \"name\": \"Kitchen partition\",\n     \"points\": [\n      [\n       4000,\n       0\n      ],\n      [\n       4000,\n       4000\n      ]\n     ],\n     \"closed\": false,\n     \"thicknessMm\": 115,\n     \"heightMm\": null,\n     \"layers\": [],\n     \"uValue\": null\n    },\n    {\n     \"id\": \"p2\",\n     \"name\": \"Bathroom partition\",\n     \"points\": [\n      [\n       0,\n       4500\n      ],\n      [\n       4000,\n       4500\n      ]\n     ],\n     \"closed\": false,\n     \"thicknessMm\": 115,\n     \"heightMm\": null,\n     \"layers\": [],\n     \"uValue\": null\n    }\n   ],\n   \"openings\": [\n    {\n     \"id\": \"w-liv\",\n     \"name\": \"Window w-liv\",\n     \"wallId\": \"ext\",\n     \"segment\": 5,\n     \"kind\": \"window\",\n     \"offsetMm\": 3500,\n     \"widthMm\": 1500,\n     \"heightMm\": 1400,\n     \"sillMm\": 850,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"w-kit\",\n     \"name\": \"Window w-kit\",\n     \"wallId\": \"ext\",\n     \"segment\": 0,\n     \"kind\": \"window\",\n     \"offsetMm\": 5000,\n     \"widthMm\": 1200,\n     \"heightMm\": 1200,\n     \"sillMm\": 1050,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"w-bath\",\n     \"name\": \"Window w-bath\",\n     \"wallId\": \"ext\",\n     \"segment\": 4,\n     \"kind\": \"window\",\n     \"offsetMm\": 1500,\n     \"widthMm\": 800,\n     \"heightMm\": 800,\n     \"sillMm\": 1400,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 20\n    },\n    {\n     \"id\": \"d-ent\",\n     \"name\": \"Door d-ent\",\n     \"wallId\": \"ext\",\n     \"segment\": 2,\n     \"kind\": \"door\",\n     \"offsetMm\": 1200,\n     \"widthMm\": 1010,\n     \"heightMm\": 2135,\n     \"sillMm\": 0,\n     \"hinge\": \"end\",\n     \"swing\": \"left\",\n     \"uValue\": 1.3,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"d-kit\",\n     \"name\": \"Door d-kit\",\n     \"wallId\": \"p1\",\n     \"segment\": 0,\n     \"kind\": \"door\",\n     \"offsetMm\": 2800,\n     \"widthMm\": 885,\n     \"heightMm\": 2010,\n     \"sillMm\": 0,\n     \"hinge\": \"end\",\n     \"swing\": \"right\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"d-bath\",\n     \"name\": \"Door d-bath\",\n     \"wallId\": \"p2\",\n     \"segment\": 0,\n     \"kind\": \"door\",\n     \"offsetMm\": 2600,\n     \"widthMm\": 760,\n     \"heightMm\": 2010,\n     \"sillMm\": 0,\n     \"hinge\": \"start\",\n     \"swing\": \"right\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    }\n   ],\n   \"spaces\": [\n    {\n     \"id\": \"living\",\n     \"name\": \"Living room and hall\",\n     \"at\": [\n      2000,\n      2000\n     ],\n     \"usage\": \"NUF1\",\n     \"designTempC\": null,\n     \"tiles\": true\n    },\n    {\n     \"id\": \"kitchen\",\n     \"name\": \"Kitchen\",\n     \"at\": [\n      5500,\n      2000\n     ],\n     \"usage\": \"NUF1\",\n     \"designTempC\": null,\n     \"tiles\": true\n    },\n    {\n     \"id\": \"bath\",\n     \"name\": \"Bathroom\",\n     \"at\": [\n      2000,\n      5800\n     ],\n     \"usage\": \"NUF7\",\n     \"designTempC\": 24,\n     \"tiles\": true\n    }\n   ]\n  }\n ],\n \"furniture\": [\n  {\n   \"id\": \"k1\",\n   \"name\": \"Base cabinet run\",\n   \"storeyId\": \"og1\",\n   \"kind\": \"cabinet\",\n   \"x\": 4060,\n   \"y\": 202.5,\n   \"rot\": 0,\n   \"w\": 2100,\n   \"d\": 600,\n   \"h\": 870,\n   \"elev\": 0,\n   \"clearanceMm\": null\n  },\n  {\n   \"id\": \"k2\",\n   \"name\": \"Tall fridge cabinet\",\n   \"storeyId\": \"og1\",\n   \"kind\": \"cabinet\",\n   \"x\": 6797.5,\n   \"y\": 3197.5,\n   \"rot\": 90,\n   \"w\": 600,\n   \"d\": 600,\n   \"h\": 2150,\n   \"elev\": 0,\n   \"clearanceMm\": null\n  },\n  {\n   \"id\": \"sofa\",\n   \"name\": \"Sofa\",\n   \"storeyId\": \"og1\",\n   \"kind\": \"furniture\",\n   \"x\": 300,\n   \"y\": 3600,\n   \"rot\": -90,\n   \"w\": 2200,\n   \"d\": 900,\n   \"h\": 800,\n   \"elev\": 0,\n   \"clearanceMm\": null\n  }\n ]\n}"
                  }
                },
                "example2": {
                  "summary": "Rectangular room 4 × 3 m with one window and one door",
                  "value": {
                    "room": "{\n \"format\": \"kerfwise-room\",\n \"version\": 1,\n \"name\": \"Rectangular room 4 × 3 m\",\n \"storeys\": [\n  {\n   \"id\": \"eg\",\n   \"name\": \"Ground floor\",\n   \"elevationMm\": 0,\n   \"heightMm\": 2750,\n   \"clearHeightMm\": 2500,\n   \"floor\": {\n    \"thicknessMm\": 200,\n    \"uValue\": null,\n    \"boundary\": \"ground\"\n   },\n   \"ceiling\": {\n    \"thicknessMm\": 200,\n    \"uValue\": null,\n    \"boundary\": \"outside\"\n   },\n   \"walls\": [\n    {\n     \"id\": \"w1\",\n     \"name\": \"Outer wall\",\n     \"points\": [\n      [\n       -150,\n       -150\n      ],\n      [\n       4150,\n       -150\n      ],\n      [\n       4150,\n       3150\n      ],\n      [\n       -150,\n       3150\n      ]\n     ],\n     \"closed\": true,\n     \"thicknessMm\": 300,\n     \"heightMm\": null,\n     \"layers\": [],\n     \"uValue\": null\n    }\n   ],\n   \"openings\": [\n    {\n     \"id\": \"win1\",\n     \"name\": \"Window win1\",\n     \"wallId\": \"w1\",\n     \"segment\": 0,\n     \"kind\": \"window\",\n     \"offsetMm\": 1450,\n     \"widthMm\": 1500,\n     \"heightMm\": 1250,\n     \"sillMm\": 900,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"door1\",\n     \"name\": \"Door door1\",\n     \"wallId\": \"w1\",\n     \"segment\": 2,\n     \"kind\": \"door\",\n     \"offsetMm\": 600,\n     \"widthMm\": 900,\n     \"heightMm\": 2000,\n     \"sillMm\": 0,\n     \"hinge\": \"start\",\n     \"swing\": \"left\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    }\n   ],\n   \"spaces\": [\n    {\n     \"id\": \"living\",\n     \"name\": \"Living room\",\n     \"at\": [\n      2000,\n      1500\n     ],\n     \"usage\": \"NUF1\",\n     \"designTempC\": null,\n     \"tiles\": true\n    }\n   ]\n  }\n ],\n \"furniture\": [\n  {\n   \"id\": \"sb\",\n   \"name\": \"Sideboard\",\n   \"storeyId\": \"eg\",\n   \"kind\": \"cabinet\",\n   \"x\": 0,\n   \"y\": 2300,\n   \"rot\": -90,\n   \"w\": 1600,\n   \"d\": 450,\n   \"h\": 800,\n   \"elev\": 0,\n   \"clearanceMm\": null\n  }\n ]\n}"
                  }
                },
                "example3": {
                  "summary": "Two-storey studio house with a roof and ground slab",
                  "value": {
                    "room": "{\n \"format\": \"kerfwise-room\",\n \"version\": 1,\n \"name\": \"Two-storey studio house\",\n \"storeys\": [\n  {\n   \"id\": \"eg\",\n   \"name\": \"Ground floor\",\n   \"elevationMm\": 0,\n   \"heightMm\": 2900,\n   \"clearHeightMm\": 2600,\n   \"floor\": {\n    \"thicknessMm\": 200,\n    \"uValue\": null,\n    \"boundary\": \"ground\"\n   },\n   \"ceiling\": {\n    \"thicknessMm\": 200,\n    \"uValue\": null,\n    \"boundary\": \"heated\"\n   },\n   \"walls\": [\n    {\n     \"id\": \"eg-ext\",\n     \"name\": \"Wall eg-ext\",\n     \"points\": [\n      [\n       0,\n       0\n      ],\n      [\n       6000,\n       0\n      ],\n      [\n       6000,\n       5000\n      ],\n      [\n       0,\n       5000\n      ]\n     ],\n     \"closed\": true,\n     \"thicknessMm\": 365,\n     \"heightMm\": null,\n     \"layers\": [],\n     \"uValue\": 0.22\n    },\n    {\n     \"id\": \"eg-int\",\n     \"name\": \"Wall eg-int\",\n     \"points\": [\n      [\n       3500,\n       0\n      ],\n      [\n       3500,\n       5000\n      ]\n     ],\n     \"closed\": false,\n     \"thicknessMm\": 115,\n     \"heightMm\": null,\n     \"layers\": [],\n     \"uValue\": null\n    }\n   ],\n   \"openings\": [\n    {\n     \"id\": \"eg-door\",\n     \"name\": \"Door eg-door\",\n     \"wallId\": \"eg-ext\",\n     \"segment\": 2,\n     \"kind\": \"door\",\n     \"offsetMm\": 4200,\n     \"widthMm\": 1010,\n     \"heightMm\": 2135,\n     \"sillMm\": 0,\n     \"hinge\": \"start\",\n     \"swing\": \"left\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"eg-win1\",\n     \"name\": \"Window eg-win1\",\n     \"wallId\": \"eg-ext\",\n     \"segment\": 0,\n     \"kind\": \"window\",\n     \"offsetMm\": 1000,\n     \"widthMm\": 1500,\n     \"heightMm\": 1500,\n     \"sillMm\": 800,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"eg-win2\",\n     \"name\": \"Window eg-win2\",\n     \"wallId\": \"eg-ext\",\n     \"segment\": 1,\n     \"kind\": \"window\",\n     \"offsetMm\": 1800,\n     \"widthMm\": 1200,\n     \"heightMm\": 1250,\n     \"sillMm\": 1000,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"eg-d2\",\n     \"name\": \"Door eg-d2\",\n     \"wallId\": \"eg-int\",\n     \"segment\": 0,\n     \"kind\": \"door\",\n     \"offsetMm\": 3200,\n     \"widthMm\": 885,\n     \"heightMm\": 2010,\n     \"sillMm\": 0,\n     \"hinge\": \"end\",\n     \"swing\": \"left\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    }\n   ],\n   \"spaces\": [\n    {\n     \"id\": \"studio\",\n     \"name\": \"Studio\",\n     \"at\": [\n      1700,\n      2500\n     ],\n     \"usage\": \"NUF1\",\n     \"designTempC\": null,\n     \"tiles\": true\n    },\n    {\n     \"id\": \"utility\",\n     \"name\": \"Utility and stairs\",\n     \"at\": [\n      4700,\n      2500\n     ],\n     \"usage\": \"VF\",\n     \"designTempC\": null,\n     \"tiles\": true\n    }\n   ]\n  },\n  {\n   \"id\": \"og\",\n   \"name\": \"Upper floor\",\n   \"elevationMm\": 2900,\n   \"heightMm\": 2700,\n   \"clearHeightMm\": 2450,\n   \"floor\": {\n    \"thicknessMm\": 200,\n    \"uValue\": null,\n    \"boundary\": \"heated\"\n   },\n   \"ceiling\": {\n    \"thicknessMm\": 200,\n    \"uValue\": null,\n    \"boundary\": \"outside\"\n   },\n   \"walls\": [\n    {\n     \"id\": \"og-ext\",\n     \"name\": \"Wall og-ext\",\n     \"points\": [\n      [\n       0,\n       0\n      ],\n      [\n       6000,\n       0\n      ],\n      [\n       6000,\n       5000\n      ],\n      [\n       0,\n       5000\n      ]\n     ],\n     \"closed\": true,\n     \"thicknessMm\": 365,\n     \"heightMm\": null,\n     \"layers\": [],\n     \"uValue\": 0.22\n    }\n   ],\n   \"openings\": [\n    {\n     \"id\": \"og-win\",\n     \"name\": \"Window og-win\",\n     \"wallId\": \"og-ext\",\n     \"segment\": 0,\n     \"kind\": \"window\",\n     \"offsetMm\": 2200,\n     \"widthMm\": 1600,\n     \"heightMm\": 1300,\n     \"sillMm\": 900,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    }\n   ],\n   \"spaces\": [\n    {\n     \"id\": \"bed\",\n     \"name\": \"Bedroom\",\n     \"at\": [\n      3000,\n      2500\n     ],\n     \"usage\": \"NUF1\",\n     \"designTempC\": 18,\n     \"tiles\": true\n    }\n   ]\n  }\n ],\n \"furniture\": [\n  {\n   \"id\": \"bed1\",\n   \"name\": \"Bed\",\n   \"storeyId\": \"og\",\n   \"kind\": \"furniture\",\n   \"x\": 3800,\n   \"y\": 4817.5,\n   \"rot\": 180,\n   \"w\": 1600,\n   \"d\": 2100,\n   \"h\": 450,\n   \"elev\": 0,\n   \"clearanceMm\": 600\n  }\n ]\n}"
                  }
                },
                "example4": {
                  "summary": "Furniture check: a shelf placed in a door swing",
                  "value": {
                    "room": "{\n \"format\": \"kerfwise-room\",\n \"version\": 1,\n \"name\": \"L-shaped flat with kitchen and bathroom\",\n \"storeys\": [\n  {\n   \"id\": \"og1\",\n   \"name\": \"Flat\",\n   \"elevationMm\": 0,\n   \"heightMm\": 2800,\n   \"clearHeightMm\": 2500,\n   \"floor\": {\n    \"thicknessMm\": 200,\n    \"uValue\": null,\n    \"boundary\": \"heated\"\n   },\n   \"ceiling\": {\n    \"thicknessMm\": 200,\n    \"uValue\": null,\n    \"boundary\": \"heated\"\n   },\n   \"walls\": [\n    {\n     \"id\": \"ext\",\n     \"name\": \"External wall\",\n     \"points\": [\n      [\n       0,\n       0\n      ],\n      [\n       7000,\n       0\n      ],\n      [\n       7000,\n       4000\n      ],\n      [\n       4000,\n       4000\n      ],\n      [\n       4000,\n       7000\n      ],\n      [\n       0,\n       7000\n      ]\n     ],\n     \"closed\": true,\n     \"thicknessMm\": 405,\n     \"heightMm\": null,\n     \"layers\": [\n      {\n       \"name\": \"Lime plaster\",\n       \"thicknessMm\": 15,\n       \"lambda\": 0.87\n      },\n      {\n       \"name\": \"Clay brick\",\n       \"thicknessMm\": 240,\n       \"lambda\": 0.58\n      },\n      {\n       \"name\": \"Mineral wool insulation\",\n       \"thicknessMm\": 140,\n       \"lambda\": 0.035\n      },\n      {\n       \"name\": \"External render\",\n       \"thicknessMm\": 10,\n       \"lambda\": 0.87\n      }\n     ],\n     \"uValue\": null\n    },\n    {\n     \"id\": \"p1\",\n     \"name\": \"Kitchen partition\",\n     \"points\": [\n      [\n       4000,\n       0\n      ],\n      [\n       4000,\n       4000\n      ]\n     ],\n     \"closed\": false,\n     \"thicknessMm\": 115,\n     \"heightMm\": null,\n     \"layers\": [],\n     \"uValue\": null\n    },\n    {\n     \"id\": \"p2\",\n     \"name\": \"Bathroom partition\",\n     \"points\": [\n      [\n       0,\n       4500\n      ],\n      [\n       4000,\n       4500\n      ]\n     ],\n     \"closed\": false,\n     \"thicknessMm\": 115,\n     \"heightMm\": null,\n     \"layers\": [],\n     \"uValue\": null\n    }\n   ],\n   \"openings\": [\n    {\n     \"id\": \"w-liv\",\n     \"name\": \"Window w-liv\",\n     \"wallId\": \"ext\",\n     \"segment\": 5,\n     \"kind\": \"window\",\n     \"offsetMm\": 3500,\n     \"widthMm\": 1500,\n     \"heightMm\": 1400,\n     \"sillMm\": 850,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"w-kit\",\n     \"name\": \"Window w-kit\",\n     \"wallId\": \"ext\",\n     \"segment\": 0,\n     \"kind\": \"window\",\n     \"offsetMm\": 5000,\n     \"widthMm\": 1200,\n     \"heightMm\": 1200,\n     \"sillMm\": 1050,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"w-bath\",\n     \"name\": \"Window w-bath\",\n     \"wallId\": \"ext\",\n     \"segment\": 4,\n     \"kind\": \"window\",\n     \"offsetMm\": 1500,\n     \"widthMm\": 800,\n     \"heightMm\": 800,\n     \"sillMm\": 1400,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 20\n    },\n    {\n     \"id\": \"d-ent\",\n     \"name\": \"Door d-ent\",\n     \"wallId\": \"ext\",\n     \"segment\": 2,\n     \"kind\": \"door\",\n     \"offsetMm\": 1200,\n     \"widthMm\": 1010,\n     \"heightMm\": 2135,\n     \"sillMm\": 0,\n     \"hinge\": \"end\",\n     \"swing\": \"left\",\n     \"uValue\": 1.3,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"d-kit\",\n     \"name\": \"Door d-kit\",\n     \"wallId\": \"p1\",\n     \"segment\": 0,\n     \"kind\": \"door\",\n     \"offsetMm\": 2800,\n     \"widthMm\": 885,\n     \"heightMm\": 2010,\n     \"sillMm\": 0,\n     \"hinge\": \"end\",\n     \"swing\": \"right\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"d-bath\",\n     \"name\": \"Door d-bath\",\n     \"wallId\": \"p2\",\n     \"segment\": 0,\n     \"kind\": \"door\",\n     \"offsetMm\": 2600,\n     \"widthMm\": 760,\n     \"heightMm\": 2010,\n     \"sillMm\": 0,\n     \"hinge\": \"start\",\n     \"swing\": \"right\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    }\n   ],\n   \"spaces\": [\n    {\n     \"id\": \"living\",\n     \"name\": \"Living room and hall\",\n     \"at\": [\n      2000,\n      2000\n     ],\n     \"usage\": \"NUF1\",\n     \"designTempC\": null,\n     \"tiles\": true\n    },\n    {\n     \"id\": \"kitchen\",\n     \"name\": \"Kitchen\",\n     \"at\": [\n      5500,\n      2000\n     ],\n     \"usage\": \"NUF1\",\n     \"designTempC\": null,\n     \"tiles\": true\n    },\n    {\n     \"id\": \"bath\",\n     \"name\": \"Bathroom\",\n     \"at\": [\n      2000,\n      5800\n     ],\n     \"usage\": \"NUF7\",\n     \"designTempC\": 24,\n     \"tiles\": true\n    }\n   ]\n  }\n ],\n \"furniture\": [\n  {\n   \"id\": \"k1\",\n   \"name\": \"Base cabinet run\",\n   \"storeyId\": \"og1\",\n   \"kind\": \"cabinet\",\n   \"x\": 4060,\n   \"y\": 202.5,\n   \"rot\": 0,\n   \"w\": 2100,\n   \"d\": 600,\n   \"h\": 870,\n   \"elev\": 0,\n   \"clearanceMm\": null\n  },\n  {\n   \"id\": \"k2\",\n   \"name\": \"Tall fridge cabinet\",\n   \"storeyId\": \"og1\",\n   \"kind\": \"cabinet\",\n   \"x\": 6797.5,\n   \"y\": 3197.5,\n   \"rot\": 90,\n   \"w\": 600,\n   \"d\": 600,\n   \"h\": 2150,\n   \"elev\": 0,\n   \"clearanceMm\": null\n  },\n  {\n   \"id\": \"sofa\",\n   \"name\": \"Sofa\",\n   \"storeyId\": \"og1\",\n   \"kind\": \"furniture\",\n   \"x\": 300,\n   \"y\": 3600,\n   \"rot\": -90,\n   \"w\": 2200,\n   \"d\": 900,\n   \"h\": 800,\n   \"elev\": 0,\n   \"clearanceMm\": null\n  },\n  {\n   \"id\": \"shelf\",\n   \"name\": \"Shelf in the door swing\",\n   \"storeyId\": \"og1\",\n   \"kind\": \"cabinet\",\n   \"x\": 4060,\n   \"y\": 3600,\n   \"rot\": -90,\n   \"w\": 900,\n   \"d\": 400,\n   \"h\": 1800,\n   \"elev\": 0,\n   \"clearanceMm\": null\n  }\n ]\n}"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KerfwiseRoomQuantitiesResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "KerfwiseRoomQuantitiesInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "room": {
            "title": "Room model JSON (or a Kerfwise project)",
            "description": "Storeys with centre-line walls {points, thicknessMm, layers}, openings {wallId, segment, kind, offsetMm, widthMm, heightMm, sillMm}, spaces {name, at, usage} and furniture. A .kerfwise.json project is converted from its kitchen plan.",
            "type": "string",
            "maxLength": 400000,
            "default": "{\n \"format\": \"kerfwise-room\",\n \"version\": 1,\n \"name\": \"L-shaped flat with kitchen and bathroom\",\n \"storeys\": [\n  {\n   \"id\": \"og1\",\n   \"name\": \"Flat\",\n   \"elevationMm\": 0,\n   \"heightMm\": 2800,\n   \"clearHeightMm\": 2500,\n   \"floor\": {\n    \"thicknessMm\": 200,\n    \"uValue\": null,\n    \"boundary\": \"heated\"\n   },\n   \"ceiling\": {\n    \"thicknessMm\": 200,\n    \"uValue\": null,\n    \"boundary\": \"heated\"\n   },\n   \"walls\": [\n    {\n     \"id\": \"ext\",\n     \"name\": \"External wall\",\n     \"points\": [\n      [\n       0,\n       0\n      ],\n      [\n       7000,\n       0\n      ],\n      [\n       7000,\n       4000\n      ],\n      [\n       4000,\n       4000\n      ],\n      [\n       4000,\n       7000\n      ],\n      [\n       0,\n       7000\n      ]\n     ],\n     \"closed\": true,\n     \"thicknessMm\": 405,\n     \"heightMm\": null,\n     \"layers\": [\n      {\n       \"name\": \"Lime plaster\",\n       \"thicknessMm\": 15,\n       \"lambda\": 0.87\n      },\n      {\n       \"name\": \"Clay brick\",\n       \"thicknessMm\": 240,\n       \"lambda\": 0.58\n      },\n      {\n       \"name\": \"Mineral wool insulation\",\n       \"thicknessMm\": 140,\n       \"lambda\": 0.035\n      },\n      {\n       \"name\": \"External render\",\n       \"thicknessMm\": 10,\n       \"lambda\": 0.87\n      }\n     ],\n     \"uValue\": null\n    },\n    {\n     \"id\": \"p1\",\n     \"name\": \"Kitchen partition\",\n     \"points\": [\n      [\n       4000,\n       0\n      ],\n      [\n       4000,\n       4000\n      ]\n     ],\n     \"closed\": false,\n     \"thicknessMm\": 115,\n     \"heightMm\": null,\n     \"layers\": [],\n     \"uValue\": null\n    },\n    {\n     \"id\": \"p2\",\n     \"name\": \"Bathroom partition\",\n     \"points\": [\n      [\n       0,\n       4500\n      ],\n      [\n       4000,\n       4500\n      ]\n     ],\n     \"closed\": false,\n     \"thicknessMm\": 115,\n     \"heightMm\": null,\n     \"layers\": [],\n     \"uValue\": null\n    }\n   ],\n   \"openings\": [\n    {\n     \"id\": \"w-liv\",\n     \"name\": \"Window w-liv\",\n     \"wallId\": \"ext\",\n     \"segment\": 5,\n     \"kind\": \"window\",\n     \"offsetMm\": 3500,\n     \"widthMm\": 1500,\n     \"heightMm\": 1400,\n     \"sillMm\": 850,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"w-kit\",\n     \"name\": \"Window w-kit\",\n     \"wallId\": \"ext\",\n     \"segment\": 0,\n     \"kind\": \"window\",\n     \"offsetMm\": 5000,\n     \"widthMm\": 1200,\n     \"heightMm\": 1200,\n     \"sillMm\": 1050,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"w-bath\",\n     \"name\": \"Window w-bath\",\n     \"wallId\": \"ext\",\n     \"segment\": 4,\n     \"kind\": \"window\",\n     \"offsetMm\": 1500,\n     \"widthMm\": 800,\n     \"heightMm\": 800,\n     \"sillMm\": 1400,\n     \"hinge\": \"start\",\n     \"swing\": \"none\",\n     \"uValue\": null,\n     \"obstructionDeg\": 20\n    },\n    {\n     \"id\": \"d-ent\",\n     \"name\": \"Door d-ent\",\n     \"wallId\": \"ext\",\n     \"segment\": 2,\n     \"kind\": \"door\",\n     \"offsetMm\": 1200,\n     \"widthMm\": 1010,\n     \"heightMm\": 2135,\n     \"sillMm\": 0,\n     \"hinge\": \"end\",\n     \"swing\": \"left\",\n     \"uValue\": 1.3,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"d-kit\",\n     \"name\": \"Door d-kit\",\n     \"wallId\": \"p1\",\n     \"segment\": 0,\n     \"kind\": \"door\",\n     \"offsetMm\": 2800,\n     \"widthMm\": 885,\n     \"heightMm\": 2010,\n     \"sillMm\": 0,\n     \"hinge\": \"end\",\n     \"swing\": \"right\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    },\n    {\n     \"id\": \"d-bath\",\n     \"name\": \"Door d-bath\",\n     \"wallId\": \"p2\",\n     \"segment\": 0,\n     \"kind\": \"door\",\n     \"offsetMm\": 2600,\n     \"widthMm\": 760,\n     \"heightMm\": 2010,\n     \"sillMm\": 0,\n     \"hinge\": \"start\",\n     \"swing\": \"right\",\n     \"uValue\": null,\n     \"obstructionDeg\": 0\n    }\n   ],\n   \"spaces\": [\n    {\n     \"id\": \"living\",\n     \"name\": \"Living room and hall\",\n     \"at\": [\n      2000,\n      2000\n     ],\n     \"usage\": \"NUF1\",\n     \"designTempC\": null,\n     \"tiles\": true\n    },\n    {\n     \"id\": \"kitchen\",\n     \"name\": \"Kitchen\",\n     \"at\": [\n      5500,\n      2000\n     ],\n     \"usage\": \"NUF1\",\n     \"designTempC\": null,\n     \"tiles\": true\n    },\n    {\n     \"id\": \"bath\",\n     \"name\": \"Bathroom\",\n     \"at\": [\n      2000,\n      5800\n     ],\n     \"usage\": \"NUF7\",\n     \"designTempC\": 24,\n     \"tiles\": true\n    }\n   ]\n  }\n ],\n \"furniture\": [\n  {\n   \"id\": \"k1\",\n   \"name\": \"Base cabinet run\",\n   \"storeyId\": \"og1\",\n   \"kind\": \"cabinet\",\n   \"x\": 4060,\n   \"y\": 202.5,\n   \"rot\": 0,\n   \"w\": 2100,\n   \"d\": 600,\n   \"h\": 870,\n   \"elev\": 0,\n   \"clearanceMm\": null\n  },\n  {\n   \"id\": \"k2\",\n   \"name\": \"Tall fridge cabinet\",\n   \"storeyId\": \"og1\",\n   \"kind\": \"cabinet\",\n   \"x\": 6797.5,\n   \"y\": 3197.5,\n   \"rot\": 90,\n   \"w\": 600,\n   \"d\": 600,\n   \"h\": 2150,\n   \"elev\": 0,\n   \"clearanceMm\": null\n  },\n  {\n   \"id\": \"sofa\",\n   \"name\": \"Sofa\",\n   \"storeyId\": \"og1\",\n   \"kind\": \"furniture\",\n   \"x\": 300,\n   \"y\": 3600,\n   \"rot\": -90,\n   \"w\": 2200,\n   \"d\": 900,\n   \"h\": 800,\n   \"elev\": 0,\n   \"clearanceMm\": null\n  }\n ]\n}"
          }
        },
        "required": []
      },
      "KerfwiseRoomQuantitiesResult": {
        "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",
            "additionalProperties": false,
            "required": [
              "name",
              "totals",
              "storeys",
              "furniture",
              "warnings",
              "openInApp"
            ],
            "properties": {
              "name": {
                "type": "string"
              },
              "totals": {
                "type": "object",
                "description": "Building totals: areas m², volumes m³, paint litres, tiles, skirting m, heat load W.",
                "properties": {
                  "grossAreaM2": {
                    "type": "number"
                  },
                  "netAreaM2": {
                    "type": "number"
                  },
                  "constructionAreaM2": {
                    "type": "number"
                  },
                  "usableM2": {
                    "type": "number"
                  },
                  "technicalM2": {
                    "type": "number"
                  },
                  "circulationM2": {
                    "type": "number"
                  },
                  "grossVolumeM3": {
                    "type": "number"
                  },
                  "netVolumeM3": {
                    "type": "number"
                  },
                  "wallNetM2": {
                    "type": "number"
                  },
                  "paintL": {
                    "type": "number"
                  },
                  "tiles": {
                    "type": "number"
                  },
                  "tileBoxes": {
                    "type": "number"
                  },
                  "skirtingM": {
                    "type": "number"
                  },
                  "heatW": {
                    "type": "number"
                  },
                  "spaces": {
                    "type": "number"
                  }
                }
              },
              "storeys": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "elevationMm": {
                      "type": "number"
                    },
                    "grossAreaM2": {
                      "type": "number"
                    },
                    "netAreaM2": {
                      "type": "number"
                    },
                    "constructionAreaM2": {
                      "type": "number"
                    },
                    "usableM2": {
                      "type": "number"
                    },
                    "technicalM2": {
                      "type": "number"
                    },
                    "circulationM2": {
                      "type": "number"
                    },
                    "grossVolumeM3": {
                      "type": "number"
                    },
                    "netVolumeM3": {
                      "type": "number"
                    },
                    "wallLengthM": {
                      "type": "number"
                    },
                    "spaces": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "description": "One room enclosed by walls: areas, finishes, daylight and heat load."
                      }
                    },
                    "walls": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    }
                  }
                }
              },
              "furniture": {
                "type": "array",
                "items": {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "storeyId": {
                      "type": "string"
                    },
                    "spaceId": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "status": {
                      "enum": [
                        "ok",
                        "warning",
                        "conflict"
                      ]
                    },
                    "clearanceMm": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "requiredMm": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "issues": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              },
              "warnings": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "openInApp": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "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"
              }
            }
          }
        }
      }
    }
  }
}