{
  "openapi": "3.0.3",
  "info": {
    "title": "cron — Cron Explainer API",
    "description": "Parses a standard 5-field cron expression and returns a plain-English description plus the next upcoming run times. Pure and offline: no scheduler, no external calls. Supports ranges, lists, steps, named months/days (JAN-DEC, SUN-SAT) and the @yearly/@monthly/@weekly/@daily/@hourly shortcuts.",
    "version": "1.0.0"
  },
  "servers": [
    { "url": "https://cron.benjamin-dreier.de", "description": "Production" }
  ],
  "paths": {
    "/v1/explain": {
      "get": {
        "summary": "Explain a cron expression",
        "operationId": "explain",
        "parameters": [
          {
            "name": "expr",
            "in": "query",
            "required": true,
            "description": "A 5-field cron expression (minute hour day-of-month month day-of-week) or an @-shortcut.",
            "schema": { "type": "string" },
            "example": "*/15 9-17 * * 1-5"
          },
          {
            "name": "n",
            "in": "query",
            "required": false,
            "description": "Number of upcoming run times to return (1-20).",
            "schema": { "type": "integer", "default": 5, "minimum": 1, "maximum": 20 },
            "example": 5
          },
          {
            "name": "tz",
            "in": "query",
            "required": false,
            "description": "IANA timezone name for the returned run times. Defaults to UTC.",
            "schema": { "type": "string", "default": "UTC" },
            "example": "Europe/Berlin"
          }
        ],
        "responses": {
          "200": {
            "description": "Parsed expression with description and upcoming runs.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ExplainResponse" },
                "example": {
                  "expression": "*/15 9-17 * * 1-5",
                  "description": "Every 15 minutes, from 09:00 to 17:59, on Monday through Friday",
                  "fields": {
                    "minute": "*/15",
                    "hour": "9-17",
                    "day_of_month": "*",
                    "month": "*",
                    "day_of_week": "1-5"
                  },
                  "timezone": "UTC",
                  "next_runs": [
                    "2026-06-29T09:00:00Z",
                    "2026-06-29T09:15:00Z",
                    "2026-06-29T09:30:00Z",
                    "2026-06-29T09:45:00Z",
                    "2026-06-29T10:00:00Z"
                  ]
                }
              }
            }
          },
          "400": {
            "description": "Missing/invalid expression, timezone or n.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/Error" },
                "example": { "error": "minute: 60 is out of range 0-59" }
              }
            }
          }
        }
      }
    },
    "/healthz": {
      "get": {
        "summary": "Service health and version",
        "operationId": "health",
        "responses": {
          "200": { "description": "Service ready." }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "ExplainResponse": {
        "type": "object",
        "required": ["expression", "description", "fields", "timezone", "next_runs"],
        "properties": {
          "expression": { "type": "string", "example": "*/15 9-17 * * 1-5" },
          "description": { "type": "string", "example": "Every 15 minutes, from 09:00 to 17:59, on Monday through Friday" },
          "fields": { "$ref": "#/components/schemas/Fields" },
          "timezone": { "type": "string", "example": "UTC" },
          "next_runs": {
            "type": "array",
            "items": { "type": "string", "format": "date-time" },
            "description": "Upcoming activations as RFC 3339 timestamps. May be empty for an impossible expression (e.g. February 30th)."
          }
        }
      },
      "Fields": {
        "type": "object",
        "properties": {
          "minute": { "type": "string", "example": "*/15" },
          "hour": { "type": "string", "example": "9-17" },
          "day_of_month": { "type": "string", "example": "*" },
          "month": { "type": "string", "example": "*" },
          "day_of_week": { "type": "string", "example": "1-5" }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": { "type": "string", "example": "minute: 60 is out of range 0-59" }
        }
      }
    }
  }
}
