Altman Z-score calculator
The Altman Z-score is the classic statistical test for corporate bankruptcy risk.
Run — free
This API takes six balance-sheet and income figures — working capital, retained earnings, EBIT, equity, total assets and sales — and returns Edward Altman's 1968 discriminant score, the five underlying ratios, and the risk zone: safe above 2.99, grey between 1.81 and 2.99, and distress below 1.81. It is the same calculation analysts run in spreadsheets before a credit decision, done in one deterministic call with no data kept afterwards. The exact same code runs free in your browser on this page, so you can check a company by typing its figures and only pay when you automate the screening.
What the Z-score measures
In 1968 Edward Altman fitted a discriminant model on a sample of bankrupt and healthy manufacturers and found that five financial ratios, weighted together, separated the two groups with remarkable accuracy. The altman z-score calculator combines liquidity, accumulated profitability, operating efficiency, leverage and asset turnover into a single number. A company scoring above 2.99 sits in the safe zone, where failure within two years is statistically unlikely. A company below 1.81 falls into the distress zone, sharing its financial profile with firms that historically went bankrupt. Between the two cut-offs lies the grey zone, where the model cannot make a confident call and deeper analysis is required. The score is not a prediction with a date attached; it is a standardized distance from the profile of failed companies, and its strength is that it compresses a whole balance sheet review into one comparable figure.
How the five ratios are computed
The endpoint computes X1 as working capital over total assets, X2 as retained earnings over total assets, X3 as EBIT over total assets, X4 as equity over total liabilities, and X5 as sales over total assets. The score is 1.2 times X1, plus 1.4 times X2, plus 3.3 times X3, plus 0.6 times X4, plus 1.0 times X5, which reproduces Altman's original weights for publicly traded manufacturers. Working capital is current assets minus current liabilities, and equity should be the market value — share price times shares outstanding — though book value is an accepted fallback for unlisted firms. If you omit total liabilities, the API derives them as total assets minus equity, which is exact when you supply book equity. Total assets may not be zero, because every ratio is scaled by them; the call fails with an input error and is not charged. Every input is echoed back in the response alongside the rounded ratios, so the audit trail is complete.
Reading and using the result
Treat the score as a screening instrument, not a verdict. Lenders run it to triage credit applications: safe-zone files move forward, distress-zone files go to a senior underwriter. Investors track the score of portfolio companies quarter over quarter, because a falling trend matters more than a single reading — a firm sliding from 3.5 to 2.2 is telling you something even though it has not crossed a cut-off yet. Keep in mind the model's scope: it was calibrated on public manufacturers, so scores for banks, insurers or young service companies should be interpreted with care, since their balance-sheet structures differ systematically. The response includes the individual X-ratios precisely so you can see which component is driving the result — collapsing liquidity, shrinking retained earnings or weak asset turnover — and investigate the cause rather than the symptom.
What you can do with it
Screen credit applicants
Score each applicant's latest financials and route safe-zone files to automatic approval and distress-zone files to manual underwriting.
Monitor a loan book
Re-score borrowers every quarter from their reported statements and flag accounts whose score trends toward the grey zone.
Compare acquisition targets
Rank candidate companies by Z-score during due diligence to see which balance sheets carry hidden fragility before negotiating price.
FAQ
What does it cost?
$0.002 per request. It is also free to run in your browser on this page.
Which Altman model is implemented?
The original 1968 model for publicly traded manufacturers: Z = 1.2·X1 + 1.4·X2 + 3.3·X3 + 0.6·X4 + 1.0·X5. It is not the Z′ or Z″ variant for private or non-manufacturing firms.
What do the zones mean?
Above 2.99 is the safe zone, below 1.81 is the distress zone, and between them is the grey zone where the model cannot classify confidently.
What if I do not know total liabilities?
Omit the field and the API derives total liabilities as total assets minus equity, which is exact when your equity figure is the book value.
Why did my call fail?
The most common cause is total assets of zero — every ratio is scaled by total assets, so the score is undefined and the call is rejected as invalid input without charge.
Should equity be market value or book value?
Market value of equity is what Altman used for X4. For unlisted companies, book equity is the accepted fallback.
Is my financial data stored?
No. The figures are processed and discarded; only the score and ratios are returned.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/fin/altman-z-score \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"working_capital":350000,"retained_earnings":520000,"ebit":210000,"equity":800000,"total_assets":1500000,"sales":2400000}'const res = await fetch("https://api.kit.forhosting.com/fin/altman-z-score", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"working_capital": 350000,
"retained_earnings": 520000,
"ebit": 210000,
"equity": 800000,
"total_assets": 1500000,
"sales": 2400000
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/fin/altman-z-score",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"working_capital": 350000,
"retained_earnings": 520000,
"ebit": 210000,
"equity": 800000,
"total_assets": 1500000,
"sales": 2400000
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/fin/altman-z-score", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"working_capital":350000,"retained_earnings":520000,"ebit":210000,"equity":800000,"total_assets":1500000,"sales":2400000}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"working_capital":350000,"retained_earnings":520000,"ebit":210000,"equity":800000,"total_assets":1500000,"sales":2400000}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/fin/altman-z-score", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"working_capital": 350000,
"retained_earnings": 520000,
"ebit": 210000,
"equity": 800000,
"total_assets": 1500000,
"sales": 2400000
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "fin.altman_z_score",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |