> ## Documentation Index
> Fetch the complete documentation index at: https://docs.uptimeio.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Heartbeat Monitoring

> Get alerted when a cron job, backup or scheduled task stops checking in

Heartbeat monitors work the other way round from other monitor types: **your job pings UptimeIO**, and UptimeIO alerts you when a ping does not arrive on time. Use them for anything that runs on a schedule.

## When to use it

* Cron jobs and scheduled tasks
* Backups
* ETL and data-sync pipelines
* Batch jobs and queue workers that should report in regularly

## Create a heartbeat monitor

<Steps>
  <Step title="Create the monitor">
    Choose the **Heartbeat** type and enter a **Monitor Name**. In **Heartbeat Configuration**, set the **Expected Interval** (how often your job runs) and the **Grace Period** (how much lateness to tolerate).
  </Step>

  <Step title="Copy the heartbeat URL">
    UptimeIO generates a unique **Heartbeat Endpoint** for the monitor:

    ```text theme={null}
    https://heartbeat.uptimeio.com/heartbeat/hb_a1b2c3d4e5f6...
    ```
  </Step>

  <Step title="Ping it from your job">
    Request the URL when the job finishes successfully.
  </Step>
</Steps>

### Settings

| Setting | What it does | Default / options |
| - | - | - |
| **Monitor Name** | Name shown in your dashboard | Required, up to 80 characters |
| **Expected Interval** | How often your job should ping | Preset from 1 minute to 24 hours, or **Custom...** |
| **Grace Period** | Extra time allowed after the interval before UptimeIO alerts you | Preset from Minimal (1 second) to 1 hour, or **Custom...** (1 to 3,600 seconds) |

Preset values:

* **Expected Interval**: 1, 5, 10, 15 and 30 minutes, and 1, 6, 12 and 24 hours. Only presets at or above your plan's shortest interval are listed: 5 minutes on Free, 1 minute on Pro and Scale.
* **Grace Period**: 1 second, 30 seconds, 1, 2, 5, 10, 15 and 30 minutes, and 1 hour.

The form shows the total time before an alert: the interval plus the grace period. There are no probe locations to choose, because UptimeIO waits for your job instead of checking out.

### Example

* **Monitor Name**: `Nightly backup`
* **Expected Interval**: 24 hours
* **Grace Period**: 30 minutes

## Sending a heartbeat

The heartbeat URL needs **no authentication**: the token in the URL is the credential. Send `GET` or `POST`:

```bash theme={null}
# Simple ping
curl -fsS https://heartbeat.uptimeio.com/heartbeat/YOUR_HEARTBEAT_TOKEN

# Ping with metadata (POST)
curl -fsS -X POST https://heartbeat.uptimeio.com/heartbeat/YOUR_HEARTBEAT_TOKEN \
  -H "Content-Type: application/json" \
  -d '{ "metadata": { "duration_s": 42, "rows": 1800, "status": "ok" } }'
```

### Metadata (POST only)

You can attach an optional `metadata` object to a `POST` ping, for example how long the job took:

* Up to 10 keys; keys use letters, digits, `_` and `-`
* Values are strings (up to 500 characters), numbers or booleans
* About 2 KB in total

Pings with invalid metadata are rejected. A body that is not valid JSON is ignored and the ping is still recorded.

### Rate limits

| Limit | Applies to |
| - | - |
| 3 pings per 30 seconds per heartbeat URL | All plans |
| 1 ping per 120 seconds per heartbeat URL | Free plan, in addition |

Pings over the limit are rejected with a `429` response. A monitor rarely needs more than one ping per interval.

## When incidents open and close

* **Open**: no ping arrives within the expected interval plus the grace period. Overdue monitors are checked every 30 seconds. With an interval of 1 hour and a grace period of 5 minutes, the incident opens after 65 minutes of silence.
* **Resolve**: after **3 consecutive on-time pings**, which avoids false recoveries from an unstable job.

## Integration examples

```bash theme={null}
# crontab: nightly at 02:00, ping only if the script succeeds
0 2 * * * /opt/scripts/backup.sh && curl -fsS -m 10 --retry 3 https://heartbeat.uptimeio.com/heartbeat/YOUR_HEARTBEAT_TOKEN > /dev/null
```

```bash theme={null}
#!/bin/bash
# backup.sh - ping only when the backup succeeds
pg_dump mydb > backup.sql && curl -fsS https://heartbeat.uptimeio.com/heartbeat/YOUR_HEARTBEAT_TOKEN
```

```python theme={null}
import requests

def run_job():
    process_data()
    requests.get("https://heartbeat.uptimeio.com/heartbeat/YOUR_HEARTBEAT_TOKEN", timeout=10)
```

```javascript theme={null}
async function runTask() {
  await processQueue();
  await fetch('https://heartbeat.uptimeio.com/heartbeat/YOUR_HEARTBEAT_TOKEN');
}
```

```yaml theme={null}
# GitHub Actions
- name: Ping heartbeat
  if: success()
  run: curl -fsS ${{ secrets.HEARTBEAT_URL }}
```

## Best practices

* **Ping only on success**, so a failing job stops the pings and opens an incident.
* **Match the interval to your schedule**: hourly cron = 3,600 seconds, daily backup = 86,400.
* **Size the grace period to the job's runtime variation**: a backup that takes 10 to 20 minutes needs about 30 minutes.
* **Treat the URL as a secret.** Anyone with it can send pings and hide real failures.

## Troubleshooting

<AccordionGroup>
  <Accordion title="Incident opened but the job ran">
    The ping may have failed or gone to the wrong URL, or it was sent before the job finished. Use `curl -fsS` so errors are visible, confirm the URL, and ping at the end of the job.
  </Accordion>

  <Accordion title="No incident when the job fails">
    The job pings even on failure. Ping only after a successful run (check the exit code).
  </Accordion>

  <Accordion title="429 responses">
    You are pinging more often than 3 times per 30 seconds (or, on Free, more than once per 120 seconds). Reduce the frequency.
  </Accordion>

  <Accordion title="404 response">
    No monitor uses this token. The monitor may have been deleted or its token replaced. Copy the current URL from the monitor.
  </Accordion>

  <Accordion title="Cannot save a short interval">
    The **Expected Interval** is below your plan's shortest interval (5 minutes on Free). See [Plans](/billing/plans).
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="HTTP Monitoring" icon="globe" href="/monitors/http">
    Monitor web services and APIs
  </Card>

  <Card title="Notifications" icon="bell" href="/notifications/overview">
    Configure alerts for heartbeat monitors
  </Card>
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.