{
  "openapi": "3.1.1",
  "info": {
    "title": "Ledgerly Solar Payback Calculator API",
    "version": "1.0.0",
    "summary": "When do solar panels pay off? Payback, NPV, IRR and cost per kWh with feed-in and a loan.",
    "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://ledgerlysolarpayback.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "When do solar panels pay off? Payback, NPV, IRR and cost per kWh with feed-in and a loan.",
        "description": "Year-by-year cash flow of a PV system: bill savings from the power you use yourself, feed-in income for the guaranteed years, ageing of the panels, running costs, an inverter replacement and an optional loan. Returns simple and discounted payback, NPV, IRR, the cost per kWh produced and a payback table for other price rises and self-consumption shares. Part of Ledgerly’s Solar \u0026 Heat.\n\nMethodology:\n- Each year: yield × (1 − ageing)^(year − 1); the self-used share replaces grid power at the rising electricity price, the rest earns the feed-in payment while it is guaranteed.\n- Net cash flow = bill savings + feed-in income − running costs − inverter replacement (in its year) − loan payments; year 0 is your own money (price − subsidies − loan). Payback and the return on the investment use the flows without the loan; NPV and the return on your own money include it.\n- Loan payments come from the same monthly annuity schedule as the Loan Amortization Calculator. NPV, IRR (bisection) and fractional payback use the same functions as the Break-even Explorer.\n- LCOE = (net price + present value of running costs) ÷ present value of all kWh, before financing. The 3 × 3 table repeats the payback for the price rise ± 1 point and self-consumption ± 10 points.\n\nA model with your assumptions, not financial or tax advice: tariffs, feed-in rules and subsidies differ by country and change over time — enter the ones that apply to you.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "ledgerly_solar_payback",
        "x-owner-app": "ledgerly",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LedgerlySolarPaybackInput"
              },
              "examples": {
                "example1": {
                  "summary": "8 kWp for €14,000, 30 % self-use",
                  "value": {
                    "currency": "EUR",
                    "systemCost": 14000,
                    "annualYieldKwh": 7600,
                    "selfConsumptionPercent": 30,
                    "electricityPrice": 0.35,
                    "feedInTariff": 0.078
                  }
                },
                "example2": {
                  "summary": "With an 8 kWh battery (+€6,000), 55 % self-use, half financed",
                  "value": {
                    "currency": "EUR",
                    "systemCost": 20000,
                    "annualYieldKwh": 7600,
                    "selfConsumptionPercent": 55,
                    "electricityPrice": 0.35,
                    "feedInTariff": 0.078,
                    "loanAmount": 10000,
                    "loanRatePercent": 4.5,
                    "loanYears": 10
                  }
                },
                "example3": {
                  "summary": "US: 6 kW for $18,000 with a 30 % tax credit",
                  "value": {
                    "currency": "USD",
                    "systemCost": 18000,
                    "subsidy": 5400,
                    "annualYieldKwh": 8400,
                    "selfConsumptionPercent": 60,
                    "electricityPrice": 0.17,
                    "electricityPriceIncreasePercent": 2.5,
                    "feedInTariff": 0.05,
                    "feedInYears": 25,
                    "inverterReplacementCost": 2000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LedgerlySolarPaybackResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "LedgerlySolarPaybackInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "currency": {
            "title": "Currency",
            "type": "string",
            "maxLength": 3,
            "default": "EUR"
          },
          "systemCost": {
            "title": "System price incl. installation",
            "type": "number",
            "minimum": 0,
            "maximum": 10000000,
            "default": 14000
          },
          "subsidy": {
            "title": "Subsidies and tax refunds",
            "type": "number",
            "minimum": 0,
            "maximum": 10000000,
            "default": 0
          },
          "annualYieldKwh": {
            "title": "Yield in the first year (kWh)",
            "type": "number",
            "minimum": 0,
            "maximum": 10000000,
            "default": 7600
          },
          "selfConsumptionPercent": {
            "title": "Used in the house (% of the yield)",
            "description": "Without a battery often 25–35 %; the battery simulation gives your value.",
            "type": "number",
            "minimum": 0,
            "maximum": 100,
            "default": 30
          },
          "electricityPrice": {
            "title": "Electricity price per kWh",
            "type": "number",
            "minimum": 0,
            "maximum": 10,
            "default": 0.35
          },
          "electricityPriceIncreasePercent": {
            "title": "Electricity price increase (% per year)",
            "type": "number",
            "minimum": -10,
            "maximum": 20,
            "default": 2
          },
          "feedInTariff": {
            "title": "Feed-in payment per kWh",
            "type": "number",
            "minimum": 0,
            "maximum": 10,
            "default": 0.078
          },
          "feedInYears": {
            "title": "Years the feed-in payment is guaranteed",
            "description": "After that, exported energy earns nothing in this model.",
            "type": "integer",
            "minimum": 0,
            "maximum": 40,
            "default": 20
          },
          "degradationPercent": {
            "title": "Yield loss through ageing (% per year)",
            "type": "number",
            "minimum": 0,
            "maximum": 5,
            "default": 0.5
          },
          "maintenancePerYear": {
            "title": "Insurance, metering and upkeep per year",
            "type": "number",
            "minimum": 0,
            "maximum": 1000000,
            "default": 150
          },
          "costIncreasePercent": {
            "title": "Increase of the running costs (% per year)",
            "type": "number",
            "minimum": -10,
            "maximum": 20,
            "default": 2
          },
          "inverterReplacementCost": {
            "title": "Inverter replacement",
            "type": "number",
            "minimum": 0,
            "maximum": 1000000,
            "default": 1500
          },
          "inverterReplacementYear": {
            "title": "Inverter replaced in year (0 = never)",
            "type": "integer",
            "minimum": 0,
            "maximum": 40,
            "default": 15
          },
          "loanAmount": {
            "title": "Financed by a loan",
            "type": "number",
            "minimum": 0,
            "maximum": 10000000,
            "default": 0
          },
          "loanRatePercent": {
            "title": "Loan interest rate (% per year)",
            "type": "number",
            "minimum": 0,
            "maximum": 25,
            "default": 4.5
          },
          "loanYears": {
            "title": "Loan term (years)",
            "type": "integer",
            "minimum": 1,
            "maximum": 30,
            "default": 10
          },
          "discountRatePercent": {
            "title": "Discount rate for NPV (% per year)",
            "description": "What your money would earn elsewhere.",
            "type": "number",
            "minimum": -5,
            "maximum": 20,
            "default": 3
          },
          "horizonYears": {
            "title": "Years to compare",
            "type": "integer",
            "minimum": 1,
            "maximum": 40,
            "default": 25
          }
        },
        "required": []
      },
      "LedgerlySolarPaybackResult": {
        "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": [
              "currency",
              "netInvestment",
              "equity",
              "paybackYears",
              "discountedPaybackYears",
              "npv",
              "irrPercent",
              "projectIrrPercent",
              "lcoePerKwh",
              "loanInterest",
              "cumulativeAtHorizon",
              "scenarios",
              "years"
            ],
            "properties": {
              "currency": {
                "type": "string"
              },
              "netInvestment": {
                "type": "number"
              },
              "equity": {
                "type": "number"
              },
              "paybackYears": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "discountedPaybackYears": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "npv": {
                "type": "number"
              },
              "irrPercent": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "projectIrrPercent": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "lcoePerKwh": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "loanInterest": {
                "type": "number"
              },
              "cumulativeAtHorizon": {
                "type": "number"
              },
              "scenarios": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "priceIncreasePercent",
                    "selfConsumptionPercent",
                    "paybackYears"
                  ],
                  "properties": {
                    "priceIncreasePercent": {
                      "type": "number"
                    },
                    "selfConsumptionPercent": {
                      "type": "number"
                    },
                    "paybackYears": {
                      "type": [
                        "number",
                        "null"
                      ]
                    }
                  }
                }
              },
              "years": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "year",
                    "yieldKwh",
                    "selfUsedKwh",
                    "exportedKwh",
                    "billSavings",
                    "feedInIncome",
                    "runningCosts",
                    "loanPayments",
                    "netCashFlow",
                    "cumulative"
                  ],
                  "properties": {
                    "year": {
                      "type": "integer"
                    },
                    "yieldKwh": {
                      "type": "number"
                    },
                    "selfUsedKwh": {
                      "type": "number"
                    },
                    "exportedKwh": {
                      "type": "number"
                    },
                    "billSavings": {
                      "type": "number"
                    },
                    "feedInIncome": {
                      "type": "number"
                    },
                    "runningCosts": {
                      "type": "number"
                    },
                    "loanPayments": {
                      "type": "number"
                    },
                    "netCashFlow": {
                      "type": "number"
                    },
                    "cumulative": {
                      "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"
              }
            }
          }
        }
      }
    }
  }
}