From 6154178d1ecd334214c3e22b76fe79c40eda88d6 Mon Sep 17 00:00:00 2001 From: dgtlmoon Date: Thu, 17 Sep 2026 21:56:26 +0200 Subject: [PATCH] WIP --- changedetectionio/blueprint/ui/preview.py | 11 +- .../tests/test_preview_endpoints.py | 18 ++ docs/api_v1/index.html | 156 ++++++++++++------ 3 files changed, 125 insertions(+), 60 deletions(-) diff --git a/changedetectionio/blueprint/ui/preview.py b/changedetectionio/blueprint/ui/preview.py index 40d5e5808..f61e048d8 100644 --- a/changedetectionio/blueprint/ui/preview.py +++ b/changedetectionio/blueprint/ui/preview.py @@ -57,7 +57,6 @@ def construct_blueprint(datastore: ChangeDetectionStore): # Fallback: if processor doesn't have preview module, use default text preview content = [] - versions = [] timestamp = None extra_stylesheets = [url_for('static_content', group='styles', filename='diff.css')] @@ -70,20 +69,22 @@ def construct_blueprint(datastore: ChangeDetectionStore): ignored_line_numbers = [] blocked_line_numbers = [] - if datastore.data['watching'][uuid].history_n == 0 and (watch.get_error_text() or watch.get_error_snapshot()): + # Gate on whether there is a snapshot to show, NOT on whether an error was recorded: a + # watch that has never completed a check and has no error text either (freshly added, or + # paused before its first check) has nothing to index into, and asking for the newest of + # no versions used to be a 500 on a page reachable from the watch list. + versions = list(watch.history.keys()) + if not versions: flash(gettext("Preview unavailable - No fetch/check completed or triggers not reached"), "error") else: # So prepare the latest preview or not preferred_version = request.values.get('version') if request.method == 'POST' else request.args.get('version') - - versions = list(watch.history.keys()) timestamp = versions[-1] if preferred_version and preferred_version in versions: timestamp = preferred_version try: - versions = list(watch.history.keys()) content = watch.get_history_snapshot(timestamp=timestamp) triggered_line_numbers = html_tools.strip_ignore_text(content=content, diff --git a/changedetectionio/tests/test_preview_endpoints.py b/changedetectionio/tests/test_preview_endpoints.py index 6715685fa..1e4656c8b 100644 --- a/changedetectionio/tests/test_preview_endpoints.py +++ b/changedetectionio/tests/test_preview_endpoints.py @@ -66,3 +66,21 @@ def test_fetch_pdf(client, live_server, measure_memory_usage, datastore_path): assert changed_md5.encode('utf-8') in res.data assert b'here is a change' in res.data + + +def test_preview_of_a_watch_with_no_history(client, live_server, measure_memory_usage, datastore_path): + """/preview must not 500 on a watch that has never completed a check. + + The page is linked from the watch list, so it is reachable for a freshly added or paused + watch. The old guard only skipped the history lookup when history_n == 0 AND an error had + been recorded, so a clean never-checked watch asked for the newest of no versions and the + request died with IndexError. + """ + datastore = client.application.config.get('DATASTORE') + uuid = datastore.add_watch(url="https://example.com", extras={'paused': True}) + assert datastore.data['watching'][uuid].history_n == 0 + assert not datastore.data['watching'][uuid].get_error_text() + + res = client.get(url_for("ui.ui_preview.preview_page", uuid=uuid), follow_redirects=True) + assert res.status_code == 200 + assert b'Preview unavailable' in res.data diff --git a/docs/api_v1/index.html b/docs/api_v1/index.html index ef6820ed6..e92b666eb 100644 --- a/docs/api_v1/index.html +++ b/docs/api_v1/index.html @@ -288,8 +288,6 @@ data-styled.g66[id="sc-dTWiOz"]{content:"kMQdIk,"}/*!sc*/ .bDfgbe{border-radius:2px;background-color:rgba(104,104,207,0.05);color:rgba(50,50,159,0.9);margin:0 5px;padding:0 5px;border:1px solid rgba(50,50,159,0.1);}/*!sc*/ +{margin-left:0;}/*!sc*/ data-styled.g68[id="sc-goiVcJ"]{content:"bDfgbe,"}/*!sc*/ -.jBrfIx{background-color:transparent;border:0;color:#666;margin-left:5px;border-radius:2px;cursor:pointer;outline-color:#666;font-size:12px;}/*!sc*/ -data-styled.g69[id="sc-gSifMm"]{content:"jBrfIx,"}/*!sc*/ .eA-DYPM{margin:0 5px;vertical-align:text-top;}/*!sc*/ data-styled.g75[id="sc-bBhMX"]{content:"eA-DYPM,"}/*!sc*/ .hRtRoN:after{content:' and ';font-weight:normal;}/*!sc*/ @@ -516,6 +514,12 @@ notification preferences, and content filtering options.

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
url
required
string <uri> <= 5000 characters

URL to monitor for changes

+
link_to_open
string <= 5000 characters

Optional human-facing URL to open instead of url. Use when url points at something +that is not meant to be read in a browser (an API endpoint or RSS feed, for example). +An empty string means "use url". Exposed rendered as open_link.

title
string or null <= 5000 characters

Custom title for the web page change monitor (watch), not to be confused with page_title

tag
string <= 5000 characters
Deprecated

Whether notifications are muted

method
string
Enum: "GET" "POST" "DELETE" "PUT"

HTTP method to use

-
fetch_backend
string^(system|html_requests|html_webdriver|extra_b...
Default: "system"
fetch_backend
string^[^\r\n\t]{1,200}$
Default: "system"

Backend to use for fetching content. Common values:

+" class="sc-eVqvcJ sc-fszimp kIppRw drqpJr">

Which browser this watch checks with. The valid values depend on the install, so the +value is checked against them when you create or update a watch:

    -
  • system (default) - Use the system-wide default fetcher
  • -
  • html_requests - Fast requests-based fetcher
  • -
  • html_webdriver - Browser-based fetcher (Playwright/Puppeteer)
  • -
  • extra_browser_* - Custom browser configurations (if configured)
  • -
  • Plugin-provided fetchers (if installed)
  • +
  • system (default) - follow the global Default browser
  • +
  • a built-in engine name, e.g. html_requests (fast plain HTTP client), +html_webdriver (Playwright/Puppeteer/Selenium, depending on configuration) or +html_external_cdp (a browser you run elsewhere, reached over CDP)
  • +
  • a plugin-provided engine, if one is installed
  • +
  • the id of a saved browser from the Browsers page, which is also what a pre-0.61 +extra_browser_<name> endpoint becomes when it is migrated there
object

HTTP headers to include in requests

@@ -696,12 +706,18 @@ No watch was created - delete one to make room.

" class="sc-eVqvcJ sc-fszimp kIppRw drqpJr">

Custom server

{protocol}://{host}/api/v1/watch/{uuid}

Request samples

curl -X GET "http://localhost:5000/api/v1/watch/095be615-a8ad-4c33-8e9c-c7612fbf6c9f" \
   -H "x-api-key: YOUR_API_KEY"
-

Response samples

Content type
{
  • "uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
  • "date_created": 0,
  • "title": "string",
  • "tag": "Production, Price tracking",
  • "tags": [
    ],
  • "paused": true,
  • "notification_muted": true,
  • "method": "GET",
  • "fetch_backend": "system",
  • "headers": {
    },
  • "body": "string",
  • "proxy": "string",
  • "ignore_status_codes": true,
  • "webdriver_delay": 0,
  • "webdriver_js_execute_code": "string",
  • "time_between_check": {
    },
  • "time_between_check_use_default": true,
  • "notification_urls": [
    ],
  • "notification_title": "string",
  • "notification_body": "string",
  • "notification_format": "text",
  • "track_ldjson_price_data": true,
  • "browser_steps": [
    ],
  • "processor": "restock_diff",
  • "include_filters": [
    ],
  • "subtractive_selectors": [
    ],
  • "ignore_text": [
    ],
  • "trigger_text": [
    ],
  • "text_should_not_be_present": [
    ],
  • "extract_lines_containing": [
    ],
  • "extract_text": [
    ],
  • "trim_text_whitespace": false,
  • "sort_text_alphabetically": false,
  • "remove_duplicate_lines": false,
  • "check_unique_lines": false,
  • "strip_ignored_lines": true,
  • "filter_text_added": true,
  • "filter_text_removed": true,
  • "filter_text_replaced": true,
  • "in_stock_only": true,
  • "follow_price_changes": true,
  • "price_change_threshold_percent": 0,
  • "has_ldjson_price_data": true,
  • "notification_screenshot": false,
  • "filter_failure_notification_send": true,
  • "use_page_title_in_list": true,
  • "history_snapshot_max_length": 1,
  • "time_schedule_limit": {
    },
  • "conditions": [
    ],
  • "conditions_match_logic": "ALL",
  • "llm_backend_profile": true,
  • "llm_intent": "",
  • "llm_change_summary": "",
  • "llm_change_summary_mode": "replace",
  • "llm_prefilter": "string",
  • "llm_evaluation_cache": { },
  • "llm_last_tokens_used": 0,
  • "llm_tokens_used_cumulative": 0,
  • "llm_tokens_this_period": 0,
  • "llm_tokens_period_key": "string",
  • "last_checked": 0,
  • "last_changed": 0,
  • "last_error": "string",
  • "last_viewed": 0,
  • "link": "string",
  • "page_title": "string",
  • "check_count": 0,
  • "fetch_time": 0,
  • "previous_md5": "string",
  • "previous_md5_before_filters": "string",
  • "consecutive_filter_failures": 0,
  • "last_notification_error": "string",
  • "notification_alert_count": 0,
  • "content-type": "string",
  • "remote_server_reply": "string",
  • "browser_steps_last_error_step": 0,
  • "viewed": 0,
  • "history_n": 0,
  • "processor_config_restock_diff": {
    },
  • "processor_config_restock_diff_source": "string"
}

Update watch

Response samples

Content type
{
  • "uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
  • "date_created": 0,
  • "link_to_open": "string",
  • "title": "string",
  • "tag": "Production, Price tracking",
  • "tags": [
    ],
  • "paused": true,
  • "notification_muted": true,
  • "method": "GET",
  • "fetch_backend": "system",
  • "headers": {
    },
  • "body": "string",
  • "proxy": "string",
  • "ignore_status_codes": true,
  • "webdriver_delay": 0,
  • "webdriver_js_execute_code": "string",
  • "time_between_check": {
    },
  • "time_between_check_use_default": true,
  • "notification_urls": [
    ],
  • "notification_title": "string",
  • "notification_body": "string",
  • "notification_format": "text",
  • "track_ldjson_price_data": true,
  • "browser_steps": [
    ],
  • "processor": "restock_diff",
  • "include_filters": [
    ],
  • "subtractive_selectors": [
    ],
  • "ignore_text": [
    ],
  • "trigger_text": [
    ],
  • "text_should_not_be_present": [
    ],
  • "extract_lines_containing": [
    ],
  • "extract_text": [
    ],
  • "trim_text_whitespace": false,
  • "sort_text_alphabetically": false,
  • "remove_duplicate_lines": false,
  • "check_unique_lines": false,
  • "strip_ignored_lines": true,
  • "filter_text_added": true,
  • "filter_text_removed": true,
  • "filter_text_replaced": true,
  • "in_stock_only": true,
  • "follow_price_changes": true,
  • "price_change_threshold_percent": 0,
  • "has_ldjson_price_data": true,
  • "notification_screenshot": false,
  • "filter_failure_notification_send": true,
  • "use_page_title_in_list": true,
  • "history_snapshot_max_length": 1,
  • "time_schedule_limit": {
    },
  • "conditions": [
    ],
  • "conditions_match_logic": "ALL",
  • "llm_backend_profile": true,
  • "llm_intent": "",
  • "llm_change_summary": "",
  • "llm_change_summary_mode": "replace",
  • "llm_prefilter": "string",
  • "llm_evaluation_cache": { },
  • "llm_last_tokens_used": 0,
  • "llm_tokens_used_cumulative": 0,
  • "llm_tokens_this_period": 0,
  • "llm_tokens_period_key": "string",
  • "last_checked": 0,
  • "last_changed": 0,
  • "last_error": "string",
  • "last_viewed": 0,
  • "link": "string",
  • "open_link": "string",
  • "page_title": "string",
  • "check_count": 0,
  • "fetch_time": 0,
  • "previous_md5": "string",
  • "previous_md5_before_filters": "string",
  • "consecutive_filter_failures": 0,
  • "last_notification_error": "string",
  • "notification_alert_count": 0,
  • "content-type": "string",
  • "remote_server_reply": "string",
  • "browser_steps_last_error_step": 0,
  • "viewed": 0,
  • "history_n": 0,
  • "processor_config_restock_diff": {
    },
  • "processor_config_restock_diff_source": "string"
}

Update watch

Update an existing web page change monitor (watch) using JSON. Accepts the same structure as returned in get single watch information.

Authorizations:
ApiKeyAuth
path Parameters
uuid
required
string <uuid>

Web page change monitor (watch) unique ID

Request Body schema: application/json
required
url
string <uri> <= 5000 characters

URL to monitor for changes

+
link_to_open
string <= 5000 characters

Optional human-facing URL to open instead of url. Use when url points at something +that is not meant to be read in a browser (an API endpoint or RSS feed, for example). +An empty string means "use url". Exposed rendered as open_link.

title
string or null <= 5000 characters

Custom title for the web page change monitor (watch), not to be confused with page_title

tag
string <= 5000 characters
Deprecated

Whether notifications are muted

method
string
Enum: "GET" "POST" "DELETE" "PUT"

HTTP method to use

-
fetch_backend
string^(system|html_requests|html_webdriver|extra_b...
Default: "system"
fetch_backend
string^[^\r\n\t]{1,200}$
Default: "system"

Backend to use for fetching content. Common values:

+" class="sc-eVqvcJ sc-fszimp kIppRw drqpJr">

Which browser this watch checks with. The valid values depend on the install, so the +value is checked against them when you create or update a watch:

    -
  • system (default) - Use the system-wide default fetcher
  • -
  • html_requests - Fast requests-based fetcher
  • -
  • html_webdriver - Browser-based fetcher (Playwright/Puppeteer)
  • -
  • extra_browser_* - Custom browser configurations (if configured)
  • -
  • Plugin-provided fetchers (if installed)
  • +
  • system (default) - follow the global Default browser
  • +
  • a built-in engine name, e.g. html_requests (fast plain HTTP client), +html_webdriver (Playwright/Puppeteer/Selenium, depending on configuration) or +html_external_cdp (a browser you run elsewhere, reached over CDP)
  • +
  • a plugin-provided engine, if one is installed
  • +
  • the id of a saved browser from the Browsers page, which is also what a pre-0.61 +extra_browser_<name> endpoint becomes when it is migrated there
object

HTTP headers to include in requests

@@ -858,7 +880,7 @@ On a tag/group it is ternary and is that group's only AI control:

" class="sc-eVqvcJ sc-fszimp kIppRw drqpJr">

Production server

https://yourdomain.com/api/v1/watch/{uuid}

Custom server

-
{protocol}://{host}/api/v1/watch/{uuid}

Request samples

Content type
application/json
{
  • "title": "string",
  • "tag": "Production, Price tracking",
  • "tags": [
    ],
  • "paused": true,
  • "notification_muted": true,
  • "method": "GET",
  • "fetch_backend": "system",
  • "headers": {
    },
  • "body": "string",
  • "proxy": "string",
  • "ignore_status_codes": true,
  • "webdriver_delay": 0,
  • "webdriver_js_execute_code": "string",
  • "time_between_check": {
    },
  • "time_between_check_use_default": true,
  • "notification_urls": [
    ],
  • "notification_title": "string",
  • "notification_body": "string",
  • "notification_format": "text",
  • "track_ldjson_price_data": true,
  • "browser_steps": [
    ],
  • "processor": "restock_diff",
  • "include_filters": [
    ],
  • "subtractive_selectors": [
    ],
  • "ignore_text": [
    ],
  • "trigger_text": [
    ],
  • "text_should_not_be_present": [
    ],
  • "extract_lines_containing": [
    ],
  • "extract_text": [
    ],
  • "trim_text_whitespace": false,
  • "sort_text_alphabetically": false,
  • "remove_duplicate_lines": false,
  • "check_unique_lines": false,
  • "strip_ignored_lines": true,
  • "filter_text_added": true,
  • "filter_text_removed": true,
  • "filter_text_replaced": true,
  • "in_stock_only": true,
  • "follow_price_changes": true,
  • "price_change_threshold_percent": 0,
  • "notification_screenshot": false,
  • "filter_failure_notification_send": true,
  • "use_page_title_in_list": true,
  • "history_snapshot_max_length": 1,
  • "time_schedule_limit": {
    },
  • "conditions": [
    ],
  • "conditions_match_logic": "ALL",
  • "llm_backend_profile": true,
  • "llm_intent": "",
  • "llm_change_summary": "",
  • "llm_change_summary_mode": "replace",
  • "last_viewed": 0
}

Delete watch

{protocol}://{host}/api/v1/watch/{uuid}

Request samples

Content type
application/json
{
  • "link_to_open": "string",
  • "title": "string",
  • "tag": "Production, Price tracking",
  • "tags": [
    ],
  • "paused": true,
  • "notification_muted": true,
  • "method": "GET",
  • "fetch_backend": "system",
  • "headers": {
    },
  • "body": "string",
  • "proxy": "string",
  • "ignore_status_codes": true,
  • "webdriver_delay": 0,
  • "webdriver_js_execute_code": "string",
  • "time_between_check": {
    },
  • "time_between_check_use_default": true,
  • "notification_urls": [
    ],
  • "notification_title": "string",
  • "notification_body": "string",
  • "notification_format": "text",
  • "track_ldjson_price_data": true,
  • "browser_steps": [
    ],
  • "processor": "restock_diff",
  • "include_filters": [
    ],
  • "subtractive_selectors": [
    ],
  • "ignore_text": [
    ],
  • "trigger_text": [
    ],
  • "text_should_not_be_present": [
    ],
  • "extract_lines_containing": [
    ],
  • "extract_text": [
    ],
  • "trim_text_whitespace": false,
  • "sort_text_alphabetically": false,
  • "remove_duplicate_lines": false,
  • "check_unique_lines": false,
  • "strip_ignored_lines": true,
  • "filter_text_added": true,
  • "filter_text_removed": true,
  • "filter_text_replaced": true,
  • "in_stock_only": true,
  • "follow_price_changes": true,
  • "price_change_threshold_percent": 0,
  • "notification_screenshot": false,
  • "filter_failure_notification_send": true,
  • "use_page_title_in_list": true,
  • "history_snapshot_max_length": 1,
  • "time_schedule_limit": {
    },
  • "conditions": [
    ],
  • "conditions_match_logic": "ALL",
  • "llm_backend_profile": true,
  • "llm_intent": "",
  • "llm_change_summary": "",
  • "llm_change_summary_mode": "replace",
  • "last_viewed": 0
}

Delete watch

Delete a web page change monitor (watch) and all related history

Authorizations:
ApiKeyAuth
path Parameters
uuid
required
string <uuid>

Web page change monitor (watch) unique ID

@@ -1144,6 +1166,12 @@ multiple related watches.

" class="sc-eVqvcJ sc-fszimp kIppRw kbZred">

Create a single tag/group

Authorizations:
ApiKeyAuth
Request Body schema: application/json
required
url
string <uri> <= 5000 characters

URL to monitor for changes

+
link_to_open
string <= 5000 characters

Optional human-facing URL to open instead of url. Use when url points at something +that is not meant to be read in a browser (an API endpoint or RSS feed, for example). +An empty string means "use url". Exposed rendered as open_link.

title
required
string or null <= 5000 characters

Custom title for the web page change monitor (watch), not to be confused with page_title

tag
string <= 5000 characters
Deprecated

Whether notifications are muted

method
string
Enum: "GET" "POST" "DELETE" "PUT"

HTTP method to use

-
fetch_backend
string^(system|html_requests|html_webdriver|extra_b...
Default: "system"
fetch_backend
string^[^\r\n\t]{1,200}$
Default: "system"

Backend to use for fetching content. Common values:

+" class="sc-eVqvcJ sc-fszimp kIppRw drqpJr">

Which browser this watch checks with. The valid values depend on the install, so the +value is checked against them when you create or update a watch:

    -
  • system (default) - Use the system-wide default fetcher
  • -
  • html_requests - Fast requests-based fetcher
  • -
  • html_webdriver - Browser-based fetcher (Playwright/Puppeteer)
  • -
  • extra_browser_* - Custom browser configurations (if configured)
  • -
  • Plugin-provided fetchers (if installed)
  • +
  • system (default) - follow the global Default browser
  • +
  • a built-in engine name, e.g. html_requests (fast plain HTTP client), +html_webdriver (Playwright/Puppeteer/Selenium, depending on configuration) or +html_external_cdp (a browser you run elsewhere, reached over CDP)
  • +
  • a plugin-provided engine, if one is installed
  • +
  • the id of a saved browser from the Browsers page, which is also what a pre-0.61 +extra_browser_<name> endpoint becomes when it is migrated there
object

HTTP headers to include in requests

@@ -1344,12 +1378,18 @@ Leave empty to use the colour auto-generated from the tag name.

" class="sc-eVqvcJ sc-fszimp kIppRw drqpJr">

Custom server

{protocol}://{host}/api/v1/tag/{uuid}

Request samples

curl -X GET "http://localhost:5000/api/v1/tag/550e8400-e29b-41d4-a716-446655440000" \
   -H "x-api-key: YOUR_API_KEY"
-

Response samples

Content type
{
  • "uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
  • "date_created": 0,
  • "title": "string",
  • "tag": "Production, Price tracking",
  • "tags": [
    ],
  • "paused": true,
  • "notification_muted": true,
  • "method": "GET",
  • "fetch_backend": "system",
  • "headers": {
    },
  • "body": "string",
  • "proxy": "string",
  • "ignore_status_codes": true,
  • "webdriver_delay": 0,
  • "webdriver_js_execute_code": "string",
  • "time_between_check": {
    },
  • "time_between_check_use_default": true,
  • "notification_urls": [
    ],
  • "notification_title": "string",
  • "notification_body": "string",
  • "notification_format": "text",
  • "track_ldjson_price_data": true,
  • "browser_steps": [
    ],
  • "processor": "restock_diff",
  • "include_filters": [
    ],
  • "subtractive_selectors": [
    ],
  • "ignore_text": [
    ],
  • "trigger_text": [
    ],
  • "text_should_not_be_present": [
    ],
  • "extract_lines_containing": [
    ],
  • "extract_text": [
    ],
  • "trim_text_whitespace": false,
  • "sort_text_alphabetically": false,
  • "remove_duplicate_lines": false,
  • "check_unique_lines": false,
  • "strip_ignored_lines": true,
  • "filter_text_added": true,
  • "filter_text_removed": true,
  • "filter_text_replaced": true,
  • "in_stock_only": true,
  • "follow_price_changes": true,
  • "price_change_threshold_percent": 0,
  • "has_ldjson_price_data": true,
  • "notification_screenshot": false,
  • "filter_failure_notification_send": true,
  • "use_page_title_in_list": true,
  • "history_snapshot_max_length": 1,
  • "time_schedule_limit": {
    },
  • "conditions": [
    ],
  • "conditions_match_logic": "ALL",
  • "llm_backend_profile": true,
  • "llm_intent": "",
  • "llm_change_summary": "",
  • "llm_change_summary_mode": "replace",
  • "llm_prefilter": "string",
  • "llm_evaluation_cache": { },
  • "llm_last_tokens_used": 0,
  • "llm_tokens_used_cumulative": 0,
  • "llm_tokens_this_period": 0,
  • "llm_tokens_period_key": "string",
  • "overrides_watch": true,
  • "url_match_pattern": "string",
  • "tag_colour": "string"
}

Update tag

Response samples

Content type
{
  • "uuid": "095be615-a8ad-4c33-8e9c-c7612fbf6c9f",
  • "date_created": 0,
  • "link_to_open": "string",
  • "title": "string",
  • "tag": "Production, Price tracking",
  • "tags": [
    ],
  • "paused": true,
  • "notification_muted": true,
  • "method": "GET",
  • "fetch_backend": "system",
  • "headers": {
    },
  • "body": "string",
  • "proxy": "string",
  • "ignore_status_codes": true,
  • "webdriver_delay": 0,
  • "webdriver_js_execute_code": "string",
  • "time_between_check": {
    },
  • "time_between_check_use_default": true,
  • "notification_urls": [
    ],
  • "notification_title": "string",
  • "notification_body": "string",
  • "notification_format": "text",
  • "track_ldjson_price_data": true,
  • "browser_steps": [
    ],
  • "processor": "restock_diff",
  • "include_filters": [
    ],
  • "subtractive_selectors": [
    ],
  • "ignore_text": [
    ],
  • "trigger_text": [
    ],
  • "text_should_not_be_present": [
    ],
  • "extract_lines_containing": [
    ],
  • "extract_text": [
    ],
  • "trim_text_whitespace": false,
  • "sort_text_alphabetically": false,
  • "remove_duplicate_lines": false,
  • "check_unique_lines": false,
  • "strip_ignored_lines": true,
  • "filter_text_added": true,
  • "filter_text_removed": true,
  • "filter_text_replaced": true,
  • "in_stock_only": true,
  • "follow_price_changes": true,
  • "price_change_threshold_percent": 0,
  • "has_ldjson_price_data": true,
  • "notification_screenshot": false,
  • "filter_failure_notification_send": true,
  • "use_page_title_in_list": true,
  • "history_snapshot_max_length": 1,
  • "time_schedule_limit": {
    },
  • "conditions": [
    ],
  • "conditions_match_logic": "ALL",
  • "llm_backend_profile": true,
  • "llm_intent": "",
  • "llm_change_summary": "",
  • "llm_change_summary_mode": "replace",
  • "llm_prefilter": "string",
  • "llm_evaluation_cache": { },
  • "llm_last_tokens_used": 0,
  • "llm_tokens_used_cumulative": 0,
  • "llm_tokens_this_period": 0,
  • "llm_tokens_period_key": "string",
  • "overrides_watch": true,
  • "url_match_pattern": "string",
  • "tag_colour": "string"
}

Update tag

Update an existing tag using JSON

Authorizations:
ApiKeyAuth
path Parameters
uuid
required
string <uuid>

Tag unique ID

Request Body schema: application/json
required
url
string <uri> <= 5000 characters

URL to monitor for changes

+
link_to_open
string <= 5000 characters

Optional human-facing URL to open instead of url. Use when url points at something +that is not meant to be read in a browser (an API endpoint or RSS feed, for example). +An empty string means "use url". Exposed rendered as open_link.

title
string or null <= 5000 characters

Custom title for the web page change monitor (watch), not to be confused with page_title

tag
string <= 5000 characters
Deprecated

Whether notifications are muted

method
string
Enum: "GET" "POST" "DELETE" "PUT"

HTTP method to use

-
fetch_backend
string^(system|html_requests|html_webdriver|extra_b...
Default: "system"
fetch_backend
string^[^\r\n\t]{1,200}$
Default: "system"

Backend to use for fetching content. Common values:

+" class="sc-eVqvcJ sc-fszimp kIppRw drqpJr">

Which browser this watch checks with. The valid values depend on the install, so the +value is checked against them when you create or update a watch:

    -
  • system (default) - Use the system-wide default fetcher
  • -
  • html_requests - Fast requests-based fetcher
  • -
  • html_webdriver - Browser-based fetcher (Playwright/Puppeteer)
  • -
  • extra_browser_* - Custom browser configurations (if configured)
  • -
  • Plugin-provided fetchers (if installed)
  • +
  • system (default) - follow the global Default browser
  • +
  • a built-in engine name, e.g. html_requests (fast plain HTTP client), +html_webdriver (Playwright/Puppeteer/Selenium, depending on configuration) or +html_external_cdp (a browser you run elsewhere, reached over CDP)
  • +
  • a plugin-provided engine, if one is installed
  • +
  • the id of a saved browser from the Browsers page, which is also what a pre-0.61 +extra_browser_<name> endpoint becomes when it is migrated there
object

HTTP headers to include in requests

@@ -1530,7 +1576,7 @@ Leave empty to use the colour auto-generated from the tag name.

" class="sc-eVqvcJ sc-fszimp kIppRw drqpJr">

Production server

https://yourdomain.com/api/v1/tag/{uuid}

Custom server

-
{protocol}://{host}/api/v1/tag/{uuid}

Request samples

Content type
application/json
{
  • "title": "string",
  • "tag": "Production, Price tracking",
  • "tags": [
    ],
  • "paused": true,
  • "notification_muted": true,
  • "method": "GET",
  • "fetch_backend": "system",
  • "headers": {
    },
  • "body": "string",
  • "proxy": "string",
  • "ignore_status_codes": true,
  • "webdriver_delay": 0,
  • "webdriver_js_execute_code": "string",
  • "time_between_check": {
    },
  • "time_between_check_use_default": true,
  • "notification_urls": [
    ],
  • "notification_title": "string",
  • "notification_body": "string",
  • "notification_format": "text",
  • "track_ldjson_price_data": true,
  • "browser_steps": [
    ],
  • "processor": "restock_diff",
  • "include_filters": [
    ],
  • "subtractive_selectors": [
    ],
  • "ignore_text": [
    ],
  • "trigger_text": [
    ],
  • "text_should_not_be_present": [
    ],
  • "extract_lines_containing": [
    ],
  • "extract_text": [
    ],
  • "trim_text_whitespace": false,
  • "sort_text_alphabetically": false,
  • "remove_duplicate_lines": false,
  • "check_unique_lines": false,
  • "strip_ignored_lines": true,
  • "filter_text_added": true,
  • "filter_text_removed": true,
  • "filter_text_replaced": true,
  • "in_stock_only": true,
  • "follow_price_changes": true,
  • "price_change_threshold_percent": 0,
  • "notification_screenshot": false,
  • "filter_failure_notification_send": true,
  • "use_page_title_in_list": true,
  • "history_snapshot_max_length": 1,
  • "time_schedule_limit": {
    },
  • "conditions": [
    ],
  • "conditions_match_logic": "ALL",
  • "llm_backend_profile": true,
  • "llm_intent": "",
  • "llm_change_summary": "",
  • "llm_change_summary_mode": "replace",
  • "overrides_watch": true,
  • "url_match_pattern": "string",
  • "tag_colour": "string"
}

Delete tag

{protocol}://{host}/api/v1/tag/{uuid}

Request samples

Content type
application/json
{
  • "link_to_open": "string",
  • "title": "string",
  • "tag": "Production, Price tracking",
  • "tags": [
    ],
  • "paused": true,
  • "notification_muted": true,
  • "method": "GET",
  • "fetch_backend": "system",
  • "headers": {
    },
  • "body": "string",
  • "proxy": "string",
  • "ignore_status_codes": true,
  • "webdriver_delay": 0,
  • "webdriver_js_execute_code": "string",
  • "time_between_check": {
    },
  • "time_between_check_use_default": true,
  • "notification_urls": [
    ],
  • "notification_title": "string",
  • "notification_body": "string",
  • "notification_format": "text",
  • "track_ldjson_price_data": true,
  • "browser_steps": [
    ],
  • "processor": "restock_diff",
  • "include_filters": [
    ],
  • "subtractive_selectors": [
    ],
  • "ignore_text": [
    ],
  • "trigger_text": [
    ],
  • "text_should_not_be_present": [
    ],
  • "extract_lines_containing": [
    ],
  • "extract_text": [
    ],
  • "trim_text_whitespace": false,
  • "sort_text_alphabetically": false,
  • "remove_duplicate_lines": false,
  • "check_unique_lines": false,
  • "strip_ignored_lines": true,
  • "filter_text_added": true,
  • "filter_text_removed": true,
  • "filter_text_replaced": true,
  • "in_stock_only": true,
  • "follow_price_changes": true,
  • "price_change_threshold_percent": 0,
  • "notification_screenshot": false,
  • "filter_failure_notification_send": true,
  • "use_page_title_in_list": true,
  • "history_snapshot_max_length": 1,
  • "time_schedule_limit": {
    },
  • "conditions": [
    ],
  • "conditions_match_logic": "ALL",
  • "llm_backend_profile": true,
  • "llm_intent": "",
  • "llm_change_summary": "",
  • "llm_change_summary_mode": "replace",
  • "overrides_watch": true,
  • "url_match_pattern": "string",
  • "tag_colour": "string"
}

Delete tag

Delete a tag/group and remove it from all web page change monitors (watches)

Authorizations:
ApiKeyAuth
path Parameters
uuid
required
string <uuid>

Tag unique ID

@@ -2035,7 +2081,7 @@ installed processors (e.g. processor_config_restock_diff from the b curl -X GET "http://localhost:5000/api/v1/full-spec"