Preview · API keys are coming soon

Diffmonitors API

A small REST API for creating monitors and a streaming API for consuming their diffs. Base URL https://api.diffmonitors.com/v1.

Quickstart

Authenticate with a bearer token, create a monitor, and you’ll receive a baseline event followed by one event per detected change.

bash
export DIFFMONITORS_API_KEY="dm_live_…"

curl https://api.diffmonitors.com/v1/monitors \
  -H "Authorization: Bearer $DIFFMONITORS_API_KEY" \
  -d url="https://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.geojson" \
  -d interval="1m" \
  -d ignore="metadata.generated,bbox"

Monitors

A monitor is a URL plus a cadence and optional request settings.

POST/v1/monitorsCreate a monitor
GET/v1/monitorsList monitors
PATCH/v1/monitors/:idUpdate cadence, rules or delivery
DELETE/v1/monitors/:idDelete a monitor
POST/v1/monitors/bulkCreate up to 10,000 monitors (Enterprise)
1{
2 "url": "https://example.com/pricing",
3 "interval": "1h | 1m | 1s | 100ms (Enterprise: rate agreed per target)",
4 "method": "GET",
5 "headers": {
6 "x-api-key": "{{secret:vendor_key}}"
7 },
8 "selector": "main .pricing",
9 "ignore": [
10 "updated_at",
11 "features.*.properties.updated"
12 ],
13 "when": "plans[0].price < 49",
14 "notify": [
15 {
16 "type": "webhook",
17 "url": "https://example.com/hooks/diff"
18 },
19 {
20 "type": "slack",
21 "channel": "#pricing-intel"
22 }
23 ]
24}

Events

Every check that produces a difference emits a monitor.changed event. Events contain a summary and an RFC 6902 JSON Patch from the previous snapshot.

GET/v1/monitors/:id/eventsPaginated event history
GET/v1/snapshots/:etagFetch a stored snapshot
GET/v1/monitors/:id/diff?from=…&to=…Diff any two points in time

Webhooks

Webhooks are POSTed as JSON and signed with HMAC-SHA256 in the x-diffmonitors-signature header (t=timestamp,v1=signature). Failed deliveries retry with exponential backoff for 24 hours.

ts
import { createHmac, timingSafeEqual } from "node:crypto"

export function verify(body: string, header: string, secret: string) {
  const { t, v1 } = Object.fromEntries(header.split(",").map((p) => p.split("=")))
  const expected = createHmac("sha256", secret).update(`${t}.${body}`).digest("hex")
  return timingSafeEqual(Buffer.from(v1), Buffer.from(expected))
}

Streaming

Pro plans can subscribe to a monitor’s events over Server-Sent Events. Enterprise plans add a multiplexed WebSocket firehose across all monitors.

js
const es = new EventSource("https://stream.diffmonitors.com/v1/monitors/mon_8f2c1a/events?token=" + token)
es.addEventListener("monitor.changed", (e) => console.log(JSON.parse(e.data).patch))

Ignore rules

Rules are applied before diffing. A bare key such as time matches that key at any depth. A dotted path such as metadata.generated matches exactly, and * matches any key or array element. Arrays of objects are matched by id, uuid, key, slug, code or name when present.

Rate limits

Free1 check / hour / endpointNo API access
Pro1 check / minute / endpoint600 API requests / min
EnterpriseCustom per target, up to 100 checks / secondCustom