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

# Heartbeat Monitor Configuration

> Configure DevHelm heartbeat monitors — expected interval, grace period, and ping endpoint

Heartbeat monitors require an expected interval and grace period. DevHelm generates a unique ping URL that your service calls on each successful run.

<Tip>
  **Define this in code.** [YAML format](/mac/yaml/monitors) · [Terraform](/mac/terraform/monitors)
</Tip>

## Config fields

| Field                     | Type    | Required | Default | Description                                           |
| ------------------------- | ------- | -------- | ------- | ----------------------------------------------------- |
| `config.expectedInterval` | integer | Yes      | —       | Expected time between pings in seconds (1–86,400)     |
| `config.gracePeriod`      | integer | Yes      | —       | Extra time to wait before marking as down, in seconds |

<Note>
  The total allowed gap between pings is `expectedInterval + gracePeriod`. For a job that runs hourly with a 10-minute grace period, set `expectedInterval: 3600` and `gracePeriod: 600`.
</Note>

## Ping URL

When you create a heartbeat monitor, DevHelm generates a unique `pingUrl`. The URL is available on the monitor response object. Your service should call this URL via GET or POST on each successful run.

```bash theme={null}
curl -s https://api.devhelm.io/api/v1/heartbeat/<token>
```

### Sending payload data

You can include a JSON body with your ping. This is useful for reporting job metadata:

```bash theme={null}
curl -X POST https://api.devhelm.io/api/v1/heartbeat/<token> \
  -H "Content-Type: application/json" \
  -d '{"records_processed": 1542, "duration_ms": 8300}'
```

Use the `heartbeat_payload_contains` assertion to validate payload contents.

## Assertions

| Assertion                    | Required fields               | Description                                                           |
| ---------------------------- | ----------------------------- | --------------------------------------------------------------------- |
| `heartbeat_received`         | *(none)*                      | Passes if a ping was received within the expected window              |
| `heartbeat_max_interval`     | `maxSeconds`                  | Fails if the actual interval between pings exceeds threshold          |
| `heartbeat_interval_drift`   | `maxDeviationPercent` (1–100) | Fails if the interval varies more than the allowed percentage         |
| `heartbeat_payload_contains` | `path`, `value`               | Fails if the ping payload at the given path doesn't contain the value |

## Examples

### Cron job (hourly)

```yaml theme={null}
monitors:
  - name: Hourly ETL
    type: HEARTBEAT
    config:
      expectedInterval: 3600
      gracePeriod: 600
    assertions:
      - config:
          type: heartbeat_received
        severity: fail
```

### With payload validation

```yaml theme={null}
monitors:
  - name: Report generator
    type: HEARTBEAT
    config:
      expectedInterval: 86400
      gracePeriod: 3600
    assertions:
      - config:
          type: heartbeat_received
        severity: fail
      - config:
          type: heartbeat_payload_contains
          path: status
          value: success
        severity: fail
      - config:
          type: heartbeat_interval_drift
          maxDeviationPercent: 25
        severity: warn
```

## Next steps

<CardGroup cols={2}>
  <Card title="Heartbeat overview" icon="heart-pulse" href="/monitoring/heartbeat/overview">
    When to use heartbeat monitors.
  </Card>

  <Card title="Cron job guide" icon="clock" href="/guides/cron-job-monitoring">
    Patterns for background job monitoring.
  </Card>
</CardGroup>
