{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/openephemeris-com/json-schema/openephemeris-com-zodiacal-releasing-response-schema.json",
  "title": "ZodiacalReleasingResponse",
  "description": "Zodiacal releasing timeline — L1 general periods dated in 360-day years, each with its L2 sub-periods dated in 30-day months, plus peak and current-period identification.",
  "x-generated": "2026-10-31",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/openephemeris-com-openapi.json#/components/schemas/ZodiacalReleasingResponse",
  "properties": {
    "calculation_metadata": {
      "description": "Metadata about the calculation.",
      "properties": {
        "algorithm_version": {
          "description": "Version of the releasing engine. 2.0.0 is the first that implements the canonical technique; 1.x ran level 1 in months and reported a static per-sign is_loosing.",
          "type": "string"
        },
        "birth_datetime": {
          "description": "Birth datetime, ISO 8601 UTC.",
          "type": "string"
        },
        "max_years": {
          "description": "Calendar years the timeline was run for.",
          "type": "integer"
        },
        "processing_time_ms": {
          "description": "Server processing time in milliseconds.",
          "type": "number"
        },
        "target_datetime": {
          "description": "Datetime the current period was resolved for, ISO 8601 UTC.",
          "type": [
            "string",
            "null"
          ]
        }
      },
      "type": [
        "object",
        "null"
      ]
    },
    "current_period": {
      "description": "The L1 general period active at the target datetime, with its active sub-period. Absent when the target falls outside the timeline.",
      "properties": {
        "end_date": {
          "description": "End of this general period, ISO 8601 UTC.",
          "type": "string"
        },
        "is_angular": {
          "description": "Whether this is a peak (angular) chapter.",
          "type": "boolean"
        },
        "l1_index": {
          "description": "Index into l1_periods.",
          "type": "integer"
        },
        "ruler": {
          "description": "Ruling planet name.",
          "type": "string"
        },
        "sign": {
          "description": "Sign index (0–11).",
          "type": "integer"
        },
        "sign_name": {
          "description": "Sign name.",
          "type": "string"
        },
        "start_date": {
          "description": "Start of this general period, ISO 8601 UTC.",
          "type": "string"
        },
        "sub_period": {
          "description": "The L2 sub-period active at the target datetime.",
          "properties": {
            "end_date": {
              "description": "End of this sub-period, ISO 8601 UTC.",
              "type": "string"
            },
            "is_angular": {
              "description": "Whether this sign is angular from the Lot.",
              "type": "boolean"
            },
            "is_loosing": {
              "description": "Whether this sub-period is the one entered at a loosing of the bond.",
              "type": "boolean"
            },
            "months": {
              "description": "Duration in 30-day months.",
              "type": "integer"
            },
            "ruler": {
              "description": "Ruling planet name.",
              "type": "string"
            },
            "sign": {
              "description": "Sign index (0–11).",
              "type": "integer"
            },
            "sign_name": {
              "description": "Sign name.",
              "type": "string"
            },
            "start_date": {
              "description": "Start of this sub-period, ISO 8601 UTC.",
              "type": "string"
            }
          },
          "type": [
            "object",
            "null"
          ]
        },
        "years": {
          "description": "Duration in 360-day years.",
          "type": "integer"
        },
        "years_into_period": {
          "description": "How far into this general period the target date falls, in 360-day years.",
          "type": "number"
        }
      },
      "type": [
        "object",
        "null"
      ]
    },
    "l1_periods": {
      "description": "Level-1 general periods in the zodiacal releasing timeline.",
      "items": {
        "properties": {
          "end_date": {
            "description": "End of this general period, ISO 8601 UTC.",
            "type": "string"
          },
          "is_angular": {
            "description": "Whether this sign is angular (1st, 4th, 7th, 10th) from the Lot. Angular periods are peak chapters.",
            "type": "boolean"
          },
          "l2_periods": {
            "description": "Level-2 sub-periods within this general period, in sequence, including the jump at any loosing of the bond.",
            "items": {
              "properties": {
                "end_date": {
                  "description": "End of this sub-period, ISO 8601 UTC.",
                  "type": "string"
                },
                "is_angular": {
                  "description": "Whether this sign is angular (1st, 4th, 7th, 10th) from the Lot.",
                  "type": "boolean"
                },
                "is_loosing": {
                  "description": "True of the FIRST sub-period after a loosing of the bond — the sequence reached the sign its general period began on and jumped to the opposite sign instead.",
                  "type": "boolean"
                },
                "months": {
                  "description": "Duration in 30-day months — this sign's own minor years. A final sub-period truncated by the end of its general period keeps its natural value here; only end_date is clipped.",
                  "type": "integer"
                },
                "ruler": {
                  "description": "Ruling planet name.",
                  "type": "string"
                },
                "sign": {
                  "description": "Sign index (0–11).",
                  "type": "integer"
                },
                "sign_name": {
                  "description": "Sign name.",
                  "type": "string"
                },
                "start_date": {
                  "description": "Start of this sub-period, ISO 8601 UTC.",
                  "type": "string"
                }
              },
              "type": "object"
            },
            "type": [
              "array",
              "null"
            ]
          },
          "ruler": {
            "description": "Ruling planet name.",
            "type": "string"
          },
          "sign": {
            "description": "Sign index (0–11).",
            "type": "integer"
          },
          "sign_name": {
            "description": "Sign name.",
            "type": "string"
          },
          "start_date": {
            "description": "Start of this general period, ISO 8601 UTC.",
            "type": "string"
          },
          "years": {
            "description": "Duration in 360-day years — this sign's minor years.",
            "type": "integer"
          }
        },
        "type": "object"
      },
      "title": "L1 Periods",
      "type": "array"
    },
    "lot_sign": {
      "description": "Sign index of the Lot actually released from (0–11). When spirit_advanced is true this is one sign past the submitted lot_sign.",
      "type": "integer"
    },
    "lot_sign_name": {
      "description": "Name of the sign actually released from (e.g., 'Leo').",
      "type": "string"
    },
    "output_mode": {
      "description": "Output projection mode (json | llm).",
      "type": [
        "string",
        "null"
      ]
    },
    "peak_period_index": {
      "description": "Index of the longest angular L1 period (the peak chapter).",
      "type": "integer"
    },
    "spirit_advanced": {
      "description": "True when Valens' same-sign rule (IV, 4:7) moved Spirit forward one sign because it shared Fortune's. It changes every date in the timeline, so surface it.",
      "type": "boolean"
    },
    "starting_lot": {
      "description": "Name of the releasing Lot ('fortune' or 'spirit').",
      "type": "string"
    },
    "success": {
      "description": "Whether the calculation succeeded.",
      "title": "Success",
      "type": "boolean"
    },
    "total_years": {
      "description": "Total 360-day years covered by the L1 timeline.",
      "type": "integer"
    }
  },
  "required": [
    "success",
    "starting_lot",
    "lot_sign",
    "lot_sign_name",
    "spirit_advanced",
    "l1_periods",
    "total_years",
    "peak_period_index"
  ],
  "type": "object"
}