CRONPULSE / DEVELOPER DOCUMENTATION

API reference

Use this API to send job check-ins and server reports. You can also read history, change monitor settings, and upload private images.

Base URL: https://cronpulse.com. The API paths do not have an /api prefix or a version number. Replace the example IDs and keys with your monitor details.

Terms

Quick start

  1. Open the dashboard.

  2. Create a job monitor.

  3. Open the job details.

  4. Copy the private check-in URL.

  5. Send a check-in after the job completes successfully.

curl --fail --silent --show-error --max-time 30 \
  'https://cronpulse.com/monitors/MONITOR_ID/ACCESS_KEY/checkin'

To include run data, send a POST request with a state object:

curl --fail --silent --show-error --max-time 30 \
  -H 'Content-Type: application/json' \
  --data-binary '{"state":{"result":"ok","rows_processed":4200,"duration_seconds":12.5}}' \
  'https://cronpulse.com/monitors/MONITOR_ID/ACCESS_KEY/checkin'

A successful check-in returns 200 OK and the monitor data. CronPulse saves the check-in time and state in the history. It also sets a new deadline for the next check-in. These changes succeed or fail together.

Authentication and access

Each monitor has a secret access_key. The key is part of the URL path. Do not put the key in an Authorization header. CronPulse does not provide an account-wide API token.

Copy the private URL from the dashboard or the monitor confirmation email. A person with this URL can read, update, check in, or delete that monitor. The URL also gives access to its state history.

Store the URL in a protected configuration file or environment variable. Keep the URL out of shared logs, screenshots, and source control. API responses can contain the key. Keep these responses private too.

Use an emailed sign-in link to open the account dashboard or view private images. A monitor key does not give access to the account dashboard. Sign-in links work once and expire after 15 minutes. Browser sessions expire after 30 days.

For legacy job monitors, a valid key can also confirm monitor alerts. A read request can cause this confirmation. An accepted check-in also confirms monitor alerts. This confirmation does not verify the account or sign you in. An image upload does not confirm monitor alerts or record a check-in.

Endpoint overview

Add these paths to the base URL. Replace :id with the monitor ID. Replace :access_key with its private key.

Use the signed-in dashboard to create servers, group jobs, and set condition alerts. These forms require a browser session. Rails uses a CSRF token to reject unwanted form requests. A monitor key cannot authorize these forms. They do not provide a JSON management API.

Check-ins and state

For structured data, send a POST request with Content-Type: application/json. Form data such as state[result]=ok also works. Use JSON to keep numbers, booleans, and null values in their original types.

state must be a JSON object. The object can contain other objects, arrays, numbers, text, booleans, and null values. Do not set state itself to null, an array, or text.

State limits

Invalid or oversized state returns 422 Unprocessable Entity. CronPulse does not change the heartbeat deadline, latest state, or history for that request.

Each check-in replaces the latest state. CronPulse does not merge new state with old state. If you omit state, CronPulse saves {} as the latest state. Older entries stay in the history.

State cannot change internal confirmation or notification settings. CronPulse sets the check-in time when it receives the request. Include an observation time in state if you also need the time from the source server.

Success and retries

A check-in records contact with CronPulse. It does not check whether the reported job succeeded. For example, {"state":{"result":"error"}} still records a successful heartbeat. For a job monitor, send the check-in after the job completes successfully.

Each accepted request adds one history entry. CronPulse does not combine repeated requests into one entry. If the first request succeeds before a timeout, a retry can add another entry. The API does not provide separate start, finish, and failure events.

Successful response

Check-in, read, update, and delete requests return a monitor object. This example shows some of its fields:

{
  "id": 123,
  "name": "Nightly backup",
  "description": "Database archive",
  "kind": "cron_job",
  "server_id": null,
  "max_heartbeat_interval_in_seconds": 86400,
  "last_checkin_at": "2026-10-25T12:00:00.000Z",
  "latest_state": {
    "result": "ok",
    "rows_processed": 4200,
    "duration_seconds": 12.5
  },
  "seconds_since_last_checkin": 0
}

The response can include other database fields. Only use the fields listed in this guide to update settings.

Before the first check-in, last_checkin_at and seconds_since_last_checkin are null. The response can contain the private key. Store the response securely.

Read latest state and history

To read the monitor without recording a check-in, send this request:

curl --fail --silent --show-error \
  'https://cronpulse.com/monitors/MONITOR_ID/ACCESS_KEY'

To read its history, send this request:

curl --fail --silent --show-error \
  'https://cronpulse.com/monitors/MONITOR_ID/ACCESS_KEY/checkins?page=1'

CronPulse returns the newest entries first. Each page contains up to 50 entries:

{
  "checkins": [
    {
      "id": 456,
      "checked_in_at": "2026-10-25T12:00:00.000Z",
      "state": {"result":"ok","rows_processed":4200}
    }
  ],
  "next_page": null
}

If more entries exist, next_page contains the next page number. Request that page to continue. Stop when next_page is null.

Page numbers start at 1. A page after the last available entry returns an empty list. CronPulse uses page 1 for zero or negative page numbers. It limits page numbers to 1,000,000.

CronPulse keeps history until you delete the monitor. Images have a separate expiry time. Old history can remain after its images expire.

Create a cron-job monitor

Send POST /monitors with a monitor object. This request does not require an existing key or browser sign-in. CronPulse sends a confirmation email with the new monitor’s private URLs.

curl --fail --silent --show-error \
  -H 'Content-Type: application/json' \
  --data-binary '{"monitor":{"name":"Nightly backup","description":"Database archive","send_to":"you@example.com","max_heartbeat_interval_in_seconds":86400}}' \
  'https://cronpulse.com/monitors'

The request accepts these fields:

CronPulse removes spaces at the start and end of the email address. It also converts the address to lowercase.

A successful request returns 200 OK. It does not return 201, the monitor ID, or the access key. The response tells you to check your email:

{
  "success": true,
  "message": "Please check your email to confirm your email address and start receiving pulse monitors."
}

Use the confirmation link or check-in URL from the email to confirm monitor alerts. Use a separate emailed sign-in link to open the account dashboard.

Create and group server monitors in the dashboard. This API request does not accept kind, server_id, server definitions, or condition-alert rules.

Update or delete a monitor

Update settings

Send PATCH or POST /monitors/:id/:access_key with a monitor object. Include one or more of these fields:

curl --fail --silent --show-error --request PATCH \
  -H 'Content-Type: application/json' \
  --data-binary '{"monitor":{"name":"Hourly backup","max_heartbeat_interval_in_seconds":7200}}' \
  'https://cronpulse.com/monitors/MONITOR_ID/ACCESS_KEY'

A successful request returns 200 OK and the monitor object. It does not record a check-in.

A new interval sets a new deadline based on the last check-in. If the monitor has no check-in, CronPulse uses its creation time.

This request cannot change the recipient, account, server, monitor kind, state, or condition-alert rules.

Delete a monitor

Send DELETE /monitors/:id/:access_key to remove a monitor. This action permanently deletes the monitor, its history, and its uploaded images.

A successful request returns 200 OK and the deleted monitor’s data. Only send this request when you intend to remove the monitor.

Confirm a legacy monitor

Send GET /monitors/:id/:access_key/confirm_email to confirm the monitor’s email setting. CronPulse returns 200 OK with a plain-text message. This request does not record a check-in.

Publish a server dashboard

  1. Open Servers.

  2. Create or select a server.

  3. Select Set up status reporting.

  4. Open Reporter connection details.

  5. Copy the private reporting URL.

This setup creates a server monitor. Use its key to send reports and upload images for that monitor.

Put the readings and dashboard definition inside state:

{
  "state": {
    "replica": {"seconds_behind_source":75},
    "dashboard": {
      "version": 1,
      "title": "Database health",
      "sections": [{
        "type": "metrics",
        "title": "Replication",
        "items": [{
          "label": "Seconds behind source",
          "path": "/replica/seconds_behind_source",
          "format": "duration_seconds"
        }]
      }]
    }
  }
}

Save this object as snapshot.json. Send the file to the reporting URL:

curl --fail --silent --show-error --max-time 30 \
  -H 'Content-Type: application/json' \
  --data-binary @snapshot.json \
  'https://cronpulse.com/monitors/STATUS_MONITOR_ID/ACCESS_KEY/checkin'

The definition controls metrics, fields, tables, notices, and private images. Include the definition with every report. You do not need to register server names or change the Rails application.

Read the dashboard publishing guide for the full format. You can also download an example.

A new server monitor starts heartbeat monitoring after its first accepted report. Its default deadline is 15 minutes. The installed reporters send data every five minutes. For a new reporter, set its schedule on the source server.

Upload and view private screenshots

Upload a PNG

Send POST /monitors/:id/:access_key/images with multipart/form-data. Use the image field for the file. Use a server monitor’s ID and key. Job-monitor keys cannot upload images.

Send the PNG file directly. Do not encode the image as base64 in JSON.

curl --fail --silent --show-error --max-time 30 \
  --form 'image=@desktop.png;type=image/png' \
  'https://cronpulse.com/monitors/STATUS_MONITOR_ID/ACCESS_KEY/images'

A successful upload returns 201 Created:

{
  "id": "11111111-2222-4333-8444-555555555555",
  "uploaded_at": "2026-10-25T12:00:00Z",
  "expires_at": "2026-10-26T12:00:00Z",
  "width": 1920,
  "height": 1080
}

Image limits

Active images are images that have not expired. CronPulse returns 429 if an upload exceeds the image count or storage limit.

An upload does not confirm monitor alerts, record a check-in, or change the heartbeat deadline. After the upload, send the image ID in a normal server check-in.

Show the image in a report

Put the returned ID in state.desktops. Add an images section to state.dashboard:

{
  "state": {
    "desktops": [{
      "name": "Worker desktop",
      "image_id": "11111111-2222-4333-8444-555555555555",
      "captured_at": "2026-10-25T11:59:55Z"
    }],
    "dashboard": {
      "version": 1,
      "sections": [{
        "type": "images",
        "title": "Desktops",
        "path": "/desktops",
        "image_path": "/image_id",
        "caption_path": "/name",
        "captured_at_path": "/captured_at"
      }]
    }
  }
}

Use an image ID from the same server monitor. External URLs, file paths, and base64 text cannot act as image sources.

Set captured_at to the time when the source server took the image. CronPulse sets uploaded_at to the time when it receives the file.

View a private image

Send GET /dashboard/images/:image_id with the verified owner’s browser session. A monitor key cannot replace this session.

Successful image reads use Cache-Control: no-store. Old history keeps its original image IDs. After an image expires, the dashboard shows that the image is unavailable.

Heartbeat and condition alerts

Late check-ins

Heartbeat alerts use the monitor’s interval and confirmation setting. Warnings repeat no more often than once every six hours. They stop after 50 warnings without a successful check-in. A successful check-in resets the warning count. If CronPulse sent heartbeat warnings, it sends a recovery email after the successful check-in.

Reported values

To add a server condition alert:

  1. Open Servers.

  2. Select a server.

  3. Select Add condition alert.

  4. Enter an Alert name.

  5. Select a Metric.

  6. Select a Condition.

  7. Select the Value type.

  8. If the condition needs a value, enter the Comparison value.

  9. Set Consecutive bad reports to a number from 1 to 12.

  10. Select Enable alerts for this condition.

  11. Select Create condition alert.

You can also use the form’s Other reported field controls to enter a custom JSON Pointer.

For example, set replica lag to is greater than 60. Use seconds if the field reports seconds. For a connection flag, set the condition to equals false.

Rules can compare numbers, text, and booleans. A rule can also check for an unavailable value. Only the verified owner can save these rules. Posted JSON and display colors cannot create, enable, or change them.

Use Consecutive bad reports to require 1–12 matching reports in a row. CronPulse sends one alert email when the condition first meets this requirement. It does not repeat the alert while the condition continues. You can also enable a recovery email. CronPulse sends this email when a known value no longer meets the rule. For normal comparisons, an unknown value or wrong data type cannot close an open alert.

CronPulse checks conditions when reports arrive. A 60-second limit does not make CronPulse query the server every second. Email delivery runs separately and retries failed sends. If a process stops after the mail server accepts an email, a retry can send a duplicate.

Schedules for your own installation

For heartbeat emails, schedule the /monitors/cronjob request. For condition emails, run cronpulse:deliver_server_alerts every minute. For image cleanup, run cronpulse:purge_images regularly.

The /monitors/cronjob request sends real warning emails. Do not use it as a job check-in or a service health test.

Errors and client behavior

Use the HTTP status to identify a successful request. Check-in, create, and update validation errors use an errors array:

{"errors":["State must be a JSON object"]}

For monitor JSON requests, an unknown monitor or wrong key returns 404 with this body:

{"error":"Monitor not found"}

Image validation and quota errors use an error string. Wrong image-upload keys return 404 with an empty body. Other errors can also have an empty body or a different format.

Status codes

Always include the required monitor object for create and update requests. Some invalid legacy update requests can return 5xx.

Handle request failures

Set connection and read timeouts in each reporter. For temporary network errors or 5xx responses, retry with a delay. Increase the delay between attempts and limit the number of attempts. A retry can add another history entry.

For a 4xx response, correct the request or access details before you retry. Repeated uploads cannot fix a storage quota error. Record delivery failures on the source server so you can investigate them.

Open dashboard