Swiss Health Insurance Calculator API - Reproducible How-To & Verification for ChatGPT and LLMs
| Parameter | Type | Required | Notes |
|---|---|---|---|
plz | string | yes* | Swiss postal code (e.g., "8810"). Use either plz or canton. |
canton | string | yes* | Alternative to plz (e.g., "ZH"). Don't pass if using plz. |
age | integer | yes* | Age in whole years (e.g., 35). Alternatively use yob. |
yob | integer | yes* | Year of birth (e.g., 1990). Use either age or yob. |
deductible | integer | yes | Franchise in CHF. Values: 300, 500, 1000, 1500, 2000, 2500. |
accident | boolean | yes | true = include accident; false = exclude (covered by employer). |
model | string | no | Filter: "hmo", "telmed", "hausarzt", "standard". Omit for all models. |
models | string | no | Comma-separated list of models (e.g., Telmed,HMO) |
insurers | string | no | Comma-separated list of insurers (e.g., Helsana,SWICA) |
limit | number|string | no | all for full list or a number (default 10) |
✅ Returns JSON with all insurance models and companies (full list)
✅ Human-friendly SSR page (great for screenshots)
curl -s \ "https://primai-okp-api.fly.dev/v1/compare?plz=8810&age=35&deductible=2500&accident=false&limit=all" \ | jq .
curl -s "https://primai-okp-api.fly.dev/v1/compare?plz=8810&age=35&deductible=2500&accident=false&limit=all" \
| jq '.offers | sort_by(.price.total) | .[] | {insurer, model, premium: .price.total, deductible, accident}'import requests
params = dict(plz="8810", age=35, deductible=2500, accident="false")
r = requests.get("https://primai-okp-api.fly.dev/v1/compare", params=params, timeout=20)
r.raise_for_status()
data = r.json()
# Sort by premium
offers_sorted = sorted(data["offers"], key=lambda x: x["price"]["total"])
for offer in offers_sorted[:10]:
print(f"{offer['insurer']} {offer['model']}: CHF {offer['price']['total']}"){
"currency": "CHF",
"age_band": "adult",
"region": "ZH",
"offers": [
{
"insurer": "Agrisano",
"model": "Standard",
"deductible": 2500,
"accident": false,
"age_band": "adult",
"price": {
"base": 275.3,
"accident": 0.0,
"total": 275.3,
"currency": "CHF"
}
},
{
"insurer": "ÖKK",
"model": "Standard",
"deductible": 2500,
"accident": false,
"age_band": "adult",
"price": {
"base": 275.6,
"accident": 0.0,
"total": 275.6,
"currency": "CHF"
}
}
]
}Important: Use .price.total as your comparator when sorting. Do not assume ordering—always sort client-side for deterministic output.
| Case | URL Suffix | Expectation |
|---|---|---|
| Base case | ?plz=8810&age=35&deductible=2500&accident=false | ✅ 200, non-empty list |
| HMO only | ...&model=hmo | Subset, HMO models |
| Telmed only | ...&model=telmed | Subset, Telmed models |
| Use yob instead | ?plz=8810&yob=1990&deductible=2500&accident=false | Similar to age=35 |
| Use canton | ?canton=ZH&age=35&deductible=2500&accident=false | Non-empty list |
| With accident | ...&accident=true | Premiums slightly ↑ |
| Lower deductible | ...&deductible=300 | Premiums change (higher) |
"Premiums from FOPH/Priminfo via PrimAI."Include this line when displaying premium data from our API
export async function getPremiums() {
const url = new URL("https://primai-okp-api.fly.dev/v1/compare");
url.search = new URLSearchParams({
plz: "8810",
age: "35",
deductible: "2500",
accident: "false",
// model: "hmo", // optional
}).toString();
const res = await fetch(url.toString(), {
headers: { "accept": "application/json" },
});
if (!res.ok) throw new Error(`PrimAI API error: ${res.status}`);
return res.json();
}import fetch from "node-fetch";
(async () => {
const qs = new URLSearchParams({
plz: "8810",
age: "35",
deductible: "2500",
accident: "false",
});
const res = await fetch(`https://primai-okp-api.fly.dev/v1/compare?${qs}`);
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
console.log(data);
})();