Skip to main content

Documentation

Complete guide to setting up website monitoring with PingZen. API documentation, code examples, and best practices.

Authentication

All API requests require authentication. Two methods are available: a personal API key (for most integrations) and a JWT token (for web applications and endpoints that don’t yet support the key).

API Key

Create a personal API key from your profile menu. Use the X-API-Key header:

curl -H "X-API-Key: YOUR_API_KEY" \
  https://pingzen.dev/api/v1/monitors

To create an API key: Click on your profile → API Keys → Create New Key

Where X-API-Key works, and where JWT is required

Important

At this time, X-API-Key is accepted only on the monitors endpoints (CRUD, pause/resume, reorder, main statistics, and timeline). All other endpoints — /workspaces, /alerts, /incidents, /status-pages, /monitor-groups, /probes, /heartbeats (except the no-auth /ping/...), /maintenance, /feedback, /dashboard, /web-push, /scheduled-reports, /webhooks, /webhook-checks, /api-checks, /api-keys, /auth/*, /analytics, /telegram-bot, /alert-channel-configs — currently require a JWT token. This is a divergence from the historical promise of the docs; we’re closing it incrementally.

What X-API-Key covers right now:

GET/api/v1/monitorsCRUD (GET/POST/PATCH/DELETE), /reorder, /pause, /resume, /reset-stats, /results, /timeline, /status-ranges, /response-time-distribution, /cert-chain, /dnsbl-providers
POST/api/v1/ping/:ping_key/:slugno auth (uses ping_key) — for heartbeats

Inside /monitors/*, these still require JWT (known divergence, being fixed): GET /:id/stats, POST /:id/check, GET /:id/sla, GET /:id/sla/export/csv|pdf, GET /:id/dnsbl/provider-history, POST /test.

JWT Token

For web applications and endpoints that don’t accept the API key, use a JWT from /auth/login:

# 1. Obtain a token (pass email and password)
ACCESS=$(curl -sS -X POST https://pingzen.dev/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"you@example.com","password":"…"}' \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["access_token"])')

# 2. Use it as Authorization: Bearer
curl -H "Authorization: Bearer $ACCESS" https://pingzen.dev/api/v1/workspaces

The access token lives for 15 minutes; for long-running integrations use the refresh_token from the same response and the /auth/refresh endpoint.

Endpoints

Complete list of all available API endpoints.

Monitors

Monitor management (22 endpoints, grouped by purpose).

CRUD

GET/api/v1/monitors— List your monitors
POST/api/v1/monitors— Create a monitor
GET/api/v1/monitors/:id— Get monitor details
PATCH/api/v1/monitors/:id— Update monitor
DELETE/api/v1/monitors/:id— Delete monitor

Operations

POST/api/v1/monitors/:id/pause— Pause monitoring
POST/api/v1/monitors/:id/resume— Resume monitoring
POST/api/v1/monitors/:id/check— Run manual check (JWT)
POST/api/v1/monitors/:id/reset-stats— Wipe accumulated history (requires confirm)
PUT/api/v1/monitors/reorder— Set custom display order
POST/api/v1/monitors/test— Test a config without saving (JWT)

Stats & history

GET/api/v1/monitors/:id/stats— Aggregate statistics (JWT)
GET/api/v1/monitors/:id/results— Raw check-result history
GET/api/v1/monitors/:id/timeline— Status change timeline
GET/api/v1/monitors/:id/status-ranges— Run-length-encoded status ranges
GET/api/v1/monitors/:id/response-time-distribution— Response time percentiles (P50/P90/P95/P99)
GET/api/v1/monitors/:id/sla— SLA report (JWT)
GET/api/v1/monitors/:id/sla/export/csv— Export SLA as CSV (JWT)
GET/api/v1/monitors/:id/sla/export/pdf— Export SLA as PDF (JWT)

Diagnostics

GET/api/v1/monitors/:id/cert-chain— Live inspect TLS certificate chain
GET/api/v1/monitors/:id/dnsbl/provider-history— DNSBL per-provider history (JWT)
GET/api/v1/monitors/dnsbl-providers— Default DNSBL provider list

Alerts

Alert configuration.

GET/api/v1/alerts— List alerts
POST/api/v1/alerts— Create alert
PATCH/api/v1/alerts/:id— Update alert
DELETE/api/v1/alerts/:id— Delete alert
POST/api/v1/alerts/:id/test— Send test alert
POST/api/v1/alerts/:id/toggle— Toggle alert active/inactive
GET/api/v1/alerts/:id/history— Get alert delivery history
GET/api/v1/alerts/history— All alert delivery history (per workspace)
GET/api/v1/alerts/channels/availability— Available delivery channels (Telegram, Discord, Email, Slack, …)
POST/api/v1/alerts/test-send— Send a test message to an arbitrary channel (without saving an alert)

Incidents

Incident management.

GET/api/v1/incidents— List incidents
GET/api/v1/incidents/:id— Get incident details
PUT/api/v1/incidents/:id— Update incident
POST/api/v1/incidents/:id/updates— Add status update
POST/api/v1/incidents/:id/resolve— Resolve incident
DELETE/api/v1/incidents/:id— Delete incident

Status Pages

Public status pages.

GET/api/v1/status-pages— List status pages
POST/api/v1/status-pages— Create status page
GET/api/v1/status-pages/:id— Get status page
PUT/api/v1/status-pages/:id— Update status page
DELETE/api/v1/status-pages/:id— Delete status page
POST/api/v1/status-pages/:id/monitors— Add a monitor to the status page
DELETE/api/v1/status-pages/:id/monitors/:monitor_id— Remove a monitor from the status page
GET/api/v1/public/status/:slug— Public status (no auth)

Workspaces

Workspace management.

GET/api/v1/workspaces— List your workspaces
GET/api/v1/workspaces/default— Get your default workspace (fastest way to discover workspace_id)
GET/api/v1/workspaces/summary— Compact list (id, name) — handy for dropdowns
POST/api/v1/workspaces— Create workspace
PUT/api/v1/workspaces/:id— Update workspace
DELETE/api/v1/workspaces/:id— Delete workspace
POST/api/v1/workspaces/:id/set-default— Set default workspace
POST/api/v1/workspaces/:id/regenerate-ping-key— Rotate ping_key (existing heartbeat ping URLs stop working)

Heartbeats (Cron)

Cron job monitoring.

GET/api/v1/heartbeats— List heartbeat monitors
POST/api/v1/heartbeats— Create heartbeat monitor
GET/api/v1/heartbeats/:id— Get heartbeat monitor details
PATCH/api/v1/heartbeats/:id— Update heartbeat monitor
DELETE/api/v1/heartbeats/:id— Delete heartbeat monitor
POST/api/v1/heartbeats/:id/pause— Pause heartbeat monitor
POST/api/v1/heartbeats/:id/resume— Resume heartbeat monitor
POST/api/v1/heartbeats/:id/regenerate-secret— Regenerate authentication secret
GET/api/v1/heartbeats/:id/stats— Get heartbeat statistics (uptime, ping counts)
GET/api/v1/heartbeats/:id/pings— Get ping history (paginated)
GET/api/v1/ping/:ping_key/:slug— Record ping via GET (no auth, for simple cron jobs)
POST/api/v1/ping/:ping_key/:slug— Record ping via POST (no auth, with optional payload)
POST/api/v1/ping/:ping_key/:slug/start— Record job start signal (no auth)
POST/api/v1/ping/:ping_key/:slug/success— Record job success signal (no auth)
POST/api/v1/ping/:ping_key/:slug/fail— Record job failure signal (no auth)

API Keys

API key management.

GET/api/v1/api-keys— List API keys
POST/api/v1/api-keys— Create API key
DELETE/api/v1/api-keys/:id— Revoke API key

Maintenance

Maintenance windows.

GET/api/v1/maintenance— List maintenance windows
POST/api/v1/maintenance— Create maintenance window
GET/api/v1/maintenance/:id— Get maintenance window details
PUT/api/v1/maintenance/:id— Update maintenance window
DELETE/api/v1/maintenance/:id— Delete maintenance window
POST/api/v1/maintenance/:id/cancel— Cancel maintenance

Monitor Groups

Group management (12 endpoints, grouped by purpose).

Group CRUD

GET/api/v1/monitor-groups— List monitor groups
POST/api/v1/monitor-groups— Create monitor group
GET/api/v1/monitor-groups/:id— Get monitor group details
PUT/api/v1/monitor-groups/:id— Update group (name, description, paused flag)
DELETE/api/v1/monitor-groups/:id— Delete monitor group

Memberships (monitors & tags)

POST/api/v1/monitor-groups/:id/monitors— Add monitors to group
DELETE/api/v1/monitor-groups/:id/monitors— Remove monitors from group
POST/api/v1/monitor-groups/:id/tags— Add tags
DELETE/api/v1/monitor-groups/:id/tags— Remove tags

Status & stats

GET/api/v1/monitor-groups/stats— Aggregate stats across all groups
GET/api/v1/monitor-groups/:id/status— Get aggregate group status
PUT/api/v1/monitor-groups/:id/status— Update aggregate group status

Telegram Groups

Telegram group alerts.

GET/api/v1/telegram-groups— List linked Telegram groups
POST/api/v1/telegram-groups/link— Generate deep-link URL for Telegram group
DELETE/api/v1/telegram-groups/:id— Unlink Telegram group

Scheduled Reports

Automated email reports.

GET/api/v1/scheduled-reports— List scheduled reports
POST/api/v1/scheduled-reports— Create scheduled report
GET/api/v1/scheduled-reports/:id— Get report details
PUT/api/v1/scheduled-reports/:id— Update scheduled report
DELETE/api/v1/scheduled-reports/:id— Delete scheduled report
POST/api/v1/scheduled-reports/:id/pause— Pause report
POST/api/v1/scheduled-reports/:id/resume— Resume report
POST/api/v1/scheduled-reports/:id/run— Run report manually
POST/api/v1/scheduled-reports/:id/toggle— Toggle active flag (pause/resume in one call)
GET/api/v1/scheduled-reports/:id/runs— Report execution history

Alert Channel Configs

Channel credentials (SMTP, Twilio, etc.).

GET/api/v1/alert-channel-configs— List channel configurations
POST/api/v1/alert-channel-configs— Create channel config
PATCH/api/v1/alert-channel-configs/:id— Update channel config
DELETE/api/v1/alert-channel-configs/:id— Delete channel config
POST/api/v1/alert-channel-configs/:id/test— Send a test message via this config
POST/api/v1/alert-channel-configs/:id/activate— Activate (re-enable after auto-disable from a delivery error streak)
POST/api/v1/alert-channel-configs/:id/deactivate— Temporarily disable without deleting
GET/api/v1/alert-channel-configs/channels/:channel— Active config for a channel (telegram, discord, slack, …)

Dashboard

Aggregated statistics.

GET/api/v1/dashboard/stats— Aggregated dashboard statistics
GET/api/v1/dashboard/uptime-summary— Overall uptime summary across all monitors
GET/api/v1/dashboard/alerts-summary— Alerts summary
GET/api/v1/dashboard/incidents— Incidents summary
GET/api/v1/dashboard/combined— All dashboard data in one call

Webhooks (Outgoing)

Event webhook delivery (12 endpoints, grouped by purpose).

Webhook CRUD

GET/api/v1/webhooks— List webhooks
POST/api/v1/webhooks— Create webhook
GET/api/v1/webhooks/:id— Get webhook details
PATCH/api/v1/webhooks/:id— Update webhook
DELETE/api/v1/webhooks/:id— Delete webhook

Actions

POST/api/v1/webhooks/:id/test— Send a test payload
POST/api/v1/webhooks/:id/secret— Rotate HMAC signing secret (existing signatures stop being accepted on your side)

Deliveries & DLQ

GET/api/v1/webhooks/:id/deliveries— Delivery history
GET/api/v1/webhooks/:id/stats— Aggregate delivery statistics (success/error/p50/p95)
GET/api/v1/webhooks/:id/dlq— Dead Letter Queue: deliveries that failed all retries
POST/api/v1/webhooks/:id/dlq/:dlq_id/retry— Retry a DLQ entry
POST/api/v1/webhooks/:id/dlq/:dlq_id/resolve— Mark a DLQ entry resolved (without retrying)

Reference

GET/api/v1/webhooks/events— Available event types (used when creating a webhook)

Webhook Checks (Incoming)

Accept incoming webhooks from external services (10 endpoints + 1 public receiver, grouped by purpose).

Check CRUD

GET/api/v1/webhook-checks— List incoming webhook checks
POST/api/v1/webhook-checks— Create incoming webhook check
GET/api/v1/webhook-checks/:id— Get webhook check details
PUT/api/v1/webhook-checks/:id— Update webhook check
DELETE/api/v1/webhook-checks/:id— Delete webhook check

Check operations

POST/api/v1/webhook-checks/:id/pause— Pause webhook check
POST/api/v1/webhook-checks/:id/resume— Resume webhook check
POST/api/v1/webhook-checks/:id/regenerate-secret— Rotate secret (the existing HMAC signature from the source stops being accepted)

Events & stats

GET/api/v1/webhook-checks/:id/events— Incoming webhook check events
GET/api/v1/webhook-checks/:id/stats— Aggregate stats for an incoming check

Public receiver (no auth)

POST/api/v1/webhook-check/:slug— Record a delivery (this URL is what you hand to the external service)

Feedback

User feedback and feature requests.

POST/api/v1/feedback— Submit feedback
GET/api/v1/feedback— List feedback
GET/api/v1/feedback/:id— Get feedback details
PUT/api/v1/feedback/:id/status— Update feedback status (admin)
DELETE/api/v1/feedback/:id— Delete feedback (admin)

Web Push

Browser push notifications.

GET/api/v1/web-push/vapid-public-key— Get VAPID public key
POST/api/v1/web-push/subscribe— Subscribe to push notifications
POST/api/v1/web-push/unsubscribe— Unsubscribe from push notifications

Probe

Probe identification and IP addresses.

GET/api/v1/probe/ips— Get probe IP addresses (public, no auth)

Request Examples

Detailed cURL examples.

List monitors

curl -H "X-API-Key: YOUR_API_KEY" \
  https://pingzen.dev/api/v1/monitors?workspace_id=1

How to find your workspace_id

The workspace_id field is required in the payload when creating monitors, alerts, reports, and status pages. There are two ways to get it.

Option 1: via UI (fastest). Open the workspaces page — each workspace card shows its ID. For most users it’s 1.

Option 2: via API (for CI/scripts). The /api/v1/workspaces* endpoints currently require JWT, not X-API-Key (see “Where X-API-Key works” above). Steps:

# 1. Log in — get an access_token
ACCESS=$(curl -sS -X POST https://pingzen.dev/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d '{"email":"you@example.com","password":"…"}' \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["access_token"])')

# 2. Default workspace (the one pre-selected in the UI)
curl -sS -H "Authorization: Bearer $ACCESS" \
  https://pingzen.dev/api/v1/workspaces/default
# → {"id": 42, "name": "My Workspace", "is_default": true, ...}

# 3. Or a compact list of all (id, name) for dropdowns
curl -sS -H "Authorization: Bearer $ACCESS" \
  https://pingzen.dev/api/v1/workspaces/summary

One-liner “log in → fetch default id” for CI:

ACCESS=$(curl -sS -X POST https://pingzen.dev/api/v1/auth/login \
  -H 'Content-Type: application/json' \
  -d "{\"email\":\"$EMAIL\",\"password\":\"$PASS\"}" \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["access_token"])')

WORKSPACE_ID=$(curl -sS -H "Authorization: Bearer $ACCESS" \
  https://pingzen.dev/api/v1/workspaces/default \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["id"])')

echo "$WORKSPACE_ID"   # → 42

Then plug $WORKSPACE_ID into the POST /api/v1/monitors payload below (that one is an X-API-Key endpoint).

Create a monitor

curl -X POST https://pingzen.dev/api/v1/monitors \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name": "My Site", "url": "https://example.com", "protocol": "https", "workspace_id": 1, "interval_seconds": 60}'

Get monitor

curl -H "X-API-Key: YOUR_API_KEY" \
  https://pingzen.dev/api/v1/monitors/123

Update monitor

curl -X PATCH https://pingzen.dev/api/v1/monitors/123 \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"interval_seconds": 60, "name": "Updated Name"}'

Minimum interval_seconds depends on plan: FREE — 60s, paid — 30s. A value below the plan minimum returns 422 with a descriptive error.

Delete monitor

curl -X DELETE https://pingzen.dev/api/v1/monitors/123 \
  -H "X-API-Key: YOUR_API_KEY"

Create a heartbeat monitor

Create a heartbeat monitor for cron jobs and scheduled tasks. Returns a unique ping URL and secret. /heartbeats CRUD currently requires JWT (see “Where X-API-Key works”); workspace_id is passed as a query parameter, not in the body:

curl -X POST "https://pingzen.dev/api/v1/heartbeats?workspace_id=$WORKSPACE_ID" \
  -H "Authorization: Bearer $ACCESS" \
  -H "Content-Type: application/json" \
  -d '{"name": "Daily Backup", "expected_interval_seconds": 86400, "grace_period_seconds": 600}'

Send heartbeat ping (GET)

Simplest integration — just add to crontab or end of script. No authentication required.

# Simplest: chain with && so ping fires only on success
0 3 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 https://pingzen.dev/api/v1/ping/YOUR_PING_KEY/YOUR_SLUG

# Or just a standalone ping
curl https://pingzen.dev/api/v1/ping/aBcDeFgHiJkLmNoPqR/daily-backup

Heartbeat lifecycle signals

Report job lifecycle signals (start/success/fail) with optional payload and duration. Use X-Secret header for authentication.

# Report success with payload and duration
curl -X POST https://pingzen.dev/api/v1/ping/aBcDeFgHiJkLmNoPqR/daily-backup/success \
  -H "X-Secret: YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"duration_ms": 45000, "payload": {"rows": 500000}}'

# Report failure — triggers instant alert (no waiting for missed interval)
curl -X POST https://pingzen.dev/api/v1/ping/aBcDeFgHiJkLmNoPqR/daily-backup/fail \
  -H "X-Secret: YOUR_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"payload": {"error": "disk full"}}'

# One-liner for cron: success OR fail
/usr/local/bin/backup.sh \
  && curl -fsS -m 10 https://pingzen.dev/api/v1/ping/aBcDeFgHiJkLmNoPqR/daily-backup/success \
  || curl -fsS -m 10 https://pingzen.dev/api/v1/ping/aBcDeFgHiJkLmNoPqR/daily-backup/fail

Code Examples

Python Example

import requests

# Get your API key from: Profile → API Keys → Create New Key
PINGZEN_API_KEY = "YOUR_API_KEY"
BASE_URL = "https://pingzen.dev/api/v1"

headers = {
    "X-API-Key": PINGZEN_API_KEY,
    "Content-Type": "application/json"
}

# Create a monitor
monitor_data = {
    "name": "My Website",
    "url": "https://example.com",
    "protocol": "https",
    "interval_seconds": 60,
    "workspace_id": 1
}

response = requests.post(
    f"{BASE_URL}/monitors",
    headers=headers,
    json=monitor_data
)

print(response.json())

# Get all monitors (response is {monitors: [...], total, page, page_size})
data = requests.get(
    f"{BASE_URL}/monitors",
    headers=headers,
    params={"workspace_id": 1},  # scope to your workspace
).json()

for monitor in data["monitors"]:
    print(f"{monitor['name']}: {monitor['status']}")

JavaScript Example

// Get your API key from: Profile → API Keys → Create New Key
const PINGZEN_API_KEY = 'pz_abc12345_...';
const BASE_URL = 'https://pingzen.dev/api/v1';

const headers = {
  'X-API-Key': PINGZEN_API_KEY,
  'Content-Type': 'application/json'
};

// Create a monitor
async function createMonitor() {
  const response = await fetch(`${BASE_URL}/monitors`, {
    method: 'POST',
    headers: headers,
    body: JSON.stringify({
      name: 'My Website',
      url: 'https://example.com',
      protocol: 'https',
      interval_seconds: 60,
      workspace_id: 1
    })
  });

  const data = await response.json();
  console.log(data);
}

// Get all monitors (response is {monitors: [...], total, page, page_size})
async function getMonitors() {
  const response = await fetch(
    `${BASE_URL}/monitors?workspace_id=1`,  // scope to your workspace
    { headers: headers },
  );

  const data = await response.json();
  data.monitors.forEach(monitor => {
    console.log(`${monitor.name}: ${monitor.status}`);
  });
}

createMonitor();
getMonitors();

Heartbeat / Cron Monitoring Examples

Monitor cron jobs, scheduled tasks, and background processes. Create a heartbeat monitor, then send pings from your scripts to confirm they ran.

Bash / Cron Job

#!/bin/bash
# === Pattern 1: Chain with && (recommended for cron) ===
# curl runs ONLY if backup succeeds (exit code 0)
# If backup fails — no ping — PingZen alerts after grace period
#
# 0 2 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 https://pingzen.dev/api/v1/ping/YOUR_PING_KEY/YOUR_SLUG

# === Pattern 2: Report both success AND failure (best) ===
# /success on success, /fail on failure — instant alert, no waiting
#
# 0 2 * * * /usr/local/bin/backup.sh \
#   && curl -fsS -m 10 https://pingzen.dev/api/v1/ping/YOUR_PING_KEY/YOUR_SLUG/success \
#   || curl -fsS -m 10 https://pingzen.dev/api/v1/ping/YOUR_PING_KEY/YOUR_SLUG/fail

# === Pattern 3: Full script with duration and payload ===
PING_KEY="YOUR_PING_KEY"
SLUG="daily-backup"
SECRET="YOUR_SECRET"
PING_URL="https://pingzen.dev/api/v1/ping/$PING_KEY/$SLUG"
SECONDS=0  # Bash built-in timer

# Your backup logic
pg_dump mydb > /backups/mydb_$(date +%F).sql

if [ $? -eq 0 ]; then
  # Report success with duration
  curl -fsS -m 10 -X POST "$PING_URL/success" \
    -H "X-Secret: $SECRET" \
    -H "Content-Type: application/json" \
    -d "{\"duration_ms\": $((SECONDS * 1000))}"
else
  # Report failure — instant alert
  curl -fsS -m 10 -X POST "$PING_URL/fail" \
    -H "X-Secret: $SECRET" \
    -H "Content-Type: application/json" \
    -d "{\"payload\": {\"error\": \"pg_dump failed\"}}"
fi

Python Heartbeat

import requests

BASE_URL = "https://pingzen.dev/api/v1"

# /heartbeats CRUD currently requires JWT (X-API-Key not yet supported).
# Log in once and reuse the token; refresh via /auth/refresh after 15 minutes.
login = requests.post(
    f"{BASE_URL}/auth/login",
    json={"email": "you@example.com", "password": "..."},
).json()
ACCESS = login["access_token"]
WORKSPACE_ID = requests.get(
    f"{BASE_URL}/workspaces/default",
    headers={"Authorization": f"Bearer {ACCESS}"},
).json()["id"]

# Create a heartbeat monitor (workspace_id goes in the query, not the body)
heartbeat = requests.post(
    f"{BASE_URL}/heartbeats",
    params={"workspace_id": WORKSPACE_ID},
    headers={"Authorization": f"Bearer {ACCESS}", "Content-Type": "application/json"},
    json={
        "name": "Daily Backup",
        "expected_interval_seconds": 86400,
        "grace_period_seconds": 600,
    },
).json()

ping_key = heartbeat["ping_key"]  # Workspace secret key
slug = heartbeat["slug"]
secret = heartbeat["secret"]      # Save this — shown only once!
ping_url = f"{BASE_URL}/ping/{ping_key}/{slug}"
print(f"Ping URL: {ping_url}")

# Send a ping at the end of your script (no auth needed for the ping itself,
# X-Secret authenticates lifecycle signals)
requests.post(
    f"{ping_url}/success",
    headers={"X-Secret": secret, "Content-Type": "application/json"},
    json={"duration_ms": 12000, "payload": {"status": "ok"}},
)

JavaScript Heartbeat

const BASE_URL = 'https://pingzen.dev/api/v1';

// /heartbeats CRUD currently requires JWT (X-API-Key not yet supported).
// Login once, reuse the token; refresh via /auth/refresh after 15 minutes.
async function login(email, password) {
  const res = await fetch(`${BASE_URL}/auth/login`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ email, password }),
  });
  return (await res.json()).access_token;
}

async function defaultWorkspaceId(access) {
  const res = await fetch(`${BASE_URL}/workspaces/default`, {
    headers: { 'Authorization': `Bearer ${access}` },
  });
  return (await res.json()).id;
}

// Create a heartbeat monitor (workspace_id goes in the query, not the body)
async function createHeartbeat(access, workspaceId) {
  const response = await fetch(
    `${BASE_URL}/heartbeats?workspace_id=${workspaceId}`,
    {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${access}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        name: 'Nightly Report',
        expected_interval_seconds: 86400,
        grace_period_seconds: 600,
      }),
    },
  );

  const data = await response.json();
  console.log('Ping URL:', `${BASE_URL}/ping/${data.ping_key}/${data.slug}`);
  console.log('Secret:', data.secret); // Save — shown only once!
  return data;
}

// Send heartbeat ping from your cron job (no JWT needed; X-Secret authenticates)
async function sendPing(pingKey, slug, secret) {
  await fetch(`${BASE_URL}/ping/${pingKey}/${slug}/success`, {
    method: 'POST',
    headers: {
      'X-Secret': secret,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      duration_ms: 5000,
      payload: { rows_processed: 1000 },
    }),
  });
}

OpenAPI & AI Agents

PingZen provides machine-readable specifications for AI agent integration and automation tools.

Rate Limits

PlanRequests/HourBurst Limit
Free100/hour10/minute

Common Questions

What protocols can I monitor?

PingZen supports 23 protocols: HTTP/HTTPS, WebSocket (WS/WSS), TCP, UDP, ICMP Ping, gRPC, DNS, WHOIS, SSL certificates, Email (SMTP/IMAP/POP3), FTP/FTPS, DNSBL, PageSpeed, SOCKS5, MTProxy, API Check, and Transaction. You can monitor websites, APIs, servers, databases, and any network service.

How fast can I get alerts?

Telegram alerts are delivered within 1-2 seconds of detection. Slack and Discord notifications arrive almost instantly. You can configure multiple alert channels for redundancy.

Can I organize monitors by project?

Yes! PingZen supports workspaces, which let you organize monitors by project, environment, or team. Each workspace can have its own alert configurations and team members.

Is there an API for automation?

Absolutely. PingZen provides a full REST API with OpenAPI documentation. You can create, update, and delete monitors programmatically.

How do status pages work?

Status pages are public, branded pages showing your services' uptime. You can display real-time status and allow customers to subscribe for updates.

What happens if I reach my monitor limit?

We'll notify you when approaching your limit. You can pause some monitors or contact us for increased capacity. We never stop monitoring without warning, ensuring your critical services stay protected.

Ready to stop missing downtime?

Join thousands of teams who trust PingZen. Setup takes 30 seconds.