{"openapi":"3.0.3","info":{"title":"API — test live (Swagger UI)","version":"1.0.0","description":"All services are documented here. **Try it out** sends real requests: your client IP must be in `users.permitted_ip`, and the `api_key` + operation flags must match the same `users` row. `/docs` and `/openapi.json` are public (no ACL), but the API calls below are ACL-protected (except `GET /health`).\n\n"},"servers":[{"url":"https://test-api.inscape.ro","description":"API base URL"}],"tags":[{"name":"Health","description":"No ACL"},{"name":"Vehicle","description":"DRPCIV / vehicle"},{"name":"Company","description":"get companies info"},{"name":"CNP","description":"CNP validation"},{"name":"Sanctions","description":"Sanctions lists"},{"name":"Address","description":"Address / postal code"},{"name":"Messaging","description":"SMS / email"},{"name":"AI","description":"AI processing — offer comparison; policy extraction from .pdf / .txt / .doc(x); `pdf_password` only for encrypted PDFs"},{"name":"Seismic","description":"Earthquake catalogue"},{"name":"Risk Data Hub","description":"JRC Risk Data Hub loss"},{"name":"EIOPA","description":"EIOPA register of insurance undertakings"}],"paths":{"/health":{"get":{"tags":["Health"],"operationId":"health","summary":"Health check","description":"No IP ACL. Response `{ ok: true }`.","responses":{"200":{"description":"API is healthy.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthOkResponse"},"example":{"ok":true}}}}}}},"/getInfoByVin":{"post":{"tags":["Vehicle"],"operationId":"getInfoByVin","summary":"Vehicle data by VIN (DRPCIV)","description":"Requires `check_vin`, `api_key`, and client IP in `users.permitted_ip` (same `users` row).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetInfoByVinRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","vin":"WVWZZZ1JZ3W386752"}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/getInfoByPlate":{"post":{"tags":["Vehicle"],"operationId":"getInfoByPlate","summary":"Vehicle data by registration plate","description":"Requires `check_plate`, `api_key`, and allowed client IP.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetInfoByPlateRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","plate":"B123ABC"}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/getCompanyInfo":{"post":{"tags":["Company"],"operationId":"getCompanyInfo","summary":"Company data by tax ID (ONRC)","description":"Requires `check_company`, `api_key`, and allowed IP. Set `show*` / `show_*` flags to 1 to include extra sections.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetCompanyInfoRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","cui":"12345678","showFinancial":1,"showPhones":1,"showEmails":1,"showAdmins":1,"showWebsites":1,"showCourtCases":1}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/getUboInfo":{"post":{"tags":["Company"],"operationId":"getUboInfo","summary":"UBO","description":"Same contract as `/getCompanyInfo` (`check_company` + API key + allowed IP).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetUboInfoRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","cui":"12345678"}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/getArrCompanyInfo":{"post":{"tags":["Company"],"operationId":"getArrCompanyInfo","summary":"ARR public transport operator (licente.arr.ro)","description":"","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetArrCompanyInfoRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","arr_id":"12345"}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/checkCnp":{"post":{"tags":["CNP"],"operationId":"checkCnp","summary":"CNP validation","description":"Requires `check_cnp`, `api_key`, and allowed IP.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckCnpRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","cnp":"1800101019999"}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/checkSanctions":{"post":{"tags":["Sanctions"],"operationId":"checkSanctions","summary":"Sanctions list search","description":"Requires `permit_sanctions`, `api_key`, and allowed IP.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckSanctionsRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","sub_user_id":"broker id","name":"Ionel Popisteanu","surname":"","aka":"","min_score":90,"max_result":10}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/getAddress/counties":{"post":{"tags":["Address"],"operationId":"getAddressCounties","summary":"List counties","description":"Requires `check_address`, `api_key`, and allowed IP.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAddressCountiesRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY"}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/getAddress/cities":{"post":{"tags":["Address"],"operationId":"getAddressCities","summary":"List cities by county","description":"Requires `check_address`, `api_key`, and allowed IP.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAddressCitiesRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","county":"Alba"}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/getAddress/streets":{"post":{"tags":["Address"],"operationId":"getAddressStreets","summary":"Street suggestions (prefix)","description":"Requires `check_address`, `api_key`, and allowed IP. The city must belong to the given county.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAddressStreetsRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","county":"Alba","city":"Alba Iulia","q":"Horea"}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/getAddress/zip":{"post":{"tags":["Address"],"operationId":"getAddressZip","summary":"Postal code lookup (city + street + number)","description":"Requires `check_address`, `api_key`, and allowed IP.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetAddressZipRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","city":"Alba Iulia","street":"Bulevard Horea","number":10,"hasAlphaSuffix":false}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/sendSms":{"post":{"tags":["Messaging"],"operationId":"sendSms","summary":"Send SMS (sendsms.ro)","description":"Requires `send_sms`, `api_key`, and allowed IP.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendSmsRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","to":"40722123456","text":"Code: 123456"}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/sendEmail":{"post":{"tags":["Messaging"],"operationId":"sendEmail","summary":"Send email (SMTP)","description":"Requires `send_email`, `api_key`, and allowed IP. Body must include `to`, `subject`, and at least `text` or `html`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendEmailRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","to":"client@example.com","subject":"Subject","text":"Short message"}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/compareOffers":{"post":{"tags":["AI"],"operationId":"compareOffers","summary":"Compare insurance offers (AI processing)","description":"Requires `permit_compare`, `api_key`, and allowed IP. Optional **`analysisCriteria`**: per-field **0/1** flags for which columns appear in each **`offers[]`** item; **omit or `{}`** → full default field set (same as legacy). Optional **`response_transport`** in body: omit or **`sync`** → **JSON** `application/json` (legacy fields plus `response_transport: \\\"sync\\\"`). **`stream`** → **`text/event-stream`** (SSE) with the same request body:\n\n**SSE (`stream`):**\n1. `event: meta` — e.g. `{ \\\"response_transport\\\": \\\"stream\\\" }`.\n2. `event: ai_delta` — `{ \\\"text\\\": \\\"...\\\" }`, consecutive Gemini text chunks (includes `aiVerdict` tokens as they appear in the model JSON).\n3. `event: complete` — terminal payload: on success (`error: 0`, full `aiRawResponse`, **`tokensUsed`** (total only), parsed `aiVerdict` and **`excelExport`** when JSON is valid — see `CompareOffersStreamCompleteSuccess`); on failure `CompareOffersStreamCompleteError`.\n\nFiles: at least two offers, each `name` + `data` (Base64). Encrypted PDFs: set `pdf_password` / `pdfPassword` on that entry in `files` only.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompareOffersRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","analysisCriteria":{"insurerName":1,"premium":1,"sumInsured":1,"startDate":1,"endDate":1,"mainCovers":1,"specialClauses":1,"deductible":1,"majorExclusions":1,"installments":1},"lang":"ro","files":[{"name":"offer1.pdf","data":"<BASE64>"},{"name":"offer2.pdf","data":"<BASE64>"}]},"examples":{"syncDefault":{"summary":"Sync — explicit full `analysisCriteria` (same as `{}`/omit: all flags **1**; each key **1**=include, **0**=exclude in `offers[]`)","value":{"user_id":1,"api_key":"YOUR_API_KEY","analysisCriteria":{"insurerName":1,"premium":1,"sumInsured":1,"startDate":1,"endDate":1,"mainCovers":1,"specialClauses":1,"deductible":1,"majorExclusions":1,"installments":1},"lang":"ro","files":[{"name":"offer1.pdf","data":"<BASE64>"},{"name":"offer2.pdf","data":"<BASE64>"}]}},"stream":{"summary":"Stream (SSE) — add `response_transport`; full criteria shown","value":{"user_id":1,"api_key":"YOUR_API_KEY","response_transport":"stream","analysisCriteria":{"insurerName":1,"premium":1,"sumInsured":1,"startDate":1,"endDate":1,"mainCovers":1,"specialClauses":1,"deductible":1,"majorExclusions":1,"installments":1},"lang":"ro","files":[{"name":"offer1.pdf","data":"<BASE64>"},{"name":"offer2.pdf","data":"<BASE64>","pdf_password":"only-if-encrypted"}]}},"limitedFields":{"summary":"Partial columns — exclude `premium` and `installments`","value":{"user_id":1,"api_key":"YOUR_API_KEY","analysisCriteria":{"insurerName":1,"premium":0,"sumInsured":1,"startDate":1,"endDate":1,"mainCovers":1,"specialClauses":1,"deductible":1,"majorExclusions":1,"installments":0},"lang":"ro","files":[{"name":"offer1.pdf","data":"<BASE64>"},{"name":"offer2.pdf","data":"<BASE64>"}]}}}}}},"responses":{"200":{"description":"Depends on **`response_transport`**: for **sync** (or omission) the body is JSON; validation errors remain JSON for **stream** mode **before** SSE starts (e.g. 400 during file preparation). After streaming starts the body is **SSE** (`text/event-stream`); otherwise **`application/json`**. ","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/CompareOffersSyncSuccessResponse"},{"$ref":"#/components/schemas/StandardApiError"}]},"examples":{"syncSuccess":{"summary":"Sync success","value":{"error":0,"response_transport":"sync","aiRawResponse":"{\"comparisonMetadata\":{...},\"offers\":[...],\"aiVerdict\":{...}}","tokensUsed":12800}},"streamPrepError":{"summary":"Stream: validation error before SSE (JSON)","value":{"error":1,"info":"for comparison you must upload at least two files"}}}},"text/event-stream":{"schema":{"type":"string","description":"Server-Sent Events; each `data:` line is JSON for that event type (see operation description)."},"examples":{"streamFlow":{"summary":"Typical flow (conceptual)","value":"event: meta\ndata: {\"response_transport\":\"stream\"}\n\nevent: ai_delta\ndata: {\"text\":\"{\\\"comparisonMet\"}\n\n... event: complete\ndata: {\"error\":0,\"response_transport\":\"stream\",...}"}}}}},"400":{"description":"Same as generic POST endpoints: invalid body, fewer than two files, invalid PDF, oversized Base64, or bad `response_transport`.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"for comparison you must upload at least two files"}}}},"403":{"description":"`permit_compare` not set, wrong `api_key` for `user_id`, or IP not permitted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id 1 for compare offers"}}}},"500":{"description":"Unexpected server failure after request was accepted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/trainingAgents":{"post":{"tags":["AI"],"operationId":"trainingAgents","summary":"Training agents: simulate agent/client conversation (AI)","description":"Requires `permit_agents_training`, `api_key`, and allowed IP. Body includes `history[]` + `input` and who plays the client via `client_role_by`.\n\nOptional **`response_transport`**: omit or **`sync`** → **JSON**. **`stream`** (or alias **`sse`**) → **SSE** (`text/event-stream`) with events:\n1. `event: meta` — `{ \"response_transport\": \"stream\" }`\n2. `event: ai_delta` — `{ \"text\": \"...\" }` consecutive chunks\n3. `event: complete` — `{ error:0, response_transport:\"stream\", conversation_id, answer_id, next:{ role, content } }` or error envelope.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrainingAgentsRequest"},"examples":{"sync":{"summary":"Sync (default)","value":{"user_id":1,"api_key":"YOUR_API_KEY","response_transport":"sync","country":"RO","lang":"ro","profile":"speed","client_role_by":"ai","client_behavioral":"skeptic","history":[{"role":"agent","content":"Bună ziua! Cu ce vă pot ajuta?"},{"role":"client","content":"Sunt cam sceptic..."}],"input":{"role":"agent","content":"Înțeleg. Ce vă îngrijorează cel mai mult?"}}},"stream":{"summary":"Stream (SSE)","value":{"user_id":1,"api_key":"YOUR_API_KEY","response_transport":"stream","country":"RO","lang":"ro","profile":"speed","client_role_by":"ai","client_behavioral":"skeptic","history":[{"role":"agent","content":"Bună ziua! Cu ce vă pot ajuta?"},{"role":"client","content":"Sunt cam sceptic..."}],"input":{"role":"agent","content":"Înțeleg. Ce vă îngrijorează cel mai mult?"}}}}}}},"responses":{"200":{"description":"Depends on `response_transport`: JSON for sync (or omission); SSE (`text/event-stream`) for stream/sse. Validation errors are JSON if they occur before SSE starts.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/TrainingAgentsSyncSuccessResponse"},{"$ref":"#/components/schemas/StandardApiError"}]}},"text/event-stream":{"schema":{"type":"string","description":"Server-Sent Events; each `data:` line is JSON (see operation description)."}}}},"400":{"description":"Invalid body (missing history/input), invalid response_transport, or client_behavioral missing for client_role_by=ai.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty history array"}}}},"403":{"description":"`permit_agents_training` not set, wrong `api_key` for `user_id`, or IP not permitted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id 1 for agents training simulation (trainingAgents)"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/trainingAgentEvaluation":{"post":{"tags":["AI"],"operationId":"trainingAgentEvaluation","summary":"Evaluate a training conversation (consultative sales scoring)","description":"Requires `permit_agents_training`, `api_key`, and allowed IP. Sends full training transcript and returns a consultative-sales evaluation (0-100) with per-criterion scores and evidence.\n\nOptional **`response_transport`**: omit or **`sync`** → **JSON**. **`stream`** (or alias **`sse`**) → **SSE** (`text/event-stream`) with events:\n1. `event: meta` — `{ \"response_transport\": \"stream\" }`\n2. `event: ai_delta` — `{ \"text\": \"...\" }` consecutive chunks (raw JSON text from the model)\n3. `event: complete` — `{ error:0, response_transport:\"stream\", conversation_id, answer_id, aiRawResponse, parse_ok, evaluation? | parse_error? }`.\n","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TrainingAgentEvaluationRequest"},"examples":{"sync":{"summary":"Sync (default)","value":{"user_id":1,"api_key":"YOUR_API_KEY","response_transport":"sync","conversation_id":"conv_123","country":"RO","lang":"ro","profile":"speed","history":[{"role":"agent","content":"Bună ziua! Cu ce vă pot ajuta?"},{"role":"client","content":"Sunt cam sceptic..."},{"role":"agent","content":"Înțeleg. Ce v-a făcut să fiți sceptic?"}]}},"stream":{"summary":"Stream (SSE)","value":{"user_id":1,"api_key":"YOUR_API_KEY","response_transport":"stream","conversation_id":"conv_123","country":"RO","lang":"ro","profile":"speed","history":[{"role":"agent","content":"Bună ziua! Cu ce vă pot ajuta?"},{"role":"client","content":"Sunt cam sceptic..."},{"role":"agent","content":"Înțeleg. Ce v-a făcut să fiți sceptic?"}]}}}}}},"responses":{"200":{"description":"Depends on `response_transport`: JSON for sync (or omission); SSE (`text/event-stream`) for stream/sse. Validation errors are JSON if they occur before SSE starts.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/TrainingAgentEvaluationSyncSuccessResponse"},{"$ref":"#/components/schemas/TrainingAgentEvaluationSyncParseErrorResponse"},{"$ref":"#/components/schemas/StandardApiError"}]}},"text/event-stream":{"schema":{"type":"string","description":"Server-Sent Events; each `data:` line is JSON (see operation description)."}}}},"400":{"description":"Invalid body (missing history) or invalid response_transport.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty history array"}}}},"403":{"description":"`permit_agents_training` not set, wrong `api_key` for `user_id`, or IP not permitted.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: ..."}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/extractPolicyFromPdf":{"post":{"tags":["AI"],"operationId":"extractPolicyFromPdf","summary":"Extract policy data: PDF, .txt text, .doc/.docx Word (AI processing)","description":"Requires `permit_extraction`, `api_key`, and allowed IP. **PDF:** unencrypted = file attachment to AI processing; encrypted = `pdf_password` + local text extraction. **.txt:** UTF-8 text in prompt (truncated by `POLICY_PDF_TEXT_MAX_CHARS`). **.doc / .docx:** file attachment with correct MIME to AI processing. Password-protected Word is not supported. Max size: `MAX_POLICY_PDF_MB` / `MAX_COMPARE_FILE_SIZE`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ExtractPolicyFromPdfRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","name":"polita.txt","data":"<BASE64_UTF8_TEXT>"}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/getSeismicEvents":{"post":{"tags":["Seismic"],"operationId":"getSeismicEvents","summary":"Seismic events, daily update","description":"Source: https://www.seismicportal.eu","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSeismicEventsRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","from":"2026-04-01","to":"2026-04-27","min_mag":3,"minlat":43.5,"maxlat":48.5,"minlon":20.5,"maxlon":29.5}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/getRiskDataHubLosses":{"post":{"tags":["Risk Data Hub"],"operationId":"getRiskDataHubLosses","summary":"Risk Data Hub losses (daily update)","description":"Source: The international disaster database https://www.emdat.be/","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetRiskDataHubLossesRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","from":"2024-01-01","to":"2025-12-31","country_code":"RO"}}}},"responses":{"200":{"description":"JSON response (success payload is operation-specific; logical errors may still use `{ error: 1, info }` in the body on some routes).","content":{"application/json":{"schema":{"type":"object","additionalProperties":true}}}},"400":{"description":"Invalid JSON body, missing required fields, or validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a non-empty plate (or registrationPlate)"}}}},"403":{"description":"Forbidden: caller IP is not allowed in `users.permitted_ip` (or not in CIDR), API key mismatch, or the `users` flag for this operation is disabled.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: api_key does not match user_id for this operation"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/searchEiopaUndertakings":{"post":{"tags":["EIOPA"],"operationId":"searchEiopaUndertakings","summary":"Search EIOPA insurance undertakings by name","description":"Requires `permit_eiopa=1`, `api_key`, and allowed client IP (users.permitted_ip / CIDR). Searches `undertaking_name_norm` name tokens and optional filters: `eu_operating_country`, `home_country`, `active_only`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchEiopaUndertakingsRequest"},"example":{"user_id":8,"api_key":"test1","name":"Allianz","eu_operating_country":"RO","home_country":"SK","active_only":true,"limit":50}}}},"responses":{"200":{"description":"Search results.","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/SearchEiopaUndertakingsSuccessResponse"},{"$ref":"#/components/schemas/StandardApiError"}]}}}},"400":{"description":"Invalid body / validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include name (non-empty string)"}}}},"403":{"description":"Forbidden: missing permit_eiopa, bad api_key, or IP not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: user_id 8 has no access to EIOPA register search (searchEiopaUndertakings)"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}},"/insurancePlanForDomestic":{"post":{"tags":["AI"],"operationId":"insurancePlanForDomestic","summary":"Generate a personalized domestic insurance plan (AI, generic)","description":"Requires `permit_insurance_plan=1`, `api_key`, and allowed IP. Generates a generic (non-product, non-insurer) insurance plan. All amounts are in EUR. Output includes both JSON (`plan_json`) and text (`plan_text`) in requested `lang` (BCP-47).","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InsurancePlanForDomesticRequest"},"example":{"user_id":1,"api_key":"YOUR_API_KEY","lang":"fr","household":{"members":[{"role":"adult","age":35,"sex":"F"},{"role":"adult","age":37,"sex":"M"},{"role":"child","age":6,"sex":"F"}]},"home":{"type":"apartment","ownership":"mortgage","year_built":2012,"city":"Bucarest"},"goals":[{"key":"protect_home","priority":5},{"key":"protect_liability","priority":4},{"key":"protect_health","priority":4}],"budget":{"monthly_target_eur":80,"flexibility":"medium"}}}}},"responses":{"200":{"description":"Plan response (sync).","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/InsurancePlanForDomesticSyncSuccessResponse"},{"$ref":"#/components/schemas/StandardApiError"}]}}}},"400":{"description":"Invalid body / validation failed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Body must include a positive integer user_id (or userId)"}}}},"403":{"description":"Forbidden: missing permit_insurance_plan, bad api_key, or IP not allowed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Forbidden for IP 192.0.2.1: user_id 1 has no access to insurance plan generation (insurancePlanForDomestic)"}}}},"500":{"description":"Unexpected server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StandardApiError"},"example":{"error":1,"info":"Internal server error"}}}}}}}},"components":{"schemas":{"StandardApiError":{"type":"object","required":["error","info"],"additionalProperties":true,"properties":{"error":{"type":"integer","enum":[1],"description":"Fixed value `1` for this API's error envelope.","example":1},"info":{"type":"string","description":"Human-readable reason (English or Romanian depending on the message source)."}}},"HealthOkResponse":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","enum":[true],"description":"Always `true` when HTTP 200.","example":true}}},"PostAuthBase":{"type":"object","required":["user_id","api_key"],"properties":{"user_id":{"type":"string","example":"1","description":"User ID from `users.user_id` (or use `userId`)"},"userId":{"type":"string","description":"Alias for `user_id`"},"api_key":{"type":"string","example":"YOUR_API_KEY","description":"API key from the same `users` row (or use `apiKey`)"},"apiKey":{"type":"string","description":"Alias for `api_key`"}}},"GetInfoByVinRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["vin"],"properties":{"vin":{"type":"string","description":"VIN, 17 characters","example":"WVWZZZ1JZ3W386752"},"VIN":{"type":"string","description":"Alias for `vin`"}}}]},"GetInfoByPlateRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["plate"],"properties":{"plate":{"type":"string","example":"B123ABC"},"registrationPlate":{"type":"string","description":"Alias for `plate`"}}}]},"GetCompanyInfoRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["cui"],"properties":{"cui":{"type":"string","description":"Tax ID (digits only)","example":"12345678"},"taxCode":{"type":"string","description":"Alias for `cui`"},"CUI":{"type":"string","description":"Alias for `cui`"},"showFinancial":{"type":"integer","enum":[0,1],"description":"1 = include financial data"},"show_financial":{"type":"integer","enum":[0,1]},"showPhones":{"type":"integer","enum":[0,1]},"show_phones":{"type":"integer","enum":[0,1]},"showEmails":{"type":"integer","enum":[0,1]},"show_emails":{"type":"integer","enum":[0,1]},"showAdmins":{"type":"integer","enum":[0,1]},"show_admins":{"type":"integer","enum":[0,1]},"showAdmin":{"type":"integer","enum":[0,1]},"show_admin":{"type":"integer","enum":[0,1]},"showWebsites":{"type":"integer","enum":[0,1]},"show_websites":{"type":"integer","enum":[0,1]},"showCourtCases":{"type":"integer","enum":[0,1]},"show_court_cases":{"type":"integer","enum":[0,1]}}}]},"GetUboInfoRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["cui"],"properties":{"cui":{"type":"string","example":"12345678"},"taxCode":{"type":"string"},"CUI":{"type":"string"}}}]},"GetArrCompanyInfoRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","properties":{"arr_id":{"type":"string","description":"Public ID from `https://licente.arr.ro/publica/{id}` (aliases: `id`, `arr_public_id`)","example":"12345"},"id":{"type":"string","description":"Alias for `arr_id`"},"arr_public_id":{"type":"string"},"arrPublicId":{"type":"string"}}}]},"CheckCnpRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["cnp"],"properties":{"cnp":{"type":"string","description":"13 digits","example":"1800101019999"},"CNP":{"type":"string"}}}]},"CheckSanctionsRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["name"],"properties":{"name":{"type":"string","example":"Ionel Popisteanu"},"sub_user_id":{"type":"string","description":"Broker ID (optional)"},"subUserId":{"type":"string"},"surname":{"type":"string"},"Surname":{"type":"string"},"aka":{"type":"string"},"AKA":{"type":"string"},"min_score":{"type":"integer","default":90},"minScore":{"type":"integer"},"max_result":{"type":"integer","default":10},"maxResult":{"type":"integer"}}}]},"GetAddressCountiesRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","properties":{}}]},"GetAddressCitiesRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["county"],"properties":{"county":{"type":"string","example":"Alba"},"County":{"type":"string"}}}]},"GetAddressStreetsRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["county","city","q"],"properties":{"county":{"type":"string","example":"Alba"},"County":{"type":"string"},"city":{"type":"string","example":"Alba Iulia"},"City":{"type":"string"},"q":{"type":"string","description":"Street name prefix (recommended ≥2 chars)","example":"Horea"},"Q":{"type":"string"}}}]},"GetAddressZipRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["city","street","number"],"properties":{"city":{"type":"string","example":"Alba Iulia"},"City":{"type":"string"},"street":{"type":"string","example":"Bulevard Horea"},"Street":{"type":"string"},"number":{"type":"integer","minimum":0,"example":10},"Number":{"type":"integer"},"hasAlphaSuffix":{"type":"boolean","description":"House number has letter suffix (e.g. 10A)","example":false},"HasAlphaSuffix":{"type":"boolean"}}}]},"SendSmsRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["to","text"],"properties":{"to":{"type":"string","description":"Destination phone number","example":"40722123456"},"text":{"type":"string","example":"Code: 123456"}}}]},"SendEmailRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["to","subject"],"properties":{"to":{"type":"string","format":"email","example":"client@example.com"},"subject":{"type":"string","example":"Subject"},"text":{"type":"string","description":"Plain text message (require `text` or `html`)"},"html":{"type":"string","description":"HTML message"},"from":{"type":"string"},"replyTo":{"type":"string"}}}]},"CompareOfferFile":{"type":"object","required":["name","data"],"properties":{"name":{"type":"string","example":"offer.pdf","description":"File name with extension (`.pdf`, `.txt`, `.doc`, `.docx` — controlled by `COMPARE_PERMITTED_EXTENSIONS`)."},"data":{"type":"string","description":"Base64 file contents (may include `data:...;base64,` prefix). For non-encrypted PDFs omit `pdf_password`."},"pdf_password":{"type":"string","description":"Optional. Only for **encrypted PDFs**: password for that file. You can upload multiple files in `files`; only the encrypted ones need this field. Same flow as `POST /extractPolicyFromPdf` (pdf.js text extraction; truncation via `COMPARE_PDF_TEXT_MAX_CHARS` / `POLICY_PDF_TEXT_MAX_CHARS`). Ignored for `.txt` / `.doc` / `.docx`.","example":"secret-pdf-password"},"pdfPassword":{"type":"string","description":"Alias for `pdf_password`."}}},"AiVerdict":{"type":"object","description":"`ai_delta` SSE events carry raw Gemini text; after JSON parsing, verdict data also appears in `excelExport`.","properties":{"bestValueInsurer":{"type":"string","example":"Company X SA"},"reasoning":{"type":"string","description":"Up to ~100 words, same language as requested, without diacritics for ro/cs where applicable."}}},"CompareOfferExcelRow":{"type":"object","description":"One row per offer; `headers` in `excelExport` list column names in the same order.","properties":{"offerIndex":{"type":"integer","minimum":1},"insurerName":{"type":"string","nullable":true},"premium":{"type":"number","nullable":true},"sumInsured":{"type":"number","nullable":true},"startDate":{"type":"string","nullable":true},"endDate":{"type":"string","nullable":true},"mainCovers":{"type":"string"},"specialClauses":{"type":"string"},"deductible":{"type":"string"},"majorExclusions":{"type":"string"},"installments":{"type":"string","nullable":true}}},"CompareOffersExcelExport":{"type":"object","description":"Tabular payload ready to map to an Excel sheet (headers + rows + metadata + embedded `aiVerdict`).","properties":{"sheetName":{"type":"string","example":"compare_offers"},"headers":{"type":"array","items":{"type":"string"},"example":["offerIndex","insurerName","premium","sumInsured","startDate","endDate","mainCovers","specialClauses","deductible","majorExclusions","installments"]},"rows":{"type":"array","items":{"$ref":"#/components/schemas/CompareOfferExcelRow"}},"comparisonMetadata":{"type":"object","properties":{"policyType":{"type":"string"},"currency":{"type":"string","example":"RON"},"numberOfOffers":{"type":"integer","minimum":0}}},"aiVerdict":{"$ref":"#/components/schemas/AiVerdict"}}},"CompareOffersSyncSuccessResponse":{"type":"object","required":["error","response_transport","aiRawResponse","tokensUsed"],"properties":{"error":{"type":"integer","enum":[0],"description":"Gemini success; raw JSON text in `aiRawResponse`."},"response_transport":{"type":"string","enum":["sync"],"description":"Default mode when `response_transport` is omitted from the request."},"aiRawResponse":{"type":"string","description":"Single JSON text from the model (`comparisonMetadata`, `offers[]`, `aiVerdict`). Parse client-side, or use **stream** mode for a pre-built `excelExport`."},"tokensUsed":{"type":"integer","minimum":0,"description":"Total tokens reported by Gemini for this request (`usageMetadata.totalTokenCount`). One number for billing/visibility; prompt vs. completion breakdown is not exposed here.","example":12800}}},"TrainingAgentsRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["client_role_by","history","input"],"properties":{"response_transport":{"type":"string","enum":["sync","stream","sse"],"description":"Optional. \"sync\" (default) returns JSON; \"stream\" / \"sse\" returns SSE (`text/event-stream`)."},"country":{"type":"string","example":"RO"},"lang":{"type":"string","example":"ro"},"profile":{"type":"string","enum":["speed","expert"],"example":"speed"},"conversation_id":{"type":"string","description":"Optional session indicator. If omitted, server generates one."},"client_role_by":{"type":"string","enum":["ai","agent"],"description":"Who plays the client role: \"ai\" or \"agent\"."},"client_behavioral":{"type":"string","enum":["agreeable","skeptic","neutral","hostile"],"description":"Required when client_role_by=\"ai\". Controls client tone/stance."},"history":{"type":"array","minItems":1,"items":{"type":"object","required":["role","content"],"properties":{"role":{"type":"string","enum":["agent","client"]},"content":{"type":"string"}}}},"input":{"type":"object","required":["role","content"],"properties":{"role":{"type":"string","enum":["agent","client"]},"content":{"type":"string"}}}}}]},"TrainingAgentsMessage":{"type":"object","required":["role","content"],"properties":{"role":{"type":"string","enum":["agent","client"]},"content":{"type":"string"}}},"TrainingAgentsSyncSuccessResponse":{"type":"object","required":["error","response_transport","conversation_id","answer_id","next"],"properties":{"error":{"type":"integer","enum":[0]},"response_transport":{"type":"string","enum":["sync"]},"conversation_id":{"type":"string"},"answer_id":{"type":"string"},"next":{"$ref":"#/components/schemas/TrainingAgentsMessage"}}},"TrainingAgentsStreamCompleteSuccess":{"type":"object","required":["error","response_transport","conversation_id","answer_id","next"],"properties":{"error":{"type":"integer","enum":[0]},"response_transport":{"type":"string","enum":["stream"]},"conversation_id":{"type":"string"},"answer_id":{"type":"string"},"next":{"$ref":"#/components/schemas/TrainingAgentsMessage"}}},"TrainingAgentsStreamCompleteError":{"type":"object","required":["error","response_transport","info"],"properties":{"error":{"type":"integer","enum":[1]},"response_transport":{"type":"string","enum":["stream"]},"info":{"type":"string"}}},"TrainingAgentEvaluationRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["history"],"properties":{"response_transport":{"type":"string","enum":["sync","stream","sse"],"description":"Optional. \"sync\" (default) returns JSON; \"stream\" / \"sse\" returns SSE (`text/event-stream`)."},"country":{"type":"string","example":"RO"},"lang":{"type":"string","example":"ro"},"profile":{"type":"string","enum":["speed","expert"],"example":"speed"},"conversation_id":{"type":"string","description":"Optional session indicator (correlates with /trainingAgents)."},"history":{"type":"array","minItems":1,"items":{"type":"object","required":["role","content"],"properties":{"role":{"type":"string","enum":["agent","client"]},"content":{"type":"string"}}}}}}]},"TrainingAgentEvaluationEvidence":{"type":"object","required":["role","quote"],"properties":{"role":{"type":"string","enum":["agent","client"]},"quote":{"type":"string","description":"Short verbatim excerpt from transcript."},"turn_index":{"type":"integer","minimum":1,"description":"1-based turn index in transcript."}}},"TrainingAgentEvaluationCriterionScore":{"type":"object","required":["key","name","weight","score","strengths","improvements","evidence"],"properties":{"key":{"type":"string","enum":["need_discovery","active_listening_empathy","objection_handling","value_positioning","call_control_next_steps"]},"name":{"type":"string"},"weight":{"type":"number","minimum":0,"maximum":1,"example":0.35},"score":{"type":"integer","minimum":0,"maximum":100,"example":85},"strengths":{"type":"array","items":{"type":"string"}},"improvements":{"type":"array","items":{"type":"string"}},"evidence":{"type":"array","items":{"$ref":"#/components/schemas/TrainingAgentEvaluationEvidence"}}}},"TrainingAgentEvaluation":{"type":"object","required":["version","total_score","criteria","red_flags","next_step_suggestion"],"properties":{"version":{"type":"integer","enum":[1]},"total_score":{"type":"integer","minimum":0,"maximum":100,"example":73},"criteria":{"type":"array","items":{"$ref":"#/components/schemas/TrainingAgentEvaluationCriterionScore"}},"red_flags":{"type":"array","items":{"type":"string"}},"next_step_suggestion":{"type":"string","description":"One suggested next agent message (1-2 sentences)."},"notes":{"type":"array","items":{"type":"string"}}}},"TrainingAgentEvaluationSyncSuccessResponse":{"type":"object","required":["error","response_transport","conversation_id","answer_id","evaluation","parse_ok","aiRawResponse"],"properties":{"error":{"type":"integer","enum":[0]},"response_transport":{"type":"string","enum":["sync"]},"conversation_id":{"type":"string"},"answer_id":{"type":"string"},"parse_ok":{"type":"boolean","enum":[true]},"aiRawResponse":{"type":"string","description":"Raw JSON returned by the model."},"evaluation":{"$ref":"#/components/schemas/TrainingAgentEvaluation"}}},"TrainingAgentEvaluationSyncParseErrorResponse":{"type":"object","required":["error","response_transport","conversation_id","answer_id","parse_ok","aiRawResponse","parse_error"],"properties":{"error":{"type":"integer","enum":[0]},"response_transport":{"type":"string","enum":["sync"]},"conversation_id":{"type":"string"},"answer_id":{"type":"string"},"parse_ok":{"type":"boolean","enum":[false]},"aiRawResponse":{"type":"string","description":"Raw model output which failed JSON parsing/validation."},"parse_error":{"type":"string"}}},"TrainingAgentEvaluationStreamCompleteSuccess":{"type":"object","required":["error","response_transport","conversation_id","answer_id","aiRawResponse","parse_ok","evaluation"],"properties":{"error":{"type":"integer","enum":[0]},"response_transport":{"type":"string","enum":["stream"]},"conversation_id":{"type":"string"},"answer_id":{"type":"string"},"aiRawResponse":{"type":"string"},"parse_ok":{"type":"boolean","enum":[true]},"evaluation":{"$ref":"#/components/schemas/TrainingAgentEvaluation"}}},"TrainingAgentEvaluationStreamCompleteParseError":{"type":"object","required":["error","response_transport","conversation_id","answer_id","aiRawResponse","parse_ok","parse_error"],"properties":{"error":{"type":"integer","enum":[0]},"response_transport":{"type":"string","enum":["stream"]},"conversation_id":{"type":"string"},"answer_id":{"type":"string"},"aiRawResponse":{"type":"string"},"parse_ok":{"type":"boolean","enum":[false]},"parse_error":{"type":"string"}}},"TrainingAgentEvaluationStreamCompleteError":{"type":"object","required":["error","response_transport","info"],"properties":{"error":{"type":"integer","enum":[1]},"response_transport":{"type":"string","enum":["stream"]},"info":{"type":"string"}}},"CompareOffersStreamCompleteSuccess":{"type":"object","required":["error","response_transport","tokensUsed","aiRawResponse","parse_ok"],"properties":{"error":{"type":"integer","enum":[0]},"response_transport":{"type":"string","enum":["stream"]},"tokensUsed":{"type":"integer","minimum":0,"description":"Same as sync: total tokens (`usageMetadata.totalTokenCount`) for this streamed request.","example":11830},"aiRawResponse":{"type":"string","description":"Full text aggregated from Gemini after streaming completes."},"aiVerdict":{"description":"Parsed from the model JSON; `null` when `parse_ok` is false or the field is missing.","nullable":true,"allOf":[{"$ref":"#/components/schemas/AiVerdict"}]},"excelExport":{"description":"`null` when `parse_ok` is false.","nullable":true,"allOf":[{"$ref":"#/components/schemas/CompareOffersExcelExport"}]},"parse_ok":{"type":"boolean","description":"`true` if `aiRawResponse` could be parsed as the expected comparison JSON."},"parse_error":{"type":"string","description":"Present when `parse_ok` is false."}}},"CompareOffersStreamCompleteError":{"type":"object","required":["error","response_transport","info"],"properties":{"error":{"type":"integer","enum":[1]},"response_transport":{"type":"string","enum":["stream"]},"info":{"type":"string"}}},"CompareAnalysisCriteria":{"type":"object","description":"Optional object controlling which keys appear in each element of **`offers[]`** in the model output. **Only the 10 keys below are allowed** (`additionalProperties` is forbidden; unknown keys → **400**).\n\n**Flag values (integer only, not string):**\n- **`1`** — **Include** this attribute in the comparison: the AI may extract it and **must** output the corresponding property in every `offers[]` object.\n- **`0`** — **Exclude** this attribute: **do not** include this property in `offers[]` objects.\n\n**If the whole `analysisCriteria` is omitted, `null`, or `{}`**, the server behaves as if **every key were `1`** (full legacy template).\n**If you pass a partial object**, any **omitted** key defaults to **`1`**. After merge, **at least one** key must be **`1`**, or the API returns **400**.","example":{"insurerName":1,"premium":1,"sumInsured":1,"startDate":1,"endDate":1,"mainCovers":1,"specialClauses":1,"deductible":1,"majorExclusions":1,"installments":1},"additionalProperties":false,"properties":{"insurerName":{"type":"integer","enum":[0,1],"description":"Insurer / company name in the offer. **1** = include; **0** = exclude."},"premium":{"type":"integer","enum":[0,1],"description":"Premium amount. **1** = include; **0** = exclude."},"sumInsured":{"type":"integer","enum":[0,1],"description":"Sum insured. **1** = include; **0** = exclude."},"startDate":{"type":"integer","enum":[0,1],"description":"Policy start date. **1** = include; **0** = exclude."},"endDate":{"type":"integer","enum":[0,1],"description":"Policy end date. **1** = include; **0** = exclude."},"mainCovers":{"type":"integer","enum":[0,1],"description":"Main covers (list). **1** = include; **0** = exclude."},"specialClauses":{"type":"integer","enum":[0,1],"description":"Special clauses / extra benefits. **1** = include; **0** = exclude."},"deductible":{"type":"integer","enum":[0,1],"description":"Deductibles / franchises (list). **1** = include; **0** = exclude."},"majorExclusions":{"type":"integer","enum":[0,1],"description":"Major exclusions. **1** = include; **0** = exclude."},"installments":{"type":"integer","enum":[0,1],"description":"Installment count / payment frequency (`installments` in JSON output). **1** = include; **0** = exclude."}}},"CompareOffersRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["files"],"properties":{"analysisCriteria":{"description":"See schema **`CompareAnalysisCriteria`**: ten fixed keys, each **`0`** or **`1`**. Omitted / `{}` = all **`1`** (full template).","allOf":[{"$ref":"#/components/schemas/CompareAnalysisCriteria"}]},"analysis_criteria":{"description":"Snake_case alias for `analysisCriteria`.","allOf":[{"$ref":"#/components/schemas/CompareAnalysisCriteria"}]},"response_transport":{"type":"string","enum":["sync","stream"],"description":"Optional. Omit or **`sync`** → `application/json` body (includes `response_transport: \\\"sync\\\"` and **`tokensUsed`** — total tokens only). **`stream`** → `text/event-stream` (SSE): `meta`, then `ai_delta` chunks, then `complete` with `tokensUsed`, `excelExport`, `aiVerdict`."},"responseTransport":{"type":"string","enum":["sync","stream"],"description":"camelCase alias for `response_transport`."},"lang":{"type":"string","example":"ro","description":"Output language (optional, default `ro`)."},"files":{"type":"array","description":"At least 2 offers. Each item: `name` + `data`. For encrypted PDFs add `pdf_password` only on that item.","items":{"$ref":"#/components/schemas/CompareOfferFile"},"minItems":2}}}]},"ExtractPolicyFromPdfRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["data"],"properties":{"name":{"type":"string","example":"polita.pdf","description":"File name with extension: **`.pdf`**, **`.txt`**, **`.doc`**, **`.docx`**. (Internal default `policy.pdf` is only used if `name` is missing; for .txt / Word you must set the correct extension.)"},"fileName":{"type":"string"},"filename":{"type":"string"},"data":{"type":"string","description":"Document content in **Base64**: PDF, UTF-8 text file, or Office Word. Type is inferred from `name`."},"file":{"type":"string","description":"Alias for `data`."},"pdf":{"type":"string","description":"Alias for `data`."},"pdf_password":{"type":"string","description":"Optional, **only for encrypted `.pdf`**. PDF password. If the PDF is encrypted and the field is missing → 400. If provided, text is extracted (pdf.js) and sent as text. For **`.txt` / `.doc` / `.docx`** this field is ignored (password-protected Word is not supported). Text truncation: `POLICY_PDF_TEXT_MAX_CHARS`.","example":"secret-pdf-password"},"pdfPassword":{"type":"string","description":"Alias for `pdf_password`."}}}]},"GetSeismicEventsRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["from","to","min_mag","minlat","maxlat","minlon","maxlon"],"properties":{"from":{"type":"string","format":"date","example":"2026-04-01","description":"Start date UTC (inclusive), YYYY-MM-DD"},"to":{"type":"string","format":"date","example":"2026-04-27","description":"End date UTC (inclusive), YYYY-MM-DD"},"min_mag":{"type":"number","example":3,"description":"Minimum magnitude (rows with NULL magnitude are excluded)"},"minMag":{"type":"number"},"minlat":{"type":"number","example":43.5},"minLat":{"type":"number"},"maxlat":{"type":"number","example":48.5},"maxLat":{"type":"number"},"minlon":{"type":"number","example":20.5},"minLon":{"type":"number"},"maxlon":{"type":"number","example":29.5},"maxLon":{"type":"number"}}}]},"GetRiskDataHubLossesRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["from","to"],"properties":{"from":{"type":"string","format":"date","example":"2020-01-01","description":"Start date (inclusive) on column `start`, YYYY-MM-DD"},"to":{"type":"string","format":"date","example":"2025-12-31","description":"End date (inclusive) on column `start`, YYYY-MM-DD"},"country_code":{"type":"string","minLength":2,"maxLength":2,"example":"RO","description":"Optional ISO-2 country filter (`country_code`)"},"countryCode":{"type":"string","description":"Alias for `country_code`"},"event_code":{"type":"string","example":"FLRO202507280001","description":"Optional exact `event_code`"},"eventCode":{"type":"string","description":"Alias for `event_code`"},"hazard_type":{"type":"string","example":"Flood","description":"Optional exact `hazard_type` (English, as in RDH)"},"hazardType":{"type":"string","description":"Alias for `hazard_type`"}}}]},"SearchEiopaUndertakingsRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","required":["name"],"properties":{"name":{"type":"string","description":"Undertaking name (free text)","example":"Allianz"},"query":{"type":"string","description":"Alias for `name`"},"q":{"type":"string","description":"Alias for `name`"},"eu_operating_country":{"type":"string","minLength":2,"maxLength":8,"description":"EU country where the undertaking appears to operate (`eiopa_insurance_undertakings.eu_operating_country`, from EIOPA field *EU Country where the entity operates*). Optional filter.","example":"RO"},"home_country":{"type":"string","minLength":2,"maxLength":8,"description":"Home member state (`eiopa_insurance_undertakings.home_country`). Optional filter for country of origin.","example":"DE"},"country":{"type":"string","description":"Deprecated alias for `eu_operating_country` (backward compatibility). Prefer `eu_operating_country`.","example":"RO"},"active_only":{"type":"boolean","description":"Default true. When true, filters `is_active=1`."},"activeOnly":{"type":"boolean","description":"Alias for `active_only`"},"limit":{"type":"integer","minimum":1,"maximum":200,"description":"Max rows (default 50)."}}}]},"EiopaUndertakingRow":{"type":"object","required":["id","natural_key","natural_key_sha","activity_status","is_active"],"additionalProperties":true,"properties":{"id":{"type":"integer","example":1},"natural_key":{"type":"string"},"natural_key_sha":{"type":"string"},"lei":{"type":"string","nullable":true},"home_country":{"type":"string","nullable":true},"eu_operating_country":{"type":"string","nullable":true},"cross_border_status":{"type":"string","nullable":true},"national_register_number":{"type":"string","nullable":true},"undertaking_name":{"type":"string","nullable":true},"undertaking_name_norm":{"type":"string","nullable":true},"competent_authority":{"type":"string","nullable":true},"operation_start_date":{"type":"string","nullable":true,"example":"2004-04-29"},"operation_end_date":{"type":"string","nullable":true,"example":"2015-01-01"},"activity_status":{"type":"string","enum":["active","non_active"]},"is_active":{"type":"integer","enum":[0,1]},"city":{"type":"string","nullable":true},"county":{"type":"string","nullable":true},"address":{"type":"string","nullable":true},"website_address":{"type":"string","nullable":true},"raw_json":{"type":"string"},"row_fingerprint":{"type":"string"},"first_seen_at":{"type":"string"},"last_seen_at":{"type":"string"},"last_changed_at":{"type":"string"}}},"SearchEiopaUndertakingsSuccessResponse":{"type":"object","required":["error","results"],"properties":{"error":{"type":"integer","enum":[0]},"results":{"type":"array","items":{"$ref":"#/components/schemas/EiopaUndertakingRow"}}}},"InsurancePlanForDomesticRequest":{"allOf":[{"$ref":"#/components/schemas/PostAuthBase"},{"type":"object","properties":{"lang":{"type":"string","description":"BCP-47 language code (EU languages supported), e.g. `fr`, `de`, `ro`, `pt-PT`. If omitted: follow input language.","example":"fr"},"conversation_id":{"type":"string","description":"Optional session ID for refinement.","example":"conv_domestic_001"},"conversationId":{"type":"string","description":"Alias for `conversation_id`."},"household":{"type":"object","properties":{"members":{"type":"array","items":{"type":"object","required":["role","age"],"properties":{"role":{"type":"string","enum":["adult","child","senior"]},"age":{"type":"integer","minimum":0,"maximum":120},"sex":{"type":"string","enum":["M","F","X"]}}}},"notes":{"type":"string"}}},"home":{"type":"object","properties":{"type":{"type":"string","enum":["apartment","house","duplex","other"]},"ownership":{"type":"string","enum":["owner","mortgage","rent","family_use","other"]},"year_built":{"type":"integer","minimum":1800,"maximum":2100},"city":{"type":"string"},"county":{"type":"string"},"has_mortgage":{"type":"boolean"},"notes":{"type":"string"}}},"assets":{"type":"array","items":{"type":"object","required":["category"],"properties":{"category":{"type":"string","example":"electronics"},"approx_value_eur":{"type":"number","minimum":0,"description":"All money amounts are EUR."},"notes":{"type":"string"}}}},"goals":{"type":"array","items":{"type":"object","required":["key","priority"],"properties":{"key":{"type":"string","enum":["protect_home","protect_income","protect_health","protect_life","protect_liability","protect_travel","protect_pets","protect_education","build_emergency_fund","save_long_term"]},"priority":{"type":"integer","minimum":1,"maximum":5}}}},"budget":{"type":"object","properties":{"monthly_target_eur":{"type":"number","minimum":0,"description":"Monthly target in EUR."},"flexibility":{"type":"string","enum":["low","medium","high"]}}},"preferences":{"type":"object","properties":{"risk_tolerance":{"type":"string","enum":["low","medium","high"]},"simplicity_vs_coverage":{"type":"string","enum":["simplicity","balanced","coverage"]},"deductible_preference":{"type":"string","enum":["none","low","medium","high"]}}},"constraints":{"type":"object","properties":{"must_have":{"type":"array","items":{"type":"string"}},"avoid":{"type":"array","items":{"type":"string"}}}},"notes":{"type":"string","description":"Optional freeform notes / context."}}}]},"InsurancePlanForDomesticSyncSuccessResponse":{"type":"object","required":["error","response_transport","conversation_id","answer_id","parse_ok","aiRawResponse"],"properties":{"error":{"type":"integer","enum":[0]},"response_transport":{"type":"string","enum":["sync"]},"conversation_id":{"type":"string"},"answer_id":{"type":"string"},"parse_ok":{"type":"boolean"},"aiRawResponse":{"type":"string","description":"Raw model output (expected strict JSON)."},"plan_json":{"type":"object","additionalProperties":true,"description":"Structured plan JSON (strings in requested lang, money in EUR)."},"plan_text":{"type":"string","description":"Human-readable plan text (requested lang)."},"parse_error":{"type":"string"}}}}}}