{
  "openapi": "3.1.1",
  "info": {
    "title": "Break-even Explorer API",
    "version": "1.0.0",
    "summary": "When does an investment pay for itself? Payback, NPV and IRR for solar, EVs, heat pumps…",
    "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://breakevenexplorer.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "When does an investment pay for itself? Payback, NPV and IRR for solar, EVs, heat pumps…",
        "description": "Enter an upfront investment, subsidies and the yearly savings it brings, with optional price escalation, performance degradation and maintenance. The explorer returns simple and discounted payback (fractional years), NPV, IRR and a year-by-year cumulative cash-flow table.\n\nMethodology:\n- Net investment (year 0 outflow) = upfront investment − subsidies.\n- Savings in year t = year-1 savings × (1 + escalation)^(t−1) × (1 − degradation)^(t−1), unless overridden for that year.\n- Net cash flow in year t = savings − maintenance (maintenance is constant in nominal terms).\n- Simple payback = the year in which cumulative cash flow turns non-negative, interpolated linearly within that year (savings assumed to accrue evenly).\n- Discounted payback uses cash flows discounted by (1 + r)^t; NPV = −net investment + Σ net cash flow ÷ (1 + r)^t.\n- IRR = the rate at which NPV = 0, found by bisection between −99% and 1000% (null if NPV does not change sign in that range).\n- Presets only supply defaults for escalation, degradation and horizon when those fields are left empty; the values used are always listed.",
        "tags": [
          "money"
        ],
        "x-mcp-tool": "break_even_explorer",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/BreakEvenExplorerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Rooftop solar with a grant",
                  "value": {
                    "preset": "solar",
                    "currency": "EUR",
                    "upfrontInvestment": 12000,
                    "subsidies": 1500,
                    "annualSavings": 1100,
                    "maintenancePerYear": 100,
                    "discountRatePercent": 3
                  }
                },
                "example2": {
                  "summary": "Insulation project, flat savings, 15 years",
                  "value": {
                    "preset": "custom",
                    "currency": "EUR",
                    "upfrontInvestment": 6000,
                    "subsidies": 0,
                    "annualSavings": 700,
                    "savingsEscalationPercent": 0,
                    "degradationPercent": 0,
                    "maintenancePerYear": 0,
                    "discountRatePercent": 4,
                    "horizonYears": 15
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BreakEvenExplorerResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "BreakEvenExplorerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "preset": {
            "title": "Preset",
            "description": "Presets only fill in escalation, degradation and horizon when you leave those empty; the values are listed under assumptions.",
            "type": "string",
            "enum": [
              "custom",
              "solar",
              "ev",
              "heat-pump"
            ],
            "default": "custom"
          },
          "currency": {
            "title": "Currency",
            "description": "Shown in results only; no conversion is performed.",
            "type": "string",
            "maxLength": 8,
            "default": "EUR"
          },
          "upfrontInvestment": {
            "title": "Upfront investment",
            "type": "number",
            "minimum": 0,
            "default": 10000
          },
          "subsidies": {
            "title": "Subsidies / grants / tax credits",
            "description": "Received at the start; reduces the net investment.",
            "type": "number",
            "minimum": 0,
            "default": 0
          },
          "annualSavings": {
            "title": "Savings in year 1",
            "type": "number",
            "default": 1200,
            "x-unit": "per year"
          },
          "savingsEscalationPercent": {
            "title": "Savings escalation (e.g. energy price inflation)",
            "description": "Empty = preset default.",
            "type": "number",
            "minimum": -50,
            "maximum": 50,
            "x-unit": "%/year"
          },
          "degradationPercent": {
            "title": "Performance degradation",
            "description": "Empty = preset default.",
            "type": "number",
            "minimum": 0,
            "maximum": 50,
            "x-unit": "%/year"
          },
          "maintenancePerYear": {
            "title": "Maintenance per year",
            "type": "number",
            "minimum": 0,
            "default": 0
          },
          "discountRatePercent": {
            "title": "Discount rate",
            "type": "number",
            "minimum": 0,
            "maximum": 50,
            "default": 3,
            "x-unit": "%/year"
          },
          "horizonYears": {
            "title": "Horizon",
            "description": "Empty = preset default.",
            "type": "integer",
            "minimum": 1,
            "maximum": 60,
            "x-unit": "years"
          },
          "savingsByYear": {
            "title": "Override savings for specific years (optional)",
            "description": "Savings entered here replace the escalated/degraded value for that year (before maintenance).",
            "type": "array",
            "maxItems": 60,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "year": {
                  "title": "Year",
                  "type": "integer",
                  "minimum": 1,
                  "maximum": 60
                },
                "savings": {
                  "title": "Savings",
                  "type": "number"
                }
              },
              "required": [
                "year",
                "savings"
              ]
            }
          }
        },
        "required": [
          "upfrontInvestment",
          "annualSavings"
        ]
      },
      "BreakEvenExplorerResult": {
        "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": [
              "preset",
              "currency",
              "netInvestment",
              "horizonYears",
              "escalationPercent",
              "degradationPercent",
              "discountRatePercent",
              "simplePaybackYears",
              "discountedPaybackYears",
              "npv",
              "irrPercent",
              "totalNetSavings",
              "roiPercent",
              "years"
            ],
            "properties": {
              "preset": {
                "type": "string",
                "enum": [
                  "custom",
                  "solar",
                  "ev",
                  "heat-pump"
                ]
              },
              "currency": {
                "type": "string"
              },
              "netInvestment": {
                "type": "number",
                "description": "Upfront investment − subsidies."
              },
              "horizonYears": {
                "type": "integer"
              },
              "escalationPercent": {
                "type": "number"
              },
              "degradationPercent": {
                "type": "number"
              },
              "discountRatePercent": {
                "type": "number"
              },
              "simplePaybackYears": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Fractional years until cumulative nominal cash flow reaches 0; null if not within the horizon."
              },
              "discountedPaybackYears": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "npv": {
                "type": "number"
              },
              "irrPercent": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "Internal rate of return in %; null if none exists in [−99%, 1000%]."
              },
              "totalNetSavings": {
                "type": "number",
                "description": "Sum of yearly net cash flows (savings − maintenance) over the horizon."
              },
              "roiPercent": {
                "type": [
                  "number",
                  "null"
                ],
                "description": "(total net savings − net investment) ÷ net investment; null when net investment is 0."
              },
              "years": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "year",
                    "savings",
                    "maintenance",
                    "netCashFlow",
                    "cumulative",
                    "discountedCashFlow",
                    "discountedCumulative"
                  ],
                  "properties": {
                    "year": {
                      "type": "integer"
                    },
                    "savings": {
                      "type": "number"
                    },
                    "maintenance": {
                      "type": "number"
                    },
                    "netCashFlow": {
                      "type": "number"
                    },
                    "cumulative": {
                      "type": "number"
                    },
                    "discountedCashFlow": {
                      "type": "number"
                    },
                    "discountedCumulative": {
                      "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"
              }
            }
          }
        }
      }
    }
  }
}