API Documentation

ChangePulse REST API

Programmatically manage monitors, retrieve detected changes, and integrate website monitoring into your workflows.

Secure API Keys

SHA-256 hashed keys. Generate and revoke in Settings.

RESTful JSON

Standard HTTP verbs & status codes. All responses are JSON.

Webhooks & Slack

Receive real-time change notifications via webhook or Slack.

API access requires a Pro plan ($19/mo)

Includes unlimited monitors, hourly checks, webhooks, Slack alerts & full API access.

Get Started

Authentication

All API requests must include your API key in the Authorization header using the Bearer scheme. Generate your key in Settings → API Key.

curl -H "Authorization: Bearer cp_your_api_key_here" \
  https://changepulse.io/api/v1/monitors
Keep your key secret. Never expose it in client-side code, public repos, or logs. If compromised, revoke it immediately in Settings and generate a new one.

Base URL

https://changepulse.io/api/v1

All endpoint paths below are relative to this base URL.

Rate Limits

ScopeLimitWindow
Read endpoints (GET)120 requestsper minute
Write endpoints (POST/PATCH/DELETE)30 requestsper minute

If you exceed the limit you'll receive a 429 Too Many Requests response. Wait and retry.

Error Handling

Errors return a JSON object with a message field and the appropriate HTTP status code.

// 401 Unauthorized
{
  "statusCode": 401,
  "message": "Invalid API key"
}

// 404 Not Found
{
  "statusCode": 404,
  "message": "Monitor not found"
}

// 400 Bad Request
{
  "statusCode": 400,
  "message": "Invalid URL"
}
CodeMeaning
200Success
201Created
204Deleted (no body)
400Invalid input
401Missing / invalid API key
403Plan limit or feature gate
404Resource not found
429Rate limit exceeded
500Server error

Monitors

Monitors represent URLs you're watching for changes. Each monitor has its own check interval, notification preferences, and detection history.

Changes

Each time a monitored page's content changes, a change record is created with the old/new content and a unified diff.

Check Logs

Every check attempt is logged with status, timing, and whether a change was detected. Useful for debugging and uptime tracking.

Webhook Payloads

When a change is detected, ChangePulse sends a POST request to the webhook URL configured on the monitor. Respond with any 2xx status within 10 seconds to acknowledge delivery.

Example Payload

{
  "event": "change_detected",
  "monitor": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "name": "Example Pricing Page",
    "url": "https://example.com/pricing"
  },
  "change": {
    "detectedAt": "2026-04-14T08:30:00.000Z",
    "summary": {
      "addedLines": 1,
      "removedLines": 1,
      "unchangedLines": 0
    },
    "hunks": [
      {
        "removed": ["Price: $49/mo"],
        "added":   ["Price: $59/mo"]
      }
    ],
    "rawDiff": "Index: https://example.com/pricing\n--- https://example.com/pricing\tprevious\n+++ https://example.com/pricing\tcurrent\n@@ -1,1 +1,1 @@\n-Price: $49/mo\n+Price: $59/mo",
    "oldContentLength": 1234,
    "newContentLength": 1240
  }
}

Field Reference

FieldDescription
eventAlways "change_detected"
monitor.idUUID of the monitor that triggered the alert
monitor.nameHuman-readable name of the monitor
monitor.urlThe URL being monitored
change.detectedAtTimestamp when the change was detected
change.summary.addedLinesNumber of lines added in this diff
change.summary.removedLinesNumber of lines removed in this diff
change.summary.unchangedLinesNumber of context lines that did not change
change.hunksParsed diff hunks. Each hunk has "added" and "removed" string arrays for easy comparison
change.hunks[].removedLines that were present before the change (stripped of leading "-")
change.hunks[].addedLines that are present after the change (stripped of leading "+")
change.rawDiffFull unified diff string — useful for advanced parsing or display
change.oldContentLengthCharacter count of the previous page content
change.newContentLengthCharacter count of the new page content
Use hunks for easy "before / after" comparisons without parsing the diff string.
rawDiff is the full unified diff — useful for rich diff rendering or tools like diff2html.
Failed deliveries are logged in the Webhooks tab in Settings but are not retried automatically.

Quick-Start Examples

Create a monitor & poll for changes (bash)

# 1. Create a monitor
MONITOR=$(curl -s -X POST https://changepulse.io/api/v1/monitors \
  -H "Authorization: Bearer $CP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://example.com/pricing","intervalMinutes":60}')

MONITOR_ID=$(echo $MONITOR | jq -r '.id')

# 2. Check for recent changes
curl -s https://changepulse.io/api/v1/monitors/$MONITOR_ID/changes \
  -H "Authorization: Bearer $CP_API_KEY" | jq .

Node.js / JavaScript

const API_KEY = process.env.CP_API_KEY;
const BASE = 'https://changepulse.io/api/v1';

// List all monitors
const monitors = await fetch(`${BASE}/monitors`, {
  headers: { Authorization: `Bearer ${API_KEY}` },
}).then(r => r.json());

console.log(`You have ${monitors.length} monitors`);

// Pause a monitor
await fetch(`${BASE}/monitors/${monitors[0].id}`, {
  method: 'PATCH',
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ status: 'paused' }),
});

Python

import requests, os

API_KEY = os.environ["CP_API_KEY"]
BASE = "https://changepulse.io/api/v1"
headers = {"Authorization": f"Bearer {API_KEY}"}

# List monitors
monitors = requests.get(f"{BASE}/monitors", headers=headers).json()
print(f"Monitoring {len(monitors)} URLs")

# Get changes for first monitor
changes = requests.get(
    f"{BASE}/monitors/{monitors[0]['id']}/changes",
    headers=headers,
    params={"limit": 5},
).json()

for c in changes:
    print(f"  {c['detectedAt']}: {len(c['diffText'])} chars changed")

Ready to integrate?

Generate your API key in Settings and start making requests in seconds. The Pro plan includes unlimited monitors and full API access.