{
  "openapi": "3.1.0",
  "info": {
    "title": "Bharat Ephemeris API",
    "version": "1.0.0",
    "summary": "Sovereign Vedic astronomy — sidereal planetary positions computed in-house.",
    "description": "A 100% in-house Vedic ephemeris. Sidereal (nirāyana) planetary longitudes are computed from classical Indian mathematical astronomy — Sūrya-Siddhānta mean motions refined by the Kerala school (Nīlakaṇṭha Somayājī, Tantrasaṅgraha, 1501) with dṛk-saṃskāra corrections — in dependency-free TypeScript, computed in-memory on the Edge. No Swiss Ephemeris, no VSOP87, and no NASA/JPL data files are in the runtime numeric chain; JPL Horizons is used only offline as a measuring tape.\n\nMeasured over 1,000 test dates spanning 2000–2050 vs NASA/JPL Horizons: the Sun agrees to 7.8 arcseconds (0.13′) at the 95th percentile, the Moon to 30.3″ (0.51′), and the worst-case planet (Mercury) to 129.7″ (2.16′). The p95 qualifier is load-bearing. Full machine-readable residuals: https://bharatephemeris.com/data/accuracy-bench.json (CC-BY-4.0).\n\nThe public endpoints below require no API key. Higher-volume production access is available by request (mailto:hello@bharatephemeris.com). Human-readable reference: https://bharatephemeris.com/api-docs.",
    "contact": {
      "name": "Bharat Ephemeris",
      "url": "https://bharatephemeris.com/developers",
      "email": "hello@bharatephemeris.com"
    },
    "license": {
      "name": "AGPL-3.0-or-later (open source) / commercial terms on request",
      "url": "https://bharatephemeris.com/developers"
    }
  },
  "externalDocs": {
    "description": "Full API reference, accuracy method, and provenance",
    "url": "https://bharatephemeris.com/api-docs"
  },
  "servers": [
    { "url": "https://bharatephemeris.com", "description": "Production" }
  ],
  "tags": [
    { "name": "Chart", "description": "Birth-chart (janma-kuṇḍalī) computation." },
    { "name": "Panchang", "description": "Calendar — pañcāṅga, ghaṭī, muhūrta, festivals." },
    { "name": "Knowledge", "description": "Reference facts." },
    { "name": "System", "description": "Health & status." }
  ],
  "paths": {
    "/api/chart": {
      "post": {
        "tags": ["Chart"],
        "operationId": "computeChart",
        "summary": "Compute a full sidereal birth chart",
        "description": "The primary public endpoint. POST a birth instant and coordinates; get back sidereal grahas, lagna, bhāvas, 16 vargas, aṣṭakavarga, yogas, ārūḍhas, kārakas, avasthās and daśā. No API key required.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/ChartRequest" },
              "example": {
                "year": 1990, "month": 1, "day": 1,
                "hour": 12, "minute": 0,
                "lat": 28.6139, "lon": 77.2090, "tzHours": 5.5
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Computed chart.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ChartResponse" }
              }
            }
          },
          "400": {
            "description": "Invalid or out-of-range input.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    },
    "/api/v1/bharat/chart": {
      "post": {
        "tags": ["Chart"],
        "operationId": "computeChartV1",
        "summary": "Compute a chart (typed, ayanāṃśa-selectable request)",
        "description": "Sovereign-substrate variant with an ISO-typed request: IANA timezone, selectable ayanāṃśa variant, and mean/true node mode. Same computation kernel as /api/chart.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/BharatChartRequest" },
              "example": {
                "birthDate": "1990-01-01",
                "birthTime": "12:00:00",
                "birthPlace": { "lat": 28.6139, "lon": 77.2090, "tz": "Asia/Kolkata" },
                "ayanamsa": "lahiri",
                "nodeMode": "mean"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Computed chart (substrate envelope).",
            "content": { "application/json": { "schema": { "type": "object" } } }
          },
          "400": {
            "description": "Validation error.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    },
    "/api/panchang": {
      "get": {
        "tags": ["Panchang"],
        "operationId": "getPanchang",
        "summary": "Current-instant pañcāṅga",
        "description": "Returns the pañcāṅga (tithi, karaṇa, yoga, nakṣatra, vāra) for the current instant. Takes no query parameters. For historical festival dates use /api/utsavas; for a birth chart use POST /api/chart.",
        "responses": {
          "200": { "description": "Current pañcāṅga.", "content": { "application/json": { "schema": { "type": "object" } } } },
          "400": {
            "description": "Unsupported query parameters were supplied.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/Error" } } }
          }
        }
      }
    },
    "/api/ghadi": {
      "get": {
        "tags": ["Panchang"],
        "operationId": "getGhadi",
        "summary": "Current traditional time units",
        "description": "Kali/Vikrama/Śaka years, saṃvatsara, ṛtu, māsa, pakṣa, tithi, vāra, muhūrta, ghaṭī and vighaṭī for the current instant.",
        "responses": {
          "200": { "description": "Current ghaṭī reckoning.", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/muhurta": {
      "get": {
        "tags": ["Panchang"],
        "operationId": "getMuhurta",
        "summary": "Day's muhūrta, choghadiya and horā windows",
        "parameters": [
          { "name": "date", "in": "query", "required": true, "schema": { "type": "string", "format": "date" }, "description": "YYYY-MM-DD.", "example": "2026-07-23" },
          { "name": "lat", "in": "query", "required": true, "schema": { "type": "number", "minimum": -90, "maximum": 90 }, "example": 28.6139 },
          { "name": "lon", "in": "query", "required": true, "schema": { "type": "number", "minimum": -180, "maximum": 180 }, "example": 77.2090 },
          { "name": "tz", "in": "query", "required": true, "schema": { "type": "number", "minimum": -14, "maximum": 14 }, "description": "UTC offset in hours.", "example": 5.5 }
        ],
        "responses": {
          "200": { "description": "Sunrise/sunset, muhūrtas, choghadiya, horā and windows.", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/utsavas": {
      "get": {
        "tags": ["Panchang"],
        "operationId": "getUtsavas",
        "summary": "Festival (utsava) dates for a year",
        "parameters": [
          { "name": "year", "in": "query", "required": true, "schema": { "type": "integer", "minimum": 1900, "maximum": 2100 }, "example": 2026 }
        ],
        "responses": {
          "200": { "description": "Festival dates for the given year.", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/kundali-facts": {
      "get": {
        "tags": ["Knowledge"],
        "operationId": "getKundaliFacts",
        "summary": "Reference facts (searchable)",
        "parameters": [
          { "name": "q", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Free-text query to filter facts." },
          { "name": "format", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Response format hint." }
        ],
        "responses": {
          "200": { "description": "Matching facts with attribution and citation.", "content": { "application/json": { "schema": { "type": "object" } } } }
        }
      }
    },
    "/api/health": {
      "get": {
        "tags": ["System"],
        "operationId": "getHealth",
        "summary": "Service health",
        "responses": {
          "200": {
            "description": "Health status.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "status": { "type": "string", "example": "ok" },
                    "time": { "type": "string", "format": "date-time" },
                    "checks": { "type": "object" }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ChartRequest": {
        "type": "object",
        "required": ["year", "month", "day", "hour", "minute", "lat", "lon", "tzHours"],
        "properties": {
          "year": { "type": "integer", "minimum": 1900, "maximum": 2100, "example": 1990 },
          "month": { "type": "integer", "minimum": 1, "maximum": 12, "example": 1 },
          "day": { "type": "integer", "minimum": 1, "maximum": 31, "example": 1 },
          "hour": { "type": "integer", "minimum": 0, "maximum": 23, "example": 12 },
          "minute": { "type": "integer", "minimum": 0, "maximum": 59, "example": 0 },
          "lat": { "type": "number", "minimum": -90, "maximum": 90, "description": "Latitude, decimal degrees (positive North).", "example": 28.6139 },
          "lon": { "type": "number", "minimum": -180, "maximum": 180, "description": "Longitude, decimal degrees (positive East).", "example": 77.2090 },
          "tzHours": { "type": "number", "minimum": -14, "maximum": 14, "description": "Fixed UTC offset in hours at the birth instant.", "example": 5.5 }
        }
      },
      "BharatChartRequest": {
        "type": "object",
        "required": ["birthDate", "birthTime", "birthPlace", "ayanamsa"],
        "properties": {
          "birthDate": { "type": "string", "format": "date", "description": "YYYY-MM-DD (Gregorian, 1900-01-01 .. 2100-12-31).", "example": "1990-01-01" },
          "birthTime": { "type": "string", "description": "HH:mm:ss, 24-hour wall-clock at birthPlace timezone.", "example": "12:00:00" },
          "birthPlace": { "$ref": "#/components/schemas/BirthPlace" },
          "ayanamsa": { "type": "string", "description": "Ayanāṃśa variant (e.g. lahiri).", "example": "lahiri" },
          "nodeMode": { "type": "string", "enum": ["mean", "true"], "default": "mean", "description": "Rāhu/Ketu computation mode." }
        }
      },
      "BirthPlace": {
        "type": "object",
        "required": ["lat", "lon"],
        "description": "Provide either tz (IANA, preferred) or tzOffsetHours.",
        "properties": {
          "lat": { "type": "number", "minimum": -90, "maximum": 90, "example": 28.6139 },
          "lon": { "type": "number", "minimum": -180, "maximum": 180, "example": 77.2090 },
          "tz": { "type": "string", "description": "IANA timezone id (preferred). Resolves DST + historical rules.", "example": "Asia/Kolkata" },
          "tzOffsetHours": { "type": "number", "minimum": -14, "maximum": 14, "description": "Fallback fixed UTC offset in hours when tz is absent.", "example": 5.5 }
        }
      },
      "ChartResponse": {
        "type": "object",
        "description": "Full computed chart. Angular values are sidereal (nirāyana) degrees after ayanāṃśa subtraction.",
        "properties": {
          "input": { "type": "object", "description": "Echo of the normalized request." },
          "jd_utc": { "type": "number", "description": "Julian Day (UTC)." },
          "jd_tt": { "type": "number", "description": "Julian Day (Terrestrial Time)." },
          "ayanamsha_deg": { "type": "number", "description": "Ayanāṃśa applied, degrees.", "example": 24.16 },
          "lagna": { "$ref": "#/components/schemas/Point" },
          "grahas": { "type": "array", "items": { "$ref": "#/components/schemas/Graha" } },
          "bhavas": { "type": "array", "items": { "type": "object" }, "description": "12 houses." },
          "vargas": { "type": "object", "description": "16 divisional charts (ṣoḍaśa-varga)." },
          "ashtakavarga": { "type": "object" },
          "yogas": { "type": "array", "items": { "type": "object" } },
          "arudhas": { "type": "object" },
          "naisargika_karakas": { "type": "object" },
          "chara_karakas": { "type": "object" },
          "avasthas": { "type": "object" },
          "dasha": { "type": "object", "description": "Vimśottarī (and related) daśā tree." },
          "current_phase": { "type": "object", "description": "Running daśā/bhukti at the birth instant." },
          "substrate_stamp": { "type": "object", "description": "Provenance stamp of the computation." }
        }
      },
      "Point": {
        "type": "object",
        "properties": {
          "sidereal_deg": { "type": "number", "example": 191.42 },
          "rashi": { "type": "string", "description": "Sidereal sign.", "example": "Tula" },
          "nakshatra_pada": { "type": "string", "description": "Nakṣatra + pāda.", "example": "Vishakha-1" }
        }
      },
      "Graha": {
        "type": "object",
        "properties": {
          "key": { "type": "string", "example": "sun" },
          "sa": { "type": "string", "description": "Sanskrit name.", "example": "सूर्य" },
          "iast": { "type": "string", "example": "Sūrya" },
          "rashi": { "type": "string", "example": "Dhanu" },
          "nakshatra_pada": { "type": "string", "example": "Mula-2" },
          "dignity": { "type": "string", "example": "neutral" },
          "retrograde": { "type": "boolean", "example": false },
          "sidereal_deg": { "type": "number", "example": 256.73 }
        }
      },
      "Error": {
        "type": "object",
        "description": "Error envelope as emitted by the route handlers.",
        "properties": {
          "error": { "type": "string", "example": "unsupported_query_parameters" },
          "message": { "type": "string", "example": "GET /api/panchang accepts no query parameters." },
          "unexpected_keys": { "type": "array", "items": { "type": "string" } }
        }
      }
    }
  }
}
