{
  "openapi": "3.1.0",
  "info": {
    "title": "PoliErgaleio Saved Calculations",
    "version": "5.0.0",
    "description": "List, load, save, update, delete and compare the signed-in user's own PoliErgaleio calculations. Requires signing in to PoliErgaleio. Password-protected saves return locked: true and must be opened on poliergaleio.com."
  },
  "servers": [
    {
      "url": "https://gpkpjfdlbsuyevfdsnbq.supabase.co/functions/v1/public-api"
    }
  ],
  "components": {
    "securitySchemes": {
      "oauth": {
        "type": "oauth2",
        "flows": {
          "authorizationCode": {
            "authorizationUrl": "https://gpkpjfdlbsuyevfdsnbq.supabase.co/auth/v1/oauth/authorize",
            "tokenUrl": "https://gpkpjfdlbsuyevfdsnbq.supabase.co/auth/v1/oauth/token",
            "scopes": {}
          }
        }
      }
    },
    "schemas": {
      "ToolResponse": {
        "type": "object",
        "properties": {
          "content": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string"
                },
                "text": {
                  "type": "string"
                }
              }
            }
          },
          "structuredContent": {
            "type": "object",
            "properties": {
              "assumptions": {
                "type": "array",
                "description": "Defaults and exclusions applied by the calculation. This does not verify where input facts came from.",
                "items": {
                  "type": "object",
                  "properties": {
                    "field": {
                      "type": "string"
                    },
                    "value": {},
                    "reason": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "field",
                    "reason"
                  ],
                  "additionalProperties": true
                }
              }
            },
            "additionalProperties": true
          },
          "series": {
            "type": "array",
            "items": {
              "type": "object"
            }
          },
          "requestId": {
            "type": "string"
          },
          "guestId": {
            "type": [
              "string",
              "null"
            ]
          }
        }
      },
      "ValidationError": {
        "type": "object",
        "properties": {
          "error": {
            "type": "string",
            "description": "Validation failure summary."
          },
          "fieldErrors": {
            "type": "array",
            "items": {
              "type": "string"
            },
            "description": "Missing, invalid or conditionally required input facts."
          },
          "hint": {
            "type": "string",
            "description": "Actionable correction guidance."
          },
          "requestId": {
            "type": "string",
            "description": "Request correlation id, also returned in X-Request-Id."
          }
        },
        "required": [
          "error"
        ],
        "additionalProperties": true
      }
    }
  },
  "security": [
    {
      "oauth": []
    }
  ],
  "paths": {
    "/tools/list_saved_calculations": {
      "post": {
        "operationId": "list_saved_calculations",
        "summary": "Lists metadata of an authenticated user's saved calculations by calculator type.",
        "description": "Use so an agent can help a user find a previously saved scenario before loading it. Never returns encrypted contents. Sign in to PoliErgaleio with OAuth to access the user’s own saved data.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "calculationType": {
                    "type": "string",
                    "title": "Calculator type",
                    "description": "Omit to list saved calculations across every calculator type.",
                    "enum": [
                      "income-tax",
                      "state-pension",
                      "retirement-planner",
                      "unemployment-benefit",
                      "capital-gains",
                      "investment-comparison"
                    ]
                  },
                  "calculationTypes": {
                    "type": "array",
                    "title": "Calculator types filter",
                    "description": "Filter by several calculator types at once. Takes precedence over calculationType.",
                    "items": {
                      "type": "string",
                      "enum": [
                        "income-tax",
                        "state-pension",
                        "retirement-planner",
                        "unemployment-benefit",
                        "capital-gains",
                        "investment-comparison"
                      ]
                    }
                  },
                  "sort": {
                    "type": "string",
                    "title": "Sort order",
                    "description": "recent = most recently updated first (default), oldest = least recently updated, created_desc/created_asc by creation date, name_asc/name_desc alphabetical. Cursor paging only applies to 'recent'.",
                    "enum": [
                      "recent",
                      "oldest",
                      "created_desc",
                      "created_asc",
                      "name_asc",
                      "name_desc"
                    ],
                    "default": "recent"
                  },
                  "limit": {
                    "type": "integer",
                    "title": "Page size",
                    "minimum": 1,
                    "maximum": 100,
                    "default": 20
                  },
                  "offset": {
                    "type": "integer",
                    "title": "Offset",
                    "minimum": 0,
                    "default": 0,
                    "description": "Rows to skip. Use with limit for page-number paging."
                  },
                  "cursor": {
                    "type": "string",
                    "title": "Cursor",
                    "description": "nextCursor from the previous page, compound <updatedAt>|<id> with an id tie-break so rows sharing updatedAt never skip. Preferred over offset for stable paging (sort: recent only)."
                  }
                },
                "additionalProperties": false,
                "required": []
              },
              "example": {
                "calculationTypes": [
                  "state-pension",
                  "retirement-planner"
                ],
                "sort": "recent",
                "limit": 10,
                "offset": 0
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                },
                "example": {
                  "content": [
                    {
                      "type": "text",
                      "text": "Showing 1 of 3 saved state-pension calculations."
                    }
                  ],
                  "structuredContent": {
                    "calculations": [
                      {
                        "id": "c1a2b3c4-5678-90ab-cdef-1234567890ab",
                        "name": "Retire at 65 baseline",
                        "calculationType": "state-pension",
                        "locked": false,
                        "createdAt": "2025-03-01T10:00:00Z",
                        "updatedAt": "2025-03-01T10:00:00Z"
                      }
                    ],
                    "totalCount": 3,
                    "limit": 10,
                    "offset": 0,
                    "hasMore": false,
                    "nextCursor": null,
                    "sort": "recent",
                    "calculationTypes": [
                      "state-pension"
                    ]
                  },
                  "requestId": "9f1c2b7a-0d84-4d1e-a0c0-8f0f2b6a1c33",
                  "guestId": null
                }
              }
            }
          },
          "400": {
            "description": "Validation error. Use fieldErrors and hint to ask for corrected inputs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth": []
          }
        ]
      }
    },
    "/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. Sign in to PoliErgaleio with OAuth to access the user’s own saved data.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "calculationId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "ID returned by list_saved_calculations."
                  }
                },
                "additionalProperties": false,
                "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": []
                    },
                    "result": {
                      "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. Use fieldErrors and hint to ask for corrected inputs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth": []
          }
        ]
      }
    },
    "/tools/save_calculation": {
      "post": {
        "operationId": "save_calculation",
        "summary": "Saves a calculator scenario to the authenticated user's stored history.",
        "description": "Use when the user asks to save, keep or remember a scenario. Stores the inputs unencrypted (with server-computed results) so list/load can return them later. Sign in to PoliErgaleio with OAuth to access the user’s own saved data.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "calculationType": {
                    "type": "string",
                    "description": "Calculator type to save under.",
                    "enum": [
                      "income-tax",
                      "state-pension",
                      "retirement-planner",
                      "unemployment-benefit",
                      "capital-gains",
                      "investment-comparison"
                    ]
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "Display name for the saved scenario."
                  },
                  "inputs": {
                    "type": "object",
                    "description": "Tool-style inputs for the matching calculator (same shape its calculator tool accepts).",
                    "additionalProperties": true
                  }
                },
                "additionalProperties": false,
                "required": [
                  "calculationType",
                  "inputs"
                ]
              },
              "example": {
                "calculationType": "income-tax",
                "name": "2026 baseline",
                "inputs": {
                  "salaryIncome": 45000,
                  "legislationVersion": "2026",
                  "employmentType": "private"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                },
                "example": {
                  "content": [
                    {
                      "type": "text",
                      "text": "Saved \"2026 baseline\" (income-tax)."
                    }
                  ],
                  "structuredContent": {
                    "id": "c1a2b3c4-5678-90ab-cdef-1234567890ab",
                    "name": "2026 baseline",
                    "calculationType": "income-tax",
                    "locked": false,
                    "createdAt": "2025-03-01T10:00:00Z",
                    "updatedAt": "2025-03-01T10:00:00Z"
                  },
                  "series": []
                }
              }
            }
          },
          "400": {
            "description": "Validation error. Use fieldErrors and hint to ask for corrected inputs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth": []
          }
        ]
      }
    },
    "/tools/update_calculation": {
      "post": {
        "operationId": "update_calculation",
        "summary": "Renames a saved calculation and/or replaces its inputs (recomputing results).",
        "description": "Use when the user asks to rename a save or re-run it with different inputs. Encrypted saves stay locked. Sign in to PoliErgaleio with OAuth to access the user’s own saved data.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "calculationId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "ID returned by list_saved_calculations."
                  },
                  "name": {
                    "type": "string",
                    "maxLength": 200,
                    "description": "New display name."
                  },
                  "inputs": {
                    "type": "object",
                    "description": "Replacement tool-style inputs; results are recomputed server-side.",
                    "additionalProperties": true
                  }
                },
                "additionalProperties": false,
                "required": [
                  "calculationId"
                ]
              },
              "example": {
                "calculationId": "c1a2b3c4-5678-90ab-cdef-1234567890ab",
                "name": "2026 baseline v2"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                },
                "example": {
                  "content": [
                    {
                      "type": "text",
                      "text": "Updated saved calculation \"2026 baseline v2\" (income-tax)."
                    }
                  ],
                  "structuredContent": {
                    "id": "c1a2b3c4-5678-90ab-cdef-1234567890ab",
                    "name": "2026 baseline v2",
                    "calculationType": "income-tax",
                    "updatedAt": "2025-03-02T10:00:00Z"
                  },
                  "series": []
                }
              }
            }
          },
          "400": {
            "description": "Validation error. Use fieldErrors and hint to ask for corrected inputs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth": []
          }
        ]
      }
    },
    "/tools/delete_saved_calculation": {
      "post": {
        "operationId": "delete_saved_calculation",
        "summary": "Deletes one saved calculation belonging to the authenticated API key's user.",
        "description": "Use when the user asks to delete or forget a saved scenario. Works on encrypted saves too. Sign in to PoliErgaleio with OAuth to access the user’s own saved data.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "calculationId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "ID returned by list_saved_calculations."
                  }
                },
                "additionalProperties": false,
                "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": "Deleted saved calculation \"2026 baseline\" (income-tax)."
                    }
                  ],
                  "structuredContent": {
                    "id": "c1a2b3c4-5678-90ab-cdef-1234567890ab",
                    "name": "2026 baseline",
                    "calculationType": "income-tax",
                    "deleted": true
                  },
                  "series": []
                }
              }
            }
          },
          "400": {
            "description": "Validation error. Use fieldErrors and hint to ask for corrected inputs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth": []
          }
        ]
      }
    },
    "/tools/compare_saved_calculations": {
      "post": {
        "operationId": "compare_saved_calculations",
        "summary": "Diffs two saved calculations (inputs and results) field by field.",
        "description": "Use for 'compare my mortgage before/after' style questions instead of reconstructing the diff from two loads. Encrypted sides report locked instead of contents. Sign in to PoliErgaleio with OAuth to access the user’s own saved data.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "properties": {
                  "calculationIdA": {
                    "type": "string",
                    "format": "uuid",
                    "description": "First saved calculation id."
                  },
                  "calculationIdB": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Second saved calculation id."
                  }
                },
                "additionalProperties": false,
                "required": [
                  "calculationIdA",
                  "calculationIdB"
                ]
              },
              "example": {
                "calculationIdA": "c1a2b3c4-5678-90ab-cdef-1234567890ab",
                "calculationIdB": "d2b3c4d5-6789-01bc-defa-2345678901bc"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ToolResponse"
                },
                "example": {
                  "content": [
                    {
                      "type": "text",
                      "text": "Compared \"2026 baseline\" (A) with \"2026 + raise\" (B): 2 differing fields."
                    }
                  ],
                  "structuredContent": {
                    "calculationA": {
                      "id": "c1a2b3c4-5678-90ab-cdef-1234567890ab",
                      "name": "2026 baseline",
                      "calculationType": "income-tax"
                    },
                    "calculationB": {
                      "id": "d2b3c4d5-6789-01bc-defa-2345678901bc",
                      "name": "2026 + raise",
                      "calculationType": "income-tax"
                    },
                    "sameType": true,
                    "totalDifferences": 2,
                    "differences": [
                      {
                        "scope": "inputs",
                        "field": "salaryIncome",
                        "valueA": 45000,
                        "valueB": 50000
                      },
                      {
                        "scope": "results",
                        "field": "netSalary",
                        "valueA": 35885.63,
                        "valueB": 39210.4
                      }
                    ]
                  },
                  "series": [
                    {
                      "chartId": "numericDeltas",
                      "title": "Numeric deltas (B − A)",
                      "xKey": "field",
                      "yKeys": [
                        "delta"
                      ],
                      "points": []
                    }
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Validation error. Use fieldErrors and hint to ask for corrected inputs.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ValidationError"
                }
              }
            }
          },
          "401": {
            "description": "Invalid API key"
          },
          "429": {
            "description": "Rate limit exceeded"
          }
        },
        "security": [
          {
            "oauth": []
          }
        ]
      }
    }
  }
}
