> ## Documentation Index
> Fetch the complete documentation index at: https://docs.context.dev/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Setting up Context.dev for a user? Follow https://docs.context.dev/agent-quickstart.md. MCP clients sign in with OAuth and need no API key; application code reads CONTEXT_DEV_API_KEY.

# Monitors

> Watch a page, a sitemap, or a site's key pages on a schedule. Get changes by signed webhook or by polling runs and changes.

A monitor captures a baseline of a target, checks the target again on a schedule, and records a change when it finds a difference that counts. Receive changes as signed webhooks, or poll runs and changes through the API.

## Pick a target

| What you want to know                                        | Target                     | Detection  |
| ------------------------------------------------------------ | -------------------------- | ---------- |
| Did the visible text on a page change?                       | `page`                     | `exact`    |
| Did something I care about change on a page?                 | `page` with `instructions` | `semantic` |
| Were URLs added to or removed from a sitemap?                | `sitemap`                  | `exact`    |
| Did something I care about change across a site's key pages? | `extract`                  | `semantic` |

These are the only supported pairs. Exact detection reports every text difference. Semantic detection confirms a text difference, then asks an AI judge whether it matters under your `instructions`. When you omit `change_detection`, it's inferred from the target as in the table. Extract monitors cost more per run than page and sitemap monitors. See [credits](/account/credits).

## Create a monitor

This monitor watches a changelog page and reports only the changes its instructions describe. Because the target has `instructions`, detection is `semantic`. The examples read your API key from `CONTEXT_DEV_API_KEY`; the [Quickstart](/quickstart) shows how to set one up.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import ContextDev from "context.dev";

  const client = new ContextDev({ apiKey: process.env.CONTEXT_DEV_API_KEY });

  const monitor = await client.monitors.create({
    name: "Changelog announcements",
    target: {
      type: "page",
      url: "https://example.com/changelog",
      instructions: "Report new features, deprecations, and breaking changes. Ignore dates and typo fixes.",
      include_selectors: ["main"],
      exclude_selectors: [".timestamp"],
    },
    webhook: { url: "https://app.example.com/webhooks/context", retry: {} },
  });
  console.log(monitor.id, monitor.initial_run_id);
  ```

  ```python Python theme={null}
  import os
  from context.dev import ContextDev

  client = ContextDev(api_key=os.environ["CONTEXT_DEV_API_KEY"])

  monitor = client.monitors.create(
      name="Changelog announcements",
      target={
          "type": "page",
          "url": "https://example.com/changelog",
          "instructions": "Report new features, deprecations, and breaking changes. Ignore dates and typo fixes.",
          "include_selectors": ["main"],
          "exclude_selectors": [".timestamp"],
      },
      webhook={"url": "https://app.example.com/webhooks/context", "retry": {}},
  )
  print(monitor.id, monitor.initial_run_id)
  ```

  ```ruby Ruby theme={null}
  require "cgi/core"
  require "context_dev"

  client = ContextDev::Client.new(api_key: ENV.fetch("CONTEXT_DEV_API_KEY"))

  monitor = client.monitors.create(
    name: "Changelog announcements",
    target: {
      type: "page",
      url: "https://example.com/changelog",
      instructions: "Report new features, deprecations, and breaking changes. Ignore dates and typo fixes.",
      include_selectors: ["main"],
      exclude_selectors: [".timestamp"],
    },
    webhook: {url: "https://app.example.com/webhooks/context", retry: {}},
  )
  puts monitor.id, monitor.initial_run_id
  ```

  ```go Go theme={null}
  package main

  import (
  	"context"
  	"fmt"
  	"os"

  	contextdev "github.com/context-dot-dev/context-go-sdk/v2"
  	"github.com/context-dot-dev/context-go-sdk/v2/option"
  	"github.com/context-dot-dev/context-go-sdk/v2/packages/param"
  )

  func main() {
  	client := contextdev.NewClient(option.WithAPIKey(os.Getenv("CONTEXT_DEV_API_KEY")))

  	monitor, err := client.Monitors.New(context.Background(), contextdev.MonitorNewParams{
  		Name: "Changelog announcements",
  		Target: contextdev.MonitorNewParamsTargetUnion{
  			OfPage: &contextdev.MonitorNewParamsTargetPage{
  				Type:             "page",
  				URL:              "https://example.com/changelog",
  				Instructions:     contextdev.String("Report new features, deprecations, and breaking changes. Ignore dates and typo fixes."),
  				IncludeSelectors: []string{"main"},
  				ExcludeSelectors: []string{".timestamp"},
  			},
  		},
  		Webhook: contextdev.MonitorNewParamsWebhook{
  			URL:   "https://app.example.com/webhooks/context",
  			Retry: param.Override[contextdev.RetryConfigParam](map[string]any{}),
  		},
  	})
  	if err != nil {
  		panic(err)
  	}
  	fmt.Println(monitor.ID, monitor.InitialRunID)
  }
  ```

  ```php PHP theme={null}
  <?php
  require __DIR__.'/vendor/autoload.php';

  use ContextDev\Client;

  $client = new Client(apiKey: getenv('CONTEXT_DEV_API_KEY'));

  $monitor = $client->monitors->create(
      name: "Changelog announcements",
      target: [
          "type" => "page",
          "url" => "https://example.com/changelog",
          "instructions" => "Report new features, deprecations, and breaking changes. Ignore dates and typo fixes.",
          "includeSelectors" => ["main"],
          "excludeSelectors" => [".timestamp"],
      ],
      webhook: ["url" => "https://app.example.com/webhooks/context", "retry" => []],
  );
  echo $monitor->id, " ", $monitor->initialRunID, PHP_EOL;
  ```

  ```bash cURL theme={null}
  curl https://api.context.dev/v1/monitors \
    -H "Authorization: Bearer $CONTEXT_DEV_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Changelog announcements",
      "target": {
        "type": "page",
        "url": "https://example.com/changelog",
        "instructions": "Report new features, deprecations, and breaking changes. Ignore dates and typo fixes.",
        "include_selectors": ["main"],
        "exclude_selectors": [".timestamp"]
      },
      "webhook": { "url": "https://app.example.com/webhooks/context", "retry": {} }
    }'
  ```
</CodeGroup>

The API returns `201` with the monitor and `initial_run_id` (trimmed):

```json theme={null}
{
  "id": "mon_123",
  "status": "active",
  "change_detection": { "type": "semantic" },
  "schedule": { "type": "interval", "frequency": 1, "unit": "days" },
  "webhook": {
    "url": "https://app.example.com/webhooks/context",
    "secret": "whsec_…",
    "events": ["change.detected"],
    "retry": { "delays_seconds": [10, 60, 300, 1800, 7200, 21600, 57600] }
  },
  "next_run_at": "2026-09-27T03:14:00.000Z",
  "initial_run_id": "run_123"
}
```

Creating a monitor queues a baseline run right away. The baseline run captures the first snapshot and never reports a change; later runs compare against it. Pass `initial_run_id` to [Retrieve a monitor run](/api-reference/monitors/retrieve-run) to confirm the baseline worked. If the run couldn't be queued, `initial_run_id` is `null` and the baseline runs at the next scheduled time.

Store `webhook.secret` to [verify signatures](/webhooks#verify-signatures). With no `schedule`, the monitor runs once a day; see [Schedules](/monitors/schedules).

## Access

A restricted API key needs `monitors:write` to create, update, delete, or run a monitor, rotate its webhook secret, and replay its webhook deliveries. `monitors:read` covers monitors, runs, changes, limits, credit usage, and delivery history. `webhook.secret` is returned only to keys with `monitors:write`. See [API keys](/account/api-keys).

## Before you rely on alerts

* The baseline run completed: `status: "completed"` and `baseline_created: true`.
* `instructions` say what matters and what to ignore.
* Your receiver verifies signatures and deduplicates events on `X-Context-Id`.
* Failed runs send no webhook, so you check runs for failures or subscribe to `run.completed` as a heartbeat.

## Related

* [Targets](/monitors/targets): page, sitemap, and extract options, detection, and updates.
* [Schedules](/monitors/schedules): intervals, run now, pause, and automatic pauses.
* [Runs and changes](/monitors/runs-and-changes): run statuses and change records.
* [Events and alerts](/monitors/webhooks): webhook events, delivery failures, and secret rotation.
* [Limits and errors](/monitors/limits-and-errors): monitor limits per plan and error codes.
* [Website change digests](/use-cases/website-change-digests): an end-to-end recipe.
* [Create a monitor reference](/api-reference/monitors/create)
