{
  "openapi": "3.1.1",
  "info": {
    "title": "Ledgerly Heat Pump Estimate API",
    "version": "1.0.0",
    "summary": "Would a heat pump be cheaper than my gas or oil boiler? Heat load, COP and running costs.",
    "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://ledgerlyheatpumpestimate.usefulweb.app"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Would a heat pump be cheaper than my gas or oil boiler? Heat load, COP and running costs.",
        "description": "Turns your past gas, oil, LPG or pellet use into heat demand, spreads it over the year with the outdoor temperatures (DWD climate normals or your own), and estimates the heat pump’s electricity from a temperature-dependent COP and heating curve. Compares running costs and CO₂ with your boiler, and shows the heat load on the coldest day and the payback of the investment. Part of Ledgerly’s Solar \u0026 Heat.\n\nMethodology:\n- Heat = fuel use × energy content × boiler efficiency (typical energy contents: natural gas 10 kWh/m³; heating oil 10 kWh/litre; liquid gas (lpg) 6.57 kWh/litre; wood pellets 4.8 kWh/kg). The hot-water share is spread evenly over the year.\n- Space heat is spread over the year by degree-hours below the heating limit, with each month’s daily means assumed normally distributed around the monthly mean (σ = 4 K, five bands); this also gives the heat-loss coefficient and the heat load on the coldest day.\n- COP = quality factor × T_flow ÷ (T_flow − T_source) in kelvin, limited to 1–7; air source uses the outdoor temperature, ground source 2 °C. The flow temperature follows a straight heating curve from your design value on the coldest day to 25 °C at the heating limit.\n- Running costs compare fuel × price + fixed boiler costs with heat-pump electricity × price + fixed heat-pump costs; CO₂ uses GEG Anlage 9 for fuels and the Umweltbundesamt’s 2025 German grid factor by default.\n\nAn estimate for comparing options, not a heat-load calculation to EN 12831 or installer advice: size the heat pump with a qualified installer, and check local subsidies and tariffs yourself.",
        "tags": [
          "apps"
        ],
        "x-mcp-tool": "ledgerly_heat_pump_estimate",
        "x-owner-app": "ledgerly",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LedgerlyHeatPumpEstimateInput"
              },
              "examples": {
                "example1": {
                  "summary": "Berlin, 20,000 kWh gas, radiators at 50 °C",
                  "value": {
                    "latitude": 52.52,
                    "longitude": 13.405,
                    "fuel": "gas",
                    "fuelUse": 20000,
                    "fuelUnit": "kwh",
                    "flowTempC": 50,
                    "fuelPrice": 0.11
                  }
                },
                "example2": {
                  "summary": "Oil: 2,500 litres a year, old radiators at 60 °C",
                  "value": {
                    "latitude": 51.05,
                    "longitude": 13.74,
                    "fuel": "oil",
                    "fuelUse": 2500,
                    "fuelUnit": "litre",
                    "boilerEfficiencyPercent": 80,
                    "flowTempC": 60,
                    "fuelPrice": 1,
                    "investment": 35000,
                    "subsidy": 10500
                  }
                },
                "example3": {
                  "summary": "Ground source with underfloor heating, own temperatures",
                  "value": {
                    "climate": "manual",
                    "monthlyTemperatures": "0.5, 1.5, 4.8, 9.2, 13.5, 16.6, 18.7, 18.2, 14.3, 9.7, 5.0, 1.6",
                    "fuel": "gas",
                    "fuelUse": 1800,
                    "fuelUnit": "m3",
                    "fuelPrice": 1.15,
                    "heatPumpType": "ground",
                    "flowTempC": 35,
                    "investment": 40000
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/LedgerlyHeatPumpEstimateResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "LedgerlyHeatPumpEstimateInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "currency": {
            "title": "Currency",
            "type": "string",
            "maxLength": 3,
            "default": "EUR"
          },
          "latitude": {
            "title": "Latitude (°, south negative)",
            "type": "number",
            "minimum": -66,
            "maximum": 66,
            "default": 52.52
          },
          "longitude": {
            "title": "Longitude (°, west negative)",
            "type": "number",
            "minimum": -180,
            "maximum": 180,
            "default": 13.405
          },
          "climate": {
            "title": "Outdoor temperatures",
            "type": "string",
            "enum": [
              "auto",
              "manual"
            ],
            "default": "auto"
          },
          "monthlyTemperatures": {
            "title": "Monthly mean temperatures (°C, 12 values, Jan–Dec)",
            "type": "string",
            "maxLength": 300,
            "default": ""
          },
          "elevation": {
            "title": "Height of the house above sea level (m; empty = like the station)",
            "type": "number",
            "minimum": -500,
            "maximum": 5000
          },
          "fuel": {
            "title": "Current heating",
            "type": "string",
            "enum": [
              "gas",
              "oil",
              "lpg",
              "pellets"
            ],
            "default": "gas"
          },
          "fuelUse": {
            "title": "Fuel used per year (from your bills)",
            "type": "number",
            "minimum": 0,
            "maximum": 10000000,
            "default": 20000
          },
          "fuelUnit": {
            "title": "Unit of the fuel use",
            "type": "string",
            "enum": [
              "kwh",
              "m3",
              "litre",
              "kg"
            ],
            "default": "kwh"
          },
          "boilerEfficiencyPercent": {
            "title": "Efficiency of the old boiler (%)",
            "description": "Condensing gas boilers about 90–95 %, older boilers 75–85 %.",
            "type": "number",
            "minimum": 40,
            "maximum": 110,
            "default": 90
          },
          "hotWaterPercent": {
            "title": "Share for hot water (%)",
            "type": "number",
            "minimum": 0,
            "maximum": 80,
            "default": 15
          },
          "heatingLimitC": {
            "title": "Heating limit temperature (°C)",
            "description": "Above this outdoor temperature the house needs no heating.",
            "type": "number",
            "minimum": 8,
            "maximum": 22,
            "default": 15
          },
          "designTempC": {
            "title": "Coldest design temperature (°C)",
            "type": "number",
            "minimum": -40,
            "maximum": 10,
            "default": -12
          },
          "heatPumpType": {
            "title": "Heat pump type",
            "type": "string",
            "enum": [
              "air",
              "ground"
            ],
            "default": "air"
          },
          "flowTempC": {
            "title": "Flow temperature on the coldest day (°C)",
            "description": "Underfloor heating 30–35 °C, large radiators 45–55 °C, small old radiators 60–70 °C.",
            "type": "number",
            "minimum": 25,
            "maximum": 75,
            "default": 50
          },
          "hotWaterTempC": {
            "title": "Hot water temperature (°C)",
            "type": "number",
            "minimum": 40,
            "maximum": 70,
            "default": 50
          },
          "carnotEfficiencyPercent": {
            "title": "Heat pump quality (% of the ideal Carnot COP)",
            "description": "Good current units reach about 40–50 % of the ideal value; 40 % is a cautious default that also covers defrosting.",
            "type": "number",
            "minimum": 20,
            "maximum": 70,
            "default": 40
          },
          "fuelPrice": {
            "title": "Fuel price per unit of the fuel use (empty = example price)",
            "description": "Example prices when empty: gas 0.11 per kWh, oil 1.00 per litre, LPG 0.80 per litre, pellets 0.35 per kg (per kWh: about a tenth). Enter your own price.",
            "type": "number",
            "minimum": 0,
            "maximum": 100
          },
          "boilerFixedPerYear": {
            "title": "Fixed boiler costs per year (standing charge, service, chimney sweep)",
            "type": "number",
            "minimum": 0,
            "maximum": 100000,
            "default": 350
          },
          "electricityPrice": {
            "title": "Heat pump electricity price per kWh",
            "type": "number",
            "minimum": 0,
            "maximum": 10,
            "default": 0.28
          },
          "heatPumpFixedPerYear": {
            "title": "Fixed heat pump costs per year (meter, service)",
            "type": "number",
            "minimum": 0,
            "maximum": 100000,
            "default": 200
          },
          "investment": {
            "title": "Heat pump price incl. installation (0 = skip payback)",
            "type": "number",
            "minimum": 0,
            "maximum": 10000000,
            "default": 30000
          },
          "subsidy": {
            "title": "Subsidies",
            "type": "number",
            "minimum": 0,
            "maximum": 10000000,
            "default": 0
          },
          "fuelCo2": {
            "title": "CO₂ of the fuel (kg per kWh; empty = German GEG value)",
            "type": "number",
            "minimum": 0,
            "maximum": 1
          },
          "electricityCo2": {
            "title": "CO₂ of grid power (kg per kWh)",
            "description": "Default: German mix 2025 incl. upstream emissions (Umweltbundesamt).",
            "type": "number",
            "minimum": 0,
            "maximum": 2,
            "default": 0.406
          }
        },
        "required": []
      },
      "LedgerlyHeatPumpEstimateResult": {
        "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",
              "climate",
              "fuelKwh",
              "heatKwh",
              "spaceHeatKwh",
              "hotWaterKwh",
              "heatLossCoefficientWPerK",
              "designHeatLoadKw",
              "heatPumpElectricityKwh",
              "seasonalCop",
              "copAtDesign",
              "boilerCostPerYear",
              "heatPumpCostPerYear",
              "savingPerYear",
              "paybackYears",
              "co2BoilerKg",
              "co2HeatPumpKg",
              "months"
            ],
            "properties": {
              "currency": {
                "type": "string"
              },
              "climate": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "kind",
                  "station"
                ],
                "properties": {
                  "kind": {
                    "type": "string",
                    "enum": [
                      "dwd",
                      "manual"
                    ]
                  },
                  "station": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "additionalProperties": false,
                    "required": [
                      "id",
                      "name",
                      "distanceKm",
                      "elevation"
                    ],
                    "properties": {
                      "id": {
                        "type": "integer"
                      },
                      "name": {
                        "type": "string"
                      },
                      "distanceKm": {
                        "type": "number"
                      },
                      "elevation": {
                        "type": "number"
                      }
                    }
                  }
                }
              },
              "fuelKwh": {
                "type": "number"
              },
              "heatKwh": {
                "type": "number"
              },
              "spaceHeatKwh": {
                "type": "number"
              },
              "hotWaterKwh": {
                "type": "number"
              },
              "heatLossCoefficientWPerK": {
                "type": "number"
              },
              "designHeatLoadKw": {
                "type": "number"
              },
              "heatPumpElectricityKwh": {
                "type": "number"
              },
              "seasonalCop": {
                "type": "number"
              },
              "copAtDesign": {
                "type": "number"
              },
              "boilerCostPerYear": {
                "type": "number"
              },
              "heatPumpCostPerYear": {
                "type": "number"
              },
              "savingPerYear": {
                "type": "number"
              },
              "paybackYears": {
                "type": [
                  "number",
                  "null"
                ]
              },
              "co2BoilerKg": {
                "type": "number"
              },
              "co2HeatPumpKg": {
                "type": "number"
              },
              "months": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "month",
                    "temperature",
                    "spaceHeatKwh",
                    "hotWaterKwh",
                    "electricityKwh",
                    "cop"
                  ],
                  "properties": {
                    "month": {
                      "type": "integer"
                    },
                    "temperature": {
                      "type": "number"
                    },
                    "spaceHeatKwh": {
                      "type": "number"
                    },
                    "hotWaterKwh": {
                      "type": "number"
                    },
                    "electricityKwh": {
                      "type": "number"
                    },
                    "cop": {
                      "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"
              }
            }
          }
        }
      }
    }
  }
}