{
  "openapi": "3.1.1",
  "info": {
    "title": "RuleDate Deadline Calculator API",
    "version": "1.0.0",
    "summary": "Business-day and deadline maths with public holidays and a step-by-step rule trace.",
    "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://ruledate.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Business-day and deadline maths with public holidays and a step-by-step rule trace.",
        "description": "Chain date operations (add business days, add months with clamping, end of month, roll to next business day) on a start date. RuleDate uses public holidays for 16 countries and their subdivisions (2024–2030) and shows every skipped date with its reason, so the result can be checked rather than trusted.\n\nMethodology:\n- A business day is a day that is not a selected weekend day, not a public holiday of the chosen country (nationwide, or of the chosen subdivision) and not an extra closure date. Only Nager.Date entries of type \"Public\" count; bank, school, optional and observance days are ignored.\n- Add business days counts business days after the start date (the start date itself is not counted); negative amounts count backwards. Every non-business day passed over is listed with all its reasons.\n- Add calendar days / weeks ignore holidays. Add months keeps the day of month; if it does not exist, \"clamp\" uses the month’s last day and \"overflow\" rolls into the next month.\n- End of month moves to the last calendar day of the month that is `amount` months after the current date. Next / previous business day roll only if the current date is not a business day (following / preceding convention).\n- Optional final rule modelled on § 193 BGB: if the result falls on a Saturday, Sunday or a public holiday at the chosen place, it moves to the next day that is none of these (extra closures and custom weekends are ignored for this rule).\n- Holiday data covers 2024–2030; dates outside that range are checked for weekends and closures only and trigger a warning.\n\nNot legal advice. Statutory and contractual deadlines have their own rules (start-day exclusion, service dates, court holidays, local holidays); verify critical deadlines with a qualified professional.",
        "tags": [
          "developer"
        ],
        "x-mcp-tool": "ruledate",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RuledateInput"
              },
              "examples": {
                "example1": {
                  "summary": "10 business days from 25 Sep 2026 in Bavaria",
                  "value": {
                    "startDate": "2026-09-25",
                    "operations": [
                      {
                        "op": "add-business-days",
                        "amount": 10
                      }
                    ],
                    "country": "DE",
                    "subdivision": "DE-BY"
                  }
                },
                "example2": {
                  "summary": "5 business days over Christmas in England, then end of month",
                  "value": {
                    "startDate": "2026-12-21",
                    "operations": [
                      {
                        "op": "add-business-days",
                        "amount": 5
                      },
                      {
                        "op": "end-of-month",
                        "amount": 0
                      },
                      {
                        "op": "previous-business-day"
                      }
                    ],
                    "country": "GB",
                    "subdivision": "GB-ENG"
                  }
                },
                "example3": {
                  "summary": "31 Aug + 1 month (clamped) + 3 days, § 193 BGB adjustment",
                  "value": {
                    "startDate": "2026-08-31",
                    "operations": [
                      {
                        "op": "add-months",
                        "amount": 1
                      },
                      {
                        "op": "add-calendar-days",
                        "amount": 3
                      }
                    ],
                    "country": "DE",
                    "finalRule": "bgb193"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RuledateResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "RuledateInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "startDate": {
            "title": "Start date",
            "type": "string",
            "format": "date"
          },
          "operations": {
            "title": "Operations (applied in order)",
            "type": "array",
            "minItems": 1,
            "maxItems": 20,
            "items": {
              "type": "object",
              "additionalProperties": false,
              "properties": {
                "op": {
                  "title": "Operation",
                  "type": "string",
                  "enum": [
                    "add-business-days",
                    "add-calendar-days",
                    "add-weeks",
                    "add-months",
                    "end-of-month",
                    "next-business-day",
                    "previous-business-day"
                  ]
                },
                "amount": {
                  "title": "Amount",
                  "description": "Negative values go backwards.",
                  "type": "integer",
                  "minimum": -3650,
                  "maximum": 3650,
                  "default": 0
                }
              },
              "required": [
                "op"
              ]
            }
          },
          "country": {
            "title": "Holiday calendar",
            "type": "string",
            "enum": [
              "none",
              "DE",
              "AT",
              "CH",
              "US",
              "GB",
              "FR",
              "NL",
              "BE",
              "ES",
              "IT",
              "PL",
              "SE",
              "DK",
              "IE",
              "CA",
              "AU"
            ],
            "default": "DE"
          },
          "subdivision": {
            "title": "Subdivision (optional)",
            "description": "ISO 3166-2 code, e.g. DE-BY (Bavaria), CH-ZH, US-CA. Without it only nationwide holidays count.",
            "type": "string",
            "maxLength": 10
          },
          "weekendDays": {
            "title": "Weekend days",
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "sun",
                "mon",
                "tue",
                "wed",
                "thu",
                "fri",
                "sat"
              ]
            },
            "default": [
              "sat",
              "sun"
            ]
          },
          "closures": {
            "title": "Extra closure dates",
            "description": "One YYYY-MM-DD per line (company holidays, bridge days).",
            "type": "array",
            "items": {
              "type": "string"
            },
            "maxItems": 366
          },
          "monthEndRule": {
            "title": "Month arithmetic",
            "type": "string",
            "enum": [
              "clamp",
              "overflow"
            ],
            "default": "clamp"
          },
          "finalRule": {
            "title": "Final adjustment",
            "type": "string",
            "enum": [
              "none",
              "bgb193"
            ],
            "default": "none"
          }
        },
        "required": [
          "startDate",
          "operations"
        ]
      },
      "RuledateResult": {
        "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",
              "finalDate",
              "finalWeekday",
              "country",
              "subdivision",
              "weekendDays",
              "steps",
              "holidaysApplied",
              "dataRange",
              "outsideDataRange"
            ],
            "properties": {
              "startDate": {
                "type": "string",
                "format": "date"
              },
              "finalDate": {
                "type": "string",
                "format": "date"
              },
              "finalWeekday": {
                "type": "string"
              },
              "country": {
                "type": "string"
              },
              "subdivision": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "weekendDays": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "steps": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "step",
                    "operation",
                    "amount",
                    "from",
                    "to",
                    "skipped",
                    "note"
                  ],
                  "properties": {
                    "step": {
                      "type": "integer",
                      "minimum": 1
                    },
                    "operation": {
                      "type": "string"
                    },
                    "amount": {
                      "type": "integer"
                    },
                    "from": {
                      "type": "string",
                      "format": "date"
                    },
                    "to": {
                      "type": "string",
                      "format": "date"
                    },
                    "note": {
                      "type": "string"
                    },
                    "skipped": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "date",
                          "weekday",
                          "reasons"
                        ],
                        "properties": {
                          "date": {
                            "type": "string",
                            "format": "date"
                          },
                          "weekday": {
                            "type": "string"
                          },
                          "reasons": {
                            "type": "array",
                            "items": {
                              "type": "string"
                            }
                          }
                        }
                      }
                    }
                  }
                }
              },
              "holidaysApplied": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "date",
                    "name",
                    "localName",
                    "scope"
                  ],
                  "properties": {
                    "date": {
                      "type": "string",
                      "format": "date"
                    },
                    "name": {
                      "type": "string"
                    },
                    "localName": {
                      "type": "string"
                    },
                    "scope": {
                      "type": "string"
                    }
                  }
                }
              },
              "dataRange": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "firstYear",
                  "lastYear"
                ],
                "properties": {
                  "firstYear": {
                    "type": "integer"
                  },
                  "lastYear": {
                    "type": "integer"
                  }
                }
              },
              "outsideDataRange": {
                "type": "boolean"
              }
            }
          },
          "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"
              }
            }
          }
        }
      }
    }
  }
}