{
  "openapi": "3.1.1",
  "info": {
    "title": "Jet Lag Planner API",
    "version": "1.0.0",
    "summary": "A day-by-day sleep, light and caffeine plan to beat jet lag, with calendar export.",
    "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://jetlagplanner.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "A day-by-day sleep, light and caffeine plan to beat jet lag, with calendar export.",
        "description": "Pick your home and destination time zones, travel date and usual sleep times. The planner computes the real time difference for that date (including daylight saving), shifts your sleep before departure, and lists when to seek or avoid bright light and when to stop caffeine until you are adapted. Download it as a calendar file.\n\nMethodology:\n- Time difference = destination UTC offset (at noon UTC on the arrival date) − home UTC offset (at noon UTC on the departure date), via the Intl time-zone database, so daylight saving is included. It is normalised to −12…+12 h; positive = eastward (clock must advance), negative = westward (delay).\n- Pre-flight: sleep and wake move 1 hour per day toward destination time (earlier for east, later for west), as suggested in the CDC Yellow Book jet-lag chapter for the 2–3 days before travel; days beyond what is needed are skipped.\n- After arrival you sleep on local time; the body clock is assumed to catch up 1 h/day after eastward and 1.5 h/day after westward travel (common planning rule of thumb, not an individual prediction).\n- Core body temperature minimum (CBTmin) is estimated at 2.5 h before the body’s habitual wake time (2 h for early birds, 3 h for night owls).\n- Light rule (phase-response curve): to advance (east) seek bright light in the 3 h after CBTmin and avoid it in the 3 h before; to delay (west) seek light in the 3 h before CBTmin and avoid it in the 3 h after. If a window falls while you sleep, use only its waking part.\n- Caffeine cut-off = 6 h before planned bedtime (CDC Yellow Book example).\n- The .ics file contains bedtime, light and caffeine events in UTC with UIDs derived from a hash of your inputs, CRLF line endings and folded lines.\n\nGeneral planning guidance, not medical advice. Ask a clinician before using melatonin or sleep medication.",
        "tags": [
          "home-travel"
        ],
        "x-mcp-tool": "jet_lag_planner",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JetLagPlannerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Berlin → New York (westward, 6 h)",
                  "value": {
                    "homeZone": "Europe/Berlin",
                    "destinationZone": "America/New_York",
                    "departureDate": "2026-11-10",
                    "bedtime": "23:00",
                    "wakeTime": "07:00",
                    "daysBefore": 3,
                    "chronotype": "intermediate"
                  }
                },
                "example2": {
                  "summary": "London → Tokyo (eastward, 9 h)",
                  "value": {
                    "homeZone": "Europe/London",
                    "destinationZone": "Asia/Tokyo",
                    "departureDate": "2027-04-02",
                    "arrivalDate": "2027-04-03",
                    "bedtime": "23:30",
                    "wakeTime": "07:30",
                    "daysBefore": 3,
                    "chronotype": "late"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/JetLagPlannerResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "JetLagPlannerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "homeZone": {
            "title": "Home time zone",
            "type": "string",
            "enum": [
              "Pacific/Honolulu",
              "America/Anchorage",
              "America/Los_Angeles",
              "America/Denver",
              "America/Phoenix",
              "America/Chicago",
              "America/Mexico_City",
              "America/New_York",
              "America/Toronto",
              "America/Bogota",
              "America/Lima",
              "America/Santiago",
              "America/Sao_Paulo",
              "America/Argentina/Buenos_Aires",
              "Atlantic/Reykjavik",
              "Europe/London",
              "Europe/Lisbon",
              "Europe/Dublin",
              "Europe/Paris",
              "Europe/Berlin",
              "Europe/Madrid",
              "Europe/Rome",
              "Europe/Zurich",
              "Europe/Vienna",
              "Europe/Amsterdam",
              "Europe/Stockholm",
              "Europe/Warsaw",
              "Europe/Athens",
              "Europe/Istanbul",
              "Europe/Moscow",
              "Africa/Cairo",
              "Africa/Johannesburg",
              "Africa/Lagos",
              "Africa/Nairobi",
              "Asia/Dubai",
              "Asia/Karachi",
              "Asia/Kolkata",
              "Asia/Bangkok",
              "Asia/Singapore",
              "Asia/Shanghai",
              "Asia/Hong_Kong",
              "Asia/Seoul",
              "Asia/Tokyo",
              "Australia/Perth",
              "Australia/Sydney",
              "Pacific/Auckland"
            ],
            "default": "Europe/Berlin"
          },
          "destinationZone": {
            "title": "Destination time zone",
            "type": "string",
            "enum": [
              "Pacific/Honolulu",
              "America/Anchorage",
              "America/Los_Angeles",
              "America/Denver",
              "America/Phoenix",
              "America/Chicago",
              "America/Mexico_City",
              "America/New_York",
              "America/Toronto",
              "America/Bogota",
              "America/Lima",
              "America/Santiago",
              "America/Sao_Paulo",
              "America/Argentina/Buenos_Aires",
              "Atlantic/Reykjavik",
              "Europe/London",
              "Europe/Lisbon",
              "Europe/Dublin",
              "Europe/Paris",
              "Europe/Berlin",
              "Europe/Madrid",
              "Europe/Rome",
              "Europe/Zurich",
              "Europe/Vienna",
              "Europe/Amsterdam",
              "Europe/Stockholm",
              "Europe/Warsaw",
              "Europe/Athens",
              "Europe/Istanbul",
              "Europe/Moscow",
              "Africa/Cairo",
              "Africa/Johannesburg",
              "Africa/Lagos",
              "Africa/Nairobi",
              "Asia/Dubai",
              "Asia/Karachi",
              "Asia/Kolkata",
              "Asia/Bangkok",
              "Asia/Singapore",
              "Asia/Shanghai",
              "Asia/Hong_Kong",
              "Asia/Seoul",
              "Asia/Tokyo",
              "Australia/Perth",
              "Australia/Sydney",
              "Pacific/Auckland"
            ],
            "default": "America/New_York"
          },
          "homeZoneCustom": {
            "title": "Other home zone (IANA name)",
            "description": "Overrides the list if filled in.",
            "type": "string",
            "maxLength": 64
          },
          "destinationZoneCustom": {
            "title": "Other destination zone (IANA name)",
            "description": "Overrides the list if filled in.",
            "type": "string",
            "maxLength": 64
          },
          "departureDate": {
            "title": "Departure date",
            "type": "string",
            "format": "date"
          },
          "arrivalDate": {
            "title": "Arrival date (local)",
            "description": "Defaults to the departure date.",
            "type": "string",
            "format": "date"
          },
          "bedtime": {
            "title": "Usual bedtime",
            "type": "string",
            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
            "default": "23:00"
          },
          "wakeTime": {
            "title": "Usual wake time",
            "type": "string",
            "pattern": "^([01]\\d|2[0-3]):[0-5]\\d$",
            "default": "07:00"
          },
          "daysBefore": {
            "title": "Days to pre-adjust before departure",
            "type": "integer",
            "minimum": 0,
            "maximum": 7,
            "default": 3
          },
          "chronotype": {
            "title": "Chronotype",
            "type": "string",
            "enum": [
              "early",
              "intermediate",
              "late"
            ],
            "default": "intermediate"
          }
        },
        "required": [
          "departureDate"
        ]
      },
      "JetLagPlannerResult": {
        "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": [
              "homeZone",
              "destinationZone",
              "offsetMinutes",
              "direction",
              "preShiftMinutes",
              "daysToAdapt",
              "schedule"
            ],
            "properties": {
              "homeZone": {
                "type": "string"
              },
              "destinationZone": {
                "type": "string"
              },
              "offsetMinutes": {
                "type": "integer",
                "description": "Destination UTC offset − home UTC offset on the travel dates, normalised to (−720, 720]."
              },
              "direction": {
                "type": "string",
                "enum": [
                  "east",
                  "west",
                  "none"
                ]
              },
              "preShiftMinutes": {
                "type": "integer",
                "minimum": 0
              },
              "daysToAdapt": {
                "type": "integer",
                "minimum": 0,
                "description": "Days after arrival until the body clock is estimated to match local time."
              },
              "schedule": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "date",
                    "phase",
                    "clock",
                    "bedtime",
                    "wakeTime",
                    "bodyTempMinimum",
                    "seekLight",
                    "avoidLight",
                    "caffeineCutoff",
                    "remainingShiftHours"
                  ],
                  "properties": {
                    "date": {
                      "type": "string",
                      "format": "date"
                    },
                    "phase": {
                      "type": "string",
                      "enum": [
                        "pre-flight",
                        "travel-day",
                        "post-arrival"
                      ]
                    },
                    "clock": {
                      "type": "string",
                      "enum": [
                        "home",
                        "destination"
                      ],
                      "description": "Which local time the times are expressed in."
                    },
                    "bedtime": {
                      "type": "string",
                      "pattern": "^\\d{2}:\\d{2}$"
                    },
                    "wakeTime": {
                      "type": "string",
                      "pattern": "^\\d{2}:\\d{2}$"
                    },
                    "bodyTempMinimum": {
                      "type": "string",
                      "pattern": "^\\d{2}:\\d{2}$"
                    },
                    "seekLight": {
                      "type": "string"
                    },
                    "avoidLight": {
                      "type": "string"
                    },
                    "caffeineCutoff": {
                      "type": "string",
                      "pattern": "^\\d{2}:\\d{2}$"
                    },
                    "remainingShiftHours": {
                      "type": "number",
                      "minimum": 0
                    }
                  }
                }
              }
            }
          },
          "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"
              }
            }
          }
        }
      }
    }
  }
}