T
TOMO
Developer Docs
BETA These docs are under partner review. Some features described are roadmap items, not yet shipped. Verify against your sandbox before relying on any contract.
● DRAFTv1.0.0finance.buy_health_insurance

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 health
  • finance.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_service or 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_premium
  • artificial_urgency_text ("Last day at this price!" without verifiable rate-change)
  • ai_generated_photo for insurer / hospital / agent imagery
  • fabricated_hospital_count (network counts must match insurer's published network)
  • inflated_claim_settlement_ratio, inflated_incurred_claims_ratio
  • editor_recommended, tomo_pick, best_for_seniors
  • commission_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.