Tutorial: Build a Green Loan Calculator with Subsidy Data
A hands-on code tutorial showing how to build a loan calculator that factors in renovation subsidies — from API call to amortization schedule to interactive display.
The renovation cost calculator tutorial showed how to display subsidy amounts. This tutorial goes further: we build a loan calculator that answers the question homeowners actually care about: “How much will I pay per month?”
The calculator combines subsidy data from the GreenCalc API with standard loan amortization math to show: total renovation cost, grants received, net amount to finance, available government loans (0% interest), commercial loan needed, and monthly payment.
The financial logic
Before writing code, let us understand the calculation flow:
- Total cost = sum of all planned work costs
- Grants = direct subsidies (MaPrimeRenov, BEG EM, etc.) + tax savings (reduced VAT, tax deductions)
- Net financing need = total cost - grants
- Government loan = 0% interest loans (Eco-PTZ in France, KfW in Germany)
- Commercial loan = net financing need - government loan (can be zero)
- Monthly payment = amortization of government loan (0%) + amortization of commercial loan (market rate)
The key insight: many homeowners need two separate loans — a government one at 0% and a commercial one at market rate. Your calculator should display both.
Step 1: The subsidy API call
First, get the subsidy breakdown. This is identical to the renovation calculator tutorial, but we focus on extracting the financial fields:
async function getSubsidies(projectData) { const res = await fetch('https://greencalc.io/api/v1/eligibility/simulate', { method: 'POST', headers: { 'X-Api-Key': 'gc_sandbox_000000000000000000000000000000000', 'Content-Type': 'application/json' }, body: JSON.stringify(projectData) }); if (!res.ok) throw new Error(`API error ${res.status}`); return res.json(); }
Test it first with curl to confirm the response structure:
curl -X POST https://greencalc.io/api/v1/eligibility/simulate \ -H "X-Api-Key: gc_sandbox_000000000000000000000000000000000" \ -H "Content-Type: application/json" \ -d '{ "country_code": "FR", "household": { "annual_income": 32000, "household_size": 3, "is_owner": true }, "property": { "type": "HOUSE", "energy_rating": "E", "postal_code": "69001", "surface_m2": 100 }, "planned_works": [ {"work_type": "HEAT_PUMP_AIR_WATER", "estimated_cost_eur": 14000}, {"work_type": "ROOF_INSULATION", "estimated_cost_eur": 8000, "surface_m2": 80} ] }'
Step 2: The amortization engine
The standard fixed-rate amortization formula. Nothing exotic — but handling the 0% government loan separately is critical:
/** * Calculate monthly payment for a fixed-rate loan. * @param {number} principal - Loan amount in EUR * @param {number} annualRate - Annual interest rate (e.g., 0.035 for 3.5%) * @param {number} years - Loan term in years * @returns {object} { monthly, totalInterest, totalPaid } */ function amortize(principal, annualRate, years) { if (principal <= 0) return { monthly: 0, totalInterest: 0, totalPaid: 0 }; const n = years * 12; // Special case: 0% interest (government loans like Eco-PTZ) if (annualRate === 0) { const monthly = principal / n; return { monthly, totalInterest: 0, totalPaid: principal }; } const r = annualRate / 12; const monthly = principal * (r * Math.pow(1 + r, n)) / (Math.pow(1 + r, n) - 1); const totalPaid = monthly * n; const totalInterest = totalPaid - principal; return { monthly, totalInterest, totalPaid }; }
Step 3: Combining subsidies with loan calculations
This is where it gets interesting. The GreenCalc API response contains both grants (free money) and loans (0% government financing). We need to separate them:
function calculateLoan(subsidyData, loanTermYears, commercialRate) { const { summary, eligible_subsidies } = subsidyData; // 1. Extract grant amounts (free money) const totalGrants = summary.total_grants_eur + summary.total_tax_savings_eur; // 2. Extract government loan amounts (0% interest) const govLoanAmount = eligible_subsidies .filter(s => s.type === 'LOAN') .reduce((sum, s) => sum + s.amount_eur, 0); // 3. Calculate net financing need const netNeed = summary.total_estimated_cost_eur - totalGrants; // 4. Government loan covers as much as possible at 0% const govLoanUsed = Math.min(govLoanAmount, netNeed); // 5. Commercial loan covers the rest const commercialLoan = Math.max(0, netNeed - govLoanUsed); // 6. Calculate monthly payments for each loan const govPayment = amortize(govLoanUsed, 0, loanTermYears); const commercialPayment = amortize(commercialLoan, commercialRate, loanTermYears); return { totalCost: summary.total_estimated_cost_eur, totalGrants, netNeed, govLoan: { amount: govLoanUsed, ...govPayment }, commercialLoan: { amount: commercialLoan, ...commercialPayment }, totalMonthly: govPayment.monthly + commercialPayment.monthly, totalInterest: commercialPayment.totalInterest }; }
Step 4: The results display
Show the user a clear breakdown of what they pay. The most important number is the total monthly payment. Secondary: how much interest they save thanks to the government 0% loan:
function renderLoanResults(calc) { const el = document.getElementById('loan-results'); el.innerHTML = ` <div class="result-card"> <h3>Your renovation financing</h3> <div class="line"> <span>Total renovation cost</span> <strong>€${fmt(calc.totalCost)}</strong> </div> <div class="line green"> <span>Government grants & tax savings</span> <strong>-€${fmt(calc.totalGrants)}</strong> </div> <div class="line bold"> <span>Amount to finance</span> <strong>€${fmt(calc.netNeed)}</strong> </div> <hr> ${calc.govLoan.amount > 0 ? ` <div class="loan-section"> <h4>Government loan (0% interest)</h4> <div class="line"> <span>Amount</span><span>€${fmt(calc.govLoan.amount)}</span> </div> <div class="line"> <span>Monthly payment</span> <span>€${fmt(calc.govLoan.monthly)}/mo</span> </div> </div>` : ''} ${calc.commercialLoan.amount > 0 ? ` <div class="loan-section"> <h4>Commercial loan</h4> <div class="line"> <span>Amount</span><span>€${fmt(calc.commercialLoan.amount)}</span> </div> <div class="line"> <span>Monthly payment</span> <span>€${fmt(calc.commercialLoan.monthly)}/mo</span> </div> <div class="line subtle"> <span>Total interest paid</span> <span>€${fmt(calc.totalInterest)}</span> </div> </div>` : ''} <div class="total-payment"> <span>Total monthly payment</span> <strong>€${fmt(calc.totalMonthly)}/mo</strong> </div> ${calc.commercialLoan.amount === 0 ? ` <div class="banner"> No commercial loan needed — government financing covers everything! </div>` : ''} </div> `; } function fmt(n) { return Math.round(n).toLocaleString('en'); }
Step 5: Putting it together
Wire the form submission to fetch subsidies, then calculate and display the loan:
document.getElementById('loan-form').addEventListener('submit', async (e) => { e.preventDefault(); const form = new FormData(e.target); // User-configurable loan parameters const loanTermYears = Number(form.get('loan_term')) || 15; const commercialRate = (Number(form.get('interest_rate')) || 3.5) / 100; // Build the subsidy request from form data const projectData = buildProjectFromForm(form); try { // 1. Get subsidy data from GreenCalc API const subsidyData = await getSubsidies(projectData); // 2. Calculate loan with subsidies factored in const loanCalc = calculateLoan(subsidyData, loanTermYears, commercialRate); // 3. Display results renderLoanResults(loanCalc); } catch (err) { console.error(err); } });
A worked example: French renovation
A household in Lyon earning €32,000/year does a €22,000 renovation (heat pump + roof insulation). The API returns:
- MaPrimeRenov: €8,000 (grant)
- CEE: €4,500 (grant)
- TVA 5.5%: €3,190 (tax saving)
- Eco-PTZ: €30,000 available at 0% (loan)
The loan calculator computes:
| Line Item | Amount |
|---|---|
| Total renovation cost | €22,000 |
| Grants + tax savings | -€15,690 |
| Amount to finance | €6,310 |
| Eco-PTZ (0%, 15 years) | €6,310 → €35/mo |
| Commercial loan needed | €0 |
| Total monthly payment | €35/month |
This household renovates their home for €35 per month with zero interest. That is less than most streaming subscription bundles. This is the kind of number that converts visitors into applicants.
Handling edge cases
- No government loan available: In Germany, BEG EM is a direct grant only (no 0% loan for individual measures). The entire net amount goes to the commercial loan. Handle this by checking if
govLoan.amount === 0. - Grants exceed the cost: For very low-income French households, grants can theoretically exceed the project cost. Cap the grants at the total cost:
Math.min(totalGrants, totalCost). - Tax deductions (Italy): Superbonus is a tax deduction recovered over 4 years, not a cash grant. You may want to show it separately with a note: “recovered via tax returns over 4 years.”
- Variable rates: Consider adding a slider for interest rate (2–6%) so users can model different bank offers.
Next steps
This tutorial gives you a working green loan calculator. To take it further:
- Add an amortization schedule table showing month-by-month principal and interest breakdown
- Add energy savings to the monthly comparison: “Your loan payment is €35/mo, but you save €80/mo on energy bills”
- Connect to a lending partner API for real-time rate quotes
- Add PDF export for users who want to take the calculation to their bank
For the subsidy calculation side, see the renovation cost calculator tutorial. For understanding how fintechs use this data in production, read our green finance API for fintech article. Full API reference at greencalc.io/docs.
Frequently Asked Questions
How do I calculate monthly payments for a green renovation loan?
Use the standard amortization formula: M = P x [r(1+r)^n] / [(1+r)^n - 1], where P is the loan principal (renovation cost minus subsidies), r is the monthly interest rate, and n is the number of monthly payments. The GreenCalc API provides the subsidy amounts to subtract from the total cost.
Should I subtract government loans (Eco-PTZ) from the commercial loan amount?
Yes. Government loans at 0% interest reduce the need for a commercial loan. Display both: the government loan terms and the commercial loan for any remaining balance. Some users may prefer one commercial loan for simplicity.
Can I embed this calculator in my website?
Yes. The calculator is pure HTML + JavaScript with no framework dependencies. Embed it directly, use an iframe, or adapt to React/Vue/Svelte. For production, proxy API calls through your backend to secure your API key.
What interest rate should I use for green renovation loans?
Green renovation loans in Europe typically carry rates between 2% and 5% in 2026. Some banks offer “green rates” with a 0.1–0.3% discount for energy renovation. Use a configurable rate so users can input their bank’s actual offer.
GreenCalc is built by AZMORIS Group. This tutorial uses illustrative rates. Always confirm loan terms with your financial institution.