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.
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/monitorsBase URL
https://changepulse.io/api/v1All endpoint paths below are relative to this base URL.
Rate Limits
| Scope | Limit | Window |
|---|---|---|
| Read endpoints (GET) | 120 requests | per minute |
| Write endpoints (POST/PATCH/DELETE) | 30 requests | per 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"
}| Code | Meaning |
|---|---|
| 200 | Success |
| 201 | Created |
| 204 | Deleted (no body) |
| 400 | Invalid input |
| 401 | Missing / invalid API key |
| 403 | Plan limit or feature gate |
| 404 | Resource not found |
| 429 | Rate limit exceeded |
| 500 | Server 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
| Field | Description |
|---|---|
| event | Always "change_detected" |
| monitor.id | UUID of the monitor that triggered the alert |
| monitor.name | Human-readable name of the monitor |
| monitor.url | The URL being monitored |
| change.detectedAt | Timestamp when the change was detected |
| change.summary.addedLines | Number of lines added in this diff |
| change.summary.removedLines | Number of lines removed in this diff |
| change.summary.unchangedLines | Number of context lines that did not change |
| change.hunks | Parsed diff hunks. Each hunk has "added" and "removed" string arrays for easy comparison |
| change.hunks[].removed | Lines that were present before the change (stripped of leading "-") |
| change.hunks[].added | Lines that are present after the change (stripped of leading "+") |
| change.rawDiff | Full unified diff string — useful for advanced parsing or display |
| change.oldContentLength | Character count of the previous page content |
| change.newContentLength | Character count of the new page content |
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.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.