Intent Spec — finance.buy_health_insurance
FULL ID: finance.buy_health_insurance
VERSION: v1.0.0
STATUS: draft
LAST UPDATED: 2026-05-13
DOMAIN: finance
PRIMARY AGENT: FinanceAgent
TTBS WEIGHTS: time=0.10 taste=0.15 budget=0.30 safety=0.45
User buys an indemnity health insurance policy (individual, family floater, senior citizen, critical illness, top-up, or super top-up). Covers sum-insured comparison, room-rent / co-pay configuration, hospital network discovery, pre-existing disease (PED) waiting-period disclosure, OPD / wellness rider configuration, IRDAI-mandated disclosures, instant or medical-underwritten issuance.
Partner exemplars: Policybazaar, Acko Health, Niva Bupa, Star Health, Care Health, HDFC ERGO Health, Tata AIG Health, Aditya Birla Health, ManipalCigna, GoDigit Health.
SECTION 1 — INTENT IDENTITY
User wants to buy an indemnity (mediclaim) health insurance policy. Distinct from:
finance.buy_term_insurance— life cover, not healthfinance.buy_travel_insurance— short-term trip health cover- Hospital cash / fixed-benefit-only policies — sub-variant; route here with
policy_type=hospital_cash - Government schemes (Ayushman Bharat, ESIC) — out of scope v1
- Renewing an existing health policy — same intent (annual renewal flow identical from contract POV)
- Group / employer-provided cover — out of scope v1
Single intent per applicant or family unit. Senior-parent floaters route here with policy_type=senior_floater.
SECTION 2 — NATURAL LANGUAGE COVERAGE
CLASSIFIES IN
- "Buy health insurance for me and my wife"
- "Family floater 10 lakh cover"
- "Mediclaim for my parents, both 65+"
- "Cheapest cashless hospital insurance"
- "Top-up policy on my corporate cover"
- "Critical illness cover ₹50 lakh"
- "Maternity insurance with no waiting period"
- "Health insurance without room rent limit"
- "Star Health vs Niva Bupa for senior parents"
- "Super top-up with ₹3L deductible"
CLASSIFIES OUT — BORDERLINE NO
- "Buy life insurance" →
finance.buy_term_insurance - "Travel insurance for Schengen trip" →
finance.buy_travel_insurance - "File a hospital claim" → v1.1+
finance.file_health_claim - "Book a doctor's appointment" →
lifestyle.book_at_home_serviceor future health intent - "Cashless hospital list in Hyderabad" — non-transactional; research path
- "Ayushman Bharat enrollment" — out of scope v1
MULTI-INTENT TRIGGERS
- "Term life + health insurance" →
finance.buy_term_insurance+finance.buy_health_insurance - "Health insurance + tax filing help" →
finance.buy_health_insurance+finance.book_tax_consultation(§80D deduction context) - "Senior parents floater + financial advisor" →
finance.buy_health_insurance+finance.book_financial_advisor_session
SECTION 3 — INPUT (TOMO → PROVIDER)
{
"intent": "finance.buy_health_insurance",
"request_id": "req_01J9Z...",
"user_locale": "en-IN",
"user_currency": "INR",
"user_location": { "lat": 17.4475, "lng": 78.3563, "city": "Hyderabad", "pincode": "500032" },
"policy_type": "family_floater", // STRICT ENUM §6
"proposer": {
"first_name": "Rakesh",
"last_name": "Kumar",
"date_of_birth": "1985-04-18",
"gender": "male",
"annual_income_inr": 1800000,
"marital_status": "married",
"state": "TS",
"pincode": "500032",
"tobacco_use": "never",
"alcohol_use": "occasional" // STRICT ENUM §6
},
"insured_members": [
{
"relationship_to_proposer": "self", // STRICT ENUM §6
"first_name": "Rakesh", "last_name": "Kumar",
"date_of_birth": "1985-04-18", "gender": "male",
"height_cm": 175, "weight_kg": 78,
"pre_existing_conditions": [], // STRICT ENUM array §6
"current_medications": [], // free text array, ≤5 entries
"hospitalizations_last_5y": 0,
"tobacco_use": "never",
"alcohol_use": "occasional"
},
{
"relationship_to_proposer": "spouse",
"first_name": "Anita", "last_name": "Kumar",
"date_of_birth": "1988-09-12", "gender": "female",
"height_cm": 162, "weight_kg": 60,
"pre_existing_conditions": [],
"current_medications": [],
"hospitalizations_last_5y": 0,
"tobacco_use": "never",
"alcohol_use": "never"
}
],
"cover_preferences": {
"sum_insured_inr": 1000000, // ₹10 lakh
"is_top_up": false,
"deductible_inr": 0, // >0 only for top-up / super top-up
"policy_tenure_years": 1, // 1 | 2 | 3
"room_rent_preference": "no_capping", // STRICT ENUM §6
"co_pay_acceptance_pct": 0, // 0-30
"addons_required": ["maternity", "opd", "annual_health_checkup"], // STRICT ENUM array §6
"preferred_hospital_network": [], // empty = open
"preferred_insurers": []
},
"ttbs_user_band": {
"time": "balanced",
"taste": "balanced",
"budget": "good",
"safety": "great"
},
"session_context": { "tomo_session_id": "ses_01J9Z...", "user_dna_hash": "dna_v3_a7c9..." }
}
| Field | Type | Constraint | Notes |
|---|---|---|---|
intent |
string | REQUIRED, STRICT ENUM | Always finance.buy_health_insurance |
policy_type |
enum | REQUIRED, STRICT ENUM §6 | Drives schema completeness rules |
proposer.date_of_birth |
string | REQUIRED, ISO_DATE | Age-banded premium |
proposer.pincode |
string | REQUIRED, 6 digits | Drives zone-based premium |
insured_members |
array | REQUIRED, min 1, max 6 | Floater max 6 (2A+4C typical) |
insured_members[].pre_existing_conditions |
array |
REQUIRED, STRICT ENUM §6 | May be empty |
cover_preferences.sum_insured_inr |
int | REQUIRED, INR_INTEGER, ≥100000 | Min ₹1L; max insurer-specific |
cover_preferences.is_top_up |
bool | REQUIRED | When TRUE, deductible_inr REQUIRED ≥100000 |
cover_preferences.deductible_inr |
int | REQUIRED, INR_INTEGER, ≥0 | Top-up: ≥1L; non-top-up: 0 |
cover_preferences.room_rent_preference |
enum | REQUIRED, STRICT ENUM §6 | |
cover_preferences.co_pay_acceptance_pct |
int | REQUIRED, 0-30 | Lower = higher premium |
cover_preferences.addons_required |
array |
REQUIRED, STRICT ENUM §6 | May be empty |
Anti-fabrication preamble: Provider may not quote a premium below the IRDAI mortality / morbidity floor for the age-gender-condition profile. Pre-existing waiting-period rules are IRDAI-fixed (max 4 years; partner-shortening below permissible bands is invalid). TOMO does not advise — partner ranks via TTBS only.
SECTION 4 — PROVIDER TOOLS
Tool 1: search_health_quotes
PURPOSE: Up to 15 quotes matching members + sum_insured + addons + preferences
SLA: p50 ≤ 800ms, p95 ≤ 2500ms, p99 ≤ 5000ms
RATE LIMIT: 60 req/min
IDEMPOTENCY: request_id; 60s cache
RETRY: 1 on 429, 2 on 5xx
Tool 2: initiate_underwriting
PURPOSE: Lock quote + medical questionnaire + KYC + nominee
SLA: p50 ≤ 1800ms, p95 ≤ 5000ms
RATE LIMIT: 30 req/min
IDEMPOTENCY: request_id
RETRY: No retry
Tool 3: schedule_medical_exam
PURPOSE: Book pre-policy medical when underwriting requires it
SLA: p50 ≤ 1200ms, p95 ≤ 3500ms
RATE LIMIT: 30 req/min
IDEMPOTENCY: underwriting_id
RETRY: 1 on 5xx
Tool 4: issue_policy
PURPOSE: Issue policy after underwriting approval + payment
SLA: p50 ≤ 2500ms, p95 ≤ 7000ms, p99 ≤ 15000ms
RATE LIMIT: 30 req/min
IDEMPOTENCY: request_id
RETRY: No retry on issuance
Tool 5: cancel_or_freelook
PURPOSE: 15-day IRDAI free-look cancellation OR pre-issuance cancellation
SLA: p50 ≤ 1500ms, p95 ≤ 4000ms
RATE LIMIT: 30 req/min
IDEMPOTENCY: policy_id
RETRY: 1 on 5xx
SECTION 5 — RESPONSE SHAPE
HealthQuote
HealthQuote:
quote_id: { type: string, constraint: REQUIRED, opaque }
insurer:
insurer_id: { type: string, constraint: REQUIRED }
name: { type: string, constraint: REQUIRED }
irdai_registration_number: { type: string, constraint: REQUIRED }
claim_settlement_ratio_pct: { type: float, constraint: REQUIRED, 0-100, semantics: "IRDAI-published latest year, health claims" }
claim_paid_amount_ratio_pct: { type: float, constraint: REQUIRED, 0-100 }
incurred_claims_ratio_pct: { type: float, constraint: REQUIRED, 0-200, semantics: "Industry standard health insurer metric" }
solvency_ratio: { type: float, constraint: REQUIRED, 1.0-5.0 }
product_name: { type: string, constraint: REQUIRED }
product_uin: { type: string, constraint: REQUIRED }
policy_type:
type: enum
constraint: REQUIRED, STRICT ENUM §6
sum_insured_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
deductible_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
is_top_up: { type: boolean, constraint: REQUIRED }
policy_tenure_years: { type: int, constraint: REQUIRED, 1-3 }
premium_breakdown:
base_premium_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
age_loading_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
addon_premium_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
zone_loading_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0, semantics: "Metro / Tier-1 / Tier-2 zone factor" }
ped_loading_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0, semantics: "Loading for pre-existing conditions" }
discount_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
gst_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0, semantics: "18% of premium" }
total_payable_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
waiting_periods:
initial_waiting_days: { type: int, constraint: REQUIRED, 0-90 }
specific_disease_waiting_years: { type: int, constraint: REQUIRED, 1-4 }
ped_waiting_years: { type: int, constraint: REQUIRED, 1-4, semantics: "IRDAI max 4 years" }
maternity_waiting_months: { type: int, constraint: REQUIRED nullable, semantics: "null when maternity not covered" }
coverage:
room_rent_cap_pct_sum_insured: { type: float, constraint: REQUIRED, 0-100, semantics: "0 = no capping" }
room_rent_cap_inr_per_day: { type: int, constraint: REQUIRED, INR_INTEGER, semantics: "0 = no capping" }
icu_cap_pct_sum_insured: { type: float, constraint: REQUIRED, 0-100 }
co_pay_pct: { type: int, constraint: REQUIRED, 0-30 }
sub_limits:
type: array<SubLimit>
constraint: REQUIRED, may be empty
shape:
category: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
cap_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
cap_pct: { type: float, constraint: REQUIRED, 0-100 }
restoration_benefit: { type: boolean, constraint: REQUIRED, semantics: "Sum-insured restored after exhaustion" }
no_claim_bonus_max_pct: { type: int, constraint: REQUIRED, 0-200 }
pre_hospitalization_days: { type: int, constraint: REQUIRED, ≥0 }
post_hospitalization_days: { type: int, constraint: REQUIRED, ≥0 }
day_care_procedures_count: { type: int, constraint: REQUIRED, ≥0 }
ambulance_cover_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
organ_donor_cover: { type: boolean, constraint: REQUIRED }
domiciliary_cover: { type: boolean, constraint: REQUIRED }
ayush_cover_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
addons_included:
type: array<Addon>
constraint: REQUIRED, may be empty
shape:
code: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
label: { type: string, constraint: REQUIRED }
premium_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
sub_limit_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0, semantics: "0 = unlimited" }
hospital_network:
cashless_hospital_count_in_city: { type: int, constraint: REQUIRED, ≥0 }
cashless_hospital_count_in_state: { type: int, constraint: REQUIRED, ≥0 }
cashless_hospital_count_nationwide: { type: int, constraint: REQUIRED, ≥0 }
network_directory_url: { type: string, constraint: REQUIRED, HTTPS URL }
medical_exam_required: { type: boolean, constraint: REQUIRED }
medical_exam_type:
type: enum
constraint: REQUIRED, STRICT ENUM §6
values: [none, tele_mer, in_person_basic, in_person_full]
estimated_issuance_days: { type: int, constraint: REQUIRED, 0-30 }
instant_issuance_possible: { type: boolean, constraint: REQUIRED }
prospectus_url: { type: string, constraint: REQUIRED, HTTPS URL }
policy_wording_url: { type: string, constraint: REQUIRED, HTTPS URL }
customer_information_sheet_url: { type: string, constraint: REQUIRED, HTTPS URL, semantics: "IRDAI-mandated CIS" }
partner_reference:
source: { type: string, constraint: REQUIRED }
deeplink: { type: string, constraint: REQUIRED, HTTPS URL }
UnderwritingDecision
UnderwritingDecision:
underwriting_id: { type: string, constraint: REQUIRED }
quote_id: { type: string, constraint: REQUIRED }
decision:
type: enum
constraint: REQUIRED, STRICT ENUM §6
values: [approved_standard, approved_loaded, approved_with_exclusions, deferred_pending_medical, declined]
loaded_premium_pct: { type: float, constraint: REQUIRED, 0-300 }
exclusions:
type: array<string>
constraint: REQUIRED, may be empty
decision_reason_code:
type: enum
constraint: REQUIRED, STRICT ENUM §6
values: [standard, ped_loading, family_history, lifestyle_loading, financial_underwriting, insufficient_data]
medical_required_after_decision: { type: boolean, constraint: REQUIRED }
decision_valid_until: { type: string, constraint: REQUIRED, ISO_DATETIME }
kyc_status:
type: enum
constraint: REQUIRED, STRICT ENUM §6
values: [verified_aadhaar, verified_pan, verified_passport, pending_manual, failed]
documents_pending:
type: array<string>
constraint: REQUIRED, may be empty
MedicalExamSchedule
MedicalExamSchedule:
exam_id: { type: string, constraint: REQUIRED }
underwriting_id: { type: string, constraint: REQUIRED }
exam_type: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
scheduled_at: { type: string, constraint: REQUIRED, ISO_DATETIME }
location:
type: object
constraint: REQUIRED
shape:
address: { type: string, constraint: REQUIRED }
city: { type: string, constraint: REQUIRED }
pincode: { type: string, constraint: REQUIRED }
is_home_visit: { type: boolean, constraint: REQUIRED }
diagnostic_partner: { type: string, constraint: REQUIRED }
tests_included:
type: array<enum>
constraint: REQUIRED, STRICT ENUM §6, may NOT be empty
reschedule_window_hours: { type: int, constraint: REQUIRED, ≥0 }
fasting_required: { type: boolean, constraint: REQUIRED }
IssuedPolicy
IssuedPolicy:
policy_id: { type: string, constraint: REQUIRED, immutable }
policy_number: { type: string, constraint: REQUIRED }
insurer_id: { type: string, constraint: REQUIRED }
product_uin: { type: string, constraint: REQUIRED }
policy_type: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
sum_insured_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
policy_start_date: { type: string, constraint: REQUIRED, ISO_DATE }
policy_end_date: { type: string, constraint: REQUIRED, ISO_DATE }
total_paid_inr: { type: int, constraint: REQUIRED, INR_INTEGER }
insured_members:
type: array<MemberRecord>
constraint: REQUIRED, min 1
shape:
member_id: { type: string, constraint: REQUIRED }
full_name: { type: string, constraint: REQUIRED }
date_of_birth: { type: string, constraint: REQUIRED, ISO_DATE }
relationship: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
ped_disclosed: { type: array<string>, constraint: REQUIRED, may be empty }
nominee:
full_name: { type: string, constraint: REQUIRED }
relationship: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
share_pct: { type: int, constraint: REQUIRED, 1-100 }
policy_pdf_url: { type: string, constraint: REQUIRED, HTTPS URL }
health_card_url: { type: string, constraint: REQUIRED, HTTPS URL, semantics: "Cashless ID card" }
freelook_period_days: { type: int, constraint: REQUIRED, 15-30 }
freelook_ends_at: { type: string, constraint: REQUIRED, ISO_DATE }
grace_period_days: { type: int, constraint: REQUIRED, 15-30 }
claim_helpline_phone: { type: string, constraint: REQUIRED, E.164 }
cashless_helpdesk_phone: { type: string, constraint: REQUIRED, E.164 }
tpa_name: { type: string, constraint: REQUIRED nullable, semantics: "Third-party admin if used" }
CancellationResult
CancellationResult:
policy_id: { type: string, constraint: REQUIRED }
cancelled_at: { type: string, constraint: REQUIRED, ISO_DATETIME }
refund_amount_inr: { type: int, constraint: REQUIRED, INR_INTEGER, ≥0 }
refund_method: { type: enum, constraint: REQUIRED, STRICT ENUM §6 }
refund_eta_days: { type: int, constraint: REQUIRED, 0-30 }
is_freelook_cancellation: { type: boolean, constraint: REQUIRED }
FORBIDDEN FIELDS
paid_placement_score,ad_bid,sponsored_rank,promotion_priority,kickback_amount,commission_padded_premiumartificial_urgency_text("Last day at this price!" without verifiable rate-change)ai_generated_photofor insurer / hospital / agent imageryfabricated_hospital_count(network counts must match insurer's published network)inflated_claim_settlement_ratio,inflated_incurred_claims_ratioeditor_recommended,tomo_pick,best_for_seniorscommission_rate,partner_revenue_share,payout_to_agent_inr
SECTION 6 — CONTROLLED VOCABULARIES
policy_type:
values:
individual: "Single life cover"
family_floater: "Shared sum-insured across family"
senior_floater: "60+ parents; loaded premium"
critical_illness: "Lump-sum on diagnosis of listed conditions"
top_up: "Activates above deductible (separate from base)"
super_top_up: "Aggregate deductible across year"
hospital_cash: "Fixed daily benefit during hospitalization"
proposer.gender / insured_members[].gender:
values: [male, female, other]
proposer.tobacco_use / alcohol_use / insured_members[]:
tobacco_use: [never, former, occasional, regular]
alcohol_use: [never, occasional, regular, heavy]
proposer.state: [AP, AR, AS, BR, CG, GA, GJ, HR, HP, JH, KA, KL, MP, MH, MN, ML, MZ, NL, OD, PB, RJ, SK, TN, TS, TR, UP, UK, WB, AN, CH, DN, DD, DL, JK, LA, LD, PY]
insured_members[].relationship_to_proposer:
values: [self, spouse, son, daughter, father, mother, father_in_law, mother_in_law, brother, sister, grandparent, grandchild]
insured_members[].pre_existing_conditions:
values:
none, hypertension, diabetes_type1, diabetes_type2, asthma, thyroid_disorder,
cardiac, cancer_remission, kidney_disease, liver_disease, mental_health,
autoimmune, neurological, respiratory_chronic, pcod_pcos, other_disclosed
cover_preferences.room_rent_preference:
values:
no_capping: "No room rent limit"
single_private: "Single private AC room"
capped_pct: "Capped at % of sum-insured"
capped_inr: "Capped at fixed INR/day"
cover_preferences.addons_required / addons_included.code:
values:
maternity: "Maternity expenses"
newborn_baby: "Newborn cover from day 1"
opd: "Out-patient department cover"
annual_health_checkup: "Free annual checkup"
consumables: "Non-medical consumables"
room_rent_waiver: "Waive room rent capping"
co_pay_waiver: "Remove co-pay"
ped_waiting_reduction: "Reduce PED waiting period"
international_treatment: "Specified critical conditions abroad"
organ_donor_extended: "Donor cover beyond base"
air_ambulance: "Air ambulance cover"
home_healthcare: "Domiciliary / home-care"
mental_health_extended: "Mental health beyond IRDAI mandate"
wellness_rewards: "Premium discount on healthy living"
restore_benefit_super: "Multi-restore in policy year"
coverage.sub_limits[].category:
values:
cataract, knee_replacement, hip_replacement, hernia, dialysis,
chemotherapy, radiotherapy, maternity_normal, maternity_csection,
ayush, mental_health, opd, dental, vision
decision_reason_code:
values: [standard, ped_loading, family_history, lifestyle_loading, financial_underwriting, insufficient_data]
medical_exam_type:
values: [none, tele_mer, in_person_basic, in_person_full]
tests_included:
values:
height_weight, blood_pressure, urine_routine, fasting_blood_sugar,
hba1c, lipid_profile, liver_function, kidney_function, hiv,
hepatitis_b, hepatitis_c, ecg, treadmill_test, chest_xray, cotinine_nicotine,
thyroid_panel, complete_blood_count
kyc_status: [verified_aadhaar, verified_pan, verified_passport, pending_manual, failed]
nominee.relationship:
values: [spouse, son, daughter, father, mother, brother, sister, grandparent, grandchild, legal_guardian, charitable_trust]
refund_method: [original_payment, bank_transfer, cheque]
SECTION 7 — TTBS DIMENSIONS
TIME (weight = 0.10):
signals_used:
- instant_issuance_possible
- estimated_issuance_days
- medical_exam_required (FALSE preferred)
weighting:
instant: 0.40
issuance_days: 0.35
no_medical: 0.25
TASTE (weight = 0.15):
signals_used:
- insurer matches preferred_insurers
- insurer matches user DNA history
- hospital_network includes user's preferred_hospital_network
- product_name brand familiarity
weighting:
preferred_insurer: 0.40
dna_familiarity: 0.25
hospital_match: 0.20
brand_signal: 0.15
BUDGET (weight = 0.30):
signals_used:
- premium_breakdown.total_payable_inr
- addon_premium_inr fit to addons_required
- co_pay_pct (lower = higher premium but lower out-of-pocket — balance per user_band)
- deductible_inr (top-up only)
weighting:
total: 0.65
addon_fit: 0.20
co_pay_balance: 0.10
deductible_fit: 0.05
user_band_handling:
ok: cheapest passing safety floor
good: balanced
great: premium-insensitive
SAFETY (weight = 0.45):
signals_used:
- insurer.claim_settlement_ratio_pct
- insurer.claim_paid_amount_ratio_pct
- insurer.incurred_claims_ratio_pct (75-95 healthy band)
- insurer.solvency_ratio
- hospital_network.cashless_hospital_count_in_city
- hospital_network.cashless_hospital_count_in_state
- coverage.restoration_benefit
- coverage.no_claim_bonus_max_pct
- waiting_periods.ped_waiting_years (lower preferred)
- waiting_periods.specific_disease_waiting_years (lower preferred)
weighting:
csr: 0.25
amount_ratio: 0.15
icr: 0.10
solvency: 0.10
cashless_city: 0.15
cashless_state: 0.05
restoration: 0.05
ncb_max: 0.05
ped_waiting: 0.05
specific_waiting: 0.05
user_band_handling:
fast: relax CSR to 93%
balanced: floor 95%
great: prefer CSR ≥97% AND cashless_city ≥1000 even at higher premium
Locked weights per finance.buy_health_insurance: time 0.10 / taste 0.15 / budget 0.30 / safety 0.45.
SECTION 8 — COMPLETION CONTRACT
POST /api/v1/cpc/mcp_provider/<your_partner_id>
Body:
{
"intent": "finance.buy_health_insurance",
"external_id": "<policy_id>",
"request_id": "<request_id>",
"amount_inr": 2200, // NET partner commission only (typically 12-25% of first-year premium)
"gst_inr": 396,
"tips_inr": 0,
"pass_through_inr": 18000, // first-year premium remitted to insurer
"closed_at": "2026-05-30T11:20:00+05:30",
"status": "completed",
"insurer_id": "niva_bupa",
"product_uin": "IRDAI/HLT/NB/P-H/V.III/121/2023-24",
"policy_type": "family_floater",
"sum_insured_inr": 1000000,
"insured_members_count": 2,
"policy_tenure_years": 1
}
Renewal-year premium completions POST a follow-up with intent: finance.buy_health_insurance.renewal_year_<N> and trail-commission amount_inr.
HMAC-SHA256 over canonical body, 5-min replay window, NET-only commission.
SECTION 9 — WIDGET
HealthInsuranceWidget (planned). Interim: comparison ListingsWidget.
Field mapping:
- HealthQuote.insurer.name + logo → header
- product_name → subhead
- claim_settlement_ratio_pct + incurred_claims_ratio_pct → dual pill
- premium_breakdown.total_payable_inr → big price
- sum_insured_inr → "₹X cover"
- hospital_network.cashless_hospital_count_in_city → "X cashless in city"
- waiting_periods.ped_waiting_years → "PED Xy" pill
- coverage.room_rent_cap_pct_sum_insured → "No room cap" badge when 0
- coverage.restoration_benefit → green badge
- addons_included.length → "+X addons" pill
- instant_issuance_possible → green instant badge
- customer_information_sheet_url → "View CIS" link
SECTION 10 — CACHING POLICY
| Call | TTL | Rationale |
|---|---|---|
| search_health_quotes | 60s | Premiums age/zone driven, low fluctuation |
| initiate_underwriting | NO CACHE | Idempotent |
| schedule_medical_exam | NO CACHE | Live calendar |
| issue_policy | NO CACHE | — |
| cancel_or_freelook | NO CACHE | — |
| Insurer static (CSR, ICR, AUM, logos) | 24h | IRDAI publishes annually |
| Product wording / prospectus / CIS | 7d | Versioned by product_uin |
| Hospital network directory | 24h | Insurer publishes updates |
SECTION 11 — ERROR CODES
| Code | HTTP | Meaning | Retry |
|---|---|---|---|
INVALID_REQUEST |
400 | Malformed | No |
RATE_LIMITED |
429 | Throttle | 1, 2s |
INTERNAL_ERROR |
500 | Partner failure | 2, exp |
SIGNATURE_INVALID |
401 | HMAC fail | No |
AGE_OUT_OF_RANGE |
422 | Member age outside insurer entry/exit | No |
MEMBER_COUNT_EXCEEDED |
422 | Floater max 6 / insurer-specific | No |
PED_DECLINED |
422 | Disclosed condition outside appetite | No |
SUM_INSURED_OUT_OF_RANGE |
422 | Below min or above max | No |
DEDUCTIBLE_INVALID |
422 | Top-up deductible <1L or mismatched | No |
KYC_FAILED |
422 | KYC verification failed | No |
MEDICAL_DEFERRED |
200 (advisory) | medical_required=true | n/a |
UNDERWRITING_DECLINED |
422 | Final decline | No |
NOMINEE_INVALID |
422 | Missing or share % ≠ 100 | No |
ZONE_NOT_SERVICED |
422 | Pincode outside insurer service zone | No |
PAYMENT_FAILED |
402 | Gateway declined | No |
INSURER_DOWN |
503 | Insurer API unavailable | 1 retry, 2s |
FREELOOK_WINDOW_EXPIRED |
410 | Past free-look | No |
PRODUCT_DISCONTINUED |
410 | UIN no longer sold | No |
SECTION 12 — SANDBOX → PRODUCTION CHECKLIST
[ ] All five tools implemented
[ ] At least 6 insurers in catalog
[ ] All IRDAI registration numbers verifiable
[ ] All product UINs verifiable on IRDAI approval list
[ ] CSR, claim amount ratio, ICR, solvency match latest IRDAI publication
[ ] customer_information_sheet_url returns IRDAI-mandated CIS for the UIN
[ ] policy_wording_url returns IRDAI-compliant wording for the UIN
[ ] prospectus_url present and current
[ ] Mortality / morbidity floor enforced; no below-floor quotes
[ ] PED waiting periods within IRDAI bands (max 4 years)
[ ] Specific disease waiting within IRDAI bands
[ ] Room rent / co-pay / sub-limits accurately reflected per product
[ ] Hospital network counts match insurer's published network for state / city
[ ] network_directory_url returns live, browsable hospital list
[ ] Cashless network counts NOT padded with empanelled-but-inactive hospitals
[ ] All controlled vocabularies respected
[ ] HMAC signing verified
[ ] amount_inr in CPC is partner COMMISSION only (NET), NOT total premium
[ ] pass_through_inr correctly captures premium remitted to insurer
[ ] freelook_period_days ≥ 15
[ ] grace_period_days ≥ 15
[ ] No forbidden fields anywhere
[ ] SLA p95 met
[ ] IRDAI corporate-agent / broker / web-aggregator license uploaded
[ ] TPA partnerships disclosed (if applicable)
[ ] Compliance: GSTIN, IRDAI license, privacy policy URL, grievance officer
[ ] Customer support: 24×7 claims + 24×7 cashless helpdesk
[ ] Diagnostic partner contracts (if offering pre-policy medical)
SECTION 13 — ANTI-FABRICATION RULES
RULE 1: No paid_placement / ad / kickback fields. Health insurance commissions
are 15-30% — bias risk is high; TOMO audits monthly.
RULE 2: claim_settlement_ratio_pct, claim_paid_amount_ratio_pct, and
incurred_claims_ratio_pct MUST match IRDAI's latest annual publication.
Inflation = suspension. TOMO audits quarterly.
RULE 3: solvency_ratio must match IRDAI publication. Same enforcement.
RULE 4: base_premium_inr cannot be below the IRDAI / IIB morbidity-rate
floor for the age-gender-pincode-PED profile. Below-floor = invalid.
RULE 5: irdai_registration_number must be insurer's current registration.
product_uin must be on IRDAI's approved-product list.
RULE 6: policy_wording_url, prospectus_url, and customer_information_sheet_url
must be IRDAI-approved documents for the specific UIN. Marketing
brochures in these slots = customer-harm + regulatory + suspension.
RULE 7: waiting_periods.ped_waiting_years cannot be shorter than the IRDAI
permissible minimum for the product class. Misstating waiting = the
single most customer-harming fabrication possible; immediate suspension.
RULE 8: Hospital network counts must reflect ACTIVE cashless agreements as
of the quote timestamp. Counting historical or empanelled-but-paused
hospitals = customer-harm at claim time + suspension.
RULE 9: network_directory_url must return a live, searchable directory.
Static PDF dated >90 days = stale = warning, then suspension.
RULE 10: co_pay_pct must be the actual policy co-pay. Quoting 0% co-pay
then issuing a 10% co-pay policy = customer-harm + suspension.
RULE 11: room_rent_cap fields must reflect actual product caps. "No capping"
must mean no capping — not "no capping up to specified hospitals."
RULE 12: artificial_urgency_text forbidden ("Last day at this rate!").
Premium revisions are notified to IRDAI before taking effect.
RULE 13: No AI-generated insurer / hospital / agent imagery.
RULE 14: amount_inr in CPC is partner's NET commission only — NEVER the
total premium. Falsely reporting premium as revenue = suspension.
RULE 15: No "Best for Seniors" / "Recommended" / "Top Pick" badges. Health
insurance recommendation is regulated; TOMO orchestrates source-
blind TTBS only.
RULE 16: information_completeness_score (hidden ranking factor, weight 0.10)
rewards full §5 shape. Sparse responses rank lower automatically.
RULE 17: ped_loading_inr must be supported by documented underwriting reason
from decision_reason_code. Arbitrary loading = customer-harm.
RULE 18: tpa_name must be the actual TPA processing claims for this insurer-
product. Misstating TPA = claim-time customer-harm + suspension.
VERSION HISTORY
v1.0.0 — 2026-05-13 — Initial spec. Indemnity health only (no investment).
Family-floater, individual, senior, critical-illness,
top-up, super top-up, hospital-cash variants under one
intent via policy_type discriminator. Safety-dominant
TTBS (weight 0.45). NET commission base. IRDAI waiting-
period bands enforced. Cashless network audit rules.