{
  "openapi": "3.1.1",
  "info": {
    "title": "Cron Job Explorer API",
    "version": "1.0.0",
    "summary": "Paste a crontab or CronJob YAML: plain-English schedules, DST-exact next runs, herds and overlaps.",
    "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://cronjobexplorer.usefulweb.site"
    }
  ],
  "paths": {
    "/api/v1/calculate": {
      "post": {
        "operationId": "calculate",
        "summary": "Paste a crontab or CronJob YAML: plain-English schedules, DST-exact next runs, herds and overlaps.",
        "description": "Paste crontab lines (5-field, @daily macros, 6-field with seconds, Quartz with ? L W #), Kubernetes CronJob YAML or GitHub Actions schedules, plus an optional run-history CSV. Get a plain-English description and the next runs of every job in any IANA time zone with correct DST handling, minutes where many jobs start at once, overlapping schedules, jobs that run longer than their interval and failure/retry statistics.\n\nMethodology:\n- Fields: minute 0–59, hour 0–23, day-of-month 1–31, month 1–12 or JAN–DEC, day-of-week 0–7 or SUN–SAT (0 and 7 = Sunday); lists, ranges, steps (*/n, a-b/n, a/n). @yearly, @monthly, @weekly, @daily/@midnight and @hourly are expanded; @reboot has no time schedule.\n- Day matching follows Vixie cron/cronie: when both day-of-month and day-of-week are restricted (neither starts with \"*\"), a day matches if EITHER matches; if one starts with \"*\" (including \"*/2\"), both must match.\n- 6-field lines with a leading seconds field are detected automatically; \"?\", L, W and # select Quartz semantics (day-of-week 1–7 with 1 = Sunday, L = last day, 15W = nearest weekday, 6#3 = third Friday, 5L = last Thursday, optional year field).\n- Next runs are computed by walking local calendar days in the job’s time zone and converting each matching wall-clock time to UTC with Intl (IANA tz database). DST, cronie rules: fixed-time jobs scheduled in a skipped hour run right after the switch and run only once in a repeated hour; jobs with \"*\" in the minute or hour field follow the new wall clock (skip the gap, run in both passes of a repeated hour). The \"wall-clock\" policy skips non-existent times and runs repeated times twice.\n- Herd minutes: within the analysis window, start times of all jobs are bucketed per minute; minutes with at least the threshold of distinct jobs are reported. Overlaps list job pairs sharing start minutes.\n- Run history: per job, runs, failures, timeouts, retries (status contains \"retr\", attempt > 1, or a failed run followed by a new start before the next scheduled run), duration statistics, missed scheduled runs between first and last recorded start, and whether the p95 duration exceeds the shortest interval between scheduled runs (overlapping self-runs). Peak concurrency uses the p95 durations (1 minute when unknown).\n- Kubernetes CronJob: metadata.name, spec.schedule, spec.timeZone, suspend and concurrencyPolicy are read; GitHub Actions on.schedule cron entries are always UTC.",
        "tags": [
          "devcloud"
        ],
        "x-mcp-tool": "cron_job_explorer",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CronJobExplorerInput"
              },
              "examples": {
                "example1": {
                  "summary": "Crontab + Kubernetes CronJob with run history (Berlin)",
                  "value": {
                    "crontab": "# m h dom mon dow command\nCRON_TZ=Europe/Berlin\nMAILTO=ops@example.com\n# Nightly database backup\n30 2 * * * /usr/local/bin/backup-db.sh --full\n*/15 * * * * /opt/app/bin/sync-inventory\n0 * * * * /opt/app/bin/rotate-logs # log-rotate\n0 2 * * * /usr/bin/flock -n /tmp/report.lock python3 /opt/app/reports/build_report.py\n0 9-17/2 * * 1-5 /opt/app/bin/send-digest\n0 0 1 * * /opt/app/bin/invoice-run\n@daily /usr/local/bin/cleanup-tmp\n0 30 6 ? * MON-FRI # quartz-warmup\n---\napiVersion: batch/v1\nkind: CronJob\nmetadata:\n  name: cache-warmer\nspec:\n  schedule: \"0 2 * * *\"\n  timeZone: \"Europe/Berlin\"\n  concurrencyPolicy: Allow\n  jobTemplate:\n    spec:\n      template:\n        spec:\n          containers:\n            - name: warmer\n              image: example/warmer:1.4\n",
                    "history": "job,start,end,status\nNightly database backup,2026-10-08T02:30:00,2026-10-08T03:12:00,success\nNightly database backup,2026-10-09T02:30:00,2026-10-09T03:41:00,success\nNightly database backup,2026-10-10T02:30:00,2026-10-10T02:31:10,failed\nNightly database backup,2026-10-10T02:45:00,2026-10-10T03:30:00,success\nNightly database backup,2026-10-11T02:30:00,2026-10-11T03:20:00,success\nsync-inventory,2026-10-11T09:00:00,2026-10-11T09:21:00,success\nsync-inventory,2026-10-11T09:15:00,2026-10-11T09:33:00,success\nsync-inventory,2026-10-11T09:30:00,2026-10-11T09:31:00,error\nsync-inventory,2026-10-11T09:45:00,2026-10-11T10:04:00,success\npython3 build_report.py,2026-10-10T02:00:00,2026-10-10T02:40:00,success\npython3 build_report.py,2026-10-11T02:00:00,2026-10-11T02:52:00,success\n",
                    "timeZone": "Europe/Berlin",
                    "from": "2026-10-12T08:00",
                    "count": 5
                  }
                },
                "example2": {
                  "summary": "DST weekend: fall-back night 25 Oct 2026",
                  "value": {
                    "crontab": "# hourly-ish ETL\n30 2 * * * /opt/etl/nightly.sh # nightly-etl\n*/30 1-3 * * * /opt/etl/poll.sh # poller\n0 30 2 * * ? # quartz-0230",
                    "timeZone": "Europe/Berlin",
                    "from": "2026-10-24T12:00",
                    "count": 6,
                    "horizonHours": 48
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Calculation result envelope.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CronJobExplorerResult"
                }
              }
            }
          },
          "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"
                }
              }
            }
          }
        }
      },
      "CronJobExplorerInput": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "crontab": {
            "title": "Crontab / schedules",
            "description": "One job per line. CRON_TZ=Zone lines change the zone for following jobs. A trailing \"# name\" or the comment line above names a job. Kubernetes CronJob / GitHub Actions YAML documents can be pasted too (separate with ---).",
            "type": "string",
            "maxLength": 200000
          },
          "history": {
            "title": "Run history CSV (optional)",
            "description": "Header job,start,end,status (optional attempt). Times without offset are read in the selected time zone. Job names match the job name or appear in its command.",
            "type": "string",
            "maxLength": 400000
          },
          "timeZone": {
            "title": "Time zone",
            "description": "IANA zone used for jobs without their own CRON_TZ / timeZone, and for displaying times.",
            "type": "string",
            "maxLength": 64,
            "default": "UTC"
          },
          "from": {
            "title": "Start from (local time)",
            "description": "Defaults to now. Local date-time YYYY-MM-DDTHH:mm",
            "type": "string"
          },
          "count": {
            "title": "Next runs per job",
            "type": "integer",
            "minimum": 1,
            "maximum": 50,
            "default": 5
          },
          "format": {
            "title": "Expression format",
            "type": "string",
            "enum": [
              "auto",
              "standard",
              "seconds",
              "quartz"
            ],
            "default": "auto"
          },
          "dstPolicy": {
            "title": "DST handling",
            "type": "string",
            "enum": [
              "auto",
              "vixie",
              "wall-clock"
            ],
            "default": "auto"
          },
          "horizonHours": {
            "title": "Analysis window",
            "description": "Window for the timeline, herd minutes and overlaps.",
            "type": "integer",
            "minimum": 1,
            "maximum": 168,
            "default": 24,
            "x-unit": "hours"
          },
          "herdThreshold": {
            "title": "Herd threshold",
            "description": "Flag minutes where at least this many jobs start together.",
            "type": "integer",
            "minimum": 2,
            "maximum": 100,
            "default": 3
          }
        },
        "required": [
          "crontab"
        ]
      },
      "CronJobExplorerResult": {
        "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": [
              "timeZone",
              "from",
              "jobs",
              "herdMinutes",
              "overlaps",
              "history",
              "peakConcurrency"
            ],
            "properties": {
              "timeZone": {
                "type": "string"
              },
              "from": {
                "type": "string"
              },
              "jobs": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "name",
                    "schedule",
                    "format",
                    "source",
                    "timeZone",
                    "command",
                    "line",
                    "description",
                    "valid",
                    "error",
                    "suspended",
                    "fixedTime",
                    "dstPolicy",
                    "nextRuns",
                    "runsInWindow",
                    "minIntervalMinutes",
                    "notes"
                  ],
                  "properties": {
                    "name": {
                      "type": "string"
                    },
                    "schedule": {
                      "type": "string"
                    },
                    "format": {
                      "type": "string"
                    },
                    "source": {
                      "type": "string",
                      "enum": [
                        "crontab",
                        "kubernetes",
                        "github-actions"
                      ]
                    },
                    "timeZone": {
                      "type": "string"
                    },
                    "command": {
                      "type": "string"
                    },
                    "line": {
                      "type": "integer"
                    },
                    "description": {
                      "type": "string"
                    },
                    "valid": {
                      "type": "boolean"
                    },
                    "error": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "suspended": {
                      "type": "boolean"
                    },
                    "fixedTime": {
                      "type": "boolean"
                    },
                    "dstPolicy": {
                      "type": "string"
                    },
                    "nextRuns": {
                      "type": "array",
                      "items": {
                        "type": "object",
                        "additionalProperties": false,
                        "required": [
                          "utc",
                          "local",
                          "offset",
                          "dst"
                        ],
                        "properties": {
                          "utc": {
                            "type": "string"
                          },
                          "local": {
                            "type": "string"
                          },
                          "offset": {
                            "type": "string"
                          },
                          "dst": {
                            "type": [
                              "string",
                              "null"
                            ]
                          }
                        }
                      }
                    },
                    "runsInWindow": {
                      "type": "integer",
                      "minimum": 0
                    },
                    "minIntervalMinutes": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "notes": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              },
              "herdMinutes": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "utc",
                    "local",
                    "jobs"
                  ],
                  "properties": {
                    "utc": {
                      "type": "string"
                    },
                    "local": {
                      "type": "string"
                    },
                    "jobs": {
                      "type": "array",
                      "items": {
                        "type": "string"
                      }
                    }
                  }
                }
              },
              "overlaps": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "a",
                    "b",
                    "sharedStarts",
                    "identical"
                  ],
                  "properties": {
                    "a": {
                      "type": "string"
                    },
                    "b": {
                      "type": "string"
                    },
                    "sharedStarts": {
                      "type": "integer"
                    },
                    "identical": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "history": {
                "type": "array",
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "job",
                    "matchedJob",
                    "runs",
                    "failures",
                    "timeouts",
                    "retries",
                    "successRate",
                    "avgDurationMin",
                    "p95DurationMin",
                    "maxDurationMin",
                    "lastStatus",
                    "lastStart",
                    "exceedsInterval",
                    "missedRuns"
                  ],
                  "properties": {
                    "job": {
                      "type": "string"
                    },
                    "matchedJob": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "runs": {
                      "type": "integer"
                    },
                    "failures": {
                      "type": "integer"
                    },
                    "timeouts": {
                      "type": "integer"
                    },
                    "retries": {
                      "type": "integer"
                    },
                    "successRate": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "avgDurationMin": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "p95DurationMin": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "maxDurationMin": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "lastStatus": {
                      "type": "string"
                    },
                    "lastStart": {
                      "type": "string"
                    },
                    "exceedsInterval": {
                      "type": "boolean"
                    },
                    "missedRuns": {
                      "type": [
                        "integer",
                        "null"
                      ]
                    }
                  }
                }
              },
              "peakConcurrency": {
                "type": [
                  "object",
                  "null"
                ],
                "additionalProperties": false,
                "properties": {
                  "count": {
                    "type": "integer"
                  },
                  "local": {
                    "type": "string"
                  },
                  "jobs": {
                    "type": "array",
                    "items": {
                      "type": "string"
                    }
                  }
                }
              }
            }
          },
          "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"
              }
            }
          }
        }
      }
    }
  }
}