Skip to main content
Track relevant changes to careers, pricing, product, or company pages and turn them into a digest. Context.dev detects changes; your application saves events, decides what belongs in the digest, and handles notification delivery. Adapt uses Context.dev to monitor websites. This recipe connects Monitors to a durable event store, with polling to recover missed deliveries and expose failed checks.

Define what matters on each source

Create a watchlist with an application ID, source URL, owner, and description of the relevant change. Choose the target by the question you want to answer: Use the monitoring guide for cURL and SDK requests. For example, send this body to POST /monitors, replacing the source and webhook URL:
Monitor request body
The interval must be at least 10 minutes. Save the returned monitor id, initial_run_id, and generated webhook secret with your watchlist record. Store the secret securely. The first run establishes a baseline; it is not a new-change alert.

Verify and persist before acknowledging

Read the raw webhook body and verify X-Context-Signature using the signature verification implementation. The signature covers the timestamp and raw bytes. This Python equivalent uses the same protocol:
verify_webhook.py
Reject a false verification result before parsing or storing the event. Compute the signature from the original request bytes. The following Python store starts after that verification step. accept_verified_event also checks that the event belongs to the monitor associated with the verified secret. Route your webhook using the application watch ID, resolve its stored monitor and secret, then verify the signature, validate the payload, and call this function.
digest_store.py
Validate parsed events against the change.detected or run.completed schema before calling the store. Return 2xx only after the event insert commits. A worker can then call process_events; its transaction saves the derived records and marks the event processed together. Deduplicate both levels. Event id handles a repeated delivery. Change id handles a changed run arriving through both event subscriptions, or later through polling. Both paths should produce one digest item.

Reconcile deliveries and failed checks

run.completed reports completed runs, including baselines and runs with no change. Failed and skipped checks require the runs API; absence of a webhook does not mean “no change.” The following polling worker imports the store functions above. It reads every page of runs and changes and uses the same record IDs as the webhook path. For a larger history, persist a reconciliation cursor and continue the job across bounded worker executions.
reconcile_digest.py
The changes list returns summaries. Fetch the full change by its ID if the digest needs a diff or before-and-after evidence that was not saved from a webhook. A later fetch should fill missing detail on the existing change, not create another item. Only advance your reconciliation checkpoint after every page is saved. If a request fails, keep already saved rows, leave the job incomplete, and resume with a bounded retry policy. Inspect the monitor’s webhook_failure and individual run delivery records when diagnosing delivery problems.

Make freshness visible in the digest

Compute the last successful observation from completed runs rather than from the latest attempt:
Last successful check
Show the latest failed or skipped check alongside this value. A baseline is a successful observation, but it has not yet compared two snapshots. Keep that distinction visible for newly added sources. Each digest item should link to the observed URL and include its detection time. For sitemap changes, a newly discovered URL is a candidate for follow-up extraction; its appearance alone does not prove that a new product or job exists. Keep the original change evidence available behind summaries. Build delivery around a saved digest edition and its change IDs. Use an outbox or equivalent durable queue, and record provider delivery state so worker retries do not repeatedly send the same edition. Notification channels and summarization belong to your application.

Exercise duplicate and missing events

Process one change event twice, then process the run.completed event for the same changed run: the store should contain one change. Skip another webhook and reconcile it through the API. Add a failed run and check that the last successful observation remains intact while the failure appears in the watchlist.

Monitor setup and signatures

Configure targets, intervals, and verified webhook delivery.

Structured datasets

Refresh extracted records after a relevant source change.