{
  "openapi": "3.1.0",
  "info": {
    "title": "DatumSpot Calculator API",
    "version": "1.0.0",
    "description": "Source-cited architecture & construction calculators. Stateless and free; nothing is stored. Results are reference estimates — verify against the adopted code edition and your AHJ. Not a compliance certification.",
    "contact": {
      "url": "https://datumspot.com"
    }
  },
  "servers": [
    {
      "url": "https://datumspot.com"
    }
  ],
  "paths": {
    "/api/calc/convert_length": {
      "post": {
        "operationId": "convert_length",
        "summary": "Feet-inch-fraction converter",
        "description": "Parse a construction dimension (e.g. \"12' 4-3/8\\\"\", \"3810 mm\", \"4.5'\") and convert between feet-inch-fraction, decimal feet, decimal inches, and metric. A bare number is read as inches.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "raw": {
                    "type": "string",
                    "description": "The dimension to parse, e.g. \"12' 6\\\"\", \"148.375\\\"\", \"3/8\\\"\", or \"3810 mm\"."
                  },
                  "roundDen": {
                    "type": "integer",
                    "enum": [
                      2,
                      4,
                      8,
                      16,
                      32,
                      64
                    ],
                    "default": 16,
                    "description": "Round the imperial result to the nearest 1/den inch (2, 4, 8, 16, 32, 64)."
                  }
                },
                "required": [
                  "raw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/convert_scale": {
      "post": {
        "operationId": "convert_scale",
        "summary": "Architectural scale converter",
        "description": "Convert a length between a real-world dimension and its drawn (paper) size at a chosen architectural scale, in either direction.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "raw": {
                    "type": "string",
                    "description": "The length to convert, e.g. \"24'\" or \"3810 mm\"."
                  },
                  "scaleId": {
                    "type": "string",
                    "enum": [
                      "1-16in",
                      "3-32in",
                      "1-8in",
                      "3-16in",
                      "1-4in",
                      "3-8in",
                      "1-2in",
                      "3-4in",
                      "1in",
                      "1-5in",
                      "3in",
                      "1-5",
                      "1-10",
                      "1-20",
                      "1-50",
                      "1-100",
                      "1-200",
                      "1-500",
                      "1-1000"
                    ],
                    "description": "Architectural scale id. Options — 1-16in = 1/16\" = 1'-0\"; 3-32in = 3/32\" = 1'-0\"; 1-8in = 1/8\" = 1'-0\"; 3-16in = 3/16\" = 1'-0\"; 1-4in = 1/4\" = 1'-0\"; 3-8in = 3/8\" = 1'-0\"; 1-2in = 1/2\" = 1'-0\"; 3-4in = 3/4\" = 1'-0\"; 1in = 1\" = 1'-0\"; 1-5in = 1-1/2\" = 1'-0\"; 3in = 3\" = 1'-0\"; 1-5 = 1:5; 1-10 = 1:10; 1-20 = 1:20; 1-50 = 1:50; 1-100 = 1:100; 1-200 = 1:200; 1-500 = 1:500; 1-1000 = 1:1000"
                  },
                  "direction": {
                    "type": "string",
                    "enum": [
                      "realToDrawing",
                      "drawingToReal"
                    ],
                    "default": "realToDrawing",
                    "description": "realToDrawing = how large a real dimension is drawn on paper; drawingToReal = what a measured-on-paper length represents in reality."
                  }
                },
                "required": [
                  "raw",
                  "scaleId"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/ada_ramp_slope": {
      "post": {
        "operationId": "ada_ramp_slope",
        "summary": "ADA ramp slope calculator",
        "description": "Ramp run, sloped length, landings, and handrail requirement for a given rise, with 2010 ADA §405 compliance flags.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "riseRaw": {
                    "type": "string",
                    "description": "Total vertical rise, e.g. \"30\\\"\" or \"760 mm\"."
                  },
                  "slope": {
                    "type": "number",
                    "description": "Running slope as a rise/run ratio (default 0.08333 = 1:12, the ADA max). e.g. 0.05 for 1:20."
                  }
                },
                "required": [
                  "riseRaw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/stud_spacing": {
      "post": {
        "operationId": "stud_spacing",
        "summary": "Stud spacing reference",
        "description": "Field-stud count and bay layout for a wall at 16\" or 24\" on-center. Excludes corner, intersection, and rough-opening studs (IRC R602.3).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "wallLengthRaw": {
                    "type": "string",
                    "description": "Wall length, e.g. \"24'\" or \"7315 mm\"."
                  },
                  "spacing": {
                    "type": "integer",
                    "enum": [
                      16,
                      24
                    ],
                    "default": 16,
                    "description": "On-center spacing in inches (16 or 24)."
                  }
                },
                "required": [
                  "wallLengthRaw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/stair_calculator": {
      "post": {
        "operationId": "stair_calculator",
        "summary": "Stair calculator",
        "description": "Riser count, riser height, tread run, pitch, and the 2R+T comfort check for a straight flight, with IRC R311.7 compliance flags.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "totalRiseRaw": {
                    "type": "string",
                    "description": "Total floor-to-floor rise, e.g. \"9' 0\\\"\" or \"2740 mm\"."
                  },
                  "treadDepthIn": {
                    "type": "number",
                    "default": 11,
                    "description": "Tread (run) depth in inches (default 11; code minimum is 10)."
                  }
                },
                "required": [
                  "totalRiseRaw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/stair_stringer": {
      "post": {
        "operationId": "stair_stringer",
        "summary": "Stair stringer calculator",
        "description": "Stringer slope length, plumb/level cut angles, framing-square rise & run, and the cut-stringer throat check. Reuses the code-checked stair layout (IRC R311.7).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "totalRiseRaw": {
                    "type": "string",
                    "description": "Total floor-to-floor rise, e.g. \"9' 0\\\"\" or \"2740 mm\"."
                  },
                  "treadDepthIn": {
                    "type": "number",
                    "default": 11,
                    "description": "Tread (run) depth in inches."
                  },
                  "boardWidthIn": {
                    "type": "number",
                    "default": 11.25,
                    "description": "Stringer board actual width in inches — 2×10 = 9.25, 2×12 = 11.25, 2×14 = 13.25."
                  }
                },
                "required": [
                  "totalRiseRaw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/roof_pitch": {
      "post": {
        "operationId": "roof_pitch",
        "summary": "Roof pitch converter",
        "description": "Convert a roof slope between rise-in-12 (\"6:12\"), degrees, and percent grade. Pure geometry.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "value": {
                    "type": "string",
                    "description": "The slope value, interpreted per \"unit\". For unit=pitch accepts \"6\" or \"6:12\"; for degrees a number of degrees; for percent a grade %."
                  },
                  "unit": {
                    "type": "string",
                    "enum": [
                      "pitch",
                      "degrees",
                      "percent"
                    ],
                    "default": "pitch",
                    "description": "How to interpret value: pitch (rise-in-12), degrees, or percent."
                  }
                },
                "required": [
                  "value"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/rafter_length": {
      "post": {
        "operationId": "rafter_length",
        "summary": "Rafter length calculator",
        "description": "Common-rafter run, rise, line length, plumb/seat cut angles, and per-foot length factors for a symmetric gable from a span and pitch.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "spanRaw": {
                    "type": "string",
                    "description": "Total building width, out-to-out of the wall plates, e.g. \"24'\"."
                  },
                  "pitchRaw": {
                    "type": "string",
                    "description": "Roof pitch as rise-in-12, e.g. \"6\" or \"6:12\"."
                  },
                  "overhangRaw": {
                    "type": "string",
                    "description": "Horizontal eave projection past the wall (optional)."
                  },
                  "ridgeThicknessRaw": {
                    "type": "string",
                    "description": "Ridge board thickness — rafter shortens by half of it (optional)."
                  }
                },
                "required": [
                  "spanRaw",
                  "pitchRaw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/roofing_estimate": {
      "post": {
        "operationId": "roofing_estimate",
        "summary": "Roofing calculator",
        "description": "Roof surface area, \"squares\" (100 sq ft), and shingle bundles from a building footprint and roof pitch, with a waste allowance.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "lengthRaw": {
                    "type": "string",
                    "description": "Footprint length, e.g. \"40'\"."
                  },
                  "widthRaw": {
                    "type": "string",
                    "description": "Footprint width, e.g. \"28'\"."
                  },
                  "pitchRaw": {
                    "type": "string",
                    "description": "Roof pitch as rise-in-12, e.g. \"6\" or \"6:12\"."
                  },
                  "waste": {
                    "type": "number",
                    "default": 0.1,
                    "minimum": 0,
                    "description": "Waste allowance as a fraction (e.g. 0.1 for 10%)."
                  }
                },
                "required": [
                  "lengthRaw",
                  "widthRaw",
                  "pitchRaw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/drywall_paint_takeoff": {
      "post": {
        "operationId": "drywall_paint_takeoff",
        "summary": "Drywall & paint takeoff",
        "description": "Drywall sheets and paint gallons for a rectangular wall or ceiling area. Sheet sizes are physical; paint coverage is a ~350 sf/gal rule of thumb.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "widthRaw": {
                    "type": "string",
                    "description": "Surface width, e.g. \"24'\"."
                  },
                  "heightRaw": {
                    "type": "string",
                    "description": "Surface height, e.g. \"9'\"."
                  },
                  "sheet": {
                    "type": "string",
                    "enum": [
                      "4x8",
                      "4x9",
                      "4x10",
                      "4x12"
                    ],
                    "default": "4x8",
                    "description": "Drywall sheet size — 4x8 = 4 × 8 ft; 4x9 = 4 × 9 ft; 4x10 = 4 × 10 ft; 4x12 = 4 × 12 ft"
                  }
                },
                "required": [
                  "widthRaw",
                  "heightRaw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/square_footage": {
      "post": {
        "operationId": "square_footage",
        "summary": "Square footage calculator",
        "description": "Area in sq ft, sq yd, m², and acres from length × width, optionally repeated (quantity) and costed ($/sq ft).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "lengthRaw": {
                    "type": "string",
                    "description": "Length, e.g. \"12'\" or \"3.66 m\"."
                  },
                  "widthRaw": {
                    "type": "string",
                    "description": "Width, e.g. \"10'\"."
                  },
                  "quantity": {
                    "type": "integer",
                    "default": 1,
                    "minimum": 1,
                    "description": "Number of identical areas (whole number ≥ 1)."
                  },
                  "price": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Optional price per square foot for a cost estimate."
                  }
                },
                "required": [
                  "lengthRaw",
                  "widthRaw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/tile_flooring": {
      "post": {
        "operationId": "tile_flooring",
        "summary": "Tile & flooring calculator",
        "description": "Tiles (and boxes) to cover a floor or wall area, with a waste allowance for cuts and breakage.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "areaLengthRaw": {
                    "type": "string",
                    "description": "Area length, e.g. \"12'\"."
                  },
                  "areaWidthRaw": {
                    "type": "string",
                    "description": "Area width, e.g. \"10'\"."
                  },
                  "tileWidthRaw": {
                    "type": "string",
                    "description": "Single tile width, e.g. \"12\\\"\"."
                  },
                  "tileHeightRaw": {
                    "type": "string",
                    "description": "Single tile height, e.g. \"24\\\"\"."
                  },
                  "waste": {
                    "type": "number",
                    "default": 0.1,
                    "minimum": 0,
                    "description": "Waste allowance as a fraction (e.g. 0.1 for 10%)."
                  },
                  "perBox": {
                    "type": "integer",
                    "minimum": 1,
                    "description": "Optional tiles per box, to compute box count."
                  }
                },
                "required": [
                  "areaLengthRaw",
                  "areaWidthRaw",
                  "tileWidthRaw",
                  "tileHeightRaw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/concrete_takeoff": {
      "post": {
        "operationId": "concrete_takeoff",
        "summary": "Concrete takeoff",
        "description": "Concrete volume (cubic yards, cubic metres) and bag counts for slabs, footings, walls, columns, and round piers, with a waste allowance. Dimensions per shape — slab: Length × Width × Thickness; footing: Length × Width × Depth; wall: Length × Height × Thickness; column: Width × Depth × Height; round: Diameter × Height.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "shape": {
                    "type": "string",
                    "enum": [
                      "slab",
                      "footing",
                      "wall",
                      "column",
                      "round"
                    ],
                    "description": "Pour shape. slab = Slab; footing = Footing; wall = Wall; column = Column (rectangular); round = Round pier / sonotube"
                  },
                  "d1Raw": {
                    "type": "string",
                    "description": "First dimension (see shape legend in the description)."
                  },
                  "d2Raw": {
                    "type": "string",
                    "description": "Second dimension (see shape legend)."
                  },
                  "d3Raw": {
                    "type": "string",
                    "description": "Third dimension — required for box shapes (slab/footing/wall/column), ignored for round."
                  },
                  "count": {
                    "type": "integer",
                    "default": 1,
                    "minimum": 1,
                    "description": "Number of identical elements."
                  },
                  "wastePct": {
                    "type": "number",
                    "default": 0.1,
                    "minimum": 0,
                    "description": "Waste allowance as a fraction (default 0.1 = 10%)."
                  }
                },
                "required": [
                  "shape",
                  "d1Raw",
                  "d2Raw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/tributary_area": {
      "post": {
        "operationId": "tributary_area",
        "summary": "Tributary area & load takedown",
        "description": "Floor/roof area a column carries and the load it takes down (interior/edge/corner), using ASCE 7-22 minimum live loads.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "position": {
                    "type": "string",
                    "enum": [
                      "interior",
                      "edge",
                      "corner"
                    ],
                    "description": "Column position: interior (full bay), edge (half), or corner (quarter)."
                  },
                  "bayXRaw": {
                    "type": "string",
                    "description": "Bay spacing in the X direction, e.g. \"24'\"."
                  },
                  "bayYRaw": {
                    "type": "string",
                    "description": "Bay spacing in the Y direction, e.g. \"30'\"."
                  },
                  "loadPsf": {
                    "type": "number",
                    "description": "Uniform load in psf. ASCE 7-22 T.4.3-1 minimum live loads: residential 40, office 50, assembly/lobby 100, light storage 125, roof 20."
                  }
                },
                "required": [
                  "position",
                  "bayXRaw",
                  "bayYRaw",
                  "loadPsf"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/beam_span_depth": {
      "post": {
        "operationId": "beam_span_depth",
        "summary": "Beam span quick-reference",
        "description": "Rough member depth from a span using typical span-to-depth (L/d) ratios. Preliminary sizing only — not a span table or code check.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "memberId": {
                    "type": "string",
                    "enum": [
                      "wood-joist",
                      "wood-beam",
                      "steel-beam",
                      "steel-joist",
                      "concrete-beam",
                      "concrete-slab"
                    ],
                    "description": "Member type — wood-joist = Wood floor joist; wood-beam = Glulam / LVL beam; steel-beam = Steel beam; steel-joist = Open-web steel joist; concrete-beam = Concrete beam; concrete-slab = One-way concrete slab"
                  },
                  "spanRaw": {
                    "type": "string",
                    "description": "Clear span, e.g. \"16'\" or \"4.9 m\"."
                  }
                },
                "required": [
                  "memberId",
                  "spanRaw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/guardrail_balusters": {
      "post": {
        "operationId": "guardrail_balusters",
        "summary": "Guardrail baluster spacing",
        "description": "Even baluster/picket count and clear gap for a guard span under the 4\" sphere rule (a sphere of the max size must NOT pass, so gaps come out strictly under the limit).",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "spanRaw": {
                    "type": "string",
                    "description": "Clear span between guard posts, e.g. \"72\\\"\"."
                  },
                  "balusterWidthRaw": {
                    "type": "string",
                    "description": "Width of one baluster/picket, e.g. \"1.5\\\"\" for a 2×2 or \"0.75\\\"\" for metal."
                  },
                  "maxGapRaw": {
                    "type": "string",
                    "default": "4\"",
                    "description": "Maximum allowed clear gap — the code sphere (default 4\")."
                  }
                },
                "required": [
                  "spanRaw",
                  "balusterWidthRaw"
                ],
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/guardrail_code_reference": {
      "post": {
        "operationId": "guardrail_code_reference",
        "summary": "Guardrail code reference",
        "description": "Cited guard height and opening (sphere) limits for residential (IRC §R312.1) and commercial (IBC §1015). Reference only — DatumSpot does not re-host code tables.",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "code": {
                    "type": "string",
                    "enum": [
                      "residential",
                      "commercial"
                    ],
                    "description": "Optional filter: residential (IRC) or commercial (IBC). Omit for both."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    },
    "/api/calc/ada_dimension_reference": {
      "post": {
        "operationId": "ada_dimension_reference",
        "summary": "ADA dimensions reference",
        "description": "Cited dimensional requirements from the 2010 ADA Standards (turning space, clear floor space, reach ranges, doors, toilets, parking, and more). Omit category to list all categories.",
        "requestBody": {
          "required": false,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "category": {
                    "type": "string",
                    "enum": [
                      "turning-space",
                      "clear-floor-space",
                      "knee-toe",
                      "reach-ranges",
                      "protruding-objects",
                      "doors",
                      "water-closet",
                      "lavatory",
                      "drinking-fountain",
                      "parking",
                      "service-counter",
                      "handrails"
                    ],
                    "description": "Category id — turning-space (Wheelchair turning space); clear-floor-space (Clear floor or ground space); knee-toe (Knee & toe clearance); reach-ranges (Reach ranges); protruding-objects (Protruding objects); doors (Doors & maneuvering clearance); water-closet (Toilet (water closet)); lavatory (Lavatory & sink); drinking-fountain (Drinking fountain); parking (Accessible parking); service-counter (Counters & work surfaces); handrails (Handrails)"
                  },
                  "variant": {
                    "type": "string",
                    "description": "Optional variant id within the category (e.g. approach direction). Omit for all variants."
                  }
                },
                "additionalProperties": false
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "tool": {
                      "type": "string"
                    },
                    "ok": {
                      "type": "boolean"
                    },
                    "summary": {
                      "type": "string"
                    },
                    "data": {
                      "type": "object"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "description": "Invalid input"
          },
          "404": {
            "description": "Unknown tool"
          }
        }
      }
    }
  }
}
