{"openapi":"3.1.0","info":{"title":"assurs.ch — independent LAMal comparison for agents","version":"2.4.0","description":"Official Swiss LAMal premium comparison and client-approved contact requests to Swiss Premium Insurance (SPI). Flow: prepareLamalQuote, present offers with the cashback sentence, ask consent_request, submitOfferRequest once. No API key. Read operations never send email.","termsOfService":"https://assurs.ch/agents/terms.html","contact":{"name":"Swiss Premium Insurance","email":"contact@sp-insurance.ch","url":"https://assurs.ch/agents/"},"x-privacy-policy":"https://assurs.ch/agents/privacy.html"},"externalDocs":{"description":"Protocol, connect recipes and resources.","url":"https://assurs.ch/llms.txt"},"servers":[{"url":"https://api.assurs.ch"}],"security":[],"paths":{"/api/v1/lamal/quote":{"post":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"prepareLamalQuote","summary":"Step 1: compact LAMal comparison with cashback and submission instructions.","description":"Send the exact client criteria; model_group any means all categories. Returns the top 10 offers, every eligible model, comparison_id, the cashback sentence and submission (request_id, consent texts). Read-only: no lead, no email.","externalDocs":{"description":"The same quote by GET for browsing tools (same fields as query parameters).","url":"https://api.assurs.ch/api/v1/lamal/quote?premium_year=2027&postal_code=1955&municipality=Chamoson&birth_year=1988&deductible_chf=2500&accident_included=false&model_group=TEL_DIG&language=en"},"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PremiumRequest"},"example":{"premium_year":2027,"postal_code":"1955","municipality":"Chamoson","birth_year":1988,"deductible_chf":2500,"accident_included":false,"model_group":"TEL_DIG","language":"en"}}}},"responses":{"200":{"description":"Compact comparison; reading it sends nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompactPremiumComparison"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}},"get":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"getLamalQuote","summary":"Same compact comparison through query parameters.","description":"Prefer POST: query criteria can appear in hosting access logs. Same engine, prices, ranking and coverage as prepareLamalQuote.","parameters":[{"$ref":"#/components/parameters/premium_year"},{"$ref":"#/components/parameters/postal_code"},{"$ref":"#/components/parameters/municipality"},{"$ref":"#/components/parameters/municipality_bfs"},{"$ref":"#/components/parameters/birth_year"},{"$ref":"#/components/parameters/deductible_chf"},{"$ref":"#/components/parameters/accident_included"},{"$ref":"#/components/parameters/model_group"},{"$ref":"#/components/parameters/language"}],"responses":{"200":{"description":"Compact comparison; reading it sends nothing.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompactPremiumComparison"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/api/v1/lamal/premiums":{"post":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"compareLamalPremiums","summary":"Full comparison for independent verification; large response.","description":"Same engine as the quote plus the exact legacy result, per-model restrictions and source evidence. May exceed tool response limits; use prepareLamalQuote in conversations.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PremiumRequest"},"example":{"premium_year":2027,"postal_code":"1955","municipality":"Chamoson","birth_year":1988,"deductible_chf":2500,"accident_included":false,"model_group":"TEL_DIG","language":"en"}}}},"responses":{"200":{"description":"Full comparison; null results_url means sharing is not configured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PremiumComparison"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}},"get":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"compareLamalPremiumsGet","summary":"Full comparison through query parameters.","description":"Prefer POST to keep criteria out of access logs. Identical result to compareLamalPremiums.","parameters":[{"$ref":"#/components/parameters/premium_year"},{"$ref":"#/components/parameters/postal_code"},{"$ref":"#/components/parameters/municipality"},{"$ref":"#/components/parameters/municipality_bfs"},{"$ref":"#/components/parameters/birth_year"},{"$ref":"#/components/parameters/deductible_chf"},{"$ref":"#/components/parameters/accident_included"},{"$ref":"#/components/parameters/model_group"},{"$ref":"#/components/parameters/language"}],"responses":{"200":{"description":"Full comparison; null results_url means sharing is not configured.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PremiumComparison"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/api/v1/lamal/metadata":{"get":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"getLamalMetadata","summary":"Read the supported year, model_group codes, deductibles, data provenance and endpoints.","description":"No input. Validate criteria before quoting; read contact_action.enabled and the operations map. Unknown dates are null, never the build time.","responses":{"200":{"description":"Current rules, provenance and endpoints.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Metadata"}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/api/v1/lamal/offer-requests/test":{"post":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"testOfferRequest","summary":"Dry run of submitOfferRequest: validates and previews, never sends.","security":[],"description":"Same body and checks as submitOfferRequest, with synthetic contact details. No email, lead, entitlement or payment; separate quota. Returns the consent statement and cashback line a real send would use.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferRequestV2"},"example":{"request_id":"d3b4f6a2-5c1e-4b8a-9f0e-2a7c1d9e4b61","comparison_id":"<comparison_id from the quote>","insurer_id":1509,"language":"fr","contact":{"email":"client@example.ch"},"client_consent":true,"agent":{"name":"chatgpt"}}}}},"responses":{"200":{"description":"Validated only; nothing sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferTestReceipt"},"example":{"status":"validated_test","request_id":"d3b4f6a2-5c1e-4b8a-9f0e-2a7c1d9e4b61","email_sent":false,"payment_created":false,"recipient":"contact@sp-insurance.ch","preview":{"insurer_name":"Assura","model_name":"Assura Basis","premium_monthly_chf":245.1,"criteria_summary":"1955 Chamoson, 1988, CHF 2500, sans accident, TEL_DIG","contact_fields":["email"],"language":"fr","cashback_line":"…","consent_statement":"…"}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"409":{"$ref":"#/components/responses/Conflict"},"410":{"$ref":"#/components/responses/Gone"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/api/v1/lamal/offer-requests":{"post":{"x-openai-isConsequential":true,"x-mcp-annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"submitOfferRequest","summary":"Step 4: send the client-approved offer request to Swiss Premium Insurance.","security":[{},{"agentIntegrationKey":[]}],"description":"Call once, only after the client explicitly agreed to consent_request. Sends one email to contact@sp-insurance.ch; no account needed. Copy request_id and comparison_id from submission. On 429 rate_limited/502 retry the identical body; on 409 follow guidance. Report status and request_id.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferRequestV2"},"example":{"request_id":"d3b4f6a2-5c1e-4b8a-9f0e-2a7c1d9e4b61","comparison_id":"<comparison_id from the quote>","insurer_id":1509,"language":"fr","contact":{"email":"client@example.ch"},"client_consent":true,"agent":{"name":"chatgpt"}}}}},"responses":{"200":{"description":"Email provider accepted it for delivery to SPI; not inbox delivery, not read by SPI, not a contract. Same request_id and body deduplicated 24 hours.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferReceipt"},"example":{"status":"accepted","request_id":"d3b4f6a2-5c1e-4b8a-9f0e-2a7c1d9e4b61","email_sent":true,"recipient":"contact@sp-insurance.ch","accepted_at":"2026-10-22T09:30:00.000Z","follow_up_by":"Swiss Premium Insurance","expected_contact_channel":"email","cashback":{"program_status":"active","program_version":"2026-10-22.1","requested":true,"lamal_amount_chf":30,"lca_basis":"one_month_premium","contract_status":"not_verified","payment_created":false,"terms_url":"https://api.assurs.ch/rewards/terms","next_steps":"Keep this request_id. If the contract is concluded through Swiss Premium Insurance and approved by the insurer, SPI pays the cashback to the client. No claim form is needed."},"correction_or_cancellation":"mailto:contact@sp-insurance.ch?subject=Correction%20ou%20retrait%20d3b4f6a2-5c1e-4b8a-9f0e-2a7c1d9e4b61","message":"Accepted for delivery to Swiss Premium Insurance for follow-up. Not an insurance contract or proof of inbox delivery."}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"409":{"$ref":"#/components/responses/Conflict"},"410":{"$ref":"#/components/responses/Gone"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"502":{"$ref":"#/components/responses/BadGateway"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/api/v1/adviser/handoffs":{"post":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"createAdviserHandoffLink","summary":"Create a link where the client submits the request alone; sends nothing.","description":"Link to the adviser page with optional agent attribution; no contact data, lead or email. 503 adviser_unavailable when the form is disabled: offer contact@sp-insurance.ch instead.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HandoffRequest"},"example":{"comparison_id":"<comparison_id from the quote>","agent":{"name":"chatgpt"}}}}},"responses":{"200":{"description":"Link only; attribution is neither eligibility nor identity verification.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HandoffLink"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"409":{"$ref":"#/components/responses/Conflict"},"410":{"$ref":"#/components/responses/Gone"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/api/v1/rewards/programs":{"get":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"getActiveCustomerRewards","summary":"Read the detailed cashback programme terms (LAMal and LCA).","description":"Programme objects behind cashback in the quote. Amounts belong to the client, never to agents; an offer request alone creates no entitlement. Disabled returns no programmes.","responses":{"200":{"description":"Current programme status and terms.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CashbackPrograms"}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/api/v1/rewards/terms/{program_id}":{"get":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"getActiveRewardTerms","summary":"Read one active programme by id as JSON.","parameters":[{"name":"program_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Operator-approved commercial terms and their approval source.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CashbackProgram"}}}},"404":{"$ref":"#/components/responses/NotFound"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/rewards/terms":{"get":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"readCashbackTermsPage","summary":"Human-readable cashback terms page (HTML, fr/de/it/en).","parameters":[{"name":"language","in":"query","required":false,"schema":{"type":"string","enum":["fr","de","it","en"]}}],"responses":{"200":{"description":"Noindex HTML page the client can read; the machine terms are terms_url.","content":{"text/html":{"schema":{"type":"string"}}}},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/compare":{"get":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"readComparisonPage","summary":"HTML results page without JavaScript.","description":"comparison_id alone, or the same explicit profile query as GET /api/v1/lamal/premiums. No contact data accepted; prefer results_url for sharing.","parameters":[{"name":"comparison_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"agent","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9_ -]{1,40}$"},"description":"Your agent name, for attribution only (the form and the SPI email then name it); never contact data. Accepted only together with comparison_id; a direct calculation query refuses it."},{"$ref":"#/components/parameters/premium_year_optional"},{"$ref":"#/components/parameters/postal_code_optional"},{"$ref":"#/components/parameters/municipality"},{"$ref":"#/components/parameters/municipality_bfs"},{"$ref":"#/components/parameters/birth_year_optional"},{"$ref":"#/components/parameters/deductible_chf_optional"},{"$ref":"#/components/parameters/accident_included_optional"},{"$ref":"#/components/parameters/model_group_optional"},{"$ref":"#/components/parameters/language"}],"responses":{"200":{"description":"Noindex HTML; no contacts, token, tracking or cashback promotion.","content":{"text/html":{"schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"410":{"$ref":"#/components/responses/Gone"},"422":{"$ref":"#/components/responses/UnprocessableEntity"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/adviser":{"get":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"openAdviserHandoff","summary":"HTML contact page; opening it sends nothing.","description":"The client submits the chosen contact detail and the displayed criteria. Form only when operator-enabled; otherwise a contact link. Hand adviser_url to the client with &agent=<your name>&language=<fr|de|it|en> appended.","parameters":[{"name":"comparison_id","in":"query","required":true,"schema":{"type":"string"}},{"name":"agent","in":"query","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9_ -]{1,40}$"},"description":"Your agent name, for attribution only (the form and the SPI email then name it); never contact data. Accepted only together with comparison_id; a direct calculation query refuses it."},{"name":"language","in":"query","required":false,"schema":{"type":"string","enum":["fr","de","it","en"]},"description":"Page language; defaults to the comparison language."}],"responses":{"200":{"description":"Contact form or contact link.","content":{"text/html":{"schema":{"type":"string"}}}},"400":{"$ref":"#/components/responses/BadRequest"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"},"410":{"$ref":"#/components/responses/Gone"},"429":{"$ref":"#/components/responses/TooManyRequests"},"503":{"$ref":"#/components/responses/ServiceUnavailable"}}}},"/api/lamal/v1/places":{"get":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"resolveMunicipalities","summary":"Resolve a Swiss postcode before calculating.","parameters":[{"name":"postcode","in":"query","required":true,"schema":{"type":"string","pattern":"^[0-9]{4}$"}}],"responses":{"200":{"description":"Possible communes and whether a choice is needed. Empty locations means an unknown postcode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MunicipalityLookup"}}}},"400":{"$ref":"#/components/responses/LegacyBadRequest"},"413":{"$ref":"#/components/responses/LegacyPayloadTooLarge"},"415":{"$ref":"#/components/responses/LegacyUnsupportedMediaType"},"429":{"$ref":"#/components/responses/LegacyTooManyRequests"},"500":{"$ref":"#/components/responses/LegacyServerError"}}}},"/api/lamal/v1/compare":{"post":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"calculateHousehold","summary":"Household comparison (1-12 people, one insurer for all); the legacy engine result.","description":"POST { year:2027, members:[{ birthYear, postcode, bfs?, franchise, accident:\"MIT\"|\"OHN\", careType }] }. Then ONE submitOfferRequest with comparison = verification.criteria and comparison_token = submission.comparisonToken (not comparison_id); cashback and consent texts: prepareLamalQuote.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ComparisonRequest"},"example":{"year":2027,"members":[{"birthYear":1985,"postcode":"8001","bfs":"261","franchise":2500,"accident":"MIT","careType":"any"},{"birthYear":1987,"postcode":"8001","bfs":"261","franchise":2500,"accident":"MIT","careType":"any"},{"birthYear":2015,"postcode":"8001","bfs":"261","franchise":0,"accident":"MIT","careType":"any"}]}}}},"responses":{"200":{"description":"Household offers in integer centimes, verification.criteria (copy as comparison) and submission.comparisonToken (24 h).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HouseholdOffers"}}}},"400":{"$ref":"#/components/responses/LegacyBadRequest"},"413":{"$ref":"#/components/responses/LegacyPayloadTooLarge"},"415":{"$ref":"#/components/responses/LegacyUnsupportedMediaType"},"429":{"$ref":"#/components/responses/LegacyTooManyRequests"},"500":{"$ref":"#/components/responses/LegacyServerError"}}},"get":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"calculateIndividual","summary":"Calculate one person via an ordinary HTTP GET.","description":"Prefer POST for a household or to keep criteria out of URL/access logs. Same explicit criteria and results as POST.","parameters":[{"name":"year","in":"query","required":true,"schema":{"type":"integer","const":2027}},{"name":"birthYear","in":"query","required":true,"schema":{"type":"integer","minimum":1907,"maximum":2027}},{"name":"postcode","in":"query","required":true,"schema":{"type":"string","pattern":"^[0-9]{4}$"}},{"name":"bfs","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]{1,6}$","description":"Commune OFS, obligatoire uniquement si le NPA couvre des régions ou des modèles disponibles différents. Vérifier requiresCommune dans places(postcode)."}},{"name":"franchise","in":"query","required":true,"schema":{"type":"integer","enum":[0,100,200,300,400,500,600,1000,1500,2000,2500]}},{"name":"accident","in":"query","required":true,"schema":{"type":"string","enum":["MIT","OHN"],"description":"MIT : inclus ; OHN : exclu. Ne pas déduire ce choix de l’âge ou de la profession."}},{"name":"careType","in":"query","required":true,"schema":{"type":"string","enum":["any","BASE","PRAXIS","FLEX","TEL_DIG","PHARM"]}},{"name":"currentProduct","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]+\\|[^|]+$","maxLength":100,"description":"Clé renvoyée par searchReferences ; facultative."}},{"name":"currentPremium","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]{1,5}([.,][0-9]{1,2})?$","description":"CHF par mois, base seule, nette de redistribution, avant subsides. Remplace la référence calculée."}}],"responses":{"200":{"description":"Calculated individual offers.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HouseholdComparison"}}}},"400":{"$ref":"#/components/responses/LegacyBadRequest"},"413":{"$ref":"#/components/responses/LegacyPayloadTooLarge"},"415":{"$ref":"#/components/responses/LegacyUnsupportedMediaType"},"429":{"$ref":"#/components/responses/LegacyTooManyRequests"},"500":{"$ref":"#/components/responses/LegacyServerError"}}}},"/api/lamal/v1/offer-requests/test":{"post":{"x-openai-isConsequential":false,"x-mcp-annotations":{"readOnlyHint":true,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"operationId":"testOfferRequestLegacy","summary":"Legacy camelCase test; prefer POST /api/v1/lamal/offer-requests/test. Never sends email.","security":[],"description":"Safe test with synthetic contact details and a real calculation token. No email, DNS contact validation, stored lead, entitlement or payment. Test remains available when real contact sending is disabled. A test reference is not a receipt for a real request.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferRequest"}}}},"responses":{"200":{"description":"Validated only; no email sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyTestReceipt"}}}},"400":{"$ref":"#/components/responses/LegacyBadRequest"},"409":{"$ref":"#/components/responses/LegacyConflict"},"413":{"$ref":"#/components/responses/LegacyPayloadTooLarge"},"415":{"$ref":"#/components/responses/LegacyUnsupportedMediaType"},"429":{"$ref":"#/components/responses/LegacyTooManyRequests"},"500":{"$ref":"#/components/responses/LegacyServerError"}}}},"/api/lamal/v1/offer-requests":{"post":{"operationId":"submitOfferRequestLegacy","summary":"Legacy camelCase send; prefer POST /api/v1/lamal/offer-requests. Sends an email to SPI.","x-openai-isConsequential":true,"x-mcp-annotations":{"readOnlyHint":false,"destructiveHint":false,"idempotentHint":true,"openWorldHint":false},"security":[{},{"agentIntegrationKey":[]}],"description":"SEND ONLY AFTER EXPLICIT CLIENT CONFIRMATION of the selected offer, exact criteria, contact details and destination contact@sp-insurance.ch. Reuse the calculation token; one RFC 4122 requestId kept for every retry. Emails SPI only; accepted means provider acceptance, not inbox delivery or a quote.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfferRequest"}}}},"responses":{"200":{"description":"Provider accepted this request; SPI will follow up. Repeated identical requestId is deduplicated for 24 hours within a running service and by the email provider.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyReceipt"}}}},"400":{"$ref":"#/components/responses/LegacyBadRequest"},"401":{"$ref":"#/components/responses/LegacyUnauthorized"},"409":{"$ref":"#/components/responses/LegacyConflict"},"413":{"$ref":"#/components/responses/LegacyPayloadTooLarge"},"415":{"$ref":"#/components/responses/LegacyUnsupportedMediaType"},"429":{"$ref":"#/components/responses/LegacyTooManyRequests"},"500":{"$ref":"#/components/responses/LegacyServerError"},"502":{"$ref":"#/components/responses/LegacyBadGateway"},"503":{"$ref":"#/components/responses/LegacyServiceUnavailable"}}}}},"components":{"securitySchemes":{"agentIntegrationKey":{"type":"http","scheme":"bearer","description":"Optional integration attribution in public mode; mandatory only in registered-only deployments. Never place in shared links or conversation prompts. Model identity remains self-declared."}},"parameters":{"premium_year":{"name":"premium_year","in":"query","required":true,"schema":{"type":"integer","const":2027,"description":"Tariff year: always 2027, the only imported year (metadata.supported_years). Required, no default."}},"premium_year_optional":{"name":"premium_year","in":"query","required":false,"schema":{"type":"integer","const":2027,"description":"Tariff year: always 2027, the only imported year (metadata.supported_years). Required, no default."}},"postal_code":{"name":"postal_code","in":"query","required":true,"schema":{"type":"string","pattern":"^[0-9]{4}$"}},"postal_code_optional":{"name":"postal_code","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]{4}$"}},"municipality":{"name":"municipality","in":"query","required":false,"schema":{"type":"string","minLength":1,"maxLength":100,"description":"Official municipality name; required with ambiguous region/model availability unless municipality_bfs is given."}},"municipality_bfs":{"name":"municipality_bfs","in":"query","required":false,"schema":{"type":"string","pattern":"^[0-9]{1,6}$"}},"birth_year":{"name":"birth_year","in":"query","required":true,"schema":{"type":"integer","minimum":1907,"maximum":2027,"description":"Exact four-digit birth year, not an age."}},"birth_year_optional":{"name":"birth_year","in":"query","required":false,"schema":{"type":"integer","minimum":1907,"maximum":2027,"description":"Exact four-digit birth year, not an age."}},"deductible_chf":{"name":"deductible_chf","in":"query","required":true,"schema":{"type":"integer","enum":[0,100,200,300,400,500,600,1000,1500,2000,2500],"description":"Annual deductible: adults (19 or older in 2027) 300, 500, 1000, 1500, 2000 or 2500; children (18 or under) 0, 100, 200, 300, 400, 500 or 600. No interpolation."}},"deductible_chf_optional":{"name":"deductible_chf","in":"query","required":false,"schema":{"type":"integer","enum":[0,100,200,300,400,500,600,1000,1500,2000,2500],"description":"Annual deductible: adults (19 or older in 2027) 300, 500, 1000, 1500, 2000 or 2500; children (18 or under) 0, 100, 200, 300, 400, 500 or 600. No interpolation."}},"accident_included":{"name":"accident_included","in":"query","required":true,"schema":{"type":"boolean","description":"Explicit JSON boolean required (not the string \"true\"). Do not infer legal eligibility to exclude accident cover."}},"accident_included_optional":{"name":"accident_included","in":"query","required":false,"schema":{"type":"boolean","description":"Explicit JSON boolean required (not the string \"true\"). Do not infer legal eligibility to exclude accident cover."}},"model_group":{"name":"model_group","in":"query","required":true,"schema":{"type":"string","enum":["any","BASE","PRAXIS","FLEX","TEL_DIG","PHARM"],"description":"any = all categories; BASE = free choice of doctor; PRAXIS = family doctor / HMO network; FLEX = hybrid model; TEL_DIG = telemedicine first; PHARM = pharmacy first."}},"model_group_optional":{"name":"model_group","in":"query","required":false,"schema":{"type":"string","enum":["any","BASE","PRAXIS","FLEX","TEL_DIG","PHARM"],"description":"any = all categories; BASE = free choice of doctor; PRAXIS = family doctor / HMO network; FLEX = hybrid model; TEL_DIG = telemedicine first; PHARM = pharmacy first."}},"language":{"name":"language","in":"query","required":false,"schema":{"type":"string","enum":["fr","de","it","en"],"default":"fr","description":"Language of the client texts and HTML pages; a region suffix is ignored."}}},"responses":{"LegacyBadRequest":{"description":"Malformed JSON, invalid criteria, unresolved commune, missing client consent or invalid contact. No email sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyError"}}}},"LegacyPayloadTooLarge":{"description":"Request body exceeds 24,000 bytes.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyError"}}}},"LegacyUnsupportedMediaType":{"description":"Use Content-Type: application/json.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyError"}}}},"LegacyTooManyRequests":{"description":"Rate limit reached. Respect Retry-After. Calculation limits are separate from the shared contact send quota.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyError"}}},"headers":{"Retry-After":{"schema":{"type":"string"}}}},"LegacyServerError":{"description":"Calculation temporarily unavailable; do not invent prices.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyError"}}}},"LegacyConflict":{"description":"comparison_refresh_required: recalculate and obtain confirmation again if the selected offer changes; keep the original requestId for an unchanged retry. request_conflict: the same requestId has different content; do not silently resubmit with a new ID.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyError"}}}},"LegacyUnauthorized":{"description":"Invalid supplied Bearer key, or deployment configured for registered integrations only. Public mode requires no API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyError"}}}},"LegacyServiceUnavailable":{"description":"Agent submissions or email delivery disabled by the operator. Comparison remains available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyError"}}}},"LegacyBadGateway":{"description":"Delivery unconfirmed. Retry the same requestId and payload; do not claim success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyError"}}}},"BadRequest":{"description":"client_consent_required, invalid_insurer, contact_required, invalid_email, invalid_phone, invalid_email_domain, invalid_request_id, unexpected_field; correct the field in errors.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Unauthorized":{"description":"Invalid Bearer key, or registered keys required. Public mode needs none.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"NotFound":{"description":"Unknown resource or no active terms.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Conflict":{"description":"comparison_refresh_required, dataset_changed, cashback_terms_outdated or request_conflict; follow guidance, keep request_id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"Gone":{"description":"comparison_link_expired; run a new comparison.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"UnprocessableEntity":{"description":"Quote criteria errors (invalid_criteria, municipality_required, invalid_municipality); errors[].choices lists accepted values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"TooManyRequests":{"description":"rate_limited: retry the identical request after retry_after_seconds. contact_daily_limit: not retryable; Retry-After until the daily window ends.","headers":{"Retry-After":{"schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"BadGateway":{"description":"delivery_unconfirmed; retry with the same request_id, never claim success.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"ServiceUnavailable":{"description":"mail_unavailable, agent_requests_disabled, adviser_unavailable or service_unavailable; offer adviser_url or contact@sp-insurance.ch, never claim an email was sent.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"schemas":{"ComparisonRequest":{"title":"SPI — comparaison LAMal 2027","type":"object","additionalProperties":false,"required":["year","members"],"properties":{"year":{"type":"integer","const":2027},"members":{"type":"array","minItems":1,"maxItems":12,"items":{"type":"object","additionalProperties":false,"required":["birthYear","postcode","franchise","accident","careType"],"properties":{"birthYear":{"type":"integer","minimum":1907,"maximum":2027},"postcode":{"type":"string","pattern":"^[0-9]{4}$"},"bfs":{"type":"string","pattern":"^[0-9]{1,6}$","description":"Commune OFS, obligatoire uniquement si le NPA couvre des régions ou des modèles disponibles différents. Vérifier requiresCommune dans places(postcode)."},"franchise":{"type":"integer","enum":[0,100,200,300,400,500,600,1000,1500,2000,2500]},"accident":{"type":"string","enum":["MIT","OHN"],"description":"MIT : inclus ; OHN : exclu. Ne pas déduire ce choix de l’âge ou de la profession."},"careType":{"type":"string","enum":["any","BASE","PRAXIS","FLEX","TEL_DIG","PHARM"]},"currentProduct":{"type":"string","pattern":"^[0-9]+\\|[^|]+$","maxLength":100,"description":"Clé renvoyée par searchReferences ; facultative."},"currentPremium":{"type":"string","pattern":"^[0-9]{1,5}([.,][0-9]{1,2})?$","description":"CHF par mois, base seule, nette de redistribution, avant subsides. Remplace la référence calculée."}}}}}},"Contact":{"type":"object","additionalProperties":false,"anyOf":[{"required":["email"]},{"required":["phone"]}],"description":"Fill email or phone; leave the other as an empty string or omit it. Never invent a client name, email or phone.","properties":{"name":{"type":"string","minLength":0,"maxLength":120},"email":{"type":"string","maxLength":160,"description":"Client email such as client@example.ch; an empty string or an omitted key means the client gave a phone instead."},"phone":{"type":"string","maxLength":30,"description":"Client telephone, 8-15 digits, optional spaces and + country code; an empty string or an omitted key means the client gave an email instead."},"message":{"type":"string","minLength":0,"maxLength":1500}}},"OfferRequest":{"type":"object","additionalProperties":false,"required":["requestId","comparison","comparisonToken","insurerId","language","contact","clientConsent"],"properties":{"requestId":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Any RFC 4122 UUID (versions 1-8); reuse submission.request_id from the v2 quote, or generate one once per client-approved request. Reuse the same UUID and payload on retries; never generate a fresh ID after a timeout."},"comparison":{"$ref":"#/components/schemas/ComparisonRequest"},"comparisonToken":{"type":"string","minLength":1,"maxLength":1000,"description":"Copy submission.comparisonToken from a successful calculation. Valid 24 hours; bound to these exact criteria, prices and catalogue; survives restarts."},"insurerId":{"type":"integer","description":"insurerId of the offer explicitly selected by the client from the returned comparison."},"language":{"type":"string","enum":["fr","de","it","en","es","pt","zh"]},"contact":{"$ref":"#/components/schemas/Contact"},"clientConsent":{"type":"boolean","const":true,"description":"Only true after the client has explicitly confirmed sending their contact details, household criteria and selected offer to Swiss Premium Insurance for follow-up. Do not infer consent from a calculation request."},"subsidyRequested":{"type":"boolean","default":false},"agent":{"type":"string","enum":["chatgpt","claude","gemini","other"],"description":"Legacy self-declared name. Prefer agentContext for Muse, Codex, Claude Code and custom agents."},"agentContext":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","pattern":"^[A-Za-z0-9_ -]{1,40}$","description":"Agent name, lower-cased by the server (spaces become _; a literal <placeholder> counts as other). Known names: chatgpt, claude, gemini, grok, openclaw, muse, codex, claude_code, copilot, perplexity, mistral, coding_agent, other; any other short identifier is accepted."},"kind":{"type":"string","enum":["personal_assistant","conversational_assistant","coding_agent"]},"display_name":{"type":"string","minLength":1,"maxLength":80,"description":"Optional custom agent name, no client name or conversation content."},"displayName":{"type":"string","minLength":1,"maxLength":80,"description":"Optional custom agent name, no client name or conversation content."},"integration_id":{"type":"string","pattern":"^[a-zA-Z0-9._-]{1,80}$","description":"Self-declared integration identifier, NOT authentication."},"integrationId":{"type":"string","pattern":"^[a-zA-Z0-9._-]{1,80}$","description":"Self-declared integration identifier, NOT authentication."},"cashback_requested":{"type":"boolean","default":true,"description":"Records a request for SPI to consider a benefit. Not a claim, eligibility, approval, amount or payment promise. Does not change prices or ranking."},"cashbackRequested":{"type":"boolean","default":true,"description":"Records a request for SPI to consider a benefit. Not a claim, eligibility, approval, amount or payment promise. Does not change prices or ranking."}}}}},"LegacyError":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":false},"code":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string"},"message":{"type":"string"},"choices":{"type":"array","items":{"type":"object"}}}}}}},"HouseholdComparison":{"type":"object","required":["ok","tariffYear","currency","amountUnit","offers","verification","submission"],"properties":{"ok":{"type":"boolean","const":true},"tariffYear":{"type":"integer"},"currency":{"type":"string","const":"CHF"},"amountUnit":{"type":"string","const":"centime"},"redistributionMonthlyCentsPerPerson":{"type":"integer","description":"Integer CHF centimes; divide by 100 for CHF."},"eligibleInsurerCount":{"type":"integer"},"knownReferenceCount":{"type":"integer"},"referenceMonthlyCents":{"type":["integer","null"],"description":"Integer CHF centimes; divide by 100 for CHF."},"offers":{"type":"array","maxItems":10,"items":{"type":"object","required":["rank","insurerId","insurerName","monthlyCents","annualCents","people"],"properties":{"rank":{"type":"integer"},"insurerId":{"type":"integer"},"insurerName":{"type":"string"},"monthlyCents":{"type":"integer","description":"Integer CHF centimes; divide by 100 for CHF."},"annualCents":{"type":"integer","description":"Integer CHF centimes; divide by 100 for CHF."},"monthlySavingCents":{"type":["integer","null"],"description":"Integer CHF centimes; divide by 100 for CHF."},"annualSavingCents":{"type":["integer","null"],"description":"Integer CHF centimes; divide by 100 for CHF."},"people":{"type":"array","items":{"type":"object","required":["memberIndex","productKey","monthlyGrossCents","monthlyNetCents"],"properties":{"memberIndex":{"type":"integer"},"productKey":{"type":"string"},"modelName":{"type":"string"},"careType":{"type":"string"},"careTypeLabel":{"type":"string"},"monthlyGrossCents":{"type":"integer","description":"Integer CHF centimes; divide by 100 for CHF."},"monthlyNetCents":{"type":"integer","description":"Integer CHF centimes; divide by 100 for CHF."},"referenceMonthlyCents":{"type":["integer","null"],"description":"Integer CHF centimes; divide by 100 for CHF."},"referenceKind":{"type":["string","null"]},"monthlySavingCents":{"type":["integer","null"],"description":"Integer CHF centimes; divide by 100 for CHF."}}}}}}},"limitations":{"type":"array","items":{"type":"string"}},"sources":{"type":"object"},"verification":{"type":"object","description":"Exact criteria, per-member OFSP lookup keys, source URLs and SHA-256 fingerprints, catalogue/module hashes and independent Python verifier.","properties":{"criteria":{"$ref":"#/components/schemas/ComparisonRequest"},"revision":{"type":"string"},"manifestUrl":{"type":"string"},"hashes":{"type":"object"},"sourceFiles":{"type":"array","items":{"type":"object"}},"members":{"type":"array","items":{"type":"object"}},"verifierUrl":{"type":"string"},"instructions":{"type":"string"}}},"submission":{"type":"object","required":["endpoint","comparisonToken","expiresAt","clientConsentRequired"],"properties":{"endpoint":{"type":"string"},"comparisonToken":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"},"clientConsentRequired":{"type":"boolean","const":true}}}}},"MunicipalityLookup":{"type":"object","properties":{"ok":{"type":"boolean"},"requiresCommune":{"type":"boolean"},"locations":{"type":"array","items":{"type":"object","properties":{"bfs":{"type":"string"},"commune":{"type":"string"},"canton":{"type":"string"},"region":{"type":"string"},"locality":{"type":"string"}}}}}},"LegacyTestReceipt":{"type":"object","properties":{"ok":{"const":true},"status":{"const":"validated_test"},"requestId":{"type":"string","format":"uuid"},"testMode":{"const":true},"emailSent":{"const":false},"paymentCreated":{"const":false}}},"LegacyReceipt":{"type":"object","required":["ok","status","requestId","recipient","message","acceptedAt","followUpBy","expectedContactChannel","correctionOrCancellation"],"properties":{"ok":{"type":"boolean","const":true},"status":{"type":"string","const":"accepted"},"requestId":{"type":"string","format":"uuid"},"recipient":{"type":"string","const":"contact@sp-insurance.ch"},"message":{"type":"string"},"acceptedAt":{"type":"string","format":"date-time"},"followUpBy":{"const":"Swiss Premium Insurance"},"expectedContactChannel":{"const":"email_or_phone"},"correctionOrCancellation":{"type":"string","format":"uri"}}},"HouseholdOffers":{"type":"object","required":["ok","tariffYear","offers","verification","submission"],"description":"Legacy engine result: integer centimes, one insurer for all members. No cashback object, client_messages or request_id here: take them from prepareLamalQuote and mint any RFC 4122 request_id.","properties":{"ok":{"const":true},"tariffYear":{"type":"integer"},"eligibleInsurerCount":{"type":"integer"},"offers":{"type":"array","maxItems":10,"items":{"type":"object","properties":{"rank":{"type":"integer"},"insurerId":{"type":"integer","description":"Send as insurer_id in submitOfferRequest."},"insurerName":{"type":"string"},"monthlyCents":{"type":"integer","minimum":0,"description":"Household net premium per month, integer centimes."},"annualCents":{"type":"integer","minimum":0},"people":{"type":"array","items":{"type":"object","properties":{"memberIndex":{"type":"integer"},"productKey":{"type":"string"},"modelName":{"type":"string","description":"Official French model name."},"careType":{"type":"string"},"monthlyNetCents":{"type":"integer","minimum":0}}}}}}},"verification":{"type":"object","properties":{"criteria":{"$ref":"#/components/schemas/ComparisonRequest","description":"Copy unchanged as comparison in submitOfferRequest."}}},"submission":{"type":"object","properties":{"comparisonToken":{"type":"string","description":"Send as comparison_token together with comparison = verification.criteria; valid 24 hours; never put it in a link."},"expiresAt":{"type":"string","format":"date-time"}}}}},"ErrorResponse":{"type":"object","required":["status","code","guidance","retryable"],"properties":{"status":{"const":"error"},"code":{"type":"string"},"errors":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string","description":"Field to correct, dotted path such as contact.email; an unknown key is named as sent."},"message":{"type":"string"},"reason":{"type":"string"},"choices":{"type":"array","items":{},"description":"Accepted values; for an unknown key, the documented field name to send instead."}}}},"guidance":{"type":"string","description":"What to do next; follow it literally."},"retryable":{"type":"boolean","description":"true only for 429 rate_limited, 502 and 503: retry the identical request; false for contact_daily_limit."},"retry_after_seconds":{"type":"integer"},"documentation":{"type":"string","format":"uri","description":"Protocol document (https://assurs.ch/llms.txt) with the field names and literal bodies; present on 4xx errors."}}},"PremiumRequest":{"type":"object","additionalProperties":false,"description":"Criteria for one person. For a household (2-12 people, one insurer for all) use calculateHousehold.","required":["premium_year","postal_code","birth_year","deductible_chf","accident_included","model_group"],"properties":{"premium_year":{"type":"integer","const":2027,"description":"Tariff year: always 2027, the only imported year (metadata.supported_years). Required, no default."},"postal_code":{"type":"string","pattern":"^[0-9]{4}$"},"municipality":{"type":"string","minLength":1,"maxLength":100,"description":"Official municipality name; required with ambiguous region/model availability unless municipality_bfs is given."},"municipality_bfs":{"type":"string","pattern":"^[0-9]{1,6}$"},"birth_year":{"type":"integer","minimum":1907,"maximum":2027,"description":"Exact four-digit birth year, not an age."},"deductible_chf":{"type":"integer","enum":[0,100,200,300,400,500,600,1000,1500,2000,2500],"description":"Annual deductible: adults (19 or older in 2027) 300, 500, 1000, 1500, 2000 or 2500; children (18 or under) 0, 100, 200, 300, 400, 500 or 600. No interpolation."},"accident_included":{"type":"boolean","description":"Explicit JSON boolean required (not the string \"true\"). Do not infer legal eligibility to exclude accident cover."},"model_group":{"type":"string","enum":["any","BASE","PRAXIS","FLEX","TEL_DIG","PHARM"],"description":"any = all categories; BASE = free choice of doctor; PRAXIS = family doctor / HMO network; FLEX = hybrid model; TEL_DIG = telemedicine first; PHARM = pharmacy first."},"language":{"type":"string","enum":["fr","de","it","en"],"default":"fr","description":"Language of the client texts and HTML pages; a region suffix is ignored."}}},"LocalizedText":{"type":"object","properties":{"fr":{"type":"string"},"de":{"type":"string"},"it":{"type":"string"},"en":{"type":"string"}}},"CashbackSummary":{"type":"object","required":["status"],"description":"Cashback SPI pays the client once a contract is concluded through SPI and approved by the insurer. Never a lower premium.","properties":{"status":{"enum":["active","disabled"]},"version":{"type":"string","description":"Send back as cashback_terms_version."},"paid_by":{"const":"Swiss Premium Insurance"},"paid_to":{"const":"client"},"changes_premium":{"const":false},"automatic_payment":{"const":false},"lamal":{"type":"object","properties":{"amount_chf":{"type":["number","null"]},"basis":{"type":"string","description":"fixed_chf"}}},"lca":{"type":"object","properties":{"amount_chf":{"type":["number","null"]},"basis":{"type":"string","description":"one_month_premium; amount set by SPI after review."}}},"trigger":{"type":"string"},"client_sentence":{"anyOf":[{"$ref":"#/components/schemas/LocalizedText"},{"type":"null"}],"description":"Say verbatim in the client language; fr, de, it and en on both routes; null when disabled."},"rationale":{"anyOf":[{"$ref":"#/components/schemas/LocalizedText"},{"type":"null"}],"description":"fr, de, it and en; null when disabled."},"terms_url":{"type":"string","format":"uri"},"programs_url":{"type":"string","format":"uri"},"contact":{"type":"string"}}},"CashbackProgram":{"type":"object","required":["program_id","version","status","product_line","payer","basis","amount_chf","trigger","conditions","terms_url","approval"],"properties":{"program_id":{"type":"string"},"version":{"type":"string"},"status":{"const":"active"},"product_line":{"enum":["LAMAL","LCA"]},"payer":{"const":"Swiss Premium Insurance"},"currency":{"const":"CHF"},"basis":{"enum":["fixed_chf","one_month_equivalent"]},"amount_chf":{"type":["number","null"]},"amount_determination":{"type":"string"},"trigger":{"const":"contract_concluded_and_insurer_approved"},"conditions":{"type":"array","items":{"type":"string"}},"client_summary":{"$ref":"#/components/schemas/LocalizedText"},"rationale":{"$ref":"#/components/schemas/LocalizedText"},"valid_from":{"type":"string"},"valid_until":{"type":["string","null"]},"how_to_request":{"type":"string"},"changes_insurer_premium":{"const":false},"automatic_payment":{"const":false},"approval":{"type":"object","description":"Programme published and paid by Swiss Premium Insurance Sàrl; SPI confirms each concluded contract with the insurer."},"terms_url":{"type":"string","format":"uri"},"terms_page_url":{"type":"string","format":"uri"},"contact":{"type":"string"}}},"CashbackPrograms":{"type":"object","required":["status","programs"],"properties":{"status":{"enum":["disabled","active"]},"programs":{"type":"array","items":{"$ref":"#/components/schemas/CashbackProgram"}}}},"DataProvenance":{"type":"object","required":["authority","dataset_version","manifest_url","limitations"],"description":"Origin and freshness of the official data; manifest_url lists source files and the last official sync.","properties":{"authority":{"type":"string"},"source_url":{"type":"string","format":"uri"},"dataset_version":{"type":"string"},"last_validated_at":{"type":["string","null"],"format":"date-time"},"validation_status":{"type":"string"},"manifest_url":{"type":"string","format":"uri"},"limitations":{"type":"array","items":{"type":"string"}}}},"Pricing":{"type":"object","properties":{"currency":{"const":"CHF"},"period":{"const":"month"},"environmental_rebate_treatment":{"type":"string"},"environmental_credit_monthly_cents":{"type":"integer","minimum":0}}},"Operator":{"type":"object","properties":{"name":{"const":"Swiss Premium Insurance"},"role":{"const":"insurance_broker"},"assistance_is_optional":{"const":true}}},"CompactOffer":{"type":"object","required":["rank","offer_id","insurer_id","insurer_name","model_name","model_group","premium_monthly_chf","premium_monthly_net_cents"],"properties":{"rank":{"type":"integer"},"offer_id":{"type":"string"},"source_offer_id":{"type":"string"},"insurer_id":{"type":"integer","description":"Send as insurer_id in submitOfferRequest."},"insurer_name":{"type":"string"},"model_name":{"type":"string","description":"Official French model name."},"model_group":{"type":"string","enum":["BASE","PRAXIS","FLEX","TEL_DIG","PHARM"]},"premium_monthly_chf":{"type":"number","description":"Net official monthly premium in CHF; quote this value."},"premium_monthly_gross_cents":{"type":"integer","minimum":0},"premium_monthly_net_cents":{"type":"integer","minimum":0},"deductible_chf":{"type":"integer"},"accident_included":{"type":"boolean"}}},"PremiumOffer":{"type":"object","required":["offer_id","insurer_id","insurer_name","model_name","model_group","premium_monthly_chf","premium_monthly_net_cents","consumer_reward"],"properties":{"rank":{"type":"integer"},"offer_id":{"type":"string"},"source_offer_id":{"type":"string"},"insurer_id":{"type":"integer","description":"Send as insurer_id in submitOfferRequest."},"insurer_name":{"type":"string"},"model_name":{"type":"string","description":"Official French model name."},"model_group":{"type":"string","enum":["BASE","PRAXIS","FLEX","TEL_DIG","PHARM"]},"premium_monthly_chf":{"type":"number","description":"Net official monthly premium in CHF; quote this value."},"premium_monthly_gross_cents":{"type":"integer","minimum":0},"premium_monthly_net_cents":{"type":"integer","minimum":0},"deductible_chf":{"type":"integer"},"accident_included":{"type":"boolean"},"first_contact_requirement":{"type":"string"},"model_terms_url":{"type":["string","null"],"format":"uri"},"insurer_url":{"type":["string","null"],"format":"uri"},"restrictions":{"type":"object","properties":{"municipality_availability_checked":{"const":true},"provider_network_verified":{"const":false},"exact_model_terms_verified":{"const":false}}},"consumer_reward":{"type":"null","description":"Always null: individual eligibility is unverified. Never deduct cashback from the official premium."}}},"EligibleModelTable":{"type":"object","required":["columns","rows"],"description":"Every eligible model as a table, same engine and filters as offers; complete coverage, not limited to broker agreements.","properties":{"columns":{"type":"array","items":{"type":"string"},"const":["insurer_id","insurer_name","model_name","model_group","premium_monthly_chf"]},"rows":{"type":"array","items":{"type":"array","items":{"type":["integer","number","string"]}}}}},"Submission":{"type":"object","description":"How to send the client-approved request. Keep comparisonToken private; never put it in a link.","properties":{"endpoint":{"type":"string","format":"uri","description":"POST target of submitOfferRequest."},"test_endpoint":{"type":"string","format":"uri"},"testEndpoint":{"type":"string","format":"uri","deprecated":true,"description":"Alias of test_endpoint."},"method":{"const":"POST"},"content_type":{"const":"application/json"},"enabled":{"type":"boolean","description":"false: sending is disabled; offer adviser_url instead."},"request_id":{"type":"string","format":"uuid","description":"Fresh per response; copy it as request_id of the submission."},"comparison_id":{"type":["string","null"]},"comparison":{"type":"object","description":"Legacy criteria; copy unchanged with comparisonToken when comparison_id is unavailable."},"comparisonToken":{"type":"string"},"token_valid_until":{"type":"string","format":"date-time","description":"comparison_token lifetime (24 h)."},"comparison_id_valid_until":{"type":["string","null"],"format":"date-time","description":"comparison_id lifetime (30 days); results_url and adviser_url follow it. Prefer comparison_id over the token."},"expiresAt":{"type":"string","format":"date-time","deprecated":true,"description":"Alias of token_valid_until."},"clientConsentRequired":{"const":true},"request_template":{"type":"object","description":"submitOfferRequest body to fill; contact.email and contact.phone are empty strings: fill the ones you have."},"client_messages":{"type":"object","description":"fr, de, it and en.","properties":{"consent_request":{"$ref":"#/components/schemas/LocalizedText","description":"Ask this verbatim in the client language, filling {fields}, {insurer}, {model} and {premium}."},"consent_confirmation":{"$ref":"#/components/schemas/LocalizedText"}}},"instructions":{"type":["string","array"],"items":{"type":"string"},"description":"Numbered steps to follow."},"on_error":{"type":"object","additionalProperties":{"type":"string"},"description":"Error code to action."},"no_post_tool":{"type":"string"}}},"CompactPremiumComparison":{"type":"object","required":["status","result_type","response_format","profile","comparison_id","cashback","submission","offers","eligible_models","eligible_model_count","data","pricing","full_response_url","results_url","operator"],"properties":{"status":{"const":"ok"},"result_type":{"const":"non_binding_lamal_premium_comparison"},"profile":{"type":"object","description":"Criteria as applied plus resolved municipality, canton and region."},"comparison_id":{"type":["string","null"],"description":"Reference for submitOfferRequest; valid 30 days."},"cashback":{"$ref":"#/components/schemas/CashbackSummary"},"submission":{"$ref":"#/components/schemas/Submission"},"data":{"$ref":"#/components/schemas/DataProvenance"},"pricing":{"$ref":"#/components/schemas/Pricing"},"eligible_insurer_count":{"type":"integer"},"results_url":{"type":["string","null"],"format":"uri","description":"HTML results page to share with the client; no token."},"adviser_url":{"type":["string","null"],"format":"uri","description":"Page where the client submits alone; null when the form is disabled."},"link_expires_at":{"type":["string","null"],"format":"date-time"},"operator":{"$ref":"#/components/schemas/Operator"},"response_format":{"const":"compact"},"offers":{"type":"array","maxItems":10,"items":{"$ref":"#/components/schemas/CompactOffer"},"description":"Top 10 by net premium, same ranking as assurs.ch."},"model_groups":{"type":"object","additionalProperties":{"type":"string"},"description":"First-contact rule per model_group code present in offers."},"eligible_models":{"$ref":"#/components/schemas/EligibleModelTable"},"eligible_model_count":{"type":"integer"},"model_details":{"type":"string"},"full_response_url":{"type":"string","format":"uri","description":"Full response for independent verification; no token or contact data."}}},"PremiumComparison":{"type":"object","required":["status","result_type","profile","comparison_id","cashback","data","pricing","offers","eligible_models","results_url","operator","comparison"],"properties":{"status":{"const":"ok"},"result_type":{"const":"non_binding_lamal_premium_comparison"},"profile":{"type":"object","description":"Criteria as applied plus resolved municipality, canton and region."},"comparison_id":{"type":["string","null"],"description":"Reference for submitOfferRequest; valid 30 days."},"cashback":{"$ref":"#/components/schemas/CashbackSummary"},"submission":{"$ref":"#/components/schemas/Submission"},"data":{"type":"object","required":["authority","dataset_version","manifest_url","limitations"],"description":"Origin and freshness of the official data; manifest_url lists source files and the last official sync.","properties":{"authority":{"type":"string"},"source_url":{"type":"string","format":"uri"},"dataset_version":{"type":"string"},"last_validated_at":{"type":["string","null"],"format":"date-time"},"validation_status":{"type":"string"},"manifest_url":{"type":"string","format":"uri"},"limitations":{"type":"array","items":{"type":"string"}},"last_successful_official_sync_at":{"type":["string","null"],"format":"date-time"},"market_scope":{"type":"string"},"source_files":{"type":"array","items":{"type":"object"}}}},"pricing":{"$ref":"#/components/schemas/Pricing"},"eligible_insurer_count":{"type":"integer"},"results_url":{"type":["string","null"],"format":"uri","description":"HTML results page to share with the client; no token."},"adviser_url":{"type":["string","null"],"format":"uri","description":"Page where the client submits alone; null when the form is disabled."},"link_expires_at":{"type":["string","null"],"format":"date-time"},"operator":{"$ref":"#/components/schemas/Operator"},"offers":{"type":"array","maxItems":10,"items":{"$ref":"#/components/schemas/PremiumOffer"}},"eligible_models":{"type":"array","items":{"$ref":"#/components/schemas/PremiumOffer"},"description":"All eligible imported models with the same filters. Not restricted to broker distribution agreements."},"comparison":{"type":"object","description":"Exact legacy engine result and OFSP verification keys, without the token. Save as quote.json for verify-quote.py."},"customer_benefits":{"$ref":"#/components/schemas/CashbackPrograms"}}},"Metadata":{"type":"object","properties":{"api_version":{"type":"string"},"supported_years":{"type":"array","items":{"type":"integer"}},"data":{"$ref":"#/components/schemas/DataProvenance"},"deductibles_chf":{"type":"object","description":"Accepted deductibles for child and adult."},"models":{"type":"object","additionalProperties":{"type":"string"},"description":"model_group codes and their meaning."},"operator":{"$ref":"#/components/schemas/Operator"},"contact_action":{"type":"object","properties":{"enabled":{"type":"boolean"},"requires_integration_key":{"type":"boolean"},"client_consent_required":{"const":true},"submit_endpoint":{"type":"string","format":"uri"},"test_endpoint":{"type":"string","format":"uri"},"handoff_form_enabled":{"type":"boolean"},"token_lifetime_hours":{"type":"integer"},"request_id_policy":{"type":"string"}}},"operations":{"type":"object","additionalProperties":{"type":"string","description":"Absolute URL; rewards_terms is a URI template with {program_id}."},"description":"URL of every operation and document."}}},"OfferRequestV2":{"type":"object","additionalProperties":false,"required":["request_id","contact","client_consent"],"anyOf":[{"required":["comparison_id"]},{"required":["comparison","comparison_token"]}],"description":"Send exactly one of comparison_id or comparison + comparison_token. Copy request_id, comparison_id and insurer_id from the quote.","properties":{"request_id":{"type":"string","format":"uuid","pattern":"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$","description":"Copy submission.request_id from the quote (any RFC 4122 UUID). Reuse the same value and body on every retry."},"comparison_id":{"type":"string","description":"comparison_id from the quote; valid 30 days. Preferred."},"comparison":{"type":"object","description":"submission.comparison copied unchanged; only with comparison_token."},"comparison_token":{"type":"string","maxLength":1000,"description":"submission.comparisonToken with the identical submission.comparison; alternative to comparison_id."},"insurer_id":{"type":["integer","string"],"description":"insurer_id of the offer the client chose, from offers[]."},"offer_id":{"type":"string","description":"offers[].offer_id or source_offer_id; alternative to insurer_id."},"language":{"type":"string","enum":["fr","de","it","en","es","pt","zh"],"description":"Client language; defaults to the comparison language. fr, de, it, en have localised client texts and pages; es, pt, zh are recorded for SPI (preview and pages fall back to en/fr)."},"contact":{"$ref":"#/components/schemas/Contact"},"client_consent":{"type":"boolean","const":true,"description":"true only after the client explicitly answered yes to consent_request. Never infer consent from a comparison."},"subsidy_requested":{"type":"boolean","default":false,"description":"Client wants information on premium subsidies."},"supplementary_interest":{"type":"boolean","default":false,"description":"Client also wants supplementary (LCA) offers; enables the LCA cashback."},"agent":{"$ref":"#/components/schemas/AgentContext","description":"Who is calling: { name:\"chatgpt\" } etc. Self-declared, not authentication."},"cashback_terms_version":{"type":"string","description":"cashback.version shown to the client; 409 cashback_terms_outdated when stale."}}},"CashbackReceipt":{"type":"object","properties":{"program_status":{"enum":["active","disabled"]},"program_version":{"type":"string"},"requested":{"type":"boolean"},"lamal_amount_chf":{"type":["number","null"]},"lca_basis":{"type":["string","null"]},"contract_status":{"const":"not_verified"},"payment_created":{"const":false},"terms_url":{"type":"string","format":"uri"},"next_steps":{"type":"string","description":"Tell the client this."}}},"OfferReceipt":{"type":"object","required":["status","request_id","email_sent","recipient","accepted_at","follow_up_by","message"],"properties":{"status":{"const":"accepted"},"request_id":{"type":"string","format":"uuid"},"email_sent":{"const":true,"description":"Provider acceptance; not inbox delivery or a contract."},"recipient":{"const":"contact@sp-insurance.ch"},"accepted_at":{"type":"string","format":"date-time"},"follow_up_by":{"const":"Swiss Premium Insurance"},"expected_contact_channel":{"type":"string","enum":["email","phone","email_or_phone"]},"cashback":{"$ref":"#/components/schemas/CashbackReceipt"},"correction_or_cancellation":{"type":"string","format":"uri","description":"mailto link to correct or withdraw; give it to the client."},"message":{"type":"string"}}},"OfferTestReceipt":{"type":"object","required":["status","request_id","email_sent","payment_created","recipient","preview"],"properties":{"status":{"const":"validated_test"},"request_id":{"type":"string","format":"uuid"},"email_sent":{"const":false},"payment_created":{"const":false},"recipient":{"const":"contact@sp-insurance.ch"},"preview":{"type":"object","description":"What a real send would contain.","properties":{"insurer_name":{"type":"string"},"model_name":{"type":"string"},"premium_monthly_chf":{"type":"number"},"criteria_summary":{"type":"string"},"contact_fields":{"type":"array","items":{"type":"string"}},"language":{"type":"string"},"cashback_line":{"type":["string","null"]},"consent_statement":{"type":"string"}}}}},"HandoffRequest":{"type":"object","additionalProperties":false,"required":["comparison_id"],"properties":{"comparison_id":{"type":"string"},"agent":{"$ref":"#/components/schemas/AgentContext"},"agentContext":{"$ref":"#/components/schemas/AgentContext","deprecated":true,"description":"Deprecated alias of agent; not with agent."}}},"HandoffLink":{"type":"object","required":["handoff_url","submits_lead","transmits_contact_data"],"properties":{"status":{"const":"ready"},"handoff_url":{"type":"string","format":"uri"},"expires_at":{"type":"string","format":"date-time"},"submits_lead":{"const":false},"transmits_contact_data":{"const":false}}},"AgentContext":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string","pattern":"^[A-Za-z0-9_ -]{1,40}$","description":"Agent name, lower-cased by the server (spaces become _; a literal <placeholder> counts as other). Known names: chatgpt, claude, gemini, grok, openclaw, muse, codex, claude_code, copilot, perplexity, mistral, coding_agent, other; any other short identifier is accepted."},"kind":{"type":"string","enum":["personal_assistant","conversational_assistant","coding_agent"]},"display_name":{"type":"string","minLength":1,"maxLength":80,"description":"Optional custom agent name, no client name or conversation content."},"displayName":{"type":"string","minLength":1,"maxLength":80,"description":"Optional custom agent name, no client name or conversation content."},"integration_id":{"type":"string","pattern":"^[a-zA-Z0-9._-]{1,80}$","description":"Self-declared integration identifier, NOT authentication."},"integrationId":{"type":"string","pattern":"^[a-zA-Z0-9._-]{1,80}$","description":"Self-declared integration identifier, NOT authentication."},"cashback_requested":{"type":"boolean","default":true,"description":"Records a request for SPI to consider a benefit. Not a claim, eligibility, approval, amount or payment promise. Does not change prices or ranking."},"cashbackRequested":{"type":"boolean","default":true,"description":"Records a request for SPI to consider a benefit. Not a claim, eligibility, approval, amount or payment promise. Does not change prices or ranking."}}}}}}
