{
  "openapi": "3.1.0",
  "info": {
    "title": "TheShia API",
    "version": "1.0.0",
    "description": "Free, open JSON APIs for Shia prayer times (Jafari methods, TwilightAngle high-latitude rule), Hijri conversion, crescent visibility, Islamic events, and calendar feeds. No keys or accounts. GET-only; responses are hard-cached at the edge — cache on your side too. Per-IP limit: 100 uncached requests/minute.",
    "contact": {
      "url": "https://theshia.org/en/api"
    }
  },
  "servers": [
    {
      "url": "https://theshia.org/api/v1"
    }
  ],
  "components": {
    "parameters": {
      "lat": {
        "name": "lat",
        "in": "query",
        "schema": {
          "type": "number",
          "minimum": -90,
          "maximum": 90
        },
        "description": "Latitude, decimal degrees (rounded to 2 dp for caching)."
      },
      "lng": {
        "name": "lng",
        "in": "query",
        "schema": {
          "type": "number",
          "minimum": -180,
          "maximum": 180
        },
        "description": "Longitude, decimal degrees (2 dp)."
      },
      "city": {
        "name": "city",
        "in": "query",
        "schema": {
          "type": "string"
        },
        "description": "City id from /cities (e.g. london, tehran, karbala). Sets lat, lng and tz."
      },
      "calendar": {
        "name": "calendar",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "moonsighting",
            "iran"
          ],
          "default": "moonsighting"
        },
        "description": "Hijri reckoning."
      },
      "hy": {
        "name": "hy",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1317,
          "maximum": 1523
        },
        "description": "Hijri year (≈ Gregorian 1900–2100)."
      },
      "hm": {
        "name": "hm",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 12
        },
        "description": "Hijri month, 1 = Muharram."
      },
      "lang": {
        "name": "lang",
        "in": "query",
        "schema": {
          "type": "string",
          "enum": [
            "en",
            "ar",
            "fa",
            "ur"
          ],
          "default": "en"
        }
      },
      "method": {
        "name": "method",
        "in": "query",
        "schema": {
          "type": "string",
          "default": "Tehran"
        },
        "description": "Calculation method id (see /methods): Tehran, Jafari, SheikhKalbasi, IslamicCentreOfEngland, AlKhoeiFoundation, MuslimWorldLeague, Egyptian, Karachi, UmmAlQura, Dubai, MoonsightingCommittee, NorthAmerica, Kuwait, Qatar, Singapore, Turkey. Prayer-times also accepts a comma list, \"all\", or \"custom\" with angle parameters."
      }
    }
  },
  "paths": {
    "/prayer-times": {
      "get": {
        "summary": "Prayer times — Jafari (Shia) calculation for any location",
        "description": "Location via lat+lng or city. Range via date=YYYY-MM-DD, year+month, or year alone (full year, single method). Budget: days × methods ≤ 496. Always applied: TwilightAngle high-latitude rule; imsak = fajr − 10 min; midnight = midpoint(maghrib, next fajr).",
        "parameters": [
          {
            "$ref": "#/components/parameters/lat"
          },
          {
            "$ref": "#/components/parameters/lng"
          },
          {
            "$ref": "#/components/parameters/city"
          },
          {
            "$ref": "#/components/parameters/method"
          },
          {
            "name": "date",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "month",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 12
            }
          },
          {
            "name": "year",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1900,
              "maximum": 2100
            }
          },
          {
            "name": "tz",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "IANA timezone — adds local HH:mm strings. Auto-filled from city."
          },
          {
            "name": "fajrAngle",
            "in": "query",
            "schema": {
              "type": "number",
              "minimum": 4,
              "maximum": 24
            },
            "description": "method=custom only (required)."
          },
          {
            "name": "ishaAngle",
            "in": "query",
            "schema": {
              "type": "number",
              "minimum": 4,
              "maximum": 24
            },
            "description": "method=custom: this OR ishaInterval."
          },
          {
            "name": "ishaInterval",
            "in": "query",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 180
            },
            "description": "Minutes after maghrib."
          },
          {
            "name": "maghribAngle",
            "in": "query",
            "schema": {
              "type": "number",
              "minimum": 0.5,
              "maximum": 12
            }
          },
          {
            "name": "maghribInterval",
            "in": "query",
            "schema": {
              "type": "number",
              "minimum": 0,
              "maximum": 120
            },
            "description": "Minutes after sunset."
          }
        ],
        "responses": {
          "200": {
            "description": "meta { lat, lng, city?, tz, qibla } + days[] of ISO 8601 UTC instants (imsak, fajr, sunrise, dhuhr, asr, sunset, maghrib, isha, midnight; + local {} when tz set). Multiple methods: results[] of { method, days }.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          },
          "400": {
            "description": "Validation error: { error }"
          }
        }
      }
    },
    "/methods": {
      "get": {
        "summary": "The sixteen calculation methods",
        "responses": {
          "200": {
            "description": "methods[]: { id, label {en,ar,fa,ur}, description, source, default }",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            }
          }
        }
      }
    },
    "/qibla": {
      "get": {
        "summary": "Qibla bearing for coordinates",
        "parameters": [
          {
            "name": "lat",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number",
              "minimum": -90,
              "maximum": 90
            }
          },
          {
            "name": "lng",
            "in": "query",
            "required": true,
            "schema": {
              "type": "number",
              "minimum": -180,
              "maximum": 180
            }
          }
        ],
        "responses": {
          "200": {
            "description": "{ qibla } — degrees clockwise from true north."
          }
        }
      }
    },
    "/cities": {
      "get": {
        "summary": "Search 325 curated cities (en/ar/fa/ur)",
        "parameters": [
          {
            "name": "q",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Up to 10 matches: { id, names {en,ar,fa,ur}, country, lat, lng, tz }."
          }
        }
      }
    },
    "/hijri": {
      "get": {
        "summary": "Hijri ⇄ Gregorian conversion, both directions",
        "description": "Forward: date=YYYY-MM-DD (default today) | year&month | year (day maps). Reverse: hy&hm[&hd] (whole-month map without hd). Answer source per result: table (announced sighting / official reckoning) → computed (crescent-visibility calculation, Tehran reference) → tabular (arithmetic estimate).",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "year",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1900,
              "maximum": 2100
            }
          },
          {
            "name": "month",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 12
            }
          },
          {
            "$ref": "#/components/parameters/hy"
          },
          {
            "$ref": "#/components/parameters/hm"
          },
          {
            "name": "hd",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 30
            },
            "description": "Hijri day — checked against the month's real length."
          },
          {
            "$ref": "#/components/parameters/calendar"
          },
          {
            "name": "offset",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": -2,
              "maximum": 2,
              "default": 0
            },
            "description": "Local-sighting day adjustment (forward conversion only)."
          }
        ],
        "responses": {
          "200": {
            "description": "gregorian, weekday, hijri {year,month,day}, monthName {en,ar,fa,ur}, formatted {en,ar,fa,ur}, monthLength, calendarUsed, source."
          },
          "400": {
            "description": "Validation error"
          }
        }
      }
    },
    "/moon-visibility": {
      "get": {
        "summary": "Crescent visibility — grid or per-location (Yallop/Shaukat)",
        "description": "Anchored to a Hijri month's lunation (default: current). Grid mode: world zone grid for one evening of the sighting window. Point mode (lat&lng or city): the seven evenings from conjunction + firstVisible dates per criterion.",
        "parameters": [
          {
            "$ref": "#/components/parameters/hy"
          },
          {
            "$ref": "#/components/parameters/hm"
          },
          {
            "name": "evening",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": -2,
              "maximum": 2,
              "default": 0
            },
            "description": "Relative to the sighting evening."
          },
          {
            "name": "res",
            "in": "query",
            "schema": {
              "type": "integer",
              "enum": [
                5,
                2
              ],
              "default": 5
            },
            "description": "Grid cell size, degrees."
          },
          {
            "$ref": "#/components/parameters/lat"
          },
          {
            "$ref": "#/components/parameters/lng"
          },
          {
            "$ref": "#/components/parameters/city"
          }
        ],
        "responses": {
          "200": {
            "description": "Grid: rows[] of digit strings (0 not visible … 4 telescope; lat +70..−60, lon −180..+180, cell centers lat = 70−(row+0.5)·res), counts, legend with q thresholds. Point: evenings[] { date, q, zone } + firstVisible per criterion. meta: conjunction (UTC, ΔT-corrected), monthBegins + source, sightingEvening."
          }
        }
      }
    },
    "/events": {
      "get": {
        "summary": "Curated Islamic events (73, Shia dates, four languages)",
        "description": "Events recur on Hijri month/day. List (default / hm=), resolve to a year (hy=), or query what's coming (upcoming=N). A day-30 event resolves to null in 29-day years.",
        "parameters": [
          {
            "$ref": "#/components/parameters/hm"
          },
          {
            "$ref": "#/components/parameters/hy"
          },
          {
            "name": "upcoming",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 73
            }
          },
          {
            "name": "importance",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "major"
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "occasion",
                "birth",
                "martyrdom",
                "death",
                "holy"
              ]
            }
          },
          {
            "name": "details",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "1"
              ]
            },
            "description": "Include detail paragraphs (en/ar/fa)."
          },
          {
            "$ref": "#/components/parameters/calendar"
          }
        ],
        "responses": {
          "200": {
            "description": "events[]: { id, hijriMonth, hijriDay, type, importance, title {en,ar,fa,ur} } (+ hijriYear, gregorian, daysUntil, source in resolved modes)."
          }
        }
      }
    },
    "/eclipses": {
      "get": {
        "summary": "Solar & lunar eclipses 2020–2040",
        "description": "Types, times of maximum (UTC), gamma, magnitudes, lunar phase durations, greatest-eclipse ground points and Hijri dates — fresh Meeus ch. 49/54 engine, verified against the NASA GSFC catalog (maxima within ~1 minute).",
        "parameters": [
          {
            "name": "kind",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "solar",
                "lunar"
              ]
            }
          },
          {
            "name": "type",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "total",
                "annular",
                "hybrid",
                "partial",
                "penumbral"
              ]
            }
          },
          {
            "name": "from",
            "in": "query",
            "description": "YYYY or YYYY-MM-DD",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "in": "query",
            "description": "YYYY (through that year's end) or YYYY-MM-DD",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "upcoming",
            "in": "query",
            "description": "next N eclipses from today with daysUntil; not combinable with from/to",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 24
            }
          },
          {
            "$ref": "#/components/parameters/calendar"
          }
        ],
        "responses": {
          "200": {
            "description": "eclipse list",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "meta": {
                      "type": "object"
                    },
                    "eclipses": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "properties": {
                          "kind": {
                            "type": "string",
                            "enum": [
                              "solar",
                              "lunar"
                            ]
                          },
                          "type": {
                            "type": "string",
                            "enum": [
                              "total",
                              "annular",
                              "hybrid",
                              "partial",
                              "penumbral"
                            ]
                          },
                          "utc": {
                            "type": "string",
                            "format": "date-time"
                          },
                          "gamma": {
                            "type": "number"
                          },
                          "magnitude": {
                            "type": [
                              "number",
                              "null"
                            ],
                            "description": "greatest partial magnitude (solar) / umbral magnitude (lunar)"
                          },
                          "penumbralMag": {
                            "type": "number"
                          },
                          "durationsMin": {
                            "type": "object",
                            "properties": {
                              "penumbral": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "partial": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "total": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              }
                            }
                          },
                          "greatest": {
                            "type": "object",
                            "properties": {
                              "lat": {
                                "type": "number"
                              },
                              "lon": {
                                "type": "number"
                              },
                              "central": {
                                "type": "boolean"
                              }
                            }
                          },
                          "hijri": {
                            "type": "object",
                            "properties": {
                              "hy": {
                                "type": "integer"
                              },
                              "hm": {
                                "type": "integer"
                              },
                              "hd": {
                                "type": "integer"
                              }
                            }
                          },
                          "daysUntil": {
                            "type": "integer"
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/day-status": {
      "get": {
        "summary": "Day status — machine-readable flags for any date",
        "description": "Hijri date, the day's events, and flags (extended mourning period, liturgical season, eid, fasting recommendations/prohibitions, evening-anchored nights of worship) so sites and apps can theme themselves automatically.",
        "parameters": [
          {
            "name": "date",
            "in": "query",
            "description": "YYYY-MM-DD (default: today UTC)",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "$ref": "#/components/parameters/calendar"
          }
        ],
        "responses": {
          "200": {
            "description": "day status",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "date": {
                      "type": "string",
                      "format": "date"
                    },
                    "weekday": {
                      "type": "string"
                    },
                    "calendarUsed": {
                      "type": "string"
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "table",
                        "computed",
                        "tabular"
                      ]
                    },
                    "hijri": {
                      "type": "object",
                      "properties": {
                        "hy": {
                          "type": "integer"
                        },
                        "hm": {
                          "type": "integer"
                        },
                        "hd": {
                          "type": "integer"
                        },
                        "monthName": {
                          "type": "object"
                        }
                      }
                    },
                    "events": {
                      "type": "array",
                      "items": {
                        "type": "object"
                      }
                    },
                    "flags": {
                      "type": "object",
                      "properties": {
                        "mourning": {
                          "type": "boolean"
                        },
                        "season": {
                          "type": [
                            "object",
                            "null"
                          ],
                          "properties": {
                            "id": {
                              "type": "string"
                            },
                            "kind": {
                              "type": "string",
                              "enum": [
                                "mourning",
                                "festive",
                                "worship"
                              ]
                            }
                          }
                        },
                        "eid": {
                          "type": "boolean"
                        },
                        "fastingRecommended": {
                          "type": "boolean"
                        },
                        "fastingForbidden": {
                          "type": "boolean"
                        },
                        "ashuraImsak": {
                          "type": "boolean"
                        },
                        "nightOfWorshipEve": {
                          "type": "boolean"
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/events.ics": {
      "get": {
        "summary": "Islamic events calendar feed (ICS/webcal)",
        "description": "All-day VEVENTs, ~14 months around today. Subscribe via webcal:// or paste the https URL into Google Calendar → From URL. Refreshes daily.",
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          },
          {
            "name": "importance",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "major"
              ]
            }
          },
          {
            "$ref": "#/components/parameters/calendar"
          }
        ],
        "responses": {
          "200": {
            "description": "text/calendar",
            "content": {
              "text/calendar": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/prayer-times.ics": {
      "get": {
        "summary": "Prayer times calendar feed for a city (ICS/webcal)",
        "parameters": [
          {
            "name": "city",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/method"
          },
          {
            "$ref": "#/components/parameters/lang"
          },
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 7,
              "maximum": 90,
              "default": 60
            },
            "description": "Rolling window."
          },
          {
            "name": "offsets",
            "in": "query",
            "description": "masjid-kit jamaat offsets, e.g. fajr:10,maghrib:5 (minutes -60..180)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "name",
            "in": "query",
            "description": "masjid display name for the calendar title and summaries (max 60 chars)",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "text/calendar — the five daily prayers as timed UTC events."
          }
        }
      }
    },
    "/fasting.ics": {
      "get": {
        "summary": "Recommended fasting days feed (ICS/webcal)",
        "description": "All-day VEVENTs for Ayyam al-Bid (13–15 of every Hijri month) and the emphasized recommended fasts, ~14 months around today. Refreshes daily.",
        "parameters": [
          {
            "$ref": "#/components/parameters/lang"
          },
          {
            "$ref": "#/components/parameters/calendar"
          }
        ],
        "responses": {
          "200": {
            "description": "text/calendar",
            "content": {
              "text/calendar": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/night.ics": {
      "get": {
        "summary": "Salat al-Layl wake-up feed (ICS/webcal)",
        "description": "One timed event at the last third of every night (maghrib + 2/3 of the night to the next fajr) for a city — subscribe and let the phone's calendar do the waking.",
        "parameters": [
          {
            "name": "city",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "method",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "$ref": "#/components/parameters/lang"
          },
          {
            "name": "days",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 7,
              "maximum": 90,
              "default": 60
            }
          }
        ],
        "responses": {
          "200": {
            "description": "text/calendar",
            "content": {
              "text/calendar": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    }
  }
}