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

# PATCH /monitor/{id}

> Change a monitor — its schedule, goal, targets or webhook — or pause and resume it. Free.

## Overview

Send only the fields you want to change; everything else stays as it is. The response is the updated monitor.

## Pause and resume

```json theme={"theme":"css-variables"}
{ "status": "paused" }
```

A paused monitor keeps its settings and history but runs no scheduled checks, so it costs nothing. Set `"status": "active"` to resume. The next check runs at the next scheduled time — runs missed while paused are not replayed. A check can still be run by hand while paused, with [`POST /monitor/{id}/run`](/api-reference/endpoint/monitor-run).

## Example request

<CodeGroup>
  ```bash cURL theme={"theme":"css-variables"}
  curl -X PATCH "https://api.prefetch.io/monitor/mon_3f9a1c2b7d4e4f6a8b0c1d2e3f4a5b6c" \
    -H "X-API-Key: $PREFETCH_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "schedule": { "text": "every 2 hours" },
      "goal": "Alert me when the Pro plan price changes"
    }'
  ```

  ```javascript Node.js theme={"theme":"css-variables"}
  const res = await fetch(`https://api.prefetch.io/monitor/${monitorId}`, {
    method: "PATCH",
    headers: {
      "X-API-Key": process.env.PREFETCH_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ status: "paused" }),
  });
  const { data } = await res.json();
  console.log(data.status, data.next_run_at); // "paused" null
  ```

  ```python Python theme={"theme":"css-variables"}
  import os, requests

  r = requests.patch(
      f"https://api.prefetch.io/monitor/{monitor_id}",
      headers={"X-API-Key": os.environ["PREFETCH_API_KEY"]},
      json={"status": "active"},
  )
  print(r.json()["data"]["next_run_at"])
  ```
</CodeGroup>

## What each field does

| Field | Effect |
| - | - |
| `name`, `retention_days` | Replaced. |
| `schedule` | Replaced; the next run is recalculated. |
| `goal` | Replaced. Setting a goal turns judging on; `null` clears it and turns judging off. |
| `judge_enabled` | Turns judging on or off without touching the goal. |
| `targets` | Replaces the **whole list** — see below. |
| `webhook` | Replaced. The signing secret is kept unless you send a new `secret` or `"rotate_secret": true`. `null` removes the webhook. |
| `status` | `active` or `paused`. |

## Changing targets

Each target keeps its own snapshots, so what you get on the next check depends on whether a target is still the same target:

* A target you send with its existing `id` keeps its snapshots.
* A target without an `id` that watches **the same URLs** as an existing one inherits that target's id, and its snapshots, automatically. Changing only its options — adding an `exclude_selectors`, say — keeps its history.
* Any other target is new. Its first check is a silent baseline: every page is `new`, and nothing is announced.

Snapshots of targets you leave out are deleted.

<Note>
  Changing what a target compares — its selectors, or switching it to the json mode — can make the next check report pages as `changed` once, because the old snapshot was taken the old way. From the check after that, the comparison is like for like again.
</Note>

## Rotating the signing secret

```json theme={"theme":"css-variables"}
{ "webhook": { "url": "https://you.example.org/hooks/prefetch", "rotate_secret": true } }
```

The new secret is in the response, and applies to every delivery from then on, including retries of events queued before the change.

## Related

<CardGroup cols={2}>
  <Card title="GET /monitor/{id}" icon="eye" href="/api-reference/endpoint/monitor-get">
    The monitor as it now runs.
  </Card>

  <Card title="DELETE /monitor/{id}" icon="trash" href="/api-reference/endpoint/monitor-delete">
    Delete it for good.
  </Card>
</CardGroup>


## OpenAPI

````yaml PATCH /monitor/{id}
openapi: 3.1.0
info:
  title: Prefetch API
  description: >-
    Extract brand identity, company data, screenshots, IAB classifications, and
    clean page content from any URL.
  version: 1.0.0
  contact:
    email: support@prefetch.io
servers:
  - url: https://api.prefetch.io
    description: Production
security:
  - apiKey: []
tags:
  - name: Endpoints
    description: Data extraction endpoints. All require authentication and consume credits.
  - name: Health
    description: Health and readiness probes. No authentication required.
paths:
  /monitor/{id}:
    patch:
      tags:
        - Endpoints
      summary: Update a monitor
      description: >-
        Changes any subset of the monitor's fields. `status: "paused"` stops its
        schedule and `"active"` resumes it. Replacing `targets` keeps the
        snapshots of targets that still watch the same URLs. Free.
      operationId: updateMonitor
      parameters:
        - $ref: '#/components/parameters/monitorId'
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MonitorUpdateRequest'
      responses:
        '200':
          description: Monitor updated.
          content:
            application/json:
              schema:
                type: object
                properties:
                  success:
                    type: boolean
                    enum:
                      - true
                  data:
                    $ref: '#/components/schemas/MonitorData'
                  meta:
                    $ref: '#/components/schemas/Meta'
                required:
                  - success
                  - data
                  - meta
              example:
                success: true
                data:
                  id: mon_3f9a1c2b7d4e4f6a8b0c1d2e3f4a5b6c
                  name: Competitor pricing
                  status: paused
                  schedule:
                    cron: 0 9 * * 1-5
                    timezone: Europe/Athens
                    text: every weekday at 9am
                  next_run_at: null
                  last_run_at: '2026-10-12T06:00:04.112Z'
                  current_check_id: null
                  goal: Alert me when a plan price or its included features change
                  judge_enabled: true
                  targets:
                    - id: tgt_8d1e0f2a3b4c5d6e
                      type: scrape
                      urls:
                        - https://example.com/pricing
                      scrape_options:
                        only_main_content: true
                        include_links: true
                        include_images: false
                        include_selectors: []
                        exclude_selectors: []
                      change_tracking:
                        modes:
                          - json
                        json_prompt: 'Each plan: name, monthly price, headline features'
                    - id: tgt_1a2b3c4d5e6f7a8b
                      type: crawl
                      url: https://example.com/changelog
                      crawl_options:
                        limit: 25
                        max_depth: 2
                        include_paths:
                          - ^/changelog/
                        exclude_paths: []
                        allow_subdomains: false
                        ignore_query_params: true
                        respect_robots_txt: true
                        use_sitemap: true
                        delay_ms: 0
                        concurrency: 2
                      scrape_options:
                        only_main_content: true
                        include_links: true
                        include_images: false
                        include_selectors: []
                        exclude_selectors: []
                      change_tracking:
                        modes:
                          - markdown
                  webhook:
                    url: https://you.example.org/hooks/prefetch
                    headers: {}
                    metadata:
                      env: production
                    events:
                      - monitor.page
                      - monitor.check.completed
                    secret: whsec_4f1c9e2a7b3d8e6f0a5c1b9d2e7f3a8c4b6d0e1f9a2c5b7d
                  retention_days: 30
                  estimated_credits_per_check: 55
                  estimated_credits_per_month: 1155
                  last_check_summary:
                    check_id: chk_8e2d4f6a1b3c4d5e6f7a8b9c0d1e2f3a
                    status: completed
                    finished_at: '2026-10-12T06:01:27.930Z'
                    total_pages: 19
                    same: 16
                    new: 1
                    changed: 1
                    removed: 1
                    error: 0
                  created_at: '2026-10-09T10:00:00.000Z'
                  updated_at: '2026-10-12T08:30:00.000Z'
                meta:
                  requestId: e1c4a5b6-7d8e-4f90-b1a2-3c4d5e6f7081
                  durationMs: 52
        '400':
          description: Invalid or missing parameters. The message names the field.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Missing API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '403':
          description: >-
            Revoked key, expired key, credit limit, blocklisted URL, monitor
            limit reached, or a RapidAPI subscription — monitors need a direct
            Prefetch API key.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '404':
          description: >-
            Monitor not found — or not yours. Monitor ids are unguessable, so
            another key's monitor is reported as not found rather than
            forbidden.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate limit exceeded.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Monitoring is temporarily unavailable. Retry shortly.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  parameters:
    monitorId:
      name: id
      in: path
      required: true
      description: The monitor id returned by `POST /monitor`.
      schema:
        type: string
        example: mon_3f9a1c2b7d4e4f6a8b0c1d2e3f4a5b6c
  schemas:
    MonitorUpdateRequest:
      type: object
      description: >-
        Any subset of the create fields, plus `status`. Fields you leave out
        stay as they are.
      properties:
        name:
          type: string
          maxLength: 256
        schedule:
          $ref: '#/components/schemas/MonitorSchedule'
        goal:
          type: string
          maxLength: 2000
          nullable: true
          description: '`null` clears the goal and turns judging off.'
        judge_enabled:
          type: boolean
        targets:
          type: array
          items:
            $ref: '#/components/schemas/MonitorTarget'
          minItems: 1
          maxItems: 50
          description: Replaces the whole list.
        webhook:
          allOf:
            - $ref: '#/components/schemas/MonitorWebhookRequest'
          nullable: true
          description: '`null` removes the webhook.'
        retention_days:
          type: integer
          minimum: 1
          maximum: 365
        status:
          type: string
          enum:
            - active
            - paused
          description: >-
            Pause or resume. Resuming runs at the next scheduled time; runs
            missed while paused are not replayed.
    MonitorData:
      type: object
      properties:
        id:
          type: string
          example: mon_3f9a1c2b7d4e4f6a8b0c1d2e3f4a5b6c
        name:
          type: string
        status:
          type: string
          enum:
            - active
            - paused
        schedule:
          type: object
          properties:
            cron:
              type: string
              description: >-
                The schedule the monitor runs on — always cron, whatever you
                submitted.
              example: 0 9 * * 1-5
            timezone:
              type: string
              example: Europe/Athens
            text:
              type: string
              nullable: true
              description: The phrase it was created from, if any.
              example: every weekday at 9am
        next_run_at:
          type: string
          format: date-time
          nullable: true
          description: '`null` while paused.'
        last_run_at:
          type: string
          format: date-time
          nullable: true
        current_check_id:
          type: string
          nullable: true
          description: The check running right now, if any.
        goal:
          type: string
          nullable: true
        judge_enabled:
          type: boolean
        targets:
          type: array
          items:
            $ref: '#/components/schemas/MonitorTarget'
          description: >-
            Normalised: every target has an id and every option its effective
            value.
        webhook:
          $ref: '#/components/schemas/MonitorWebhook'
        retention_days:
          type: integer
        estimated_credits_per_check:
          type: integer
          description: >-
            Upper bound: every page fetched, and judged when a goal is set. A
            real check costs less — only fetched pages are billed, and only
            changed ones judged.
        estimated_credits_per_month:
          type: integer
          description: '`estimated_credits_per_check` times the runs in an average month.'
        last_check_summary:
          allOf:
            - $ref: '#/components/schemas/MonitorSummary'
            - type: object
              properties:
                check_id:
                  type: string
                status:
                  type: string
                  enum:
                    - queued
                    - running
                    - completed
                    - failed
                    - partial
                    - skipped_overlap
                    - skipped_no_credits
                finished_at:
                  type: string
                  format: date-time
          nullable: true
          description: Counts from the most recent check, or `null` before the first one.
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
          description: When the settings last changed. Checks do not touch it.
    Meta:
      type: object
      properties:
        requestId:
          type: string
          format: uuid
          description: Unique identifier for this request.
          example: a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d
        durationMs:
          type: integer
          nullable: true
          description: Time taken to process the request in milliseconds.
          example: 1842
      required:
        - requestId
        - durationMs
    ErrorResponse:
      type: object
      properties:
        success:
          type: boolean
          enum:
            - false
          description: >-
            Always false. Absent, like `meta`, on authentication and rate-limit
            errors, which are answered before a request is processed.
        error:
          type: string
          description: >-
            Human-readable error message. The wording can change: branch on
            `error_code`.
          example: Credit limit exceeded
        error_code:
          type: string
          enum:
            - INVALID_REQUEST
            - PAYLOAD_TOO_LARGE
            - NOT_FOUND
            - CONFLICT
            - UNAUTHORIZED
            - FORBIDDEN
            - CREDITS_EXHAUSTED
            - RATE_LIMITED
            - CONCURRENCY_LIMITED
            - URL_BLOCKED
            - URL_NOT_PERMITTED
            - DNS_RESOLUTION_FAILED
            - TARGET_BLOCKED
            - TARGET_CONNECTION_FAILED
            - TARGET_TIMEOUT
            - TARGET_SSL_ERROR
            - TARGET_SERVER_ERROR
            - TARGET_CLIENT_ERROR
            - TARGET_NOT_A_PAGE
            - TARGET_UNLOADABLE
            - RESEARCH_INCONCLUSIVE
            - TIMEOUT
            - SERVICE_BUSY
            - SERVICE_UNAVAILABLE
            - INTERNAL_ERROR
          description: >-
            What went wrong, for machines. Stable: a code keeps its meaning once
            published. See [Error handling](/concepts/errors).
          example: CREDITS_EXHAUSTED
        retryable:
          type: boolean
          description: >-
            Whether the same request can succeed if sent again after a short
            wait (honour `Retry-After` when present). False for problems with
            the request or the target.
          example: false
        retryAfterSeconds:
          type: integer
          description: 'On `RATE_LIMITED`: seconds until a request will be accepted.'
        limit:
          type: integer
          description: >-
            On `CONCURRENCY_LIMITED`: how many requests this key may have in
            flight.
        meta:
          $ref: '#/components/schemas/Meta'
      required:
        - error
        - error_code
        - retryable
    MonitorSchedule:
      type: object
      description: >-
        Exactly one of `cron` or `text`. A bare string is accepted too, and read
        as cron when it has five cron fields.
      properties:
        cron:
          type: string
          description: Five-field cron expression. Runs must be at least 5 minutes apart.
          example: '*/30 * * * *'
        text:
          type: string
          description: >-
            A plain-English schedule, converted to cron: "every 30 minutes",
            "every 15 minutes starting at :07", "hourly", "every 2 hours",
            "daily", "daily at 9am", "daily at 5:30 PM", "every weekday at 9am",
            "weekly", "every monday at 8:00", "monthly".
          example: every weekday at 9am
        timezone:
          type: string
          default: UTC
          description: IANA timezone the schedule runs in.
          example: Europe/Athens
    MonitorTarget:
      oneOf:
        - $ref: '#/components/schemas/MonitorScrapeTarget'
        - $ref: '#/components/schemas/MonitorCrawlTarget'
      discriminator:
        propertyName: type
        mapping:
          scrape: '#/components/schemas/MonitorScrapeTarget'
          crawl: '#/components/schemas/MonitorCrawlTarget'
    MonitorWebhookRequest:
      type: object
      required:
        - url
      properties:
        url:
          type: string
          description: HTTPS endpoint that receives the events.
          example: https://you.example.org/hooks/prefetch
        headers:
          type: object
          additionalProperties:
            type: string
          description: >-
            Extra headers sent with every event, at most 20. `Host`,
            `Content-Type` and `X-Prefetch-*` are reserved.
          example:
            Authorization: Bearer your-token
        metadata:
          type: object
          description: Echoed back in every event, up to 4 KB.
          example:
            env: production
        events:
          type: array
          items:
            type: string
            enum:
              - monitor.page
              - monitor.check.completed
          description: 'Events to receive. Default: both.'
        secret:
          type: string
          description: >-
            Signing secret, 16–128 printable characters. Generated when omitted,
            and kept across updates unless you replace it.
        rotate_secret:
          type: boolean
          description: 'Update only: generate a new signing secret.'
    MonitorWebhook:
      type: object
      nullable: true
      properties:
        url:
          type: string
        headers:
          type: object
          additionalProperties:
            type: string
        metadata:
          type: object
        events:
          type: array
          items:
            type: string
            enum:
              - monitor.page
              - monitor.check.completed
        secret:
          type: string
          description: Verifies the `X-Prefetch-Signature` header on every event.
          example: whsec_4f1c9e2a7b3d8e6f0a5c1b9d2e7f3a8c4b6d0e1f9a2c5b7d
    MonitorSummary:
      type: object
      properties:
        total_pages:
          type: integer
        same:
          type: integer
        new:
          type: integer
        changed:
          type: integer
        removed:
          type: integer
        error:
          type: integer
    MonitorScrapeTarget:
      type: object
      title: Scrape target
      description: >-
        Watches a fixed list of pages, each fetched the way `GET /scrape` would
        fetch it.
      required:
        - type
        - urls
      properties:
        id:
          type: string
          description: >-
            Stable target id. Generated when omitted; on update, a target
            watching the same URLs keeps its id — and its snapshots —
            automatically.
          example: tgt_8d1e0f2a3b4c5d6e
        type:
          type: string
          enum:
            - scrape
        urls:
          type: array
          items:
            type: string
          minItems: 1
          maxItems: 100
          description: The pages to watch.
          example:
            - https://example.com/pricing
        scrape_options:
          $ref: '#/components/schemas/MonitorScrapeOptions'
        change_tracking:
          $ref: '#/components/schemas/MonitorChangeTracking'
    MonitorCrawlTarget:
      type: object
      title: Crawl target
      description: >-
        Re-crawls a site on every check, so pages that appear or disappear are
        reported as well as pages that change.
      required:
        - type
        - url
      properties:
        id:
          type: string
          description: Stable target id. Generated when omitted.
          example: tgt_1a2b3c4d5e6f7a8b
        type:
          type: string
          enum:
            - crawl
        url:
          type: string
          description: Where each crawl starts.
          example: https://example.com/changelog
        crawl_options:
          $ref: '#/components/schemas/MonitorCrawlOptions'
        scrape_options:
          $ref: '#/components/schemas/MonitorScrapeOptions'
        change_tracking:
          $ref: '#/components/schemas/MonitorChangeTracking'
    MonitorScrapeOptions:
      type: object
      description: >-
        How each page is rendered before it is compared — the content-shaping
        options of `GET /scrape`.
      properties:
        only_main_content:
          type: boolean
          default: true
          description: >-
            Compare the main content only, ignoring navigation, sidebars and
            footers.
        include_links:
          type: boolean
          default: true
          description: Keep link URLs in the compared markdown.
        include_images:
          type: boolean
          default: false
          description: >-
            Keep images in the compared markdown. Off by default: image URLs
            carry cache-busting hashes that change on every deploy.
        include_selectors:
          type: array
          items:
            type: string
          description: CSS selectors to compare instead of the detected main content.
          example:
            - '#pricing'
        exclude_selectors:
          type: array
          items:
            type: string
          description: >-
            CSS selectors to leave out of the comparison — the way to silence a
            timestamp or a rotating banner.
          example:
            - .last-updated
            - .testimonial
    MonitorChangeTracking:
      type: object
      properties:
        modes:
          type: array
          items:
            type: string
            enum:
              - markdown
              - json
          default:
            - markdown
          description: >-
            `markdown` diffs the page text line by line. `json` extracts the
            fields described by `json_prompt` or `json_schema` on every check
            and diffs them field by field, so a page is `changed` only when a
            tracked field changes. Both together report `changed` when either
            surface changed.
        json_prompt:
          type: string
          description: 'For the `json` mode: the fields to track, in plain English.'
          example: 'Each plan: name, monthly price, headline features'
        json_schema:
          type: object
          description: 'For the `json` mode: a JSON Schema for the extraction.'
    MonitorCrawlOptions:
      type: object
      description: The crawl options `POST /crawl` takes, without `allow_external_links`.
      properties:
        limit:
          type: integer
          minimum: 1
          maximum: 500
          default: 25
          description: Most pages each check crawls. Every page is billed on every check.
        max_depth:
          type: integer
          minimum: 0
          maximum: 5
          default: 2
          description: How many links deep to follow from the start URL.
        include_paths:
          type: array
          items:
            type: string
          description: >-
            Regular expressions matched against a URL's path and query. A URL
            must match at least one to be monitored.
          example:
            - ^/changelog/
        exclude_paths:
          type: array
          items:
            type: string
          description: Regular expressions. A matching URL is skipped.
        allow_subdomains:
          type: boolean
          default: false
          description: Follow links onto subdomains of the start URL.
        ignore_query_params:
          type: boolean
          default: true
          description: Treat URLs that differ only by query string as one page.
        respect_robots_txt:
          type: boolean
          default: true
          description: Obey the rules in `robots.txt`.
        use_sitemap:
          type: boolean
          default: true
          description: Seed each crawl from the site's sitemap as well as from links.
        delay_ms:
          type: integer
          minimum: 0
          maximum: 30000
          default: 0
          description: Politeness delay between pages.
        concurrency:
          type: integer
          minimum: 1
          maximum: 5
          default: 2
          description: Pages fetched in parallel.
  securitySchemes:
    apiKey:
      type: apiKey
      in: header
      name: X-API-Key
      description: Your Prefetch API key. Obtain one from the dashboard.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.