Cron Job Monitoring
Cron job monitors are attached to a monitor in Oh Dear. Each cron job definition gets a unique ping URL that your scheduled tasks call to report their status. This page covers creating, listing, syncing, and snoozing cron job monitors through the API.
You'll need a monitor ID for most of these endpoints.
Example request:
$ OHDEAR_TOKEN="your API token" $ curl https://ohdear.app/api/monitors/1/cron-checks \ -H "Authorization: Bearer $OHDEAR_TOKEN" \ -H 'Accept: application/json' \ -H 'Content-Type: application/json'
All endpoints below follow the same authentication pattern.
Cron check response fields #
Every cron job endpoint returns a cron check object with these fields:
{ "id": 1, "uuid": "0d210b09", "name": "cronjob number one", "type": "simple", "description": "a description goes here", "frequency_in_minutes": 15, "grace_time_in_minutes": 5, "cron_expression": null, "human_readable_cron_expression": "", "server_timezone": "Europe/Brussels", "ping_url": "https://ping.ohdear.app/0d210b09", "created_at": "2020-07-28 13:27:02", "latest_result": "pingFinished", "latest_result_label": "ok", "latest_result_label_color": "green", "latest_ping_at": "2020-11-16 09:19:40", "human_readable_latest_ping_at": "5 minutes ago", "active_snooze": null }
id: unique identifier for the cron check definitionuuid: short UUID used in the ping URLname: name you gave this cron jobtype:"simple"(frequency-based) or"cron"(crontab expression)description: optional descriptionfrequency_in_minutes: forsimpletype -- how often the job should rungrace_time_in_minutes: how long to wait after the expected run time before alertingcron_expression: forcrontype -- the crontab expression (e.g.,"* * * * *")human_readable_cron_expression: human-readable version of the cron expressionserver_timezone: timezone for crontab expression evaluationping_url: the URL your cron job should call to report its statuscreated_at: when this cron check was created (UTC)latest_result: the most recent result (see result types below)latest_result_label: human-readable status labellatest_result_label_color: color for the status labellatest_ping_at: when we last received a ping (UTC)human_readable_latest_ping_at: relative time since last pingactive_snooze: snooze details if active (see checks docs), ornull
List cron checks for a monitor #
GET /api/monitors/{monitorId}/cron-checks
Returns all cron job definitions for a monitor. Each item follows the same shape as the cron check object above.
{ "data": [ { "id": 1, "name": "cronjob number one", "type": "simple", "..." }, { "id": 2, "name": "cronjob number two", "type": "simple", "..." } ] }
Create a cron check (simple) #
POST /api/monitors/{monitorId}/cron-checks
Creates a new cron job monitor using frequency-based scheduling.
Request body (JSON):
name(string, required) -- name for this cron jobtype(string, required) -- set to"simple"for frequency-based schedulingfrequency_in_minutes(integer, required forsimple) -- how often the job should rungrace_time_in_minutes(integer, required) -- grace period before alertingdescription(string, optional) -- description for this cron job
{ "name": "your cron job name", "type": "simple", "frequency_in_minutes": 10, "grace_time_in_minutes": 15, "description": "a description goes here" }
Returns the cron check object including the ping_url you should use in your scripts to report status.
Create a cron check (crontab) #
POST /api/monitors/{monitorId}/cron-checks
Creates a new cron job monitor using a crontab expression.
Request body (JSON):
name(string, required) -- name for this cron jobtype(string, required) -- set to"cron"for crontab expression schedulingcron_expression(string, required forcron) -- the crontab expression (e.g.,"* * * * *")grace_time_in_minutes(integer, required) -- grace period before alertingserver_timezone(string, required forcron) -- timezone for evaluating the expression (e.g.,"UTC")description(string, optional) -- description for this cron job
{ "name": "your cron job name", "type": "cron", "cron_expression": "* * * * *", "grace_time_in_minutes": 10, "description": "a description goes here", "server_timezone": "UTC" }
Returns the cron check object.
Update a cron check #
PUT /api/cron-checks/{cronCheckDefinitionId}
Updates an existing cron job definition. The payload accepts the same fields as creation (name, type, frequency_in_minutes or cron_expression, grace_time_in_minutes, server_timezone, description).
Returns the updated cron check object.
Bulk sync cron checks #
POST /api/monitors/{monitorId}/cron-checks/sync
Synchronizes all cron jobs for a monitor in one call. This is a destructive action -- any cron job not included in the cron_checks array will be removed.
Request body (JSON):
cron_checks(array, required) -- array of cron check definitions. Each item uses the same fields as creating a cron check
{ "cron_checks": [ { "name": "cron job #1", "type": "cron", "cron_expression": "* * * * *", "grace_time_in_minutes": 10, "server_timezone": "UTC" }, { "name": "cron job #2", "type": "cron", "cron_expression": "0 * * * *", "grace_time_in_minutes": 10, "server_timezone": "UTC" } ] }
Returns an array of cron check objects.
Snooze a cron check #
POST /api/cron-checks/{cronCheckDefinitionId}/snooze
Temporarily silences notifications for a cron job. See the checks snooze docs for details on snoozing behavior.
Request body (JSON):
minutes(integer, required) -- how long to snooze (1 to 144,000)
Returns the cron check object with active_snooze populated.
Unsnooze a cron check #
POST /api/cron-checks/{cronCheckDefinitionId}/unsnooze
Removes the active snooze from a cron check. Returns the cron check object with active_snooze set to null.
Delete a cron check #
DELETE /api/cron-checks/{cronCheckDefinitionId}
Deletes a cron job definition.
Returns 204 No Content on success.
Result types #
The latest_result field can have the following values.
Values your application actively reports via the ping URL:
pingStarting: we received the "started" pingback from your applicationpingFinished: we received the "finished" pingback, indicating no errors occurredpingFailed: we received the "failed" pingback, indicating errors occurred
Values we may detect ourselves:
checkRanTooLate: we didn't receive a ping on time, so we marked the task as latepingEndpointDown: Oh Dear's ping endpoint was temporarily unavailablecheckFailed: the cron check failedsentCronNotExutedOnTimeNotification: we sent the "did not run on time" notificationsentPingFailedNotification: your application reported a failure and we sent a notificationcronCheckDefinitionNotRegistered: the cron check definition is not registeredcronCheckChanged: the cron check configuration was changed
The only success state is pingFinished -- all other values indicate the job is either pending, failed, or hasn't pinged yet.
Error handling #
If validation fails, you'll get an error response:
{ "message": "The given data was invalid.", "errors": { "name": ["There already exist a cron check with this name for this site."] } }
Feel free to reach out via [email protected] or on X via @OhDearApp if you have any other questions. We'd love to help!