{
  "openapi": "3.1.1",
  "info": {
    "title": "Household Chore Rotator API",
    "version": "1.0.0",
    "summary": "Fair chore rotation by effort and availability, with per-person totals and a calendar.",
    "description": "Every endpoint performs the same calculation as the human page and returns inputs, result, units, assumptions, sources, warnings and computedAt. MCP endpoint: /mcp."
  },
  "servers": [
    {
      "url": "https://householdchorerotator.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Fair chore rotation by effort and availability, with per-person totals and a calendar.",
        "description": "List your recurring chores (daily, weekly, every two weeks or monthly) with how long they take, and who lives with you and on which days they are available. The rotator builds a calendar for up to 12 weeks that balances everyone's minutes (optionally weighted, e.g. half for a child), rotates who does what, shows per-person totals and exports an .ics calendar file.\n\nMethodology:\n- Occurrences: daily chores happen every day; weekly ones once a week on their day; every-2-weeks ones in weeks 1, 3, 5 …; monthly ones every 4 weeks (13 times a year) so they stay on the same weekday. Weeks are counted from the start date.\n- Weekly-type chores without a fixed day are placed on the weekday with the least planned effort so far (that someone is available on), and keep that day.\n- Occurrences are assigned longest chore first (then by date); each goes to an available person with the lowest score = (minutes already assigned + this chore) ÷ capacity + a rotation term of ¼ × chore minutes × (how often this person already did this chore − the least anyone available did it). Ties go to the person listed first. This keeps everyone's effort proportional to their capacity and rotates the chores.\n- Target share = capacity ÷ sum of capacities. Availability limits can make a perfect balance impossible; the totals table shows the actual shares.\n- The .ics file has one all-day event per chore and day (RFC 5545: CRLF line endings, folded lines, stable UIDs derived from the inputs, DTSTAMP = time of calculation).",
        "tags": [
          "home-travel"
        ],
        "x-mcp-tool": "household_chore_rotator",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/HouseholdChoreRotatorInput"
              },
              "examples": {
                "example1": {
                  "summary": "Flat share of three, 4 weeks",
                  "value": {
                    "startDate": "2026-10-19",
                    "weeks": 4,
                    "chores": [
                      {
                        "name": "Dishes",
                        "frequency": "daily",
                        "minutes": 15,
                        "day": "any"
                      },
                      {
                        "name": "Vacuum living room",
                        "frequency": "weekly",
                        "minutes": 30,
                        "day": "sat"
                      },
                      {
                        "name": "Clean bathroom",
                        "frequency": "weekly",
                        "minutes": 45,
                        "day": "any"
                      },
                      {
                        "name": "Take out recycling",
                        "frequency": "biweekly",
                        "minutes": 10,
                        "day": "tue"
                      },
                      {
                        "name": "Defrost freezer",
                        "frequency": "monthly",
                        "minutes": 60,
                        "day": "sun"
                      }
                    ],
                    "people": [
                      {
                        "name": "Ana",
                        "days": ""
                      },
                      {
                        "name": "Ben",
                        "days": "Mon-Fri"
                      },
                      {
                        "name": "Chen",
                        "days": "Wed-Sun"
                      }
                    ]
                  }
                },
                "example2": {
                  "summary": "Family with a child at half capacity, 2 weeks",
                  "value": {
                    "startDate": "2026-11-02",
                    "weeks": 2,
                    "chores": [
                      {
                        "name": "Set the table",
                        "frequency": "daily",
                        "minutes": 5,
                        "day": "any"
                      },
                      {
                        "name": "Laundry",
                        "frequency": "weekly",
                        "minutes": 60,
                        "day": "sat"
                      },
                      {
                        "name": "Water plants",
                        "frequency": "weekly",
                        "minutes": 10,
                        "day": "wed"
                      }
                    ],
                    "people": [
                      {
                        "name": "Parent A",
                        "capacity": 1
                      },
                      {
                        "name": "Parent B",
                        "capacity": 1
                      },
                      {
                        "name": "Kid",
                        "capacity": 0.5,
                        "days": "Sat,Sun"
                      }
                    ]
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HouseholdChoreRotatorResult"
                }
              }
            }
          },
          "400": {
            "description": "Malformed JSON body.",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "422": {
            "description": "Invalid input (see errors[]).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          },
          "429": {
            "description": "Rate limit exceeded (see Retry-After).",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/Problem"
                }
              }
            }
          }
        }
      }
    },
    "/api/v1/tool": {
      "get": {
        "operationId": "getToolDefinition",
        "summary": "Inputs, output schema and examples for this tool",
        "responses": {
          "200": {
            "description": "Tool definition.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Problem": {
        "type": "object",
        "description": "RFC 9457 problem details. 422 responses include per-field `errors`.",
        "required": [
          "type",
          "title",
          "status",
          "detail"
        ],
        "properties": {
          "type": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "status": {
            "type": "integer"
          },
          "detail": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "field",
                "message"
              ],
              "properties": {
                "field": {
                  "type": "string"
                },
                "message": {
                  "type": "string"
                }
              }
            }
          }
        }
      },
      "HouseholdChoreRotatorInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "startDate": {
            "title": "Start date",
            "description": "Default: today. Weeks are counted from this day.",
            "type": "string",
            "format": "date"
          },
          "weeks": {
            "title": "Weeks to plan",
            "type": "integer",
            "minimum": 1,
            "maximum": 12,
            "default": 4
          },
          "chores": {
            "title": "Chores",
            "type": "array",
            "minItems": 1,
            "maxItems": 30,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "name": {
                  "title": "Chore",
                  "type": "string",
                  "maxLength": 60
                },
                "frequency": {
                  "title": "How often",
                  "type": "string",
                  "enum": [
                    "daily",
                    "weekly",
                    "biweekly",
                    "monthly"
                  ],
                  "default": "weekly"
                },
                "minutes": {
                  "title": "Effort",
                  "type": "number",
                  "minimum": 1,
                  "maximum": 600,
                  "default": 15,
                  "x-unit": "min"
                },
                "day": {
                  "title": "Day",
                  "type": "string",
                  "enum": [
                    "any",
                    "mon",
                    "tue",
                    "wed",
                    "thu",
                    "fri",
                    "sat",
                    "sun"
                  ],
                  "default": "any"
                }
              },
              "required": [
                "name"
              ]
            }
          },
          "people": {
            "title": "People",
            "description": "Available days like Mon-Fri or Sat,Sun (empty = every day). Capacity: 1 = full share, 0.5 = half share (e.g. a child).",
            "type": "array",
            "minItems": 1,
            "maxItems": 12,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "name": {
                  "title": "Name",
                  "type": "string",
                  "maxLength": 40
                },
                "days": {
                  "title": "Available days",
                  "type": "string",
                  "maxLength": 60
                },
                "capacity": {
                  "title": "Capacity",
                  "type": "number",
                  "minimum": 0.1,
                  "maximum": 3,
                  "default": 1
                }
              },
              "required": [
                "name"
              ]
            }
          }
        },
        "required": [
          "chores",
          "people"
        ]
      },
      "HouseholdChoreRotatorResult": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "schemaVersion",
          "tool",
          "computedAt",
          "inputs",
          "summary",
          "result",
          "units",
          "assumptions",
          "sources",
          "warnings",
          "presentation",
          "links"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string",
            "const": "1.0"
          },
          "tool": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "id",
              "name",
              "version"
            ],
            "properties": {
              "id": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "version": {
                "type": "string"
              }
            }
          },
          "computedAt": {
            "type": "string",
            "format": "date-time"
          },
          "inputs": {
            "type": "object",
            "description": "Normalised inputs actually used, including applied defaults."
          },
          "summary": {
            "type": "string"
          },
          "result": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "startDate",
              "endDate",
              "weeks",
              "assignments",
              "totals",
              "unassigned",
              "ics"
            ],
            "properties": {
              "startDate": {
                "type": "string",
                "format": "date"
              },
              "endDate": {
                "type": "string",
                "format": "date"
              },
              "weeks": {
                "type": "integer"
              },
              "assignments": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "date",
                    "weekday",
                    "week",
                    "chore",
                    "person",
                    "minutes"
                  ],
                  "properties": {
                    "date": {
                      "type": "string"
                    },
                    "weekday": {
                      "type": "string"
                    },
                    "week": {
                      "type": "integer"
                    },
                    "chore": {
                      "type": "string"
                    },
                    "person": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "minutes": {
                      "type": "number"
                    }
                  }
                }
              },
              "totals": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "person",
                    "capacity",
                    "tasks",
                    "minutes",
                    "sharePercent",
                    "targetSharePercent",
                    "minutesPerWeek"
                  ],
                  "properties": {
                    "person": {
                      "type": "string"
                    },
                    "capacity": {
                      "type": "number"
                    },
                    "tasks": {
                      "type": "integer"
                    },
                    "minutes": {
                      "type": "number"
                    },
                    "sharePercent": {
                      "type": "number"
                    },
                    "targetSharePercent": {
                      "type": "number"
                    },
                    "minutesPerWeek": {
                      "type": "array",
                      "items": {
                        "type": "number"
                      }
                    }
                  }
                }
              },
              "unassigned": {
                "type": "integer",
                "description": "Occurrences on days when nobody is available."
              },
              "ics": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "filename",
                  "events"
                ],
                "properties": {
                  "filename": {
                    "type": "string"
                  },
                  "events": {
                    "type": "integer"
                  }
                }
              }
            }
          },
          "units": {
            "type": "object",
            "additionalProperties": {
              "type": "string"
            }
          },
          "assumptions": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "sources": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": false,
              "required": [
                "title"
              ],
              "properties": {
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "publisher": {
                  "type": "string"
                },
                "retrievedAt": {
                  "type": "string"
                },
                "note": {
                  "type": "string"
                }
              }
            }
          },
          "warnings": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "presentation": {
            "type": "array",
            "items": {
              "type": "object"
            },
            "description": "Display blocks used by the human page (same data)."
          },
          "links": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "human",
              "api",
              "openapi",
              "methodology"
            ],
            "properties": {
              "human": {
                "type": "string",
                "format": "uri"
              },
              "api": {
                "type": "string",
                "format": "uri"
              },
              "openapi": {
                "type": "string",
                "format": "uri"
              },
              "methodology": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      }
    }
  }
}