{
  "openapi": "3.1.0",
  "info": {
    "title": "whathappen.today API",
    "version": "1.0.0",
    "description": "Today's date in any IANA time zone, calendar facts (ISO week, day of year), moon phase and public holidays in 20 countries (2020–2030). Free, no key, CORS enabled, 60 requests a minute per IP. Holiday dates are for reference; each answer names the official source.",
    "contact": {
      "email": "hello@whathappen.today",
      "url": "https://whathappen.today/contact/"
    }
  },
  "servers": [
    {
      "url": "https://whathappen.today"
    }
  ],
  "paths": {
    "/api/today": {
      "get": {
        "operationId": "today",
        "summary": "Today's date, week, moon and holiday status",
        "parameters": [
          {
            "name": "tz",
            "in": "query",
            "required": false,
            "description": "IANA time zone, e.g. America/New_York. Defaults to the country's main zone, else UTC.",
            "schema": {
              "type": "string",
              "example": "Asia/Tokyo"
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "ISO 3166-1 alpha-2 code of a supported country.",
            "schema": {
              "type": "string",
              "enum": [
                "US",
                "GB",
                "CA",
                "AU",
                "IN",
                "IE",
                "NZ",
                "ZA",
                "SG",
                "PH",
                "CN",
                "DE",
                "JP",
                "FR",
                "IT",
                "BR",
                "KR",
                "MX",
                "ES",
                "AE"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Today",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Day"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (60 requests a minute per IP)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/date": {
      "get": {
        "operationId": "dateInfo",
        "summary": "Facts about any date",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "required": true,
            "description": "YYYY-MM-DD",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "tz",
            "in": "query",
            "required": false,
            "description": "IANA time zone, e.g. America/New_York. Defaults to the country's main zone, else UTC.",
            "schema": {
              "type": "string",
              "example": "Asia/Tokyo"
            }
          },
          {
            "name": "country",
            "in": "query",
            "required": false,
            "description": "ISO 3166-1 alpha-2 code of a supported country.",
            "schema": {
              "type": "string",
              "enum": [
                "US",
                "GB",
                "CA",
                "AU",
                "IN",
                "IE",
                "NZ",
                "ZA",
                "SG",
                "PH",
                "CN",
                "DE",
                "JP",
                "FR",
                "IT",
                "BR",
                "KR",
                "MX",
                "ES",
                "AE"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The date",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Day"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (60 requests a minute per IP)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/holidays": {
      "get": {
        "operationId": "holidays",
        "summary": "Public holidays of a year",
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": true,
            "description": "ISO 3166-1 alpha-2 code of a supported country.",
            "schema": {
              "type": "string",
              "enum": [
                "US",
                "GB",
                "CA",
                "AU",
                "IN",
                "IE",
                "NZ",
                "ZA",
                "SG",
                "PH",
                "CN",
                "DE",
                "JP",
                "FR",
                "IT",
                "BR",
                "KR",
                "MX",
                "ES",
                "AE"
              ]
            }
          },
          {
            "name": "year",
            "in": "query",
            "required": false,
            "description": "Four-digit year, 2020–2030 (default: current year)",
            "schema": {
              "type": "integer",
              "minimum": 2020,
              "maximum": 2030
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Holiday list",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HolidayYear"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (60 requests a minute per IP)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/next-holiday": {
      "get": {
        "operationId": "nextHoliday",
        "summary": "Next public holidays after today",
        "parameters": [
          {
            "name": "country",
            "in": "query",
            "required": true,
            "description": "ISO 3166-1 alpha-2 code of a supported country.",
            "schema": {
              "type": "string",
              "enum": [
                "US",
                "GB",
                "CA",
                "AU",
                "IN",
                "IE",
                "NZ",
                "ZA",
                "SG",
                "PH",
                "CN",
                "DE",
                "JP",
                "FR",
                "IT",
                "BR",
                "KR",
                "MX",
                "ES",
                "AE"
              ]
            }
          },
          {
            "name": "tz",
            "in": "query",
            "required": false,
            "description": "IANA time zone, e.g. America/New_York. Defaults to the country's main zone, else UTC.",
            "schema": {
              "type": "string",
              "example": "Asia/Tokyo"
            }
          },
          {
            "name": "count",
            "in": "query",
            "required": false,
            "description": "How many holiday dates (1–20, default 1)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Upcoming holidays",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/NextHolidays"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (60 requests a minute per IP)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    },
    "/api/countries": {
      "get": {
        "operationId": "countries",
        "summary": "Supported countries",
        "responses": {
          "200": {
            "description": "Country list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/api/on-this-day": {
      "get": {
        "operationId": "onThisDay",
        "summary": "Events, births, deaths and observances for a date (Wikipedia, CC BY-SA 4.0)",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "required": false,
            "description": "MM-DD or YYYY-MM-DD (default: today in tz, or UTC)",
            "schema": {
              "type": "string",
              "example": "10-09"
            }
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Which list",
            "schema": {
              "type": "string",
              "enum": [
                "all",
                "events",
                "births",
                "deaths",
                "observances"
              ]
            }
          },
          {
            "name": "limit",
            "in": "query",
            "required": false,
            "description": "Items per list (1–30, default 30)",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 30
            }
          },
          {
            "name": "tz",
            "in": "query",
            "required": false,
            "description": "IANA time zone, e.g. America/New_York. Defaults to the country's main zone, else UTC.",
            "schema": {
              "type": "string",
              "example": "Asia/Tokyo"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "History lists with the attribution to display",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Invalid parameter",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          },
          "429": {
            "description": "Rate limited (60 requests a minute per IP)",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Error"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error",
          "message"
        ],
        "properties": {
          "error": {
            "type": "string"
          },
          "message": {
            "type": "string"
          },
          "docs": {
            "type": "string"
          }
        }
      },
      "Holiday": {
        "type": "object",
        "required": [
          "date",
          "name",
          "weekday",
          "observed",
          "estimated"
        ],
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "name": {
            "type": "string"
          },
          "weekday": {
            "type": "string"
          },
          "observed": {
            "type": "boolean",
            "description": "Substitute day off for a holiday on a weekend or clashing with another"
          },
          "estimated": {
            "type": "boolean",
            "description": "Depends on a moon sighting; may move by a day or two"
          },
          "daysUntil": {
            "type": "integer"
          }
        }
      },
      "CountryDay": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "isPublicHoliday": {
            "type": "boolean"
          },
          "holidays": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Holiday"
            }
          },
          "isMakeupWorkday": {
            "type": "boolean",
            "description": "China: a weekend day worked under the yearly arrangement"
          },
          "isWorkingDay": {
            "type": "boolean"
          },
          "nextHoliday": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/Holiday"
              },
              {
                "type": "null"
              }
            ]
          },
          "provisional": {
            "type": "boolean"
          },
          "scope": {
            "type": "string"
          },
          "official": {
            "type": "string",
            "format": "uri"
          }
        }
      },
      "Day": {
        "type": "object",
        "properties": {
          "date": {
            "type": "string",
            "format": "date"
          },
          "weekday": {
            "type": "string"
          },
          "isoWeekday": {
            "type": "integer"
          },
          "isoWeek": {
            "type": "integer"
          },
          "isoWeekYear": {
            "type": "integer"
          },
          "isoWeekLabel": {
            "type": "string"
          },
          "dayOfYear": {
            "type": "integer"
          },
          "daysInYear": {
            "type": "integer"
          },
          "daysLeftInYear": {
            "type": "integer"
          },
          "isLeapYear": {
            "type": "boolean"
          },
          "quarter": {
            "type": "integer"
          },
          "isWeekend": {
            "type": "boolean"
          },
          "timezone": {
            "type": "string"
          },
          "timezoneSource": {
            "type": "string",
            "enum": [
              "parameter",
              "country-default",
              "default"
            ]
          },
          "utcOffset": {
            "type": "string"
          },
          "localTime": {
            "type": "string",
            "format": "date-time"
          },
          "utc": {
            "type": "string",
            "format": "date-time"
          },
          "moon": {
            "type": "object",
            "properties": {
              "phase": {
                "type": "string"
              },
              "emoji": {
                "type": "string"
              },
              "illumination": {
                "type": "number"
              },
              "ageDays": {
                "type": "number"
              }
            }
          },
          "country": {
            "$ref": "#/components/schemas/CountryDay"
          },
          "statement": {
            "type": "string",
            "description": "One sentence summary to quote"
          }
        }
      },
      "HolidayYear": {
        "type": "object",
        "properties": {
          "country": {
            "type": "object"
          },
          "year": {
            "type": "integer"
          },
          "count": {
            "type": "integer"
          },
          "holidays": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Holiday"
            }
          },
          "makeupWorkdays": {
            "type": "array",
            "items": {
              "type": "string",
              "format": "date"
            }
          },
          "provisional": {
            "type": "boolean"
          },
          "disclaimer": {
            "type": "string"
          }
        }
      },
      "NextHolidays": {
        "type": "object",
        "properties": {
          "country": {
            "type": "object"
          },
          "today": {
            "type": "string",
            "format": "date"
          },
          "timezone": {
            "type": "string"
          },
          "holidays": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Holiday"
            }
          }
        }
      }
    }
  }
}
