# Cron Expression Builder & Validator (`perryay/cron-expression-builder-validator`) Actor

Parse, validate, and explain cron scheduling expressions with syntax validation, next-execution calculation, human-readable descriptions, batch validation (100+ expressions), and full schedule auditing with overlap and gap detection. Ideal for DevOps, SRE, and platform engineering teams.

- **URL**: https://apify.com/perryay/cron-expression-builder-validator.md
- **Developed by:** [Perry AY](https://apify.com/perryay) (community)
- **Categories:** Developer tools, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.02 / actor start

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Cron Expression Builder & Validator

### Cron Expression Builder & Validator

**Parse, validate, and explain cron scheduling expressions with enterprise-grade precision.** Designed for DevOps engineers, SRE teams, platform engineering, and CI/CD automation pipelines.

---

### What does it do?

This actor parses any standard 5-field cron expression and returns:

- **Syntax validation** — field-level error messages identifying the exact field and issue
- **Human-readable description** — converts `*/5 * * * *` → "Every 5 minutes"
- **Next execution times** — calculates the next 1–20 run timestamps in the requested timezone
- **Field-by-field analysis** — breaks down each of the 5 cron fields with individual descriptions
- **Batch validation** — validate and describe up to 100 expressions in a single run
- **Schedule audit** — overlap detection, gap analysis over 48-hour windows, and conflict identification
- **Macro resolution** — understands `@yearly`, `@monthly`, `@weekly`, `@daily`, `@hourly` and other standard macros

Three operation modes power the entire workflow:

| Mode | Purpose | Input |
|------|---------|-------|
| **validate** | Single-expression parsing, validation, and explanation | `expression` string |
| **batch** | Multi-expression validation (up to 100) | `expressions` text or `batchData` array |
| **audit** | Overlap/gap detection across a fleet of schedules | `batchData` array with labels |

---

### Features

| Feature | Description |
|---------|-------------|
| **Syntax Validation** | Field-level validation with precise error messages identifying the exact field and issue |
| **Human-Readable Description** | Converts `*/5 * * * *` → "Every 5 minutes" with rich natural-language output |
| **Next Execution Times** | Calculates the next 1–20 run timestamps in UTC with full ISO 8601 precision |
| **Field-by-Field Explanation** | Breaks down each of the 5 cron fields with individual descriptions |
| **Batch Validation** | Validate and describe up to 100 expressions in a single run with structured I/O |
| **Schedule Audit** | Full schedule analysis — overlap detection between schedules, gap analysis over 48h windows, and conflict identification |
| **Dual Input Modes** | Plain-text textarea for quick use, structured JSON array for programmatic API access |
| **Timezone Support** | Specify IANA timezone for next-execution calculation (defaults to UTC) |
| **Macro Resolution** | Understands `@yearly`, `@monthly`, `@weekly`, `@daily`, `@hourly` and other standard macros |

---

### Why use this?

Cron expressions are deceptively simple. A single misplaced `*` or off-by-one range can silently break a production pipeline, trigger a billing overrun, or cause a missed SLA. This actor eliminates that risk by giving every team member — from junior devs to veteran SREs — a precise, programmatic way to validate and understand cron schedules.

| Problem | Symptom | How This Actor Helps |
|---------|---------|----------------------|
| **Silent syntax errors** | Deploy passes but job never runs; first alert comes at 3 AM | Field-level error messages catch every syntax mistake before deployment |
| **Unintended execution times** | "Every hour" cron triggers every minute — API endpoint overwhelmed | Human-readable description catches intent-vs-reality mismatches instantly |
| **Overlapping schedules** | Two backup jobs run simultaneously, both fail from resource contention | Schedule audit detects exact overlaps, time proximity, and description collisions |
| **Coverage gaps** | No scheduled task runs for 8+ hours during a critical batch window | Gap analysis flags periods longer than 4 hours with no activity |
| **Timezone confusion** | Cron deployed in UTC but expected in local time — jobs run at wrong local hour | IANA timezone-aware next-execution calculation prevents scheduling drift |
| **Inconsistent cron formats** | Team mixes 5-field, 6-field, and non-standard notations across repos | Strict 5-field validation enforces consistency and rejects non-standard formats |
| **Audit/compliance burden** | Manual cron reviews take hours; human reviewers miss edge cases | Automated batch audit produces a complete overlap/gap report in seconds |

Without automated validation, cron fleets drift into silent failure. A `0 3 * * *` intended as daily at 3 AM but typed as `0 3 * * 0` (Sundays only) can go undetected until an incident post-mortem. This actor catches those mistakes the moment the expression is submitted — before it reaches production.

---

### Who is it for?

| Persona | Use Case | Value |
|---------|----------|-------|
| **DevOps Engineer** | Validate cron expressions before deploying to production | Catch syntax errors early, prevent silent schedule failures |
| **SRE / On-Call Engineer** | Audit existing cron fleets for overlaps and scheduling gaps | Prevent resource contention, ensure coverage during critical windows |
| **Platform Engineer** | Automate cron validation in CI/CD pipelines | Gate deployments on valid cron configurations |
| **Data Engineer** | Validate ETL pipeline schedules | Ensure data processing jobs run at correct intervals |
| **Developer** | Understand what a cron expression means without manual parsing | Convert cryptic cron strings to plain English instantly |
| **Technical Writer** | Document cron schedules in runbooks | Generate accurate human-readable schedule descriptions |
| **QA Engineer** | Test cron expression inputs in staging | Verify edge cases, ranges, and step patterns before production |

---

### Input Parameters

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `action` | string | `"validate"` | Operation mode: `validate`, `batch`, or `audit` |
| `expression` | string | — | A 5-field cron expression (required for single validation) |
| `expressions` | text | — | One cron expression per line for batch/audit mode |
| `batchData` | array | — | Structured JSON array of expression objects with optional `id` and `label` |
| `nextCount` | integer | `5` | Number of future execution times to calculate (1–20) |
| `batchMode` | boolean | `false` | Toggle structured batch input |
| `timezone` | string | `"UTC"` | IANA timezone for execution time calculation |

#### Supported Cron Field Values

| Pattern | Example | Valid? |
|---------|---------|--------|
| Wildcard | `*` | ✅ Every valid time unit |
| Number | `5` | ✅ Within field range |
| Range | `1-5` | ✅ From 1 to 5 |
| Step | `*/15` | ✅ Every 15 units |
| Range+Step | `1-30/3` | ✅ Every 3 within range |
| List | `1,15,30` | ✅ Comma-separated values |
| All combined | `1-5,10,20-30/2` | ✅ Complex expressions |

#### Field Ranges

| Field | Valid Values |
|-------|-------------|
| Minute | 0–59 |
| Hour | 0–23 |
| Day of Month | 1–31 |
| Month | 1–12 |
| Day of Week | 0–7 (0 and 7 = Sunday) |

---

### Output Format

#### Validate (single)

```json
{
  "expression": "*/5 * * * *",
  "valid": true,
  "description": "Every 5 minutes",
  "nextTimes": [
    "2026-07-20 10:00 UTC",
    "2026-07-20 10:05 UTC",
    "2026-07-20 10:10 UTC",
    "2026-07-20 10:15 UTC",
    "2026-07-20 10:20 UTC"
  ],
  "errors": [],
  "fieldAnalysis": {
    "minute": "*/5",
    "hour": "*",
    "day_of_month": "*",
    "month": "*",
    "day_of_week": "*"
  }
}
````

#### Batch

```json
{
  "expression": "0 9 * * 1-5",
  "valid": true,
  "description": "Weekdays at 9:00 AM",
  "errors": [],
  "id": "daily-report",
  "label": "Daily Report Generation"
}
```

#### Audit

```json
{
  "summary": {
    "total": 3,
    "valid": 3,
    "invalid": 0,
    "overlaps": 1,
    "gaps": 2
  },
  "results": [ ... ],
  "overlaps": [
    {
      "indexA": 0,
      "indexB": 1,
      "expressionA": "0 * * * *",
      "expressionB": "30 * * * *",
      "severity": "time_proximity",
      "description": "Schedules run within 5 seconds of each other (positions 0 and 1)"
    }
  ],
  "gaps": [
    {
      "gapStart": "2026-07-22 02:00 UTC",
      "gapEnd": "2026-07-22 08:00 UTC",
      "durationHours": 6.0,
      "durationDescription": "6h 0m"
    }
  ]
}
```

#### Invalid Expression

```json
{
  "expression": "60 * * * *",
  "valid": false,
  "description": "",
  "nextTimes": [],
  "errors": ["minute: value 60 out of range [0, 59]"],
  "fieldAnalysis": {}
}
```

***

### API Usage

#### cURL (API)

```bash
## Single expression validation
curl -s "https://api.apify.com/v2/acts/perryay~cron-expression-builder-validator/runs?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "validate",
    "expression": "*/5 * * * *",
    "nextCount": 5
  }'

## Batch validation
curl -s "https://api.apify.com/v2/acts/perryay~cron-expression-builder-validator/runs?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "batch",
    "expressions": "*/5 * * * *\n0 9 * * 1-5\n0 0 1 * *"
  }'

## Schedule audit
curl -s "https://api.apify.com/v2/acts/perryay~cron-expression-builder-validator/runs?token=<YOUR_API_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{
    "action": "audit",
    "batchData": [
      {"id": "health", "expression": "*/5 * * * *", "label": "Health Check"},
      {"id": "report", "expression": "0 9 * * 1-5", "label": "Daily Report"},
      {"id": "backup", "expression": "0 0 1 * *", "label": "Monthly Backup"}
    ]
  }'
```

#### Python (Apify Client)

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

## ── Single Validation ──
result = client.actor("perryay~cron-expression-builder-validator").call(
    run_input={
        "action": "validate",
        "expression": "*/5 * * * *",
        "nextCount": 5,
    }
)
dataset = client.dataset(result["defaultDatasetId"]).list_items()
for item in dataset.items:
    print(f"Valid: {item['valid']}")
    print(f"Description: {item['description']}")
    print(f"Next times: {item['nextTimes']}")

## ── Batch Validation ──
result = client.actor("perryay~cron-expression-builder-validator").call(
    run_input={
        "action": "batch",
        "batchData": [
            {"id": "job-1", "expression": "*/5 * * * *", "label": "Metrics"},
            {"id": "job-2", "expression": "0 9 * * 1-5", "label": "Report"},
        ],
    }
)

## ── Schedule Audit ──
result = client.actor("perryay~cron-expression-builder-validator").call(
    run_input={
        "action": "audit",
        "batchData": [
            {"id": "a", "expression": "0 * * * *"},
            {"id": "b", "expression": "30 * * * *"},
            {"id": "c", "expression": "0 0 * * *"},
        ],
    }
)
dataset = client.dataset(result["defaultDatasetId"]).list_items()
print(dataset.items[0]["summary"])
print(f"Overlaps found: {dataset.items[0]['overlaps']}")
```

#### Node.js (Apify Client)

```javascript
const ApifyClient = require('apify-client');

const client = new ApifyClient({ token: '<YOUR_API_TOKEN>' });

const result = await client.actor('perryay~cron-expression-builder-validator').call({
    action: 'validate',
    expression: '*/5 * * * *',
    nextCount: 5,
});

const dataset = await client.dataset(result.defaultDatasetId).listItems();
console.log(dataset.items[0].description); // "Every 5 minutes"
```

***

### Use Cases

#### 1. CI/CD Pipeline Gate

**Scenario:** A platform engineering team manages 200+ microservices, each with a cron-driven scheduled job. Developers frequently push cron expressions in their deployment manifests that are syntactically valid but semantically wrong — a `0 0 * * 0` instead of `0 0 * * *`, causing a daily ETL to run only on Sundays.

**How this actor helps:** Embed the actor into the CI/CD pipeline as a pre-deployment validation step. Every pull request that modifies a cron expression triggers a batch validation run. Invalid expressions block the PR with a detailed error message; valid expressions are approved automatically. The team catches cron bugs at merge time instead of incident time.

**Integration pattern:**

```bash
## GitHub Actions step
- name: Validate cron expressions
  run: |
    curl -s "https://api.apify.com/v2/acts/perryay~cron-expression-builder-validator/runs?token=${{ secrets.APIFY_TOKEN }}" \
      -H "Content-Type: application/json" \
      -d '{"action":"batch","expressions":"'"$(cat cron-expressions.txt)"'"}'
```

#### 2. Production Cron Fleet Audit

**Scenario:** An SRE team inherits a legacy system with 50+ cron jobs across 3 clusters. No one remembers the full schedule, and the team suspects overlapping backup windows are causing intermittent failures.

**How this actor helps:** Run the entire cron fleet through audit mode in a single API call. The actor returns a complete overlap/gap report: which jobs collide, which time slots have no coverage, and how long each gap lasts. The team can immediately identify the overlapping backup jobs causing contention and redistribute their schedules.

**Integration pattern:**

```python
audit_input = {
    "action": "audit",
    "batchData": [
        {"id": f"job-{i}", "expression": expr}
        for i, expr in enumerate(cron_fleet)
    ]
}
```

#### 3. ETL Pipeline Scheduling

**Scenario:** A data engineering team runs hourly aggregations, daily rollups, and monthly archive jobs across a data warehouse. A misconfigured cron causes the daily rollup to trigger before the hourly aggregation window closes, producing stale data.

**How this actor helps:** Validate each pipeline stage's cron expression before deployment and use the `description` field to confirm scheduling intent at a glance. The `nextTimes` output makes it easy to verify that downstream jobs always start after upstream ones complete.

**Integration pattern:**

```json
{
  "action": "validate",
  "expression": "45 3 * * *",
  "nextCount": 3,
  "timezone": "America/New_York"
}
```

#### 4. On-Call Schedule Handoff Documentation

**Scenario:** A new SRE joins the team and needs to understand the existing cron-based maintenance windows. The current runbook has vague descriptions like "runs periodically."

**How this actor helps:** Generate accurate, human-readable descriptions for every cron expression in the runbook. The `fieldAnalysis` output provides a structured breakdown for documentation generation, and `nextTimes` gives concrete future execution timestamps that the new hire can verify.

**Integration pattern:**

```python
for cron_line in cron_schedules:
    result = client.actor("perryay~cron-expression-builder-validator").call({
        "action": "validate",
        "expression": cron_line,
        "nextCount": 5
    })
    item = client.dataset(result["defaultDatasetId"]).list_items()[0]
    runbook.append(f"- `{cron_line}` → {item['description']}")
```

#### 5. Infrastructure Migration Validation

**Scenario:** A team is migrating from a legacy scheduling system to modern infrastructure. Hundreds of cron expressions need to be ported, and even one mis-typed expression could cause a missed ETL or a billing overrun.

**How this actor helps:** Batch-validate all migrated cron expressions before applying them to production. Pass the entire migration manifest through batch mode — invalid expressions are flagged with field-level errors, and the human-readable descriptions serve as a cross-check against the original schedules.

**Integration pattern:**

```json
{
  "action": "batch",
  "batchMode": true,
  "batchData": [
    {"id": "migrated-001", "expression": "0 */4 * * *", "label": "Legacy Backup v1"},
    {"id": "migrated-002", "expression": "30 2 * * 1", "label": "Weekly Report v2"}
  ]
}
```

#### 6. Multi-Region Scheduling

**Scenario:** A global SaaS company runs cron jobs across AWS regions (us-east-1, eu-west-1, ap-southeast-1). A scheduled maintenance window that looks correct in UTC runs at 3 AM local time in some regions but 3 PM local in others.

**How this actor helps:** Pass the `timezone` parameter to calculate next execution times in the target region's local time. Verify that the cron expression produces the intended local-time schedule before deploying to each region.

```python
for region, tz in [("us-east-1", "America/New_York"),
                   ("eu-west-1", "Europe/London"),
                   ("ap-southeast-1", "Asia/Singapore")]:
    result = client.actor("perryay~cron-expression-builder-validator").call({
        "action": "validate",
        "expression": "0 3 * * *",
        "timezone": tz,
        "nextCount": 3
    })
    print(f"{region}: {result['nextTimes']}")
```

#### 7. Security & Compliance Audit

**Scenario:** A compliance auditor requires evidence that no cron jobs run during a blackout window (e.g., 02:00–04:00 UTC during database maintenance). Manually reviewing 100+ cron expressions is error-prone and infeasible for each audit cycle.

**How this actor helps:** Run the full cron fleet through audit mode and inspect the `gaps` array for compliance. The structured JSON output serves as auditable evidence that can be included in compliance reports. Repeat on each audit cycle with a single API call.

#### 8. Developer Education & Onboarding

**Scenario:** New developers frequently struggle with cron syntax, especially complex patterns like `0 0/2 * * 1-5` (every 2 hours on weekdays). This leads to frequent PR revisions and delayed deployments.

**How this actor helps:** Developers paste their cron expression into the actor (via console or API) and immediately receive a plain-English description alongside the field analysis. The instant feedback loop teaches correct cron syntax organically, reducing PR cycle time.

***

### FAQ

**Q1: What cron expression format does this tool support?**
A: Standard 5-field UNIX cron format: `minute hour day-of-month month day-of-week`. Also supports common macros `@yearly`, `@monthly`, `@weekly`, `@daily`, `@hourly`, `@annually`, and `@midnight`.

**Q2: What's the maximum number of expressions for batch validation?**
A: Up to 100 expressions per run. Input beyond 100 is silently truncated.

**Q3: Does this support timezone-aware scheduling?**
A: Yes. You can pass an IANA timezone string (e.g. `Europe/London`, `America/New_York`, `Asia/Tokyo`) in the `timezone` field. Default is UTC.

**Q4: What does the "Schedule Audit" mode detect?**
A: Three levels of overlap: 1) **exact\_duplicate** — same expression at multiple positions, 2) **description\_collision** — different expressions with the same schedule frequency, 3) **time\_proximity** — expressions whose next execution times are within 60 seconds of each other.

**Q5: How are execution times calculated?**
A: Uses the `croniter` Python library which accurately computes the next N future timestamps from the current UTC time. Times are returned in ISO 8601 format with the requested timezone.

**Q6: Can I use this in a CI/CD pipeline?**
A: Yes. The actor accepts JSON input via API and returns structured results. Use the Apify Client SDKs for Python, JavaScript, or direct cURL calls. Example: validate all cron expressions in your infrastructure-as-code repository before deployment.

**Q7: What happens if my expression is invalid?**
A: The `errors` array contains precise error messages identifying which field failed and why (e.g., `"minute: value 60 out of range [0, 59]"`). The `valid` field will be `false`.

**Q8: Does it support non-standard cron formats (like 6-field with seconds)?**
A: No. This tool strictly validates 5-field standard UNIX cron expressions. Expressions with seconds, years, or other extended fields will be rejected.

**Q9: How accurate is the "human-readable description"?**
A: Very high for common patterns — the tool includes a dictionary of 30+ common patterns. For custom expressions, it generates a dynamic description from field-level analysis. Complex expressions with multiple ranges or lists may produce generic descriptions.

**Q10: Is there a limit on how many expressions I can process?**
A: Up to 100 expressions per run in batch or audit mode. For larger workloads, split across multiple runs.

**Q11: Is there an MCP server for this actor?**
A: Yes. See the MCP Integration section for configuration details.

**Q12: What is the `fieldAnalysis` output?**
A: A per-field breakdown of the cron parts — `minute`, `hour`, `day_of_month`, `month`, and `day_of_week`. Each shows the raw value, making it easy to see exactly what each field contains.

**Q13: How does gap detection work in audit mode?**
A: It collects the next 10 execution timestamps for each valid expression over a 48-hour window, sorts them, and flags any period longer than 4 hours between consecutive runs.

***

### Usage & Billing

This actor uses Apify's **PAY\_PER\_EVENT** pricing model. You are charged only for successful runs based on the events your usage triggers.

#### Charge Events

| Event | Trigger |
|-------|--------|
| `apify-actor-start` | Every run (base) |
| `schedule-audit` | Audit mode with overlap and gap analysis |

Platform costs (Apify's infrastructure fee) are passed through to the customer. No monthly minimum commitment.

***

### MCP Integration

This actor can be used through the [Apify MCP server](https://docs.apify.com/integrations/mcp). Once connected, your MCP client (Claude Desktop, Cursor, etc.) can discover and run this actor from the Apify Store.

#### Quick Start

1. **Install the Apify connector** in your MCP client:
   - **Claude Desktop**: Search for "Apify" in the connector directory, or use the remote server at `https://mcp.apify.com`
   - **Other clients**: See the [Apify MCP server docs](https://docs.apify.com/integrations/mcp) for setup instructions

2. **Ask your AI assistant** to use the actor. For example:
   > "Validate the cron expression `0 2 * * *` and tell me when it runs"
   >
   > "Audit these three schedules for overlaps: `*/5 * * * *`, `0 9 * * 1-5`, and `0 0 1 * *`"

#### Claude Desktop Configuration

Add the following to your `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com"
    }
  }
}
```

On first connection, your browser opens to sign in to Apify and authorize access.

> **Bearer token alternative:** For headless environments, CI/CD pipelines, or clients without browser-based OAuth, you can authenticate directly with your Apify API token:
>
> ```json
> {
>   "mcpServers": {
>     "apify": {
>       "url": "https://mcp.apify.com",
>       "headers": {
>         "Authorization": "Bearer YOUR_APIFY_TOKEN"
>       }
>     }
>   }
> }
> ```
>
> Get your API token from [Apify Console](https://console.apify.com) → **API & Integrations** section.

***

### Related Tools

- **[Subdomain Enumeration via CT](https://apify.com/perryay/subdomain-enumeration-ct-logs)** — Discover and monitor subdomains from Certificate Transparency logs alongside your cron-based monitoring schedules.
- **[HTTP Security Headers Analyzer](https://apify.com/perryay/http-security-headers-analyzer)** — Schedule regular security header audits for your web infrastructure with cron-triggered batch scanning.
- **[Website Tech Stack Detector](https://apify.com/perryay/website-tech-stack-detector)** — Automate periodic technology stack discovery to detect platform changes and version drift.
- **[Phishing URL Risk Scorer](https://apify.com/perryay/phishing-url-risk-scorer)** — Build scheduled URL risk scoring pipelines to monitor for newly emerged phishing domains.

# Actor input Schema

## `action` (type: `string`):

Operation mode: validate a single expression, batch-validate multiple expressions, or run a full schedule audit with overlap and gap detection

## `expression` (type: `string`):

A standard 5-field cron expression to validate and explain. Example: \*/5 \* \* \* \* runs every 5 minutes

## `expressions` (type: `string`):

One cron expression per line for batch validation or schedule audit mode. Up to 100 expressions supported

## `nextCount` (type: `integer`):

Number of upcoming execution times to calculate (1–20, default 5)

## `batchMode` (type: `boolean`):

Enable to provide expressions as a structured JSON array instead of plain text (requires batchData)

## `batchData` (type: `array`):

JSON array of expression objects for programmatic batch validation. Each object must have an 'expression' field. Optionally include 'id' or 'label' for cross-referencing results

## `timezone` (type: `string`):

IANA timezone for next-execution calculation (default: UTC). Examples: America/New\_York, Europe/London, Asia/Tokyo

## Actor input object example

```json
{
  "action": "validate",
  "expression": "*/5 * * * *",
  "expressions": "*/5 * * * *\n0 9 * * 1-5\n0 0 1 * *\n0 0 * * 0\n30 4 * * 1-5",
  "nextCount": 5,
  "batchMode": false,
  "batchData": [
    {
      "id": "job-alpha",
      "expression": "*/5 * * * *",
      "label": "Health Check"
    },
    {
      "id": "job-beta",
      "expression": "0 9 * * 1-5",
      "label": "Daily Report"
    },
    {
      "id": "job-gamma",
      "expression": "0 0 1 * *",
      "label": "Monthly Archive"
    }
  ],
  "timezone": "UTC"
}
```

# Actor output Schema

## `results` (type: `string`):

Validation, batch, and audit results in the default dataset — one item per expression evaluated

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "expression": "*/5 * * * *",
    "expressions": `*/5 * * * *
0 9 * * 1-5
0 0 1 * *
0 0 * * 0
30 4 * * 1-5`,
    "batchData": [
        {
            "id": "job-alpha",
            "expression": "*/5 * * * *",
            "label": "Health Check"
        },
        {
            "id": "job-beta",
            "expression": "0 9 * * 1-5",
            "label": "Daily Report"
        },
        {
            "id": "job-gamma",
            "expression": "0 0 1 * *",
            "label": "Monthly Archive"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("perryay/cron-expression-builder-validator").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "expression": "*/5 * * * *",
    "expressions": """*/5 * * * *
0 9 * * 1-5
0 0 1 * *
0 0 * * 0
30 4 * * 1-5""",
    "batchData": [
        {
            "id": "job-alpha",
            "expression": "*/5 * * * *",
            "label": "Health Check",
        },
        {
            "id": "job-beta",
            "expression": "0 9 * * 1-5",
            "label": "Daily Report",
        },
        {
            "id": "job-gamma",
            "expression": "0 0 1 * *",
            "label": "Monthly Archive",
        },
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("perryay/cron-expression-builder-validator").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "expression": "*/5 * * * *",
  "expressions": "*/5 * * * *\\n0 9 * * 1-5\\n0 0 1 * *\\n0 0 * * 0\\n30 4 * * 1-5",
  "batchData": [
    {
      "id": "job-alpha",
      "expression": "*/5 * * * *",
      "label": "Health Check"
    },
    {
      "id": "job-beta",
      "expression": "0 9 * * 1-5",
      "label": "Daily Report"
    },
    {
      "id": "job-gamma",
      "expression": "0 0 1 * *",
      "label": "Monthly Archive"
    }
  ]
}' |
apify call perryay/cron-expression-builder-validator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=perryay/cron-expression-builder-validator",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Cron Expression Builder & Validator",
        "description": "Parse, validate, and explain cron scheduling expressions with syntax validation, next-execution calculation, human-readable descriptions, batch validation (100+ expressions), and full schedule auditing with overlap and gap detection. Ideal for DevOps, SRE, and platform engineering teams.",
        "version": "2.0",
        "x-build-id": "8zH1dveGIuhSoGiKb"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/perryay~cron-expression-builder-validator/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-perryay-cron-expression-builder-validator",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/perryay~cron-expression-builder-validator/runs": {
            "post": {
                "operationId": "runs-sync-perryay-cron-expression-builder-validator",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/perryay~cron-expression-builder-validator/run-sync": {
            "post": {
                "operationId": "run-sync-perryay-cron-expression-builder-validator",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "action": {
                        "title": "Action",
                        "enum": [
                            "validate",
                            "batch",
                            "audit"
                        ],
                        "type": "string",
                        "description": "Operation mode: validate a single expression, batch-validate multiple expressions, or run a full schedule audit with overlap and gap detection",
                        "default": "validate"
                    },
                    "expression": {
                        "title": "Cron Expression",
                        "type": "string",
                        "description": "A standard 5-field cron expression to validate and explain. Example: */5 * * * * runs every 5 minutes"
                    },
                    "expressions": {
                        "title": "Multiple Expressions",
                        "type": "string",
                        "description": "One cron expression per line for batch validation or schedule audit mode. Up to 100 expressions supported"
                    },
                    "nextCount": {
                        "title": "Next Execution Count",
                        "minimum": 1,
                        "maximum": 20,
                        "type": "integer",
                        "description": "Number of upcoming execution times to calculate (1–20, default 5)",
                        "default": 5
                    },
                    "batchMode": {
                        "title": "Batch Mode",
                        "type": "boolean",
                        "description": "Enable to provide expressions as a structured JSON array instead of plain text (requires batchData)",
                        "default": false
                    },
                    "batchData": {
                        "title": "Batch Expression Array",
                        "type": "array",
                        "description": "JSON array of expression objects for programmatic batch validation. Each object must have an 'expression' field. Optionally include 'id' or 'label' for cross-referencing results",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "string",
                                    "title": "Job ID",
                                    "description": "Unique identifier for the cron job"
                                },
                                "expression": {
                                    "type": "string",
                                    "title": "Cron Expression",
                                    "description": "The 5-field cron expression to validate"
                                },
                                "label": {
                                    "type": "string",
                                    "title": "Label",
                                    "description": "Optional human-readable label for the job"
                                }
                            },
                            "required": [
                                "expression"
                            ]
                        }
                    },
                    "timezone": {
                        "title": "Timezone",
                        "type": "string",
                        "description": "IANA timezone for next-execution calculation (default: UTC). Examples: America/New_York, Europe/London, Asia/Tokyo",
                        "default": "UTC"
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
