{
  "openapi": "3.1.1",
  "info": {
    "title": "Curve Fitter & Regression Calculator API",
    "version": "1.0.0",
    "summary": "Fit lines, polynomials, exponentials or your own model: parameters, R², errors, residuals.",
    "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://prooflinecurvefit.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Fit lines, polynomials, exponentials or your own model: parameters, R², errors, residuals.",
        "description": "Paste x/y data (CSV, tabs or spaces) and fit a straight line, polynomial, exponential, power-law, logarithmic, multiple linear or your own nonlinear model, or interpolate with a natural cubic spline. You get the parameters with standard errors, t and p values and confidence intervals, R² and adjusted R², an ANOVA table, a residual plot and predictions with confidence intervals. Verified against the NIST StRD reference datasets; part of the Proofline math notebook.\n\nMethodology:\n- Models that are linear in their parameters (line, polynomial, multiple, logarithmic) are solved by Householder QR of the column-scaled design matrix — never by the normal equations, which square the condition number.\n- Exponential, power and custom models use Levenberg–Marquardt: each damped step solves [J; √λ·D]·δ ≅ [r; 0] by QR with D the column norms of the central-difference Jacobian. Exponential and power fits start from the log-linear fit but minimise the residuals of y itself.\n- Standard errors are √diag(s²·(RᵀR)⁻¹) with s² = SSE/(n − p); t and p values and confidence intervals use Student’s t with n − p degrees of freedom. For nonlinear models these are the usual linearised (asymptotic) values.\n- R² = 1 − SSE/SST (centred); without an intercept R² is uncentred, as in the NIST datasets. The F test compares the model with a constant.\n- Verified against NIST StRD certified values: Norris, Pontius, NoInt1, Longley, Wampler1 and Filip (linear) and Misra1a, Thurber, DanWood, Chwirut2 and MGH09 (nonlinear, both start points) — at least 7 matching digits for the parameters.\n- Splines: natural cubic spline (second derivative zero at both ends) from a tridiagonal system; outside the data the end cubics are continued and flagged as extrapolation.\n\nRegression statistics assume independent errors with constant variance. A high R² does not prove that the model is right — check the residual plot for patterns.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "proofline_curve_fit",
        "x-owner-app": "proofline",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/ProoflineCurveFitInput"
              },
              "examples": {
                "example1": {
                  "summary": "Straight line with prediction",
                  "value": {
                    "data": "x,y\n1,2.1\n2,3.9\n3,6.2\n4,7.8\n5,10.1",
                    "model": "linear",
                    "evaluateAt": "6"
                  }
                },
                "example2": {
                  "summary": "NIST Norris calibration data (certified line)",
                  "value": {
                    "data": "x,y\n0.2,0.1\n337.4,338.8\n118.2,118.1\n884.6,888.0\n10.1,9.2\n226.5,228.1\n666.3,668.5\n996.3,998.5\n448.6,449.1\n777.0,778.9\n558.2,559.2\n0.4,0.3\n0.6,0.1\n775.5,778.1\n666.9,668.8\n338.0,339.3\n447.5,448.9\n11.6,10.8\n556.0,557.7\n228.1,228.3\n995.8,998.0\n887.6,888.8\n120.2,119.6\n0.3,0.3\n0.3,0.6\n556.8,557.6\n339.1,339.3\n887.2,888.0\n999.0,998.5\n779.0,778.9\n11.1,10.2\n118.3,117.6\n229.2,228.9\n669.1,668.4\n448.9,449.2\n0.5,0.2",
                    "model": "linear"
                  }
                },
                "example3": {
                  "summary": "NIST Misra1a: y = b1·(1 − e^(−b2·x))",
                  "value": {
                    "data": "x y\n77.6 10.07\n114.9 14.73\n141.1 17.94\n190.8 23.93\n239.9 29.61\n289.0 35.18\n332.8 40.02\n378.4 44.82\n434.8 50.76\n477.3 55.05\n536.8 61.01\n593.1 66.40\n689.1 75.47\n760.0 81.78",
                    "model": "custom",
                    "expression": "b1*(1 - exp(-b2*x))",
                    "parameters": "b1 = 500, b2 = 0.0001"
                  }
                },
                "example4": {
                  "summary": "Exponential decay",
                  "value": {
                    "data": "t,activity\n0,5.0\n1,3.1\n2,1.8\n3,1.1\n4,0.68\n5,0.40",
                    "model": "exponential",
                    "evaluateAt": "6"
                  }
                },
                "example5": {
                  "summary": "Quadratic polynomial",
                  "value": {
                    "data": "x y\n-2 4.2\n-1 0.9\n0 0.1\n1 1.2\n2 3.8\n3 9.1",
                    "model": "polynomial",
                    "degree": 2
                  }
                },
                "example6": {
                  "summary": "Natural cubic spline interpolation",
                  "value": {
                    "data": "x,y\n0,0\n1,0.84\n2,0.91\n3,0.14\n4,-0.76",
                    "model": "spline",
                    "evaluateAt": "0.5, 2.5"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProoflineCurveFitResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "ProoflineCurveFitInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "data": {
            "title": "Data",
            "description": "One row per line, values separated by commas, tabs, semicolons or spaces; an optional header row names the columns. Use a decimal point (1.5).",
            "type": "string",
            "maxLength": 400000
          },
          "model": {
            "title": "Model",
            "type": "string",
            "enum": [
              "linear",
              "polynomial",
              "exponential",
              "power",
              "logarithmic",
              "multiple",
              "custom",
              "spline",
              "interpolation"
            ],
            "default": "linear"
          },
          "xColumn": {
            "title": "x column",
            "description": "Column number (1 = first) or header name; default the first column. Multiple regression: a comma-separated list (default: every column except y).",
            "type": "string",
            "maxLength": 200
          },
          "yColumn": {
            "title": "y column",
            "description": "Column number or header name; default the second column.",
            "type": "string",
            "maxLength": 100
          },
          "degree": {
            "title": "Polynomial degree",
            "type": "integer",
            "minimum": 1,
            "maximum": 10,
            "default": 2
          },
          "intercept": {
            "title": "Include an intercept (constant term)",
            "description": "Straight line, polynomial and multiple regression. Without it the fit goes through the origin and R² is uncentred.",
            "type": "boolean",
            "default": true
          },
          "expression": {
            "title": "Custom model y =",
            "description": "Formula in x and your parameters. Use + − * / ^, implicit products (2x), sin, cos, tan, exp, ln (natural log), log (base 10), sqrt, abs, pi and e. Angles are in radians.",
            "type": "string",
            "maxLength": 2000
          },
          "parameters": {
            "title": "Parameters with start values",
            "description": "Custom model: every parameter with a start value. Start values near the solution help Levenberg–Marquardt.",
            "type": "string",
            "maxLength": 1000
          },
          "evaluateAt": {
            "title": "Evaluate the fit at x =",
            "description": "Optional list of x values: predicted y with standard error and confidence interval (interpolated value for splines).",
            "type": "string",
            "maxLength": 4000
          },
          "confidence": {
            "title": "Confidence level",
            "type": "number",
            "minimum": 0.5,
            "maximum": 0.9999,
            "default": 0.95
          }
        },
        "required": [
          "data"
        ]
      },
      "ProoflineCurveFitResult": {
        "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": [
              "model",
              "equation",
              "n",
              "xColumns",
              "yColumn",
              "parameters",
              "r2",
              "adjR2",
              "residualSd",
              "sse",
              "dof",
              "fStatistic",
              "fP",
              "confidence",
              "converged",
              "iterations",
              "points",
              "predictions",
              "segments"
            ],
            "properties": {
              "model": {
                "type": "string",
                "enum": [
                  "linear",
                  "polynomial",
                  "exponential",
                  "power",
                  "logarithmic",
                  "multiple",
                  "custom",
                  "spline",
                  "interpolation"
                ]
              },
              "equation": {
                "type": "string"
              },
              "n": {
                "type": "integer"
              },
              "xColumns": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "yColumn": {
                "type": "string"
              },
              "parameters": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name",
                    "value",
                    "se",
                    "t",
                    "p",
                    "ciLow",
                    "ciHigh"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "value": {
                      "type": "number"
                    },
                    "se": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "t": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "p": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "ciLow": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "ciHigh": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  }
                }
              },
              "r2": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "adjR2": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "residualSd": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "sse": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "dof": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "fStatistic": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "fP": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "confidence": {
                "type": "number"
              },
              "converged": {
                "type": "boolean"
              },
              "iterations": {
                "type": [
                  "integer",
                  "null"
                ]
              },
              "points": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "x",
                    "y",
                    "fitted",
                    "residual"
                  ],
                  "properties": {
                    "x": {
                      "type": "number"
                    },
                    "y": {
                      "type": "number"
                    },
                    "fitted": {
                      "type": "number"
                    },
                    "residual": {
                      "type": "number"
                    }
                  }
                }
              },
              "predictions": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "x",
                    "y",
                    "se",
                    "ciLow",
                    "ciHigh",
                    "extrapolated"
                  ],
                  "properties": {
                    "x": {
                      "type": "number"
                    },
                    "y": {
                      "type": "number"
                    },
                    "se": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "ciLow": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "ciHigh": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "extrapolated": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "segments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "x0",
                    "x1",
                    "a",
                    "b",
                    "c",
                    "d"
                  ],
                  "properties": {
                    "x0": {
                      "type": "number"
                    },
                    "x1": {
                      "type": "number"
                    },
                    "a": {
                      "type": "number"
                    },
                    "b": {
                      "type": "number"
                    },
                    "c": {
                      "type": "number"
                    },
                    "d": {
                      "type": "number"
                    }
                  }
                }
              }
            }
          },
          "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"
              }
            }
          }
        }
      }
    }
  }
}