{
  "openapi": "3.1.0",
  "info": {
    "title": "PoliErgaleio Cyprus Financial Engines",
    "version": "1.2.0",
    "description": "Cyprus-specific income tax, state pension, retirement stress test and unemployment benefit calculators. Send your key in the x-api-key header, or omit it to use the anonymous tier."
  },
  "servers": [
    {
      "url": "https://gpkpjfdlbsuyevfdsnbq.supabase.co/functions/v1/public-api"
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      }
    },
    "schemas": {
      "ToolResponse": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string"
                },
                "text": {
                  "type": "string"
                }
              }
            }
          },
          "structuredContent": {
            "type": "object"
          },
          "series": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "requestId": {
            "type": "string"
          },
          "guestId": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      }
    }
  },
  "security": [
    {
      "apiKeyAuth": []
    }
  ],
  "paths": {
    "/whoami": {
      "get": {
        "operationId": "whoami",
        "summary": "Verify an API key and list callable tools",
        "responses": {
          "200": {
            "description": "Key status, tier, limits, usage and tools"
          }
        }
      }
    },
    "/tools/calculate_cyprus_income_tax": {
      "post": {
        "operationId": "calculate_cyprus_income_tax",
        "summary": "Computes Cyprus personal income tax, GESY (National Health System) contributions, social insurance, and net (take-home) salary.",
        "description": "Use whenever you need an accurate Cyprus net salary or effective tax rate for a resident employee. Supports salary, rental, and dividend income with 2025/2026 legislation.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "salaryIncome": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Gross annual salary in EUR."
                  },
                  "rentalIncome": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Annual rental income in EUR."
                  },
                  "hasRentalIncome": {
                    "type": "boolean",
                    "description": "Whether rental income applies."
                  },
                  "dividendIncome": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Annual dividend income in EUR."
                  },
                  "hasDividendIncome": {
                    "type": "boolean",
                    "description": "Whether dividend income applies."
                  },
                  "isDividendNonDomicile": {
                    "type": "boolean",
                    "description": "Non-dom status for dividends."
                  },
                  "employmentType": {
                    "type": "string",
                    "enum": [
                      "private",
                      "civil"
                    ],
                    "description": "'private' for private sector (8.8% SI), 'civil' for civil service (4.45% SI)."
                  },
                  "qualifiesForFirstEmployment": {
                    "type": "boolean"
                  },
                  "firstEmploymentDeduction": {
                    "type": "string",
                    "enum": [
                      "",
                      "20",
                      "50"
                    ]
                  },
                  "propertyPrice": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Property price for wear-and-tear allowance."
                  },
                  "propertyYear": {
                    "type": "integer",
                    "description": "Year the property was acquired."
                  },
                  "interestPaid": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Interest paid on rental property."
                  },
                  "isNonDomicile": {
                    "type": "boolean",
                    "description": "Non-dom status for rental income."
                  },
                  "tradeUnionSubs": {
                    "type": "number",
                    "minimum": 0,
                    "description": "EUR amount. Use 0 if not applicable."
                  },
                  "donations": {
                    "type": "number",
                    "minimum": 0,
                    "description": "EUR amount. Use 0 if not applicable."
                  },
                  "innovativeInvestment": {
                    "type": "number",
                    "minimum": 0,
                    "description": "EUR amount. Use 0 if not applicable."
                  },
                  "providentFund": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Total provident/PEPP fund contribution in EUR."
                  },
                  "legislationVersion": {
                    "type": "string",
                    "enum": [
                      "2025",
                      "2026"
                    ],
                    "description": "Tax/legislation year. Supported: 2025, 2026."
                  },
                  "maritalStatus": {
                    "type": "string",
                    "enum": [
                      "single",
                      "married",
                      "cohabiting"
                    ]
                  },
                  "numDependentChildren": {
                    "type": "integer",
                    "minimum": 0
                  },
                  "spouseIncome": {
                    "type": "number",
                    "minimum": 0
                  },
                  "housingInterestPaid": {
                    "type": "number",
                    "minimum": 0
                  },
                  "rentPaidPrimary": {
                    "type": "number",
                    "minimum": 0
                  },
                  "energyEfficiencyExpense": {
                    "type": "number",
                    "minimum": 0
                  },
                  "evExpense": {
                    "type": "number",
                    "minimum": 0
                  },
                  "homeInsurancePremium": {
                    "type": "number",
                    "minimum": 0
                  }
                },
                "required": [
                  "salaryIncome"
                ]
              },
              "example": {
                "salaryIncome": 45000,
                "legislationVersion": "2026",
                "employmentType": "private"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                },
                "example": {
                  "content": [
                    {
                      "type": "text",
                      "text": "On a gross income of €45,000, take-home (net salary after income tax, social insurance and GESY) is €35,885.63 (effective rate 20.25%)."
                    }
                  ],
                  "structuredContent": {
                    "grossIncome": 45000,
                    "netIncome": 45000,
                    "netSalary": 35885.63,
                    "chargeableIncome": 39847.5,
                    "incomeTax": 3961.88,
                    "socialInsurance": 3960,
                    "gesy": 1192.5,
                    "totalDeductions": 5152.5,
                    "availableDeductions": 3847.5,
                    "specialDefenseContribution": 0,
                    "effectiveTaxRate": 20.25
                  },
                  "series": []
                }
              }
            }
          },
          "400": {
            "description": "Validation error with fieldErrors and a hint"
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/tools/calculate_cyprus_state_pension": {
      "post": {
        "operationId": "calculate_cyprus_state_pension",
        "summary": "Estimates the Cyprus state (contributory) pension amount at retirement based on accumulated insurance units and contribution history.",
        "description": "Use for retirement planning questions about the statutory Cyprus state pension floor.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "mode": {
                    "type": "string",
                    "enum": [
                      "quick",
                      "advanced"
                    ],
                    "description": "Calculation mode."
                  },
                  "currentAge": {
                    "type": "integer",
                    "minimum": 18,
                    "maximum": 70,
                    "description": "Current age (quick mode only)."
                  },
                  "retirementAge": {
                    "type": "integer",
                    "minimum": 63,
                    "maximum": 67,
                    "description": "Planned retirement age."
                  },
                  "yearsWorked": {
                    "type": "number",
                    "minimum": 0,
                    "maximum": 49,
                    "description": "Years of contributions (quick mode)."
                  },
                  "totalInsuranceUnits": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Total insurance units/points (quick mode)."
                  },
                  "yearlyUnits": {
                    "type": "array",
                    "description": "Advanced mode only. Insurance units earned per calendar year, e.g. [{\"year\":2003,\"units\":5.2}]. Units per year must be between 0 and the statutory maximum for that year (about 5.3-6.0; 6.0 for years after 2026). A legacy object map {\"2003\": 5.2} is also accepted. Years worked and total units are derived from this array, so yearsWorked/totalInsuranceUnits are ignored in advanced mode.",
                    "items": {
                      "type": "object",
                      "properties": {
                        "year": {
                          "type": "integer",
                          "minimum": 1981,
                          "description": "Calendar year of the contributions."
                        },
                        "units": {
                          "type": "number",
                          "minimum": 0,
                          "maximum": 6,
                          "description": "Insurance units earned that year."
                        }
                      },
                      "required": [
                        "year",
                        "units"
                      ]
                    }
                  },
                  "dependents": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 10,
                    "description": "Number of dependents (spouse/children); raises the basic pension multiplier."
                  }
                },
                "required": [
                  "mode",
                  "retirementAge"
                ]
              },
              "example": {
                "mode": "quick",
                "currentAge": 45,
                "retirementAge": 65,
                "yearsWorked": 22,
                "totalInsuranceUnits": 132,
                "dependents": 0
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                },
                "example": {
                  "content": [
                    {
                      "type": "text",
                      "text": "Estimated Cyprus state pension: €1,908.11/month gross, €1,824.50/month net."
                    }
                  ],
                  "structuredContent": {
                    "estimatedMonthlyPension": 1908.11,
                    "estimatedAnnualPension": 24805.44,
                    "basicPensionComponent": 5856.84,
                    "earningsRelatedComponent": 18948.6,
                    "minimumPensionApplied": false,
                    "qualifiesForPension": true,
                    "monthlyNet": 1824.5,
                    "weeklyGross": 477.03,
                    "ghsDeduction": 657.34,
                    "incomeTax": 429.62,
                    "yearsWorked": 22,
                    "totalUnits": 132
                  },
                  "series": [
                    {
                      "chartId": "unitsByYear",
                      "title": "Insurance units by year",
                      "xKey": "year",
                      "yKeys": [
                        "units"
                      ],
                      "points": [
                        {
                          "year": 2003,
                          "units": 5.2
                        }
                      ]
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error with fieldErrors and a hint"
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/tools/run_retirement_stress_test": {
      "post": {
        "operationId": "run_retirement_stress_test",
        "summary": "Runs a deterministic projection plus Monte Carlo simulation of a retirement savings plan to estimate the probability of not running out of money.",
        "description": "Use for 'will my savings last' or portfolio-longevity questions. Supports optional pension income, spending smile, and medical shock modelling.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "currentAge": {
                    "type": "integer",
                    "minimum": 18,
                    "description": "Age today."
                  },
                  "retirementAge": {
                    "type": "integer",
                    "minimum": 18,
                    "description": "Planned retirement age."
                  },
                  "endAge": {
                    "type": "integer",
                    "description": "Planning horizon age (default 90)."
                  },
                  "currentSavings": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Current investable savings balance in EUR."
                  },
                  "monthlyContribution": {
                    "type": "number",
                    "description": "Monthly contribution until retirement in EUR."
                  },
                  "expectedAnnualReturn": {
                    "type": "number",
                    "description": "Percentage value (e.g. 2.5 for 2.5%)."
                  },
                  "expectedAnnualReturnRetirement": {
                    "type": "number",
                    "description": "Percentage value (e.g. 2.5 for 2.5%)."
                  },
                  "monthlyDrawdown": {
                    "type": "number",
                    "description": "Planned monthly withdrawal in retirement in EUR."
                  },
                  "inflationRate": {
                    "type": "number",
                    "description": "Percentage value (e.g. 2.5 for 2.5%)."
                  },
                  "statePension": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Expected monthly state pension in EUR."
                  },
                  "simulations": {
                    "type": "integer",
                    "minimum": 100,
                    "maximum": 5000,
                    "description": "Monte Carlo runs (default 1000)."
                  }
                },
                "required": [
                  "currentAge",
                  "retirementAge",
                  "currentSavings",
                  "monthlyContribution",
                  "monthlyDrawdown"
                ]
              },
              "example": {
                "currentAge": 40,
                "retirementAge": 65,
                "endAge": 90,
                "currentSavings": 80000,
                "monthlyContribution": 500,
                "expectedAnnualReturn": 6,
                "expectedAnnualReturnRetirement": 4,
                "monthlyDrawdown": 2000,
                "inflationRate": 2.5,
                "statePension": 900
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                },
                "example": {
                  "content": [
                    {
                      "type": "text",
                      "text": "This plan has an 87% probability of lasting to age 90 without depleting savings."
                    }
                  ],
                  "structuredContent": {
                    "successProbability": 87.4,
                    "medianDepletionAge": null,
                    "deterministicFinalBalance": 142300.5,
                    "worstCase10thPercentileBalance": -18500
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error with fieldErrors and a hint"
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/tools/calculate_cyprus_unemployment_benefit": {
      "post": {
        "operationId": "calculate_cyprus_unemployment_benefit",
        "summary": "Calculates Cyprus unemployment benefit entitlement (weekly/monthly amount and duration) from recent insurable earnings and household circumstances.",
        "description": "Use for redundancy or job-loss income support questions in Cyprus.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "applicationDate": {
                    "type": "string",
                    "description": "Claim date as YYYY-MM-DD."
                  },
                  "annualGrossEarnings": {
                    "type": "number",
                    "minimum": 0,
                    "description": "Gross insurable earnings for the relevant contribution year in EUR."
                  },
                  "dependentSpouse": {
                    "type": "boolean",
                    "description": "Has a dependent spouse not in paid work."
                  },
                  "dependentChildren": {
                    "type": "integer",
                    "minimum": 0,
                    "description": "Number of dependent children (capped at 2)."
                  }
                },
                "required": [
                  "applicationDate",
                  "annualGrossEarnings",
                  "dependentSpouse",
                  "dependentChildren"
                ]
              },
              "example": {
                "applicationDate": "2026-01-15",
                "annualGrossEarnings": 32240,
                "dependentSpouse": true,
                "dependentChildren": 2
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                },
                "example": {
                  "content": [
                    {
                      "type": "text",
                      "text": "Estimated unemployment benefit is €372/week for up to 156 weeks, including a dependent supplement."
                    }
                  ],
                  "structuredContent": {
                    "weeklyBenefit": 372,
                    "monthlyBenefit": 1612.8,
                    "maxEntitlementWeeks": 156,
                    "dependentSupplement": 62,
                    "eligible": true
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error with fieldErrors and a hint"
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/tools/get_pension_reference_data": {
      "post": {
        "operationId": "get_pension_reference_data",
        "summary": "Returns official Cyprus Social Insurance reference tables for a given year.",
        "description": "Use to ground pension/retirement calculations in the correct year's statutory figures, or to answer factual lookup questions.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "year": {
                    "type": "integer",
                    "minimum": 1981,
                    "description": "Reference year."
                  }
                },
                "required": [
                  "year"
                ]
              },
              "example": {
                "year": 2026
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                },
                "example": {
                  "content": [
                    {
                      "type": "text",
                      "text": "2026 Cyprus Social Insurance reference: weekly BIE €220.76, annual ceiling €68,904."
                    }
                  ],
                  "structuredContent": {
                    "weeklyBasicInsurableEarnings": 220.76,
                    "annualBasicInsurableEarnings": 11480,
                    "annualMaxInsurableEarnings": 68904,
                    "maxUnitsPerYear": 6,
                    "statutoryPensionAge": 65,
                    "minimumContributionYears": 15
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error with fieldErrors and a hint"
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/tools/parse_pension_statement": {
      "post": {
        "operationId": "parse_pension_statement",
        "summary": "Extracts structured contribution history from pasted Cyprus Social Insurance Services pension statement text.",
        "description": "Use to bootstrap calculate_cyprus_state_pension inputs from a real statement instead of manual entry.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "text": {
                    "type": "string",
                    "minLength": 1,
                    "description": "Pasted statement text."
                  }
                },
                "required": [
                  "text"
                ]
              },
              "example": {
                "text": "Year 2020 units 4.5\nYear 2021 units 5.2\n"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                },
                "example": {
                  "content": [
                    {
                      "type": "text",
                      "text": "Parsed 2 years of contributions totaling 9.7 insurance units."
                    }
                  ],
                  "structuredContent": {
                    "contributionYears": [
                      {
                        "year": 2020,
                        "units": 4.5
                      },
                      {
                        "year": 2021,
                        "units": 5.2
                      }
                    ],
                    "totalUnits": 9.7,
                    "totalContributionYears": 2,
                    "parseConfidence": 0.8
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error with fieldErrors and a hint"
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/tools/load_saved_calculation": {
      "post": {
        "operationId": "load_saved_calculation",
        "summary": "Loads one saved calculation belonging to the authenticated API key's user.",
        "description": "Use after list_saved_calculations to retrieve full details of a specific saved scenario. Locked saves return locked: true and no contents.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "calculationId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "ID returned by list_saved_calculations."
                  }
                },
                "required": [
                  "calculationId"
                ]
              },
              "example": {
                "calculationId": "c1a2b3c4-5678-90ab-cdef-1234567890ab"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                },
                "example": {
                  "content": [
                    {
                      "type": "text",
                      "text": "Loaded saved calculation 'Retire at 65 baseline' (state-pension)."
                    }
                  ],
                  "structuredContent": {
                    "id": "c1a2b3c4-5678-90ab-cdef-1234567890ab",
                    "name": "Retire at 65 baseline",
                    "calculationType": "state-pension",
                    "inputs": {
                      "mode": "quick",
                      "retirementAge": 65,
                      "yearsWorked": 22,
                      "totalInsuranceUnits": 132,
                      "yearlyUnits": []
                    },
                    "results": {
                      "monthlyGross": 1908.11,
                      "totalAnnualGross": 24805.44
                    },
                    "toolInput": {
                      "mode": "quick",
                      "retirementAge": 65,
                      "yearsWorked": 22,
                      "totalInsuranceUnits": 132,
                      "yearlyUnits": []
                    },
                    "createdAt": "2025-03-01T10:00:00Z",
                    "updatedAt": "2025-03-01T10:00:00Z"
                  },
                  "series": []
                }
              }
            }
          },
          "400": {
            "description": "Validation error with fieldErrors and a hint"
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        }
      }
    },
    "/saved-calculations": {
      "get": {
        "operationId": "list_saved_calculations",
        "summary": "List saved calculation metadata for the authenticated key",
        "parameters": [
          {
            "name": "types",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "recent",
                "oldest",
                "created_desc",
                "created_asc",
                "name_asc",
                "name_desc"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "maximum": 100
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list"
          },
          "401": {
            "description": "API key required"
          }
        }
      }
    }
  }
}
