Skip to main content

Heartbeats API

Heartbeat monitors work in reverse compared to regular monitors. Instead of Sentro checking your endpoints, your service pings Sentro at regular intervals. If Sentro does not receive a ping within the expected timeframe (plus a configurable grace period), it creates an incident and sends alerts through your configured channels.

This is ideal for monitoring:

  • Cron jobs -- Ensure your scheduled tasks actually run on time
  • Background workers -- Verify queue processors and async jobs are alive
  • Batch processes -- Confirm nightly ETL pipelines, backups, and data syncs complete
  • Scheduled reports -- Make sure report generation finishes within its window

How It Works​

  1. Create a heartbeat via the API or dashboard -- you get a unique ping URL
  2. Add a ping call to the end of your job (e.g., curl https://app.sentro.dev/api/heartbeat/{slug}/ping)
  3. Sentro watches for pings -- if one is missed beyond the grace period, an alert fires
  4. When pings resume, the incident is automatically resolved

Heartbeat Object​

{
"id": "hbt_abc123def456",
"orgId": "org_abc123",
"name": "Nightly Database Backup",
"slug": "nightly-database-backup-a1b2c3",
"pingUrl": "https://app.sentro.dev/api/heartbeat/nightly-database-backup-a1b2c3/ping",
"expectedIntervalSeconds": 86400,
"graceSeconds": 300,
"status": "ACTIVE",
"isUp": true,
"lastPingAt": "2025-01-15T02:05:12.000Z",
"nextExpectedAt": "2025-01-16T02:05:12.000Z",
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-15T02:05:12.000Z"
}
FieldTypeDescription
idstringUnique heartbeat identifier
orgIdstringOrganization that owns the heartbeat
namestringHuman-readable heartbeat name (1-100 characters)
slugstringAuto-generated unique slug used in the ping URL
pingUrlstringThe URL your service should ping: /api/heartbeat/{slug}/ping
expectedIntervalSecondsnumberExpected time between pings in seconds (30-86400)
graceSecondsnumberGrace period before marking as missed in seconds (0-3600)
statusstringACTIVE or PAUSED
isUpbooleanWhether the heartbeat is receiving pings on time
lastPingAtstring|nullISO 8601 timestamp of the last received ping
nextExpectedAtstring|nullISO 8601 timestamp when the next ping is expected
createdAtstringISO 8601 creation timestamp
updatedAtstringISO 8601 last update timestamp

List Heartbeats​

GET /v1/heartbeats

Returns all heartbeat monitors belonging to your organization.

Query Parameters​

ParameterTypeDefaultDescription
limitnumber50Number of heartbeats to return (max 200)
offsetnumber0Number of heartbeats to skip for pagination
statusstring--Filter by status: ACTIVE or PAUSED

Example Request​

curl "https://api.sentro.dev/v1/heartbeats?limit=10&status=ACTIVE" \
-H "Authorization: Bearer sentro_sk_live_your_key_here"

Response 200 OK​

{
"data": [
{
"id": "hbt_abc123def456",
"orgId": "org_abc123",
"name": "Nightly Database Backup",
"slug": "nightly-database-backup-a1b2c3",
"pingUrl": "https://app.sentro.dev/api/heartbeat/nightly-database-backup-a1b2c3/ping",
"expectedIntervalSeconds": 86400,
"graceSeconds": 300,
"status": "ACTIVE",
"isUp": true,
"lastPingAt": "2025-01-15T02:05:12.000Z",
"nextExpectedAt": "2025-01-16T02:05:12.000Z",
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-15T02:05:12.000Z"
},
{
"id": "hbt_ghi789jkl012",
"orgId": "org_abc123",
"name": "Hourly Report Generator",
"slug": "hourly-report-generator-d4e5f6",
"pingUrl": "https://app.sentro.dev/api/heartbeat/hourly-report-generator-d4e5f6/ping",
"expectedIntervalSeconds": 3600,
"graceSeconds": 60,
"status": "ACTIVE",
"isUp": true,
"lastPingAt": "2025-01-15T09:00:45.000Z",
"nextExpectedAt": "2025-01-15T10:00:45.000Z",
"createdAt": "2025-01-05T12:00:00.000Z",
"updatedAt": "2025-01-15T09:00:45.000Z"
}
],
"meta": {
"total": 2
}
}
Try it

Fetch all heartbeat monitors in your organization.

GET/v1/heartbeats?limit=50&offset=0
Query Parameters
Click ⚙ to configure your API key, then hit Send.

Get Heartbeat​

GET /v1/heartbeats/:id

Returns a single heartbeat monitor with its most recent pings.

Path Parameters​

ParameterTypeDescription
idstringThe heartbeat ID

Response 200 OK​

{
"data": {
"id": "hbt_abc123def456",
"orgId": "org_abc123",
"name": "Nightly Database Backup",
"slug": "nightly-database-backup-a1b2c3",
"pingUrl": "https://app.sentro.dev/api/heartbeat/nightly-database-backup-a1b2c3/ping",
"expectedIntervalSeconds": 86400,
"graceSeconds": 300,
"status": "ACTIVE",
"isUp": true,
"lastPingAt": "2025-01-15T02:05:12.000Z",
"nextExpectedAt": "2025-01-16T02:05:12.000Z",
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-15T02:05:12.000Z",
"recentPings": [
{
"id": "ping_001",
"ipAddress": "203.0.113.42",
"pingAt": "2025-01-15T02:05:12.000Z"
},
{
"id": "ping_002",
"ipAddress": "203.0.113.42",
"pingAt": "2025-01-14T02:04:58.000Z"
},
{
"id": "ping_003",
"ipAddress": "203.0.113.42",
"pingAt": "2025-01-13T02:05:03.000Z"
}
]
}
}

Error​

{
"error": {
"code": "NOT_FOUND",
"message": "Heartbeat with id 'hbt_invalid' not found"
}
}
Try it

Get a single heartbeat monitor with its recent pings.

GET/v1/heartbeats/:id
Path Parameters
Click ⚙ to configure your API key, then hit Send.

Create Heartbeat​

POST /v1/heartbeats

Creates a new heartbeat monitor. A unique slug and pingUrl are generated automatically. The heartbeat starts in ACTIVE status, waiting for its first ping.

note

This endpoint requires a READ_WRITE API key. Read-only keys will receive a 403 Forbidden response.

Request Body​

FieldTypeRequiredDescription
namestringYesHeartbeat name (1-100 characters)
expectedIntervalSecondsnumberNoExpected time between pings in seconds (30-86400, default: 300)
graceSecondsnumberNoGrace period before alerting in seconds (0-3600, default: 60)

Example Request​

curl -X POST https://api.sentro.dev/v1/heartbeats \
-H "Authorization: Bearer sentro_sk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"name": "Nightly Database Backup",
"expectedIntervalSeconds": 86400,
"graceSeconds": 300
}'

Response 201 Created​

{
"data": {
"id": "hbt_new456def789",
"orgId": "org_abc123",
"name": "Nightly Database Backup",
"slug": "nightly-database-backup-a1b2c3",
"pingUrl": "https://app.sentro.dev/api/heartbeat/nightly-database-backup-a1b2c3/ping",
"expectedIntervalSeconds": 86400,
"graceSeconds": 300,
"status": "ACTIVE",
"isUp": true,
"lastPingAt": null,
"nextExpectedAt": null,
"createdAt": "2025-01-15T10:00:00.000Z",
"updatedAt": "2025-01-15T10:00:00.000Z"
}
}

Validation Error​

{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid heartbeat data",
"details": {
"name": ["Name is required (1-100 characters)"],
"expectedIntervalSeconds": ["Must be between 30 and 86400"]
}
}
}

Plan Limit Error​

{
"error": {
"code": "PLAN_LIMIT",
"message": "You have reached the heartbeat limit for your plan. Upgrade to add more heartbeat monitors."
}
}
Try it

Create a new heartbeat monitor with an auto-generated ping URL.

POST/v1/heartbeats
Request Body
Click ⚙ to configure your API key, then hit Send.

Update Heartbeat​

PATCH /v1/heartbeats/:id

Updates an existing heartbeat monitor. Only the fields you include in the request body will be updated.

note

This endpoint requires a READ_WRITE API key. Read-only keys will receive a 403 Forbidden response.

Path Parameters​

ParameterTypeDescription
idstringThe heartbeat ID

Request Body​

All fields are optional. Include only the fields you want to change.

FieldTypeDescription
namestringUpdated heartbeat name (1-100 characters)
expectedIntervalSecondsnumberUpdated expected interval (30-86400)
graceSecondsnumberUpdated grace period (0-3600)
statusstringSet to ACTIVE or PAUSED

Example Request​

curl -X PATCH https://api.sentro.dev/v1/heartbeats/hbt_abc123def456 \
-H "Authorization: Bearer sentro_sk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{
"expectedIntervalSeconds": 43200,
"graceSeconds": 600
}'

Response 200 OK​

{
"data": {
"id": "hbt_abc123def456",
"orgId": "org_abc123",
"name": "Nightly Database Backup",
"slug": "nightly-database-backup-a1b2c3",
"pingUrl": "https://app.sentro.dev/api/heartbeat/nightly-database-backup-a1b2c3/ping",
"expectedIntervalSeconds": 43200,
"graceSeconds": 600,
"status": "ACTIVE",
"isUp": true,
"lastPingAt": "2025-01-15T02:05:12.000Z",
"nextExpectedAt": "2025-01-15T14:05:12.000Z",
"createdAt": "2025-01-01T00:00:00.000Z",
"updatedAt": "2025-01-15T10:30:00.000Z"
}
}
Try it

Update specific fields on an existing heartbeat monitor.

PATCH/v1/heartbeats/:id
Path Parameters
Request Body
Click ⚙ to configure your API key, then hit Send.

Delete Heartbeat​

DELETE /v1/heartbeats/:id

Permanently deletes a heartbeat monitor and all its associated ping history.

note

This endpoint requires a READ_WRITE API key. Read-only keys will receive a 403 Forbidden response.

Path Parameters​

ParameterTypeDescription
idstringThe heartbeat ID

Response 200 OK​

{
"data": {
"id": "hbt_abc123def456",
"deleted": true
}
}

Error​

{
"error": {
"code": "NOT_FOUND",
"message": "Heartbeat with id 'hbt_invalid' not found"
}
}
Try it

Permanently delete a heartbeat monitor and all its ping history.

DELETE/v1/heartbeats/:id
Path Parameters
Click ⚙ to configure your API key, then hit Send.

Sending Pings​

To report that your job completed successfully, send any HTTP request (GET, POST, or HEAD) to the heartbeat's pingUrl:

# Using curl (add this to the end of your cron job or script)
curl -fsS --retry 3 https://app.sentro.dev/api/heartbeat/nightly-database-backup-a1b2c3/ping

The ping endpoint accepts any HTTP method and returns 200 OK with a JSON body:

{
"ok": true,
"heartbeat": "Nightly Database Backup",
"receivedAt": "2025-01-15T02:05:12.000Z"
}
tip

Use curl -fsS --retry 3 to silently retry failed pings up to 3 times. This ensures transient network issues do not cause false missed-ping alerts.


Ping Object​

Pings are included in the recentPings array when fetching a single heartbeat via GET /v1/heartbeats/:id.

FieldTypeDescription
idstringUnique ping identifier
ipAddressstringIP address of the client that sent the ping
pingAtstringISO 8601 timestamp when the ping was received

Plan Limits​

The number of heartbeat monitors you can create depends on your subscription plan:

PlanHeartbeat Limit
Free3
Starter10
Pro50
MaxUnlimited

Attempting to create a heartbeat beyond your plan limit returns a 402 error with code PLAN_LIMIT.


Common Patterns​

Monitor a Cron Job​

Add a ping to the end of your crontab entry:

# Run backup every night at 2 AM, then ping Sentro
0 2 * * * /usr/local/bin/backup.sh && curl -fsS --retry 3 https://app.sentro.dev/api/heartbeat/nightly-backup-a1b2c3/ping

The && operator ensures the ping is only sent if the backup script exits successfully (exit code 0). If the script fails, no ping is sent and Sentro triggers an alert after the grace period.

Monitor a Node.js Worker​

const HEARTBEAT_URL =
"https://app.sentro.dev/api/heartbeat/queue-worker-x9y8z7/ping";

async function processQueue() {
while (true) {
const jobs = await queue.drain();
console.log(`Processed ${jobs.length} jobs`);

// Report health to Sentro after each batch
await fetch(HEARTBEAT_URL, { method: "POST" }).catch(() => {});

await sleep(60_000); // Wait 1 minute before next batch
}
}

Monitor a Python Script​

import requests

def run_etl_pipeline():
extract_data()
transform_data()
load_data()

# Signal success to Sentro
requests.get(
"https://app.sentro.dev/api/heartbeat/etl-pipeline-k3m4n5/ping",
timeout=10
)

if __name__ == "__main__":
run_etl_pipeline()

Pause and Resume​

Temporarily disable a heartbeat during planned maintenance to avoid false alerts:

# Pause before maintenance
curl -X PATCH https://api.sentro.dev/v1/heartbeats/hbt_abc123def456 \
-H "Authorization: Bearer sentro_sk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"status": "PAUSED"}'

# ... perform maintenance ...

# Resume monitoring
curl -X PATCH https://api.sentro.dev/v1/heartbeats/hbt_abc123def456 \
-H "Authorization: Bearer sentro_sk_live_your_key_here" \
-H "Content-Type: application/json" \
-d '{"status": "ACTIVE"}'