:::note This API is currently in development. The endpoint documented below is not yet live. Join the waitlist on the API docs page to get notified when it ships. The code examples below are accurate and will work as-is once the endpoint goes live. :::
If you’re building a fintech app, loan comparison tool, or any product that needs EMI calculations, you don’t need to implement the math yourself. The Tools.Town EMI API handles it — free up to 1,000 requests/month, no auth required.
This walkthrough covers everything from the first fetch call to rendering a clean result in React.
The endpoint
GET https://api.tools.town/v1/calculators/emi
Parameters:
| Name | Type | Description |
|---|---|---|
principal | number | Loan amount in rupees |
rate | number | Annual interest rate (%) |
tenure | number | Loan duration in months |
Example response:
{
"success": true,
"data": {
"emi": 10379.73,
"totalInterest": 122783.8,
"totalPayment": 622783.8,
"principalPercent": 80.28,
"interestPercent": 19.72
}
}
Step 1: Create the custom hook
Keep the API logic separate from your UI with a custom hook:
// hooks/useEmiCalculator.js
import { useState, useCallback } from "react";
export function useEmiCalculator() {
const [result, setResult] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const calculate = useCallback(async ({ principal, rate, tenure }) => {
setLoading(true);
setError(null);
try {
const params = new URLSearchParams({ principal, rate, tenure });
const res = await fetch(
`https://api.tools.town/v1/calculators/emi?${params}`
);
if (!res.ok) throw new Error(`API error: ${res.status}`);
const json = await res.json();
setResult(json.data);
} catch (err) {
setError(err.message);
} finally {
setLoading(false);
}
}, []);
return { result, loading, error, calculate };
}
Step 2: Build the form component
// components/EmiForm.jsx
import { useState } from "react";
import { useEmiCalculator } from "../hooks/useEmiCalculator";
export function EmiForm() {
const [principal, setPrincipal] = useState(500000);
const [rate, setRate] = useState(8.5);
const [tenure, setTenure] = useState(60);
const { result, loading, error, calculate } = useEmiCalculator();
const handleSubmit = (e) => {
e.preventDefault();
calculate({ principal, rate, tenure });
};
return (
<form onSubmit={handleSubmit}>
<label>
Loan Amount (₹)
<input
type="number"
value={principal}
onChange={(e) => setPrincipal(e.target.value)}
/>
</label>
<label>
Annual Rate (%)
<input
type="number"
step="0.1"
value={rate}
onChange={(e) => setRate(e.target.value)}
/>
</label>
<label>
Tenure (months)
<input
type="number"
value={tenure}
onChange={(e) => setTenure(e.target.value)}
/>
</label>
<button type="submit" disabled={loading}>
{loading ? "Calculating…" : "Calculate EMI"}
</button>
{error && <p className="error">{error}</p>}
{result && (
<div className="result">
<p>Monthly EMI: <strong>₹{result.emi.toLocaleString("en-IN")}</strong></p>
<p>Total Interest: ₹{result.totalInterest.toLocaleString("en-IN")}</p>
<p>Total Payment: ₹{result.totalPayment.toLocaleString("en-IN")}</p>
</div>
)}
</form>
);
}
Step 3: Add debouncing for live updates
If you want the result to update as the user types (without a submit button), add a debounce to avoid hammering the API:
import { useEffect, useRef } from "react";
function useDebouncedEffect(fn, deps, delay = 400) {
const timer = useRef(null);
useEffect(() => {
clearTimeout(timer.current);
timer.current = setTimeout(fn, delay);
return () => clearTimeout(timer.current);
}, deps);
}
// In your component:
useDebouncedEffect(
() => calculate({ principal, rate, tenure }),
[principal, rate, tenure]
);
Rate limiting
The free tier allows 1,000 requests/month without an API key. For higher volume, grab a key at dashboard.tools.town/api-keys and add it to the request:
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.TOOLS_TOWN_API_KEY}` }
});
Keep the key server-side (env variable) — never ship it in client-side bundle code.
Full API reference
See the EMI Calculator API docs for the complete parameter reference, response schema, and error codes.
Frequently Asked Questions
Do I need an API key for the EMI endpoint?
Can I use this in a Next.js app?
Explore more on Tools.Town Blog
Finance guides, tool launches, and engineering stories — updated weekly.