01
Getting started
CronEngine calls a URL on a schedule and tells you when it fails. Setting up your first job takes a few minutes.
Add the URL
Create a job, paste the address you want called, and pick the method. Add headers, a body or a login if your endpoint needs them.
Pick a schedule
Use the visual builder, a shortcut such as @daily, or a cron expression. The form shows the next run times.
Test and save
Press Test request to send it once and see the answer. Save, and it runs on schedule from then on.
Want to watch something instead of run it? Use a heartbeat for a script on your own server, or an uptime monitor for a website. Ready-made examples are on the integrations page.
02
Schedules
A schedule is five fields: minute, hour, day of the month, month and weekday. It runs in the timezone set in your account.
| Field | Allowed | Example |
|---|---|---|
| Minute | 0-59 | */5 every 5 minutes |
| Hour | 0-23 | 8,17 at 08:00 and 17:00 |
| Day | 1-31 or L | L the last day of the month |
| Month | 1-12 | 1,7 January and July |
| Weekday | 0-6, 0 is Sunday | 1-5 Monday to Friday |
Each field takes *, a value, a list, a range or a step, such as */15 or 9-17/2.
| Expression | Runs |
|---|---|
*/15 * * * * | Every 15 minutes |
0 8 * * 1-5 | Weekdays at 08:00 |
30 6 1 * * | The 1st of each month at 06:30 |
0 23 L * * | The last day of each month at 23:00 |
Shortcuts: @hourly, @daily (also @midnight), @weekly, @monthly and @yearly (also @annually). @reboot is not supported.
Not sure what to write? Build and check one with the cron expression generator.
Day and weekday together means both
If you fill in both the day of the month and the weekday, the job runs only when both match. 0 9 15 * 1 runs on the 15th only when it is a Monday. Some other cron tools treat this as either one.
Timezone and clock changes
0 9 * * * stays at 09:00 your time all year. When clocks go forward, a time that does not exist that night is skipped. When they go back, a repeated time runs once for each real occurrence.
Once, or after another job
Choose Once to run at a single date and time; it then shows as Completed and uses its own monthly allowance. Choose After a job (Starter and up) to start when another job finishes: after success, after failure, or either way.
03
Requests
Your endpoint has to be reachable from the internet. HTTPS is recommended whenever the request carries anything private.
| Option | Details |
|---|---|
| Method | GET, POST, PUT, PATCH, DELETE or HEAD. |
| Headers | One Name: value per line, up to 8 KB in total. |
| Body | For POST, PUT and PATCH, up to 10 KB, as JSON, form data or plain text. |
| Login | None, Bearer token, or Basic username and password. Encrypted when saved, never shown again. |
| Import | Use Import / Export in the job form to fill it in from a curl command, a CronEngine export or a crontab line. |
The login and content type have their own fields, so they cannot be set as custom headers. Connection-level headers such as Host and User-Agent are set by CronEngine.
Variables
The URL, headers and body can contain these placeholders. They are filled in at the moment the request is sent.
| Variable | Value | Example |
|---|---|---|
| {{job.id}} | This job's numeric id | 57 |
| {{job.name}} | The job name you gave it | Nightly report |
| {{execution.id}} | Id of this run, identical across its retries | exe_290aa7905d54b2220d5430fe650f2e79 |
| {{execution.attempt}} | Attempt number, 1 on the first try | 1 |
| {{execution.scheduled_at}} | When this run was due (UTC) | 2026-09-10T22:00:00Z |
| {{now}} | Current time in UTC | 2026-09-10T22:00:15Z |
| {{now.unix}} | Current time as a Unix timestamp | 1789077615 |
| {{now.date}} | Current date in your timezone | 2026-09-11 |
| {{now.time}} | Current time of day in your timezone | 00:00:15 |
| {{now.local}} | Current time in your timezone | 2026-09-11T00:00:15+02:00 |
https://api.example.com/reports/{{now.date}}
{"job":"{{job.name}}","run":"{{execution.id}}","sent":"{{now}}"}
Values are encoded for where they land, so a quote in a job name cannot break your JSON. Variables cannot be used in the hostname. Anything not in the table, including a typo, is sent exactly as written. Test request shows the finished request.
04
Success and history
By default, any 2xx or 3xx answer counts as success. No answer at all, such as a timeout or a connection error, is always a failure.
Your own rules
Choose which status codes count as success, and add text the reply must or must not contain. Combine the two with and or or.
Redirects
Followed up to 4 times, for scheduled runs and the test button alike. Every new address is checked against the same safety rules.
10 KB of the reply
The first 10 KB is read and used for text checks. Longer replies are marked as truncated.
Every run keeps its status code, duration and any error. Whether the reply itself is saved is up to you: always, only on failure, or never. Each job has a chart, and history can be exported as CSV. How many runs are kept depends on your plan, from 5 on Free to 50 on Enterprise.
05
Retries and overlap
What happens when a run is slow, or fails for a moment.
Overlap protection
On by default. If a job is still running when its next time comes, that occurrence is skipped. A skip is not a failure and sends no alert. Turn it off under Execution behavior if running twice at once is safe.
Retries
Off by default, up to 5 depending on your plan. Only failures a second try could fix are retried: timeouts, dropped connections and answers such as 429, 502 and 503. The wait grows from about 15 seconds to 2 minutes. All attempts count as one run, and you are alerted only once it is over.
Before you turn retries on
Your endpoint receives the same request again, so whatever it does may happen twice. Every attempt of one run carries the same X-CronEngine-Execution-ID header and an increasing X-CronEngine-Attempt, so your endpoint can ignore a repeat. Retries do not give a request more time: each attempt still stops at your plan’s timeout.
On the Free plan, a job that fails 20 times in a row is paused and you get one email. Fix the endpoint and resume it.
06
Heartbeats
A heartbeat watches work that runs on your own machine. Your script calls a private address when it finishes, and you get an alert when that call does not arrive on time. See the overview.
0 3 * * * /usr/local/bin/backup.sh && curl -fsS https://cronengine.com/ping/hb_your-token
The && means the ping is only sent when the script succeeded. Anyone with the address can ping it, so keep it private. Any HTTP method works.
| Address | Means |
|---|---|
/ping/hb_… | Finished, all good. This resets the clock. |
/ping/hb_…/start | Started. Optional, and lets us show how long each run took. |
/ping/hb_…/fail | It broke. Marks it down straight away. |
When is it due?
Every so often, for work that should check in at least every few minutes, hours or days. Or on a schedule with a cron expression, so 0 3 * * 1-5 expects weekday mornings and stays quiet at the weekend.
Grace time
How late a ping may be before it counts as down, so a slow night does not wake you. A heartbeat that has never been pinged shows as Waiting and does not alert.
Pings are free and do not use your scheduled runs. Examples for Laravel, GitHub Actions, Python, Node.js and PowerShell are on the integrations page.
07
Uptime monitors
An uptime monitor checks a public address on a timer and tells you when it stops answering the way it should. See the overview.
| Rule | Example | Catches |
|---|---|---|
| Status codes | 2xx,3xx | Errors, missing pages, a misconfigured domain |
| Page contains | Sign in | A page that loads but shows nothing useful |
| Page does not contain | Database error | An error page that still answers 200 |
Only the first 8 KB of the page is searched, and nothing is stored.
Confirmations and slow answers
A monitor waits for several failed checks in a row before calling a site down (two by default), so one bad second does not alert anyone. Set a slow limit and an answer that takes longer is marked slow.
Certificate expiry
From the Starter plan, a monitor on an https address can warn you before its certificate expires, at countdowns from 90 days down to 1. You can also name the issuer you expect and hear if it changes.
What a check can do
A GET or HEAD request with no headers, body or login, and a fixed 10 second timeout on every plan. To make something happen on a schedule, use a cron job instead.
Checks run as often as every 15 minutes on Free and every minute on Pro and up. Uptime monitors have their own allowance and do not use your scheduled runs.
08
Status pages
A status page shows your customers how things are doing, so they can check for themselves. Included from the Starter plan. See what it looks like.
Set one up
- 1Go to Status pages and create a page with a name. It works straight away at
cronengine.com/status/your-name. - 2Open the page. You see it as your customers do, with an editor next to it.
- 3Add monitors. From the page, choose Add monitors and press Add to page next to any heartbeat or uptime monitor, or create a new one there. Give each item the name your customers know it by, and group items under headings if you like.
- 4Share the link, or put it on your own address (below).
Only what you add is shown. The addresses you watch and their response times stay private.
Post updates
When something is wrong, write a short update and pick its stage. Open updates sit at the top of the page, and everything you wrote stays below as a history.
| Stage | Use it when |
|---|---|
| Investigating | Something is wrong and you are finding out what |
| Identified | You know the cause and are working on it |
| Monitoring | A fix is in and you are watching it |
| Resolved | It is over |
| Maintenance | Planned work, announced ahead of time |
Make it look like yours
Everything below is in the editor, and the preview changes as you go.
Logo and icon
PNG, JPEG, WebP or GIF, up to 512 KB. Left, centre or right, in three sizes.
Theme
Light, dark, or automatic to follow the visitor’s device.
Colours and layout
An accent colour, a filled or plain header, a tinted background, compact or roomy spacing.
What is shown
Hide the uptime figures, the history or the support link. Show 7, 30 or 90 days.
Language and timezone
English, Dutch, French, German or Spanish, with times in your timezone.
Your site
A button back to your website and a short line of your own in the footer.
Use your own address
On Pro and up, a page can live at an address such as status.yourcompany.com.
- 1Type the address under Address in the page editor.
- 2At your domain provider, add the record shown there. For a subdomain this is a CNAME pointing to
pages.cronengine.com. - 3Wait for it to be picked up, usually minutes, sometimes a few hours. We check it and set up the certificate automatically.
| Type | Name | Points to |
|---|---|---|
CNAME | status | pages.cronengine.com |
Use a subdomain. A bare domain such as yourcompany.com cannot hold a CNAME at most providers.
Who can see it
Anyone with the link. Set a page to unlisted and it still works for everyone with the address, but asks search engines not to list it. Visitors get no cookies. The uptime figures only count time a monitor has actually been watching, and planned maintenance still counts.
09
Alerts
Every job and monitor can send alerts to one or more channels. How many channels one job may use depends on your plan.
| Channel | How to set it up |
|---|---|
| Goes to the notification address in your settings. A new address is confirmed by email first. | |
| Slack | Add a Webhook channel with the Slack format and paste an incoming webhook URL. |
| Discord | Add a Webhook channel with the Discord format and paste the channel’s webhook URL. |
| Telegram | Create a bot with @BotFather, add it to the chat, then enter its token and the chat ID. |
| Your own webhook | A signed JSON message to any HTTPS address. See the webhook reference. |
When alerts are sent
| Option | Sends |
|---|---|
| Every failure | An alert for each failed run |
| Down and back | One alert when it starts failing, one when it recovers |
| After N failures | An alert once it has failed a number of times in a row, then on recovery |
| Every run | An alert for every run, from the Starter plan |
| None | No alerts |
These options are for cron jobs. Heartbeats and uptime monitors alert when they go down and when they come back.
Maintenance windows
Plan a window before a deploy and alerts are held, while outages are still recorded. A window has to exist before the outage starts, and can cover jobs and monitors together.
Digests and daily limits
A weekly or monthly email summary, sent on Monday or the 1st after 08:00. Email alerts have a daily limit that depends on your plan, and on Free the other channels do too. It resets at midnight UTC, and digests do not count toward it.
10
Troubleshooting
Open the run history first. The status code and the error usually point straight at the cause.
No answer, or a network error
Check that the address works from the internet, that the domain resolves, and that the certificate is valid. Private and local addresses are refused. If it is slow, it may be hitting your plan’s timeout.
401 or 403
Check the token or username and password, and that it has access to this endpoint. If a firewall sits in front, allow 45.9.188.216.
404
Check the full path and that you are calling the right environment.
405
The endpoint does not accept this method. Pick the one your route expects.
415, or the body is not understood
Make the content type match the body. For JSON, check it is valid JSON.
429
Your endpoint is limiting how often it can be called. Run the job less often or raise the limit.
5xx
The request reached your app and something went wrong there. Look in your app’s logs at the time of the run; the saved reply may help too.
A run I expected is missing
Check that the job is active. Overlap protection may have skipped a run while the previous one was still busy, and a clock change can skip a time that did not exist.
A heartbeat says down, but the script ran
The ping did not arrive. Check the machine can reach the internet and has curl installed. With && the ping is only sent when the script succeeded, so a failing script sends nothing.
An uptime monitor says down, but the site works for me
The page may take longer than 10 seconds, a firewall may block 45.9.188.216, or the text you told it to look for has changed. The check log shows the status and error of every check.
Allowlist one address
Every request CronEngine sends comes from this IP: jobs, tests, uptime checks and webhooks. Jobs identify as CronEngine-Dispatcher/2 and uptime checks as CronEngine-Uptime/1.
45.9.188.216
11
Plans and limits
Each plan covers a number of scheduled runs per 30-day month, shared by your active jobs.
A job costs as many runs as its schedule fires in 30 days. The cost is reserved when you save the job, so you never run out halfway through a month. Paused jobs cost nothing.
| Schedule | Runs per month |
|---|---|
| Every minute | 43,200 |
| Every 5 minutes | 8,640 |
| Every 15 minutes | 2,880 |
| Hourly | 720 |
| Daily | 30 |
Heartbeats, uptime monitors, status pages and one-off requests each have their own allowance and do not use scheduled runs. Every limit per plan is on the pricing page.
12
Account
Settings that apply to your whole account.
Timezone
All schedules follow it. Changing it reschedules every active job straight away.
Two-step sign-in
Add an authenticator app under Security, with recovery codes in case you lose your phone.
Sessions
See where you are signed in, sign out a single session or all others. A sign-in from a new IP address is emailed to you.
Billing
Change or cancel your plan from the billing portal. A lower plan shows what would change before you switch.
Still have a question?
Check the FAQ, or ask us directly.