AnvilJSON utilities

Anvil › Docs › /v1/cron/next

Cron next run API: when will this cron expression run?

Paste a cron expression and a time zone and see exactly when it will fire next, in local time, UTC and as Unix timestamps. Handy for checking a schedule before you deploy it, or for showing users "next run" in your own app.

In one line: GET /v1/cron/next?expr=30%209%20%2A%20%2A%201-5&tz=Europe/London&count=5 returns JSON. No key, CORS on, 60 requests a minute.
GET

/v1/cron/next

When will a cron schedule run next?. Change the values and press Send request to call the live API.

Parameters

NameTypeWhat it doesDefault
expr requiredstring5-field cron expression or @daily, @hourly…—
tzstringTime zone the schedule runs inUTC
countinteger1 to 505
fromstringStart after this moment (ISO 8601 / Unix)now

Example

Request:

GET https://api.oddlathe.com/v1/cron/next?expr=30%209%20%2A%20%2A%201-5&tz=Europe/London&count=5

Response (generated by the real code when these docs were last built; random or time-based values will differ for you):

{
 "expr": "30 9 * * 1-5",
 "timezone": "Europe/London",
 "from": "2026-11-12T01:21:01+00:00",
 "runs": [
  {
   "local": "2026-11-12T09:30+00:00",
   "utc": "2026-11-12T09:30Z",
   "weekday": "Thursday",
   "unix": 1794475800
  },
  {
   "local": "2026-11-13T09:30+00:00",
   "utc": "2026-11-13T09:30Z",
   "weekday": "Friday",
   "unix": 1794562200
  },
  {
   "local": "2026-11-16T09:30+00:00",
   "utc": "2026-11-16T09:30Z",
   "weekday": "Monday",
   "unix": 1794821400
  },
  {
   "local": "2026-11-17T09:30+00:00",
   "utc": "2026-11-17T09:30Z",
   "weekday": "Tuesday",
   "unix": 1794907800
  },
  {
   "local": "2026-11-18T09:30+00:00",
   "utc": "2026-11-18T09:30Z",
   "weekday": "Wednesday",
   "unix": 1794994200
  }
 ]
}

Code examples

curl
curl -G 'https://api.oddlathe.com/v1/cron/next' \
  --data-urlencode 'expr=30 9 * * 1-5' \
  --data-urlencode 'tz=Europe/London' \
  --data-urlencode 'count=5'
JavaScript (browser or Node 18+)
const params = new URLSearchParams({
  expr: "30 9 * * 1-5",
  tz: "Europe/London",
  count: "5"
});
const res = await fetch(`https://api.oddlathe.com/v1/cron/next?${params}`);
if (!res.ok) throw new Error((await res.json()).error.message);
const data = await res.json();
console.log(data);
Python (standard library only)
import json, urllib.parse, urllib.request

params = urllib.parse.urlencode({"expr": "30 9 * * 1-5", "tz": "Europe/London", "count": "5"})
url = "https://api.oddlathe.com/v1/cron/next?" + params
# Send a User-Agent: the edge network refuses Python's default one.
req = urllib.request.Request(url, headers={"User-Agent": "my-script/1.0"})
with urllib.request.urlopen(req, timeout=10) as r:
    data = json.load(r)
print(data)

When it's useful

  • Sanity-checking crontab, Kubernetes CronJob or CI schedules
  • Showing "next backup at…" in an admin page
  • Spotting expressions that never run, like 30 February

Good to know

  • Five fields: minute, hour, day of month, month, day of week. Lists (1,15), ranges (9-17), steps (*/15), names (mon-fri, jan), 7 as Sunday, and @hourly, @daily, @weekly, @monthly, @yearly.
  • The OR rule: if both day-of-month and day-of-week are restricted, a day matching either one counts. 0 9 1 * mon runs on the 1st and every Monday.
  • Times skipped when clocks go forward are left out; times that repeat when clocks go back run once.
  • Encode spaces in the URL as %20 (curl's --data-urlencode with -G does it for you, as in the examples).

Supports lists, ranges, steps, month and weekday names, 7 as Sunday, and the classic rule that when both day-of-month and day-of-week are restricted, either one matching is enough. Local times skipped by a DST change are left out; repeated times run once.

Errors

Errors are JSON like {"error": {"code": "…", "message": "…"}}. The ones this endpoint can return:

  • missing_param (400): a required parameter is missing or empty
  • bad_param (400): a value is the wrong type or out of range (the message says which)
  • bad_timezone (400): the zone isn't a known IANA name
  • bad_cron (400): the expression can't be parsed; the message names the field
  • rate_limited (429): over 60 requests a minute; wait for Retry-After seconds

Questions

Does it support seconds or a year field?

No. It follows classic 5-field cron (Vixie cron), which is what crontab, most CI systems and Kubernetes use.

Why does GitHub Actions run my job later than this says?

GitHub schedules are in UTC and often start several minutes late under load. Use tz=UTC to match them.

What does */7 in the minute field mean?

Minutes 0, 7, 14 … 56, then 0 again, so the gap across the hour is only 4 minutes. Steps restart every hour.

Related endpoints

Prefer a page to an API?

Published , updated · OpenAPI 3.1 spec · Limits and privacy