{
  "openapi": "3.1.1",
  "info": {
    "title": "Shelf Sag & Deflection Calculator API",
    "version": "1.0.0",
    "summary": "Check how much a shelf sags under books or a point load, with creep and a front edge strip.",
    "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://kerfwiseshelfsag.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Check how much a shelf sags under books or a point load, with creep and a front edge strip.",
        "description": "Calculate the mid-span sag of a shelf from its span, depth, thickness and material under a uniform and a point load, simply supported or fixed. Includes self-weight, long-term creep and a glued front strip or face-frame rail, and suggests a thickness, strip height or support.\n\nMethodology:\n- Euler–Bernoulli beam, maximum at mid-span: simply supported δ = 5wL⁴/(384EI) + PL³/(48EI); both ends fixed δ = wL⁴/(384EI) + PL³/(192EI). w = uniform load plus self-weight (density × g × section area), P = point load × g (g = 9.80665 m/s²).\n- Composite section by the transformed-section method: a front strip with its top flush with the shelf is scaled by n = E_strip / E_shelf; the neutral axis and I follow from the parallel-axis theorem.\n- Long-term (creep) deflection follows EN 1995-1-1 §2.3.2.2 for a permanent load: every part uses E / (1 + k_def) with k_def for service class 1 (solid wood 0.6, plywood 0.8, OSB/3 and P6 1.5, P4 particleboard and MDF 2.25).\n- Moduli are typical: solid wood from the USDA Wood Handbook (clear wood, 12 % moisture content), panels from EN 12369-1 mean values, P2 furniture board from the EN 312 minimum requirement and birch plywood from the Handbook of Finnish Plywood. Use the custom modulus for your board.\n- Suggestions: the thickness or strip height that just meets the limit (bisection, rounded up to 1 mm), the longest span that passes and the sag with a centre support (two separate half spans, conservative).\n\nA serviceability estimate, not a strength check: bending stress, pin and joint strength, knots, moisture and shelf-pin rocking are not included. Real boards vary; a test load tells the truth.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "kerfwise_shelf_sag",
        "x-owner-app": "kerfwise",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/KerfwiseShelfSagInput"
              },
              "examples": {
                "example1": {
                  "summary": "MDF bookshelf, 762 mm span, a full row of books",
                  "value": {
                    "span": 762,
                    "depth": 277,
                    "thickness": 18,
                    "material": "mdf",
                    "uniformLoad": 33,
                    "limit": "L/300"
                  }
                },
                "example2": {
                  "summary": "Same shelf with a 38 mm oak front strip",
                  "value": {
                    "span": 762,
                    "depth": 277,
                    "thickness": 18,
                    "material": "mdf",
                    "uniformLoad": 33,
                    "limit": "L/300",
                    "stripHeight": 38,
                    "stripThickness": 19,
                    "stripMaterial": "oak-red"
                  }
                },
                "example3": {
                  "summary": "Birch plywood shelf, 900 mm, 20 kg point load, short-term",
                  "value": {
                    "span": 900,
                    "depth": 300,
                    "thickness": 18,
                    "material": "ply-birch",
                    "uniformLoad": 0,
                    "pointLoad": 20,
                    "longTerm": false,
                    "limit": "L/360"
                  }
                },
                "example4": {
                  "summary": "Solid red oak, glued housings, 0.02 in per foot rule",
                  "value": {
                    "span": 1000,
                    "depth": 250,
                    "thickness": 22,
                    "material": "oak-red",
                    "support": "fixed",
                    "uniformLoad": 30,
                    "limit": "L/600"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/KerfwiseShelfSagResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "KerfwiseShelfSagInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "span": {
            "title": "Span between supports",
            "type": "number",
            "minimum": 50,
            "maximum": 5000,
            "default": 762,
            "x-unit": "mm"
          },
          "depth": {
            "title": "Shelf depth (front to back)",
            "type": "number",
            "minimum": 20,
            "maximum": 2000,
            "default": 277,
            "x-unit": "mm"
          },
          "thickness": {
            "title": "Shelf thickness",
            "type": "number",
            "minimum": 3,
            "maximum": 100,
            "default": 18,
            "x-unit": "mm"
          },
          "material": {
            "title": "Shelf material",
            "type": "string",
            "enum": [
              "pb-p2",
              "pb-p4",
              "pb-p6",
              "mdf",
              "osb3",
              "ply-birch",
              "ply-birch-cross",
              "oak-red",
              "oak-white",
              "maple-sugar",
              "maple-red",
              "beech",
              "birch-yellow",
              "cherry",
              "walnut",
              "ash-white",
              "poplar",
              "douglas-fir",
              "pine-white"
            ],
            "default": "mdf"
          },
          "customE": {
            "title": "Custom modulus of elasticity (optional)",
            "description": "Replaces the material value, for example from the board maker’s data sheet.",
            "type": "number",
            "minimum": 100,
            "maximum": 30000,
            "x-unit": "N/mm²"
          },
          "support": {
            "title": "Supports",
            "type": "string",
            "enum": [
              "simple",
              "fixed"
            ],
            "default": "simple"
          },
          "uniformLoad": {
            "title": "Uniform load along the shelf",
            "description": "A full row of books is about 30–40 kg per metre on a 300 mm deep shelf.",
            "type": "number",
            "minimum": 0,
            "maximum": 2000,
            "default": 33,
            "x-unit": "kg/m"
          },
          "pointLoad": {
            "title": "Point load at mid-span",
            "type": "number",
            "minimum": 0,
            "maximum": 2000,
            "default": 0,
            "x-unit": "kg"
          },
          "selfWeight": {
            "title": "Include the shelf’s own weight",
            "type": "boolean",
            "default": true
          },
          "longTerm": {
            "title": "Long-term load (include creep)",
            "type": "boolean",
            "default": true
          },
          "limit": {
            "title": "Sag limit",
            "type": "string",
            "enum": [
              "L/240",
              "L/300",
              "L/360",
              "L/600"
            ],
            "default": "L/300"
          },
          "stripHeight": {
            "title": "Front strip height (optional)",
            "description": "A solid edge strip or face-frame rail glued to the front edge, top flush with the shelf. Empty = none.",
            "type": "number",
            "minimum": 3,
            "maximum": 300,
            "x-unit": "mm"
          },
          "stripThickness": {
            "title": "Front strip thickness",
            "type": "number",
            "minimum": 3,
            "maximum": 100,
            "default": 19,
            "x-unit": "mm"
          },
          "stripMaterial": {
            "title": "Front strip material",
            "type": "string",
            "enum": [
              "pb-p2",
              "pb-p4",
              "pb-p6",
              "mdf",
              "osb3",
              "ply-birch",
              "ply-birch-cross",
              "oak-red",
              "oak-white",
              "maple-sugar",
              "maple-red",
              "beech",
              "birch-yellow",
              "cherry",
              "walnut",
              "ash-white",
              "poplar",
              "douglas-fir",
              "pine-white"
            ],
            "default": "oak-red"
          }
        },
        "required": []
      },
      "KerfwiseShelfSagResult": {
        "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": [
              "verdict",
              "passes",
              "material",
              "stiffener",
              "section",
              "sectionLongTerm",
              "loads",
              "deflection",
              "limit",
              "limitMm",
              "ratio",
              "spanOver",
              "suggestions",
              "warnings"
            ],
            "properties": {
              "verdict": {
                "type": "string"
              },
              "passes": {
                "type": "boolean"
              },
              "material": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "eMpa": {
                    "type": "number"
                  },
                  "densityKgM3": {
                    "type": "number"
                  },
                  "kdef": {
                    "type": "number"
                  },
                  "source": {
                    "type": "string"
                  }
                }
              },
              "stiffener": {
                "type": [
                  "object",
                  "null"
                ],
                "properties": {
                  "material": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "eMpa": {
                    "type": "number"
                  },
                  "kdef": {
                    "type": "number"
                  }
                }
              },
              "section": {
                "type": "object",
                "description": "Transformed section (instantaneous moduli): neutral axis from the top, I in mm⁴, EI in N·mm²."
              },
              "sectionLongTerm": {
                "type": "object",
                "description": "Transformed section with E / (1 + k_def) per part."
              },
              "loads": {
                "type": "object",
                "properties": {
                  "selfNPerMm": {
                    "type": "number"
                  },
                  "uniformNPerMm": {
                    "type": "number"
                  },
                  "pointN": {
                    "type": "number"
                  },
                  "totalKg": {
                    "type": "number"
                  }
                }
              },
              "deflection": {
                "type": "object",
                "properties": {
                  "selfMm": {
                    "type": "number"
                  },
                  "uniformMm": {
                    "type": "number"
                  },
                  "pointMm": {
                    "type": "number"
                  },
                  "instantMm": {
                    "type": "number"
                  },
                  "longTermMm": {
                    "type": "number"
                  },
                  "creepFactor": {
                    "type": "number"
                  },
                  "checkedMm": {
                    "type": "number"
                  }
                }
              },
              "limit": {
                "enum": [
                  "L/240",
                  "L/300",
                  "L/360",
                  "L/600"
                ]
              },
              "limitMm": {
                "type": "number"
              },
              "ratio": {
                "type": "number"
              },
              "spanOver": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "suggestions": {
                "type": "object",
                "properties": {
                  "thicknessMm": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "stiffenerHeightMm": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "maxSpanMm": {
                    "type": "number"
                  },
                  "midSupportMm": {
                    "type": "number"
                  }
                }
              },
              "warnings": {
                "type": "array",
                "items": {
                  "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"
              }
            }
          }
        }
      }
    }
  }
}