Update a monitor
curl --request PATCH \
--url https://api.prefetch.io/monitor/{id} \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"name": "<string>",
"schedule": {
"cron": "*/30 * * * *",
"text": "every weekday at 9am",
"timezone": "Europe/Athens"
},
"goal": "<string>",
"judge_enabled": true,
"targets": [
{
"type": "scrape",
"urls": [
"https://example.com/pricing"
],
"id": "tgt_8d1e0f2a3b4c5d6e",
"scrape_options": {
"only_main_content": true,
"include_links": true,
"include_images": false,
"include_selectors": [
"#pricing"
],
"exclude_selectors": [
".last-updated",
".testimonial"
]
},
"change_tracking": {
"modes": [
"markdown"
],
"json_prompt": "Each plan: name, monthly price, headline features",
"json_schema": {}
}
}
],
"webhook": {
"url": "https://you.example.org/hooks/prefetch",
"headers": {
"Authorization": "Bearer your-token"
},
"metadata": {
"env": "production"
},
"events": [],
"secret": "<string>",
"rotate_secret": true
},
"retention_days": 183
}
'import requests
url = "https://api.prefetch.io/monitor/{id}"
payload = {
"name": "<string>",
"schedule": {
"cron": "*/30 * * * *",
"text": "every weekday at 9am",
"timezone": "Europe/Athens"
},
"goal": "<string>",
"judge_enabled": True,
"targets": [
{
"type": "scrape",
"urls": ["https://example.com/pricing"],
"id": "tgt_8d1e0f2a3b4c5d6e",
"scrape_options": {
"only_main_content": True,
"include_links": True,
"include_images": False,
"include_selectors": ["#pricing"],
"exclude_selectors": [".last-updated", ".testimonial"]
},
"change_tracking": {
"modes": ["markdown"],
"json_prompt": "Each plan: name, monthly price, headline features",
"json_schema": {}
}
}
],
"webhook": {
"url": "https://you.example.org/hooks/prefetch",
"headers": { "Authorization": "Bearer your-token" },
"metadata": { "env": "production" },
"events": [],
"secret": "<string>",
"rotate_secret": True
},
"retention_days": 183
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
schedule: {cron: '*/30 * * * *', text: 'every weekday at 9am', timezone: 'Europe/Athens'},
goal: '<string>',
judge_enabled: true,
targets: [
{
type: 'scrape',
urls: ['https://example.com/pricing'],
id: 'tgt_8d1e0f2a3b4c5d6e',
scrape_options: {
only_main_content: true,
include_links: true,
include_images: false,
include_selectors: ['#pricing'],
exclude_selectors: ['.last-updated', '.testimonial']
},
change_tracking: {
modes: ['markdown'],
json_prompt: 'Each plan: name, monthly price, headline features',
json_schema: {}
}
}
],
webhook: {
url: 'https://you.example.org/hooks/prefetch',
headers: {Authorization: 'Bearer your-token'},
metadata: {env: 'production'},
events: [],
secret: '<string>',
rotate_secret: true
},
retention_days: 183
})
};
fetch('https://api.prefetch.io/monitor/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.prefetch.io/monitor/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'schedule' => [
'cron' => '*/30 * * * *',
'text' => 'every weekday at 9am',
'timezone' => 'Europe/Athens'
],
'goal' => '<string>',
'judge_enabled' => true,
'targets' => [
[
'type' => 'scrape',
'urls' => [
'https://example.com/pricing'
],
'id' => 'tgt_8d1e0f2a3b4c5d6e',
'scrape_options' => [
'only_main_content' => true,
'include_links' => true,
'include_images' => false,
'include_selectors' => [
'#pricing'
],
'exclude_selectors' => [
'.last-updated',
'.testimonial'
]
],
'change_tracking' => [
'modes' => [
'markdown'
],
'json_prompt' => 'Each plan: name, monthly price, headline features',
'json_schema' => [
]
]
]
],
'webhook' => [
'url' => 'https://you.example.org/hooks/prefetch',
'headers' => [
'Authorization' => 'Bearer your-token'
],
'metadata' => [
'env' => 'production'
],
'events' => [
],
'secret' => '<string>',
'rotate_secret' => true
],
'retention_days' => 183
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.prefetch.io/monitor/{id}"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"schedule\": {\n \"cron\": \"*/30 * * * *\",\n \"text\": \"every weekday at 9am\",\n \"timezone\": \"Europe/Athens\"\n },\n \"goal\": \"<string>\",\n \"judge_enabled\": true,\n \"targets\": [\n {\n \"type\": \"scrape\",\n \"urls\": [\n \"https://example.com/pricing\"\n ],\n \"id\": \"tgt_8d1e0f2a3b4c5d6e\",\n \"scrape_options\": {\n \"only_main_content\": true,\n \"include_links\": true,\n \"include_images\": false,\n \"include_selectors\": [\n \"#pricing\"\n ],\n \"exclude_selectors\": [\n \".last-updated\",\n \".testimonial\"\n ]\n },\n \"change_tracking\": {\n \"modes\": [\n \"markdown\"\n ],\n \"json_prompt\": \"Each plan: name, monthly price, headline features\",\n \"json_schema\": {}\n }\n }\n ],\n \"webhook\": {\n \"url\": \"https://you.example.org/hooks/prefetch\",\n \"headers\": {\n \"Authorization\": \"Bearer your-token\"\n },\n \"metadata\": {\n \"env\": \"production\"\n },\n \"events\": [],\n \"secret\": \"<string>\",\n \"rotate_secret\": true\n },\n \"retention_days\": 183\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.prefetch.io/monitor/{id}")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"schedule\": {\n \"cron\": \"*/30 * * * *\",\n \"text\": \"every weekday at 9am\",\n \"timezone\": \"Europe/Athens\"\n },\n \"goal\": \"<string>\",\n \"judge_enabled\": true,\n \"targets\": [\n {\n \"type\": \"scrape\",\n \"urls\": [\n \"https://example.com/pricing\"\n ],\n \"id\": \"tgt_8d1e0f2a3b4c5d6e\",\n \"scrape_options\": {\n \"only_main_content\": true,\n \"include_links\": true,\n \"include_images\": false,\n \"include_selectors\": [\n \"#pricing\"\n ],\n \"exclude_selectors\": [\n \".last-updated\",\n \".testimonial\"\n ]\n },\n \"change_tracking\": {\n \"modes\": [\n \"markdown\"\n ],\n \"json_prompt\": \"Each plan: name, monthly price, headline features\",\n \"json_schema\": {}\n }\n }\n ],\n \"webhook\": {\n \"url\": \"https://you.example.org/hooks/prefetch\",\n \"headers\": {\n \"Authorization\": \"Bearer your-token\"\n },\n \"metadata\": {\n \"env\": \"production\"\n },\n \"events\": [],\n \"secret\": \"<string>\",\n \"rotate_secret\": true\n },\n \"retention_days\": 183\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.prefetch.io/monitor/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"schedule\": {\n \"cron\": \"*/30 * * * *\",\n \"text\": \"every weekday at 9am\",\n \"timezone\": \"Europe/Athens\"\n },\n \"goal\": \"<string>\",\n \"judge_enabled\": true,\n \"targets\": [\n {\n \"type\": \"scrape\",\n \"urls\": [\n \"https://example.com/pricing\"\n ],\n \"id\": \"tgt_8d1e0f2a3b4c5d6e\",\n \"scrape_options\": {\n \"only_main_content\": true,\n \"include_links\": true,\n \"include_images\": false,\n \"include_selectors\": [\n \"#pricing\"\n ],\n \"exclude_selectors\": [\n \".last-updated\",\n \".testimonial\"\n ]\n },\n \"change_tracking\": {\n \"modes\": [\n \"markdown\"\n ],\n \"json_prompt\": \"Each plan: name, monthly price, headline features\",\n \"json_schema\": {}\n }\n }\n ],\n \"webhook\": {\n \"url\": \"https://you.example.org/hooks/prefetch\",\n \"headers\": {\n \"Authorization\": \"Bearer your-token\"\n },\n \"metadata\": {\n \"env\": \"production\"\n },\n \"events\": [],\n \"secret\": \"<string>\",\n \"rotate_secret\": true\n },\n \"retention_days\": 183\n}"
response = http.request(request)
puts response.read_body{
"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
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}Monitoring
PATCH /monitor/{id}
Change a monitor — its schedule, goal, targets or webhook — or pause and resume it. Free.
PATCH
/
monitor
/
{id}
Update a monitor
curl --request PATCH \
--url https://api.prefetch.io/monitor/{id} \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <api-key>' \
--data '
{
"name": "<string>",
"schedule": {
"cron": "*/30 * * * *",
"text": "every weekday at 9am",
"timezone": "Europe/Athens"
},
"goal": "<string>",
"judge_enabled": true,
"targets": [
{
"type": "scrape",
"urls": [
"https://example.com/pricing"
],
"id": "tgt_8d1e0f2a3b4c5d6e",
"scrape_options": {
"only_main_content": true,
"include_links": true,
"include_images": false,
"include_selectors": [
"#pricing"
],
"exclude_selectors": [
".last-updated",
".testimonial"
]
},
"change_tracking": {
"modes": [
"markdown"
],
"json_prompt": "Each plan: name, monthly price, headline features",
"json_schema": {}
}
}
],
"webhook": {
"url": "https://you.example.org/hooks/prefetch",
"headers": {
"Authorization": "Bearer your-token"
},
"metadata": {
"env": "production"
},
"events": [],
"secret": "<string>",
"rotate_secret": true
},
"retention_days": 183
}
'import requests
url = "https://api.prefetch.io/monitor/{id}"
payload = {
"name": "<string>",
"schedule": {
"cron": "*/30 * * * *",
"text": "every weekday at 9am",
"timezone": "Europe/Athens"
},
"goal": "<string>",
"judge_enabled": True,
"targets": [
{
"type": "scrape",
"urls": ["https://example.com/pricing"],
"id": "tgt_8d1e0f2a3b4c5d6e",
"scrape_options": {
"only_main_content": True,
"include_links": True,
"include_images": False,
"include_selectors": ["#pricing"],
"exclude_selectors": [".last-updated", ".testimonial"]
},
"change_tracking": {
"modes": ["markdown"],
"json_prompt": "Each plan: name, monthly price, headline features",
"json_schema": {}
}
}
],
"webhook": {
"url": "https://you.example.org/hooks/prefetch",
"headers": { "Authorization": "Bearer your-token" },
"metadata": { "env": "production" },
"events": [],
"secret": "<string>",
"rotate_secret": True
},
"retention_days": 183
}
headers = {
"X-API-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {'X-API-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
schedule: {cron: '*/30 * * * *', text: 'every weekday at 9am', timezone: 'Europe/Athens'},
goal: '<string>',
judge_enabled: true,
targets: [
{
type: 'scrape',
urls: ['https://example.com/pricing'],
id: 'tgt_8d1e0f2a3b4c5d6e',
scrape_options: {
only_main_content: true,
include_links: true,
include_images: false,
include_selectors: ['#pricing'],
exclude_selectors: ['.last-updated', '.testimonial']
},
change_tracking: {
modes: ['markdown'],
json_prompt: 'Each plan: name, monthly price, headline features',
json_schema: {}
}
}
],
webhook: {
url: 'https://you.example.org/hooks/prefetch',
headers: {Authorization: 'Bearer your-token'},
metadata: {env: 'production'},
events: [],
secret: '<string>',
rotate_secret: true
},
retention_days: 183
})
};
fetch('https://api.prefetch.io/monitor/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.prefetch.io/monitor/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'schedule' => [
'cron' => '*/30 * * * *',
'text' => 'every weekday at 9am',
'timezone' => 'Europe/Athens'
],
'goal' => '<string>',
'judge_enabled' => true,
'targets' => [
[
'type' => 'scrape',
'urls' => [
'https://example.com/pricing'
],
'id' => 'tgt_8d1e0f2a3b4c5d6e',
'scrape_options' => [
'only_main_content' => true,
'include_links' => true,
'include_images' => false,
'include_selectors' => [
'#pricing'
],
'exclude_selectors' => [
'.last-updated',
'.testimonial'
]
],
'change_tracking' => [
'modes' => [
'markdown'
],
'json_prompt' => 'Each plan: name, monthly price, headline features',
'json_schema' => [
]
]
]
],
'webhook' => [
'url' => 'https://you.example.org/hooks/prefetch',
'headers' => [
'Authorization' => 'Bearer your-token'
],
'metadata' => [
'env' => 'production'
],
'events' => [
],
'secret' => '<string>',
'rotate_secret' => true
],
'retention_days' => 183
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.prefetch.io/monitor/{id}"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"schedule\": {\n \"cron\": \"*/30 * * * *\",\n \"text\": \"every weekday at 9am\",\n \"timezone\": \"Europe/Athens\"\n },\n \"goal\": \"<string>\",\n \"judge_enabled\": true,\n \"targets\": [\n {\n \"type\": \"scrape\",\n \"urls\": [\n \"https://example.com/pricing\"\n ],\n \"id\": \"tgt_8d1e0f2a3b4c5d6e\",\n \"scrape_options\": {\n \"only_main_content\": true,\n \"include_links\": true,\n \"include_images\": false,\n \"include_selectors\": [\n \"#pricing\"\n ],\n \"exclude_selectors\": [\n \".last-updated\",\n \".testimonial\"\n ]\n },\n \"change_tracking\": {\n \"modes\": [\n \"markdown\"\n ],\n \"json_prompt\": \"Each plan: name, monthly price, headline features\",\n \"json_schema\": {}\n }\n }\n ],\n \"webhook\": {\n \"url\": \"https://you.example.org/hooks/prefetch\",\n \"headers\": {\n \"Authorization\": \"Bearer your-token\"\n },\n \"metadata\": {\n \"env\": \"production\"\n },\n \"events\": [],\n \"secret\": \"<string>\",\n \"rotate_secret\": true\n },\n \"retention_days\": 183\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("X-API-Key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.patch("https://api.prefetch.io/monitor/{id}")
.header("X-API-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"schedule\": {\n \"cron\": \"*/30 * * * *\",\n \"text\": \"every weekday at 9am\",\n \"timezone\": \"Europe/Athens\"\n },\n \"goal\": \"<string>\",\n \"judge_enabled\": true,\n \"targets\": [\n {\n \"type\": \"scrape\",\n \"urls\": [\n \"https://example.com/pricing\"\n ],\n \"id\": \"tgt_8d1e0f2a3b4c5d6e\",\n \"scrape_options\": {\n \"only_main_content\": true,\n \"include_links\": true,\n \"include_images\": false,\n \"include_selectors\": [\n \"#pricing\"\n ],\n \"exclude_selectors\": [\n \".last-updated\",\n \".testimonial\"\n ]\n },\n \"change_tracking\": {\n \"modes\": [\n \"markdown\"\n ],\n \"json_prompt\": \"Each plan: name, monthly price, headline features\",\n \"json_schema\": {}\n }\n }\n ],\n \"webhook\": {\n \"url\": \"https://you.example.org/hooks/prefetch\",\n \"headers\": {\n \"Authorization\": \"Bearer your-token\"\n },\n \"metadata\": {\n \"env\": \"production\"\n },\n \"events\": [],\n \"secret\": \"<string>\",\n \"rotate_secret\": true\n },\n \"retention_days\": 183\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.prefetch.io/monitor/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["X-API-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"schedule\": {\n \"cron\": \"*/30 * * * *\",\n \"text\": \"every weekday at 9am\",\n \"timezone\": \"Europe/Athens\"\n },\n \"goal\": \"<string>\",\n \"judge_enabled\": true,\n \"targets\": [\n {\n \"type\": \"scrape\",\n \"urls\": [\n \"https://example.com/pricing\"\n ],\n \"id\": \"tgt_8d1e0f2a3b4c5d6e\",\n \"scrape_options\": {\n \"only_main_content\": true,\n \"include_links\": true,\n \"include_images\": false,\n \"include_selectors\": [\n \"#pricing\"\n ],\n \"exclude_selectors\": [\n \".last-updated\",\n \".testimonial\"\n ]\n },\n \"change_tracking\": {\n \"modes\": [\n \"markdown\"\n ],\n \"json_prompt\": \"Each plan: name, monthly price, headline features\",\n \"json_schema\": {}\n }\n }\n ],\n \"webhook\": {\n \"url\": \"https://you.example.org/hooks/prefetch\",\n \"headers\": {\n \"Authorization\": \"Bearer your-token\"\n },\n \"metadata\": {\n \"env\": \"production\"\n },\n \"events\": [],\n \"secret\": \"<string>\",\n \"rotate_secret\": true\n },\n \"retention_days\": 183\n}"
response = http.request(request)
puts response.read_body{
"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
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}{
"error": "Credit limit exceeded",
"error_code": "CREDITS_EXHAUSTED",
"retryable": false,
"success": false,
"retryAfterSeconds": 123,
"limit": 123,
"meta": {
"requestId": "a3f2c1d4-7b6e-4f2a-9c1d-8e3f2a1b4c5d",
"durationMs": 1842
}
}Overview
Send only the fields you want to change; everything else stays as it is. The response is the updated monitor.Pause and resume
{ "status": "paused" }
"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.
Example request
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"
}'
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
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"])
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
idkeeps its snapshots. - A target without an
idthat watches the same URLs as an existing one inherits that target’s id, and its snapshots, automatically. Changing only its options — adding anexclude_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.
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.Rotating the signing secret
{ "webhook": { "url": "https://you.example.org/hooks/prefetch", "rotate_secret": true } }
Related
GET /monitor/{id}
The monitor as it now runs.
DELETE /monitor/{id}
Delete it for good.
Authorizations
Your Prefetch API key. Obtain one from the dashboard.
Path Parameters
The monitor id returned by POST /monitor.
Example:
"mon_3f9a1c2b7d4e4f6a8b0c1d2e3f4a5b6c"
Body
application/json
Any subset of the create fields, plus status. Fields you leave out stay as they are.
Maximum string length:
256Exactly one of cron or text. A bare string is accepted too, and read as cron when it has five cron fields.
Show child attributes
Show child attributes
null clears the goal and turns judging off.
Maximum string length:
2000Replaces the whole list.
Required array length:
1 - 50 elementsWatches a fixed list of pages, each fetched the way GET /scrape would fetch it.
- Scrape target
- Crawl target
Show child attributes
Show child attributes
null removes the webhook.
Show child attributes
Show child attributes
Required range:
1 <= x <= 365Pause or resume. Resuming runs at the next scheduled time; runs missed while paused are not replayed.
Available options:
active, paused