openapi: 3.0.3
info:
title: 'WebChange Detector'
description: 'This documentation aims to provide you with all the information you need to integrate WebChange Detector into your workflow.'
version: 1.0.0
servers:
-
url: 'https://api.webchangedetector.com'
tags:
-
name: 'AI Feedback Rules'
description: 'Manage rules for ignoring recurring false positives in AI verification results.'
-
name: Account
description: 'This object represents your account with WCD'
-
name: Batch
description: 'This object represents Batches of Queues.'
-
name: Comparison
description: 'This object represents the comparison between 2 `Screenshots` and how they differ.'
-
name: Group
description: 'This object groups together a list of URLs and group wide settings for them.'
-
name: 'Monitoring Trigger'
description: 'Starts a monitoring check for single pages when they change, e.g. when a post is saved in WordPress (trigger-based monitoring).'
-
name: Queue
description: 'This object represents a log of taking screenshots, comparing screenshots and their status.'
-
name: Screenshot
description: "This object represents the actual screenshot and the location it's stored at."
-
name: Subaccount
description: 'This object represents a Subaccount'
-
name: Url
description: 'This object represents a single URL and specific settings'
-
name: Webhook
description: 'This object contains the webhook calls a user can set to be notified for various events.'
-
name: Website
description: 'This object represents Websites.'
components:
securitySchemes:
default:
type: http
scheme: bearer
description: 'You can retrieve your token on webchangedetector.com or via the plugin.'
security:
-
default: []
paths:
/api/v2/ai-feedback-rules:
get:
summary: 'List AI Feedback Rules'
operationId: listAIFeedbackRules
description: 'Returns a paginated list of all `AiFeedbackRule` for the current user.'
parameters:
-
in: query
name: scope
description: 'Filter by scope.'
example: url
required: false
schema:
type: string
description: 'Filter by scope.'
example: url
enum:
- url
- group
- website
-
in: query
name: is_active
description: 'Filter by active status.'
example: true
required: false
schema:
type: boolean
description: 'Filter by active status.'
example: true
-
in: query
name: website_id
description: 'Filter by website UUID.'
example: 21cf8800-f906-4fa3-b1db-ed3d2977354d
required: false
schema:
type: string
description: 'Filter by website UUID.'
example: 21cf8800-f906-4fa3-b1db-ed3d2977354d
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
id: 21cf8800-f906-4fa3-b1db-ed3d2977354d
scope: url
description: 'Slider showing different slide'
region_context:
bbox:
x: 0
'y': 100
w: 1920
h: 300
is_active: true
last_matched_at: null
match_count: 0
url_id: 418e0748-a9cf-480b-86d6-88b00bac00b9
group_id: null
website_id: null
created_at: '2026-02-21 13:37:00'
updated_at: '2026-02-21 13:37:00'
properties:
data:
type: array
example:
-
id: 21cf8800-f906-4fa3-b1db-ed3d2977354d
scope: url
description: 'Slider showing different slide'
region_context:
bbox:
x: 0
'y': 100
w: 1920
h: 300
is_active: true
last_matched_at: null
match_count: 0
url_id: 418e0748-a9cf-480b-86d6-88b00bac00b9
group_id: null
website_id: null
created_at: '2026-02-21 13:37:00'
updated_at: '2026-02-21 13:37:00'
items:
type: object
properties:
id:
type: string
example: 21cf8800-f906-4fa3-b1db-ed3d2977354d
scope:
type: string
example: url
description:
type: string
example: 'Slider showing different slide'
region_context:
type: object
properties:
bbox:
type: object
properties:
x:
type: integer
example: 0
'y':
type: integer
example: 100
w:
type: integer
example: 1920
h:
type: integer
example: 300
is_active:
type: boolean
example: true
last_matched_at:
type: string
example: null
nullable: true
match_count:
type: integer
example: 0
url_id:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
group_id:
type: string
example: null
nullable: true
website_id:
type: string
example: null
nullable: true
created_at:
type: string
example: '2026-02-21 13:37:00'
updated_at:
type: string
example: '2026-02-21 13:37:00'
tags:
- 'AI Feedback Rules'
post:
summary: 'Create AI Feedback Rule'
operationId: createAIFeedbackRule
description: "Creates a new `AiFeedbackRule` from a comparison region. The backend\nauto-resolves whether the group belongs to a website and sets the\nscope accordingly."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 21cf8800-f906-4fa3-b1db-ed3d2977354d
scope: url
description: 'Slider showing different slide'
region_context:
bbox:
x: 0
'y': 100
w: 1920
h: 300
is_active: true
last_matched_at: null
match_count: 0
url_id: 418e0748-a9cf-480b-86d6-88b00bac00b9
group_id: null
website_id: null
created_at: '2026-02-21 13:37:00'
updated_at: '2026-02-21 13:37:00'
properties:
data:
type: object
properties:
id:
type: string
example: 21cf8800-f906-4fa3-b1db-ed3d2977354d
scope:
type: string
example: url
description:
type: string
example: 'Slider showing different slide'
region_context:
type: object
properties:
bbox:
type: object
properties:
x:
type: integer
example: 0
'y':
type: integer
example: 100
w:
type: integer
example: 1920
h:
type: integer
example: 300
is_active:
type: boolean
example: true
last_matched_at:
type: string
example: null
nullable: true
match_count:
type: integer
example: 0
url_id:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
group_id:
type: string
example: null
nullable: true
website_id:
type: string
example: null
nullable: true
created_at:
type: string
example: '2026-02-21 13:37:00'
updated_at:
type: string
example: '2026-02-21 13:37:00'
tags:
- 'AI Feedback Rules'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
type:
type: string
description: 'Feedback target. `visual` (default) trains the AI on a specific image region of a Comparison. `console` trains it on a browser-console log entry to ignore.'
example: visual
enum:
- visual
- console
comparison_id:
type: string
description: 'UUID of the comparison containing the region.'
example: 21cf8800-f906-4fa3-b1db-ed3d2977354d
region_id:
type: integer
description: 'The region ID within the AI verification result.'
example: 0
console_entry:
type: string
description: 'Verbatim console-log line to teach the AI to ignore. Required when `type=console`. Max 500 chars. This field is required when type is console. Must not be greater than 500 characters.'
example: '[Vue warn]: Component is missing template or render function.'
scope:
type: string
description: 'Scope for the rule: "url" for this URL only, "group_or_website" for all URLs.'
example: url
enum:
- url
- group_or_website
required:
- comparison_id
- region_id
- scope
'/api/v2/ai-feedback-rules/{id}':
put:
summary: 'Update AI Feedback Rule'
operationId: updateAIFeedbackRule
description: 'Update the active status and/or scope of an `AiFeedbackRule`.'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 21cf8800-f906-4fa3-b1db-ed3d2977354d
scope: url
description: 'Slider showing different slide'
region_context: null
is_active: false
last_matched_at: null
match_count: 0
url_id: 418e0748-a9cf-480b-86d6-88b00bac00b9
group_id: null
website_id: null
created_at: '2026-02-21 13:37:00'
updated_at: '2026-02-21 13:37:00'
properties:
data:
type: object
properties:
id:
type: string
example: 21cf8800-f906-4fa3-b1db-ed3d2977354d
scope:
type: string
example: url
description:
type: string
example: 'Slider showing different slide'
region_context:
type: string
example: null
nullable: true
is_active:
type: boolean
example: false
last_matched_at:
type: string
example: null
nullable: true
match_count:
type: integer
example: 0
url_id:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
group_id:
type: string
example: null
nullable: true
website_id:
type: string
example: null
nullable: true
created_at:
type: string
example: '2026-02-21 13:37:00'
updated_at:
type: string
example: '2026-02-21 13:37:00'
tags:
- 'AI Feedback Rules'
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
is_active:
type: boolean
description: 'Set the active status of the rule.'
example: false
scope:
type: string
description: 'Change the scope: "url" for this URL only, "group_or_website" for all URLs.'
example: url
enum:
- url
- group_or_website
delete:
summary: 'Delete AI Feedback Rule'
operationId: deleteAIFeedbackRule
description: 'Permanently deletes an `AiFeedbackRule`.'
parameters: []
responses: {}
tags:
- 'AI Feedback Rules'
parameters:
-
in: path
name: id
description: 'The ID of the ai feedback rule.'
example: non
required: true
schema:
type: string
-
in: path
name: ai_feedback_rule
description: 'The UUID of the AI Feedback Rule.'
example: 21cf8800-f906-4fa3-b1db-ed3d2977354d
required: true
schema:
type: string
/api/v2/account:
get:
summary: 'Get Account'
operationId: getAccount
description: 'Retrieves your Account. The fields `plan`, `plan_name`, `company` and `magic_login_secret` only come for full accounts (not sub accounts).'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 041c6528-783f-4e7e-b831-1a424ffeb8f3
name_first: Hans
name_last: Hacker
email: mail@example.com
webhook_secret: zq3csqdst0txgo5qe9mkqsourrxo56wd
is_subaccount: false
account_level: 0
can_manage_subaccounts: false
can_create_subaccounts: false
plan_label: null
invitation_accepted: true
plan_features:
ai_verification: true
browser_console: true
checks_done: 6982
checks_left: 3018
checks_limit: 10000
timezone: UTC
status: active
renewal_at: '2025-01-01 13:37:42'
plan: agency
plan_name: Agency
company: 'ACME Ltd'
magic_login_secret: WdKnLLcsDxpJdfmv
properties:
data:
type: object
properties:
id:
type: string
example: 041c6528-783f-4e7e-b831-1a424ffeb8f3
name_first:
type: string
example: Hans
name_last:
type: string
example: Hacker
email:
type: string
example: mail@example.com
webhook_secret:
type: string
example: zq3csqdst0txgo5qe9mkqsourrxo56wd
is_subaccount:
type: boolean
example: false
account_level:
type: integer
example: 0
can_manage_subaccounts:
type: boolean
example: false
can_create_subaccounts:
type: boolean
example: false
plan_label:
type: string
example: null
nullable: true
invitation_accepted:
type: boolean
example: true
plan_features:
type: object
properties:
ai_verification:
type: boolean
example: true
browser_console:
type: boolean
example: true
checks_done:
type: integer
example: 6982
checks_left:
type: integer
example: 3018
checks_limit:
type: integer
example: 10000
timezone:
type: string
example: UTC
status:
type: string
example: active
renewal_at:
type: string
example: '2025-01-01 13:37:42'
plan:
type: string
example: agency
plan_name:
type: string
example: Agency
company:
type: string
example: 'ACME Ltd'
magic_login_secret:
type: string
example: WdKnLLcsDxpJdfmv
tags:
- Account
put:
summary: 'Update Account'
operationId: updateAccount
description: "Updates your `Account` by setting the values of the parameters passed.\nAny parameters not provided will be left unchanged."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 041c6528-783f-4e7e-b831-1a424ffeb8f3
name_first: Jane
name_last: Doe
email: mail@example.com
webhook_secret: zq3csqdst0txgo5qe9mkqsourrxo56wd
is_subaccount: false
account_level: 0
can_manage_subaccounts: false
can_create_subaccounts: false
plan_label: null
invitation_accepted: true
plan_features:
ai_verification: true
browser_console: true
checks_done: 42
checks_left: 1337
checks_limit: 1379
timezone: UTC
status: active
renewal_at: '2025-01-01 13:37:42'
plan: agency
plan_name: Agency
company: 'ACME LLC'
magic_login_secret: WdKnLLcsDxpJdfmv
properties:
data:
type: object
properties:
id:
type: string
example: 041c6528-783f-4e7e-b831-1a424ffeb8f3
name_first:
type: string
example: Jane
name_last:
type: string
example: Doe
email:
type: string
example: mail@example.com
webhook_secret:
type: string
example: zq3csqdst0txgo5qe9mkqsourrxo56wd
is_subaccount:
type: boolean
example: false
account_level:
type: integer
example: 0
can_manage_subaccounts:
type: boolean
example: false
can_create_subaccounts:
type: boolean
example: false
plan_label:
type: string
example: null
nullable: true
invitation_accepted:
type: boolean
example: true
plan_features:
type: object
properties:
ai_verification:
type: boolean
example: true
browser_console:
type: boolean
example: true
checks_done:
type: integer
example: 42
checks_left:
type: integer
example: 1337
checks_limit:
type: integer
example: 1379
timezone:
type: string
example: UTC
status:
type: string
example: active
renewal_at:
type: string
example: '2025-01-01 13:37:42'
plan:
type: string
example: agency
plan_name:
type: string
example: Agency
company:
type: string
example: 'ACME LLC'
magic_login_secret:
type: string
example: WdKnLLcsDxpJdfmv
tags:
- Account
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
name_first:
type: string
description: 'First Name'
example: Jane
name_last:
type: string
description: 'Last Name'
example: Doe
company:
type: string
description: 'Company Name'
example: 'ACME LLC'
/api/v2/account/stats:
get:
summary: 'Get Account Stats'
operationId: getAccountStats
description: "Returns aggregated statistics for the authenticated account, computed across\nALL groups and websites (not paginated).\n\n- `estimated_monthly_checks` (top-level): estimated monthly monitoring checks. Kept for backwards compatibility.\n- `monitoring`: enabled monitoring groups; website/url counts, monthly estimate, soonest next run.\n- `manual`: enabled manual (non-monitoring) groups with selected URLs; website/url counts and checks per run.\n- `auto_update`: websites with auto-update checks enabled; count, missing-email count, active weekdays, monthly forecast."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
estimated_monthly_checks: 4520
monitoring:
websites: 12
urls: 84
estimated_monthly_checks: 4520
next_run_at: 1716900000
next_runs:
-
name: example.com
domain: example.com
next_run_at: 1716900000
-
name: shop.example
domain: shop.example
next_run_at: 1716903600
trigger_websites: 1
manual:
websites: 8
urls: 56
checks_per_run: 112
auto_update:
websites_enabled: 9
missing_email: 1
active_weekdays:
- Mon
- Wed
- Fri
estimated_monthly_checks: 1947
next_runs:
-
name: example.com
domain: example.com
next_run_at: 1716900000
-
name: shop.example
domain: shop.example
next_run_at: 1716986400
properties:
data:
type: object
properties:
estimated_monthly_checks:
type: integer
example: 4520
monitoring:
type: object
properties:
websites:
type: integer
example: 12
urls:
type: integer
example: 84
estimated_monthly_checks:
type: integer
example: 4520
next_run_at:
type: integer
example: 1716900000
next_runs:
type: array
example:
-
name: example.com
domain: example.com
next_run_at: 1716900000
-
name: shop.example
domain: shop.example
next_run_at: 1716903600
items:
type: object
properties:
name:
type: string
example: example.com
domain:
type: string
example: example.com
next_run_at:
type: integer
example: 1716900000
trigger_websites:
type: integer
example: 1
manual:
type: object
properties:
websites:
type: integer
example: 8
urls:
type: integer
example: 56
checks_per_run:
type: integer
example: 112
auto_update:
type: object
properties:
websites_enabled:
type: integer
example: 9
missing_email:
type: integer
example: 1
active_weekdays:
type: array
example:
- Mon
- Wed
- Fri
items:
type: string
estimated_monthly_checks:
type: integer
example: 1947
next_runs:
type: array
example:
-
name: example.com
domain: example.com
next_run_at: 1716900000
-
name: shop.example
domain: shop.example
next_run_at: 1716986400
items:
type: object
properties:
name:
type: string
example: example.com
domain:
type: string
example: example.com
next_run_at:
type: integer
example: 1716900000
tags:
- Account
/api/v2/account/reactivate:
post:
summary: 'Reactivate Account'
operationId: reactivateAccount
description: "Re-activates an account that was paused due to inactivity, including all its subaccounts.\nOnly the account owner can re-activate; cancelled accounts cannot be re-activated this way."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 041c6528-783f-4e7e-b831-1a424ffeb8f3
name_first: Hans
name_last: Hacker
email: mail@example.com
status: active
renewal_at: '2025-01-01 13:37:42'
properties:
data:
type: object
properties:
id:
type: string
example: 041c6528-783f-4e7e-b831-1a424ffeb8f3
name_first:
type: string
example: Hans
name_last:
type: string
example: Hacker
email:
type: string
example: mail@example.com
status:
type: string
example: active
renewal_at:
type: string
example: '2025-01-01 13:37:42'
tags:
- Account
/api/v2/batches:
get:
summary: 'List Batches'
operationId: listBatches
description: "Returns a list of all `Batch`. The `Batches` are sorted by creation date, with\nthe most recent `Batches` appearing first.\n\n`source` is one of `manual`, `monitoring`, `auto_update`. `ai_summary` is `null` for accounts without the `ai-verification` feature; `ai_summary.overall_status` is one of `everything_ok`, `needs_attention`. `website_domains` lists the unique domains of the websites linked to the batch's queue groups (empty when no website is linked).\n\n`trigger_context` is set for trigger-based monitoring runs (`source` = `monitoring`, started e.g. by saving a post in WordPress) and `null` otherwise. It holds the trigger `type`, `first_triggered_at` and the checked `pages`; each page has its `url` and `triggered_at`, plus `title`, `post_id` and `editor` when the trigger reported them. `type` is `post_save` or `manual_trigger` (\"run monitoring now\"). A `manual_trigger` run also has `scope` (`url` or `all`) and `editor` when reported; with `scope` = `all` (the whole Group) `pages` is empty."
parameters:
-
in: query
name: above_threshold
description: 'Only show Batches where there is a change detected between 2 screenshots.'
example: false
required: false
schema:
type: boolean
description: 'Only show Batches where there is a change detected between 2 screenshots.'
example: false
-
in: query
name: from
description: 'Start date for filter. Must be a valid date.'
example: '2024-07-01'
required: false
schema:
type: string
description: 'Start date for filter. Must be a valid date.'
example: '2024-07-01'
-
in: query
name: to
description: 'End date for filter, defaults to today. Must be a valid date.'
example: '2024-07-04'
required: false
schema:
type: string
description: 'End date for filter, defaults to today. Must be a valid date.'
example: '2024-07-04'
-
in: query
name: status
description: 'Comma separated list of Comparison status to filter for.'
example: 'to_fix,false_positive'
required: false
schema:
type: string
description: 'Comma separated list of Comparison status to filter for.'
example: 'to_fix,false_positive'
-
in: query
name: queue_type
description: 'Comma separated list of Queue types to filter for.'
example: 'post,comparison'
required: false
schema:
type: string
description: 'Comma separated list of Queue types to filter for.'
example: 'post,comparison'
-
in: query
name: group_ids
description: 'Comma separated list of Group IDs.'
example: '023c282c-6513-420a-a36b-a654312ab229,023c282c-6513-420a-a36b-a654312ab230'
required: false
schema:
type: string
description: 'Comma separated list of Group IDs.'
example: '023c282c-6513-420a-a36b-a654312ab229,023c282c-6513-420a-a36b-a654312ab230'
-
in: query
name: urls
description: 'Comma separated list of URL IDs to filter for.'
example: 023c282c-6513-420a-a36b-a654312ab229
required: false
schema:
type: string
description: 'Comma separated list of URL IDs to filter for.'
example: 023c282c-6513-420a-a36b-a654312ab229
-
in: query
name: websites
description: 'Comma separated list of Website IDs to filter for.'
example: 023c282c-6513-420a-a36b-a654312ab229
required: false
schema:
type: string
description: 'Comma separated list of Website IDs to filter for.'
example: 023c282c-6513-420a-a36b-a654312ab229
-
in: query
name: source
description: 'Comma separated list of Batch sources to filter for (manual, monitoring, auto_update).'
example: 'manual,auto_update'
required: false
schema:
type: string
description: 'Comma separated list of Batch sources to filter for (manual, monitoring, auto_update).'
example: 'manual,auto_update'
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
id: 0d5f8108-51f1-4961-939a-2d33c7145918
name: Monitoring
source: monitoring
trigger_context:
type: post_save
first_triggered_at: '2024-07-29T13:30:12+00:00'
pages:
-
url: example.com/about
title: 'About us'
post_id: 42
editor: Anna
triggered_at: '2024-07-29T13:31:05+00:00'
group_names:
- 'example.com - Monitoring Checks'
website_domains:
- example.com
sc_version: '2.0'
finished_at: '2024-07-29 13:37:42'
ai_summary:
summary: 'Pricing text updated and navigation menu restructured. New JS error on checkout may affect functionality.'
overall_status: needs_attention
processing_time_ms: 1234
update_results: null
comparisons_count:
ok: 0
new: 1
false_positive: 0
to_fix: 0
above_threshold: 10
queues_count:
failed: 0
browser_console_count:
added: 1
removed: 0
mixed: 0
unchanged: 0
links:
first: 'http://api.webchangedetector.test/api/v2/batches?page=1'
last: 'http://api.webchangedetector.test/api/v2/batches?page=1'
prev: null
next: null
meta:
current_page: 1
from: 1
last_page: 1
links:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/batches?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
path: 'http://api.webchangedetector.test/api/v2/batches'
per_page: 15
to: 1
total: 1
properties:
data:
type: array
example:
-
id: 0d5f8108-51f1-4961-939a-2d33c7145918
name: Monitoring
source: monitoring
trigger_context:
type: post_save
first_triggered_at: '2024-07-29T13:30:12+00:00'
pages:
-
url: example.com/about
title: 'About us'
post_id: 42
editor: Anna
triggered_at: '2024-07-29T13:31:05+00:00'
group_names:
- 'example.com - Monitoring Checks'
website_domains:
- example.com
sc_version: '2.0'
finished_at: '2024-07-29 13:37:42'
ai_summary:
summary: 'Pricing text updated and navigation menu restructured. New JS error on checkout may affect functionality.'
overall_status: needs_attention
processing_time_ms: 1234
update_results: null
comparisons_count:
ok: 0
new: 1
false_positive: 0
to_fix: 0
above_threshold: 10
queues_count:
failed: 0
browser_console_count:
added: 1
removed: 0
mixed: 0
unchanged: 0
items:
type: object
properties:
id:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
name:
type: string
example: Monitoring
source:
type: string
example: monitoring
trigger_context:
type: object
properties:
type:
type: string
example: post_save
first_triggered_at:
type: string
example: '2024-07-29T13:30:12+00:00'
pages:
type: array
example:
-
url: example.com/about
title: 'About us'
post_id: 42
editor: Anna
triggered_at: '2024-07-29T13:31:05+00:00'
items:
type: object
properties:
url:
type: string
example: example.com/about
title:
type: string
example: 'About us'
post_id:
type: integer
example: 42
editor:
type: string
example: Anna
triggered_at:
type: string
example: '2024-07-29T13:31:05+00:00'
group_names:
type: array
example:
- 'example.com - Monitoring Checks'
items:
type: string
website_domains:
type: array
example:
- example.com
items:
type: string
sc_version:
type: string
example: '2.0'
finished_at:
type: string
example: '2024-07-29 13:37:42'
ai_summary:
type: object
properties:
summary:
type: string
example: 'Pricing text updated and navigation menu restructured. New JS error on checkout may affect functionality.'
overall_status:
type: string
example: needs_attention
processing_time_ms:
type: integer
example: 1234
update_results:
type: string
example: null
nullable: true
comparisons_count:
type: object
properties:
ok:
type: integer
example: 0
new:
type: integer
example: 1
false_positive:
type: integer
example: 0
to_fix:
type: integer
example: 0
above_threshold:
type: integer
example: 10
queues_count:
type: object
properties:
failed:
type: integer
example: 0
browser_console_count:
type: object
properties:
added:
type: integer
example: 1
removed:
type: integer
example: 0
mixed:
type: integer
example: 0
unchanged:
type: integer
example: 0
links:
type: object
properties:
first:
type: string
example: 'http://api.webchangedetector.test/api/v2/batches?page=1'
last:
type: string
example: 'http://api.webchangedetector.test/api/v2/batches?page=1'
prev:
type: string
example: null
nullable: true
next:
type: string
example: null
nullable: true
meta:
type: object
properties:
current_page:
type: integer
example: 1
from:
type: integer
example: 1
last_page:
type: integer
example: 1
links:
type: array
example:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/batches?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
items:
type: object
properties:
url:
type: string
example: null
nullable: true
label:
type: string
example: '« Previous'
active:
type: boolean
example: false
path:
type: string
example: 'http://api.webchangedetector.test/api/v2/batches'
per_page:
type: integer
example: 15
to:
type: integer
example: 1
total:
type: integer
example: 1
tags:
- Batch
'/api/v2/batches/{id}':
get:
summary: 'Get Batch'
operationId: getBatch
description: "Retrieves a `Batch` object identfied by their ID.\n\n`source` is one of `manual`, `monitoring`, `auto_update`. `ai_summary` is `null` for accounts without the `ai-verification` feature; `ai_summary.overall_status` is one of `everything_ok`, `needs_attention`. `website_domains` lists the unique domains of the websites linked to the batch's queue groups (empty when no website is linked). `trigger_context` is set for trigger-based monitoring runs and `null` otherwise (shape: see List Batches)."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 0d5f8108-51f1-4961-939a-2d33c7145918
name: Foobar
source: monitoring
trigger_context: null
group_names:
- 'example.com - Monitoring Checks'
website_domains:
- example.com
sc_version: '2.0'
finished_at: '2024-07-29 13:37:42'
ai_summary:
summary: 'Pricing text updated and navigation menu restructured. New JS error on checkout may affect functionality.'
overall_status: needs_attention
processing_time_ms: 1234
update_results: null
comparisons_count:
ok: 0
new: 1
false_positive: 0
to_fix: 0
above_threshold: 10
queues_count:
failed: 0
browser_console_count:
added: 1
removed: 0
mixed: 0
unchanged: 0
properties:
data:
type: object
properties:
id:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
name:
type: string
example: Foobar
source:
type: string
example: monitoring
trigger_context:
type: string
example: null
nullable: true
group_names:
type: array
example:
- 'example.com - Monitoring Checks'
items:
type: string
website_domains:
type: array
example:
- example.com
items:
type: string
sc_version:
type: string
example: '2.0'
finished_at:
type: string
example: '2024-07-29 13:37:42'
ai_summary:
type: object
properties:
summary:
type: string
example: 'Pricing text updated and navigation menu restructured. New JS error on checkout may affect functionality.'
overall_status:
type: string
example: needs_attention
processing_time_ms:
type: integer
example: 1234
update_results:
type: string
example: null
nullable: true
comparisons_count:
type: object
properties:
ok:
type: integer
example: 0
new:
type: integer
example: 1
false_positive:
type: integer
example: 0
to_fix:
type: integer
example: 0
above_threshold:
type: integer
example: 10
queues_count:
type: object
properties:
failed:
type: integer
example: 0
browser_console_count:
type: object
properties:
added:
type: integer
example: 1
removed:
type: integer
example: 0
mixed:
type: integer
example: 0
unchanged:
type: integer
example: 0
tags:
- Batch
put:
summary: 'Update Batch'
operationId: updateBatch
description: "Updates the specified `Batch` by setting the values of the parameters passed.\nAny parameters not provided will be left unchanged."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
id: 0d5f8108-51f1-4961-939a-2d33c7145918
name: Foobar
source: monitoring
trigger_context: null
group_names:
- 'example.com - Monitoring Checks'
website_domains:
- example.com
sc_version: '2.0'
finished_at: '2024-07-29 13:37:42'
ai_summary:
summary: 'Pricing text updated and navigation menu restructured. New JS error on checkout may affect functionality.'
overall_status: needs_attention
processing_time_ms: 1234
update_results: null
comparisons_count:
ok: 0
new: 1
false_positive: 0
to_fix: 0
above_threshold: 10
queues_count:
failed: 0
browser_console_count:
added: 1
removed: 0
mixed: 0
unchanged: 0
properties:
id:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
name:
type: string
example: Foobar
source:
type: string
example: monitoring
trigger_context:
type: string
example: null
nullable: true
group_names:
type: array
example:
- 'example.com - Monitoring Checks'
items:
type: string
website_domains:
type: array
example:
- example.com
items:
type: string
sc_version:
type: string
example: '2.0'
finished_at:
type: string
example: '2024-07-29 13:37:42'
ai_summary:
type: object
properties:
summary:
type: string
example: 'Pricing text updated and navigation menu restructured. New JS error on checkout may affect functionality.'
overall_status:
type: string
example: needs_attention
processing_time_ms:
type: integer
example: 1234
update_results:
type: string
example: null
nullable: true
comparisons_count:
type: object
properties:
ok:
type: integer
example: 0
new:
type: integer
example: 1
false_positive:
type: integer
example: 0
to_fix:
type: integer
example: 0
above_threshold:
type: integer
example: 10
queues_count:
type: object
properties:
failed:
type: integer
example: 0
browser_console_count:
type: object
properties:
added:
type: integer
example: 1
removed:
type: integer
example: 0
mixed:
type: integer
example: 0
unchanged:
type: integer
example: 0
tags:
- Batch
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'The name of the Batch.'
example: Foobar
required:
- name
parameters:
-
in: path
name: id
description: 'The ID of the Batch.'
example: 0d5f8108-51f1-4961-939a-2d33c7145918
required: true
schema:
type: string
'/api/v2/batches/{id}/update-results':
put:
summary: 'Store Batch Update Results'
operationId: storeBatchUpdateResults
description: "Stores the WordPress update results (core / plugins / themes) that were applied\naround this `Batch`. The whole blob is replaced on every call, so the endpoint is\nidempotent and safe to retry.\n\nIt is accepted in ANY batch state (also while the batch is still running) and for\nANY `source`. Send it for an empty run too (`updates.core` = `null`, empty arrays,\n`summary.total_attempted` = `0`, `summary.status` = `completed`).\n\nFor a batch with `source` = `auto_update` this is what enables the Auto Update Check\nresult email: it is sent once the batch is finished AND the update results are stored,\nwhichever of the two happens last."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 0d5f8108-51f1-4961-939a-2d33c7145918
name: 'Auto Update Checks'
source: auto_update
trigger_context: null
group_names:
- 'example.com - On-Demand Checks'
website_domains:
- example.com
sc_version: '2.0'
finished_at: '2024-07-29 13:37:42'
ai_summary: null
update_results:
timestamp: 1756800000
updates:
core: null
plugins:
-
slug: akismet
name: 'Akismet Anti-Spam'
from_version: '5.3'
to_version: 5.3.1
success: true
error: null
messages: []
themes: []
summary:
total_attempted: 1
successful: 1
failed: 0
status: completed
comparisons_count:
ok: 0
new: 1
false_positive: 0
to_fix: 0
above_threshold: 10
queues_count:
failed: 0
browser_console_count:
added: 1
removed: 0
mixed: 0
unchanged: 0
properties:
data:
type: object
properties:
id:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
name:
type: string
example: 'Auto Update Checks'
source:
type: string
example: auto_update
trigger_context:
type: string
example: null
nullable: true
group_names:
type: array
example:
- 'example.com - On-Demand Checks'
items:
type: string
website_domains:
type: array
example:
- example.com
items:
type: string
sc_version:
type: string
example: '2.0'
finished_at:
type: string
example: '2024-07-29 13:37:42'
ai_summary:
type: string
example: null
nullable: true
update_results:
type: object
properties:
timestamp:
type: integer
example: 1756800000
updates:
type: object
properties:
core:
type: string
example: null
nullable: true
plugins:
type: array
example:
-
slug: akismet
name: 'Akismet Anti-Spam'
from_version: '5.3'
to_version: 5.3.1
success: true
error: null
messages: []
items:
type: object
properties:
slug:
type: string
example: akismet
name:
type: string
example: 'Akismet Anti-Spam'
from_version:
type: string
example: '5.3'
to_version:
type: string
example: 5.3.1
success:
type: boolean
example: true
error:
type: string
example: null
nullable: true
messages:
type: array
example: []
themes:
type: array
example: []
summary:
type: object
properties:
total_attempted:
type: integer
example: 1
successful:
type: integer
example: 1
failed:
type: integer
example: 0
status:
type: string
example: completed
comparisons_count:
type: object
properties:
ok:
type: integer
example: 0
new:
type: integer
example: 1
false_positive:
type: integer
example: 0
to_fix:
type: integer
example: 0
above_threshold:
type: integer
example: 10
queues_count:
type: object
properties:
failed:
type: integer
example: 0
browser_console_count:
type: object
properties:
added:
type: integer
example: 1
removed:
type: integer
example: 0
mixed:
type: integer
example: 0
unchanged:
type: integer
example: 0
tags:
- Batch
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
timestamp:
type: integer
description: 'Unix timestamp of the update run.'
example: 1756800000
updates:
type: object
description: 'The performed updates (`core`, `plugins`, `themes`).'
example: []
properties:
core:
type: object
description: 'WordPress core update, or `null` when core was not updated.'
example: null
properties:
attempted:
type: boolean
description: ''
example: false
success:
type: boolean
description: ''
example: false
from_version:
type: string
description: 'Must not be greater than 50 characters.'
example: ffedwkwaviftjjugsevy
nullable: true
to_version:
type: string
description: 'Must not be greater than 50 characters.'
example: ngbutgcc
nullable: true
error:
type: string
description: 'Must not be greater than 500 characters.'
example: onwobjtqxd
nullable: true
messages:
type: array
description: 'Must not be greater than 300 characters.'
example:
- fxmfjvovmwwgkmvimwsrikts
items:
type: string
nullable: true
plugins:
type: array
description: 'Updated plugins. Each item: `slug`, `name`, `from_version`, `to_version`, `success`, `error`, `messages`. Must not have more than 300 items.'
example: null
items:
type: object
properties:
slug:
type: string
description: 'Must not be greater than 255 characters.'
example: dioytihgpxcueki
name:
type: string
description: 'Must not be greater than 255 characters.'
example: w
nullable: true
from_version:
type: string
description: 'Must not be greater than 50 characters.'
example: llevbfamjmfjgeajjecno
nullable: true
to_version:
type: string
description: 'Must not be greater than 50 characters.'
example: tswjaujzraupjyzwjqccz
nullable: true
success:
type: boolean
description: ''
example: false
error:
type: string
description: 'Must not be greater than 500 characters.'
example: dafzfdvqazwrdxsczvjxppxaq
nullable: true
messages:
type: array
description: 'Must not be greater than 300 characters.'
example:
- zdpdgymqmglrxcycatkpaa
items:
type: string
required:
- slug
- success
themes:
type: array
description: 'Updated themes. Same item shape as `updates.plugins`. Must not have more than 300 items.'
example: null
items:
type: object
properties:
slug:
type: string
description: 'Must not be greater than 255 characters.'
example: ev
name:
type: string
description: 'Must not be greater than 255 characters.'
example: xwczqwluaphhvhqc
nullable: true
from_version:
type: string
description: 'Must not be greater than 50 characters.'
example: dudfnxlnvxfk
nullable: true
to_version:
type: string
description: 'Must not be greater than 50 characters.'
example: qkadabvgwismyieqwbwf
nullable: true
success:
type: boolean
description: ''
example: false
error:
type: string
description: 'Must not be greater than 500 characters.'
example: ybatabyimucfpdisbhjrtpogs
nullable: true
messages:
type: array
description: 'Must not be greater than 300 characters.'
example:
- ipvptwwwu
items:
type: string
required:
- slug
- success
summary:
type: object
description: 'Run summary (`total_attempted`, `successful`, `failed`, `status`).'
example: []
properties:
total_attempted:
type: integer
description: 'Must be at least 0.'
example: 40
successful:
type: integer
description: 'Must be at least 0.'
example: 23
failed:
type: integer
description: 'Must be at least 0.'
example: 8
status:
type: string
description: 'One of `completed`, `completed_with_errors`, `failed`.'
example: completed
enum:
- completed
- completed_with_errors
- failed
required:
- total_attempted
- successful
- failed
- status
required:
- timestamp
- updates
- summary
parameters:
-
in: path
name: id
description: 'The ID of the Batch.'
example: 0d5f8108-51f1-4961-939a-2d33c7145918
required: true
schema:
type: string
/api/v2/comparisons:
get:
summary: 'List Comparisons'
operationId: listComparisons
description: "Returns a list of all `Comparison`. The `Comparisons` are sorted by creation date, with\nthe most recent `Comparisons` appearing first.\n\n`batch_source` is one of `manual`, `monitoring`, `auto_update`. `batch_trigger_type` is `post_save` (a saved page started the monitoring run), `manual_trigger` (\"run monitoring now\") or `null` (scheduled monitoring and all non-monitoring runs). `browser_console_*` fields are `null` unless the account has the `browser-console-comparisons` feature. `ai_regions`, `ai_verification_status`, and `ai_verification_result` are `null` unless the account has the `ai-verification` feature; `ai_verification_status` is one of `pending`, `verified`, `failed`, `skipped`. A comparison whose before or after screenshot came back as a completely blank page is decided automatically, without AI analysis: it carries an `ai_verification_result` with the marker `capture_issue` (`after_blank`, `before_blank` or `both_blank`), a `summary` and `alerts`, and no `regions`. Only `after_blank` (the page went blank) is an alert: it sets `status = new` and `alerts = 1`. A page recovering (`before_blank`) or staying blank (`both_blank`) is recorded the same way but resolves to `status = ok` with `alerts = 0`, because there is no valid comparison to judge against a blank baseline."
parameters:
-
in: query
name: above_threshold
description: 'Is a change detected between 2 screenshots.'
example: false
required: false
schema:
type: boolean
description: 'Is a change detected between 2 screenshots.'
example: false
-
in: query
name: from
description: 'Start date for filter. Must be a valid date.'
example: '2024-07-01'
required: false
schema:
type: string
description: 'Start date for filter. Must be a valid date.'
example: '2024-07-01'
-
in: query
name: to
description: 'End date for filter, defaults to today. Must be a valid date.'
example: '2024-07-04'
required: false
schema:
type: string
description: 'End date for filter, defaults to today. Must be a valid date.'
example: '2024-07-04'
-
in: query
name: status
description: 'Comma separated list of status to filter for.'
example: 'to_fix,false_positive'
required: false
schema:
type: string
description: 'Comma separated list of status to filter for.'
example: 'to_fix,false_positive'
-
in: query
name: groups
description: 'Comma separated list of group IDs.'
example: '023c282c-6513-420a-a36b-a654312ab229,023c282c-6513-420a-a36b-a654312ab230'
required: false
schema:
type: string
description: 'Comma separated list of group IDs.'
example: '023c282c-6513-420a-a36b-a654312ab229,023c282c-6513-420a-a36b-a654312ab230'
-
in: query
name: batches
description: 'Batch IDs.'
example: '0d5f8108-51f1-4961-939a-2d33c7145918,1d5f8108-51f1-4961-939a-2d33c7145918'
required: false
schema:
type: string
description: 'Batch IDs.'
example: '0d5f8108-51f1-4961-939a-2d33c7145918,1d5f8108-51f1-4961-939a-2d33c7145918'
-
in: query
name: token
description: ''
example: autem
required: false
schema:
type: string
description: ''
example: autem
-
in: query
name: urls
description: 'Comma separated list of URL UUIDs.'
example: 023c282c-6513-420a-a36b-a654312ab229
required: false
schema:
type: string
description: 'Comma separated list of URL UUIDs.'
example: 023c282c-6513-420a-a36b-a654312ab229
-
in: query
name: websites
description: 'Comma separated list of Website UUIDs.'
example: 023c282c-6513-420a-a36b-a654312ab229
required: false
schema:
type: string
description: 'Comma separated list of Website UUIDs.'
example: 023c282c-6513-420a-a36b-a654312ab229
-
in: query
name: source
description: 'Comma separated list of Batch sources to filter for (manual, monitoring, auto_update).'
example: 'manual,auto_update'
required: false
schema:
type: string
description: 'Comma separated list of Batch sources to filter for (manual, monitoring, auto_update).'
example: 'manual,auto_update'
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
id: 21cf8800-f906-4fa3-b1db-ed3d2977354d
screenshot_1: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
screenshot_1_created_at: '2025-01-01 13:37:00'
screenshot_1_updated_at: '2025-01-01 13:37:01'
screenshot_1_link: 'https://storage.webchangedetector.com/folder/screenshot1.png'
screenshot_2: 958dce2c-8468-47d3-8bc2-7dc6bf0aadaf
screenshot_2_created_at: '2025-01-01 13:37:00'
screenshot_2_updated_at: '2025-01-01 13:37:01'
screenshot_2_link: 'https://storage.webchangedetector.com/folder/screenshot2.png'
html_title: Foobar
device: mobile
monitoring: true
group: 023c282c-6513-420a-a36b-a654312ab229
group_name: Barfoo
queue: 8ea7b88d-b5c6-4fad-8e9d-1497a54d9266
link: 'https://storage.webchangedetector.com/folder/comparison.png'
batch: 0d5f8108-51f1-4961-939a-2d33c7145918
batch_name: 'Auto Update Checks'
batch_source: monitoring
batch_trigger_type: null
difference_percent: 0.4
threshold: 0.2
status: new
public_link: 'https://www.webchangedetector.com/show-change-detection?token=f00b4r'
token: f00b4r
url: 'https://example.com'
url_id: 418e0748-a9cf-480b-86d6-88b00bac00b9
cms: wordpress
browser_console_added: null
browser_console_removed: null
browser_console_change: null
ai_regions:
-
id: 0
bbox:
x: 120
'y': 340
w: 280
h: 64
pixel_count: 1840
ai_verification_status: verified
ai_verification_result:
capture_issue: null
summary: 'Pricing text updated, may need review.'
processing_time_ms: 1234
total_regions: 1
all_good: 0
not_sure: 0
alerts: 1
regions:
-
region_id: 0
category: alert
description: 'Pricing changed from $9 to $12'
confidence: 0.92
reason: 'Numeric price text changed in hero section'
matched_feedback_rule: null
console_analysis: null
created_at: '2025-01-01 13:37:00'
links:
first: 'http://api.webchangedetector.test/api/v2/comparisons?page=1'
last: 'http://api.webchangedetector.test/api/v2/comparisons?page=1'
prev: null
next: null
meta:
current_page: 1
from: 1
last_page: 1
links:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/comparisons?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
path: 'http://api.webchangedetector.test/api/v2/comparisons'
per_page: 15
to: 1
total: 1
above_threshold_count: 3
properties:
data:
type: array
example:
-
id: 21cf8800-f906-4fa3-b1db-ed3d2977354d
screenshot_1: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
screenshot_1_created_at: '2025-01-01 13:37:00'
screenshot_1_updated_at: '2025-01-01 13:37:01'
screenshot_1_link: 'https://storage.webchangedetector.com/folder/screenshot1.png'
screenshot_2: 958dce2c-8468-47d3-8bc2-7dc6bf0aadaf
screenshot_2_created_at: '2025-01-01 13:37:00'
screenshot_2_updated_at: '2025-01-01 13:37:01'
screenshot_2_link: 'https://storage.webchangedetector.com/folder/screenshot2.png'
html_title: Foobar
device: mobile
monitoring: true
group: 023c282c-6513-420a-a36b-a654312ab229
group_name: Barfoo
queue: 8ea7b88d-b5c6-4fad-8e9d-1497a54d9266
link: 'https://storage.webchangedetector.com/folder/comparison.png'
batch: 0d5f8108-51f1-4961-939a-2d33c7145918
batch_name: 'Auto Update Checks'
batch_source: monitoring
batch_trigger_type: null
difference_percent: 0.4
threshold: 0.2
status: new
public_link: 'https://www.webchangedetector.com/show-change-detection?token=f00b4r'
token: f00b4r
url: 'https://example.com'
url_id: 418e0748-a9cf-480b-86d6-88b00bac00b9
cms: wordpress
browser_console_added: null
browser_console_removed: null
browser_console_change: null
ai_regions:
-
id: 0
bbox:
x: 120
'y': 340
w: 280
h: 64
pixel_count: 1840
ai_verification_status: verified
ai_verification_result:
capture_issue: null
summary: 'Pricing text updated, may need review.'
processing_time_ms: 1234
total_regions: 1
all_good: 0
not_sure: 0
alerts: 1
regions:
-
region_id: 0
category: alert
description: 'Pricing changed from $9 to $12'
confidence: 0.92
reason: 'Numeric price text changed in hero section'
matched_feedback_rule: null
console_analysis: null
created_at: '2025-01-01 13:37:00'
items:
type: object
properties:
id:
type: string
example: 21cf8800-f906-4fa3-b1db-ed3d2977354d
screenshot_1:
type: string
example: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
screenshot_1_created_at:
type: string
example: '2025-01-01 13:37:00'
screenshot_1_updated_at:
type: string
example: '2025-01-01 13:37:01'
screenshot_1_link:
type: string
example: 'https://storage.webchangedetector.com/folder/screenshot1.png'
screenshot_2:
type: string
example: 958dce2c-8468-47d3-8bc2-7dc6bf0aadaf
screenshot_2_created_at:
type: string
example: '2025-01-01 13:37:00'
screenshot_2_updated_at:
type: string
example: '2025-01-01 13:37:01'
screenshot_2_link:
type: string
example: 'https://storage.webchangedetector.com/folder/screenshot2.png'
html_title:
type: string
example: Foobar
device:
type: string
example: mobile
monitoring:
type: boolean
example: true
group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
group_name:
type: string
example: Barfoo
queue:
type: string
example: 8ea7b88d-b5c6-4fad-8e9d-1497a54d9266
link:
type: string
example: 'https://storage.webchangedetector.com/folder/comparison.png'
batch:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
batch_name:
type: string
example: 'Auto Update Checks'
batch_source:
type: string
example: monitoring
batch_trigger_type:
type: string
example: null
nullable: true
difference_percent:
type: number
example: 0.4
threshold:
type: number
example: 0.2
status:
type: string
example: new
public_link:
type: string
example: 'https://www.webchangedetector.com/show-change-detection?token=f00b4r'
token:
type: string
example: f00b4r
url:
type: string
example: 'https://example.com'
url_id:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
cms:
type: string
example: wordpress
browser_console_added:
type: string
example: null
nullable: true
browser_console_removed:
type: string
example: null
nullable: true
browser_console_change:
type: string
example: null
nullable: true
ai_regions:
type: array
example:
-
id: 0
bbox:
x: 120
'y': 340
w: 280
h: 64
pixel_count: 1840
items:
type: object
properties:
id:
type: integer
example: 0
bbox:
type: object
properties:
x:
type: integer
example: 120
'y':
type: integer
example: 340
w:
type: integer
example: 280
h:
type: integer
example: 64
pixel_count:
type: integer
example: 1840
ai_verification_status:
type: string
example: verified
ai_verification_result:
type: object
properties:
capture_issue:
type: string
example: null
nullable: true
summary:
type: string
example: 'Pricing text updated, may need review.'
processing_time_ms:
type: integer
example: 1234
total_regions:
type: integer
example: 1
all_good:
type: integer
example: 0
not_sure:
type: integer
example: 0
alerts:
type: integer
example: 1
regions:
type: array
example:
-
region_id: 0
category: alert
description: 'Pricing changed from $9 to $12'
confidence: 0.92
reason: 'Numeric price text changed in hero section'
matched_feedback_rule: null
items:
type: object
properties:
region_id:
type: integer
example: 0
category:
type: string
example: alert
description:
type: string
example: 'Pricing changed from $9 to $12'
confidence:
type: number
example: 0.92
reason:
type: string
example: 'Numeric price text changed in hero section'
matched_feedback_rule:
type: string
example: null
nullable: true
console_analysis:
type: string
example: null
nullable: true
created_at:
type: string
example: '2025-01-01 13:37:00'
links:
type: object
properties:
first:
type: string
example: 'http://api.webchangedetector.test/api/v2/comparisons?page=1'
last:
type: string
example: 'http://api.webchangedetector.test/api/v2/comparisons?page=1'
prev:
type: string
example: null
nullable: true
next:
type: string
example: null
nullable: true
meta:
type: object
properties:
current_page:
type: integer
example: 1
from:
type: integer
example: 1
last_page:
type: integer
example: 1
links:
type: array
example:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/comparisons?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
items:
type: object
properties:
url:
type: string
example: null
nullable: true
label:
type: string
example: '« Previous'
active:
type: boolean
example: false
path:
type: string
example: 'http://api.webchangedetector.test/api/v2/comparisons'
per_page:
type: integer
example: 15
to:
type: integer
example: 1
total:
type: integer
example: 1
above_threshold_count:
type: integer
example: 3
tags:
- Comparison
'/api/v2/comparisons/{id}':
get:
summary: 'Get Comparison'
operationId: getComparison
description: "Retrieves a `Comparison` object identfied by their ID.\n\n`batch_source` is one of `manual`, `monitoring`, `auto_update`. `batch_trigger_type` is `post_save` (a saved page started the monitoring run), `manual_trigger` (\"run monitoring now\") or `null` (scheduled monitoring and all non-monitoring runs). `browser_console_*` fields are `null` unless the account has the `browser-console-comparisons` feature. `ai_regions`, `ai_verification_status`, and `ai_verification_result` are `null` unless the account has the `ai-verification` feature; `ai_verification_status` is one of `pending`, `verified`, `failed`, `skipped`. A comparison whose before or after screenshot came back as a completely blank page is decided automatically, without AI analysis: it carries an `ai_verification_result` with the marker `capture_issue` (`after_blank`, `before_blank` or `both_blank`), a `summary` and `alerts`, and no `regions`. Only `after_blank` (the page went blank) is an alert: it sets `status = new` and `alerts = 1`. A page recovering (`before_blank`) or staying blank (`both_blank`) is recorded the same way but resolves to `status = ok` with `alerts = 0`, because there is no valid comparison to judge against a blank baseline."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 21cf8800-f906-4fa3-b1db-ed3d2977354d
screenshot_1: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
screenshot_1_created_at: '2025-01-01 13:37:00'
screenshot_1_updated_at: '2025-01-01 13:37:01'
screenshot_1_link: 'https://storage.webchangedetector.com/folder/screenshot1.png'
screenshot_2: 958dce2c-8468-47d3-8bc2-7dc6bf0aadaf
screenshot_2_created_at: '2025-01-01 13:37:00'
screenshot_2_updated_at: '2025-01-01 13:37:01'
screenshot_2_link: 'https://storage.webchangedetector.com/folder/screenshot2.png'
html_title: Foobar
device: mobile
monitoring: true
group: 023c282c-6513-420a-a36b-a654312ab229
group_name: Barfoo
queue: 8ea7b88d-b5c6-4fad-8e9d-1497a54d9266
link: 'https://storage.webchangedetector.com/folder/comparison.png'
batch: 0d5f8108-51f1-4961-939a-2d33c7145918
batch_name: 'Auto Update Checks'
batch_source: monitoring
batch_trigger_type: null
difference_percent: 0.4
threshold: 0.2
status: new
public_link: 'https://www.webchangedetector.com/show-change-detection?token=f00b4r'
token: f00b4r
url: 'https://example.com'
url_id: 418e0748-a9cf-480b-86d6-88b00bac00b9
cms: wordpress
browser_console_added: null
browser_console_removed: null
browser_console_change: null
ai_regions:
-
id: 0
bbox:
x: 120
'y': 340
w: 280
h: 64
pixel_count: 1840
ai_verification_status: verified
ai_verification_result:
capture_issue: null
summary: 'Pricing text updated, may need review.'
processing_time_ms: 1234
total_regions: 1
all_good: 0
not_sure: 0
alerts: 1
regions:
-
region_id: 0
category: alert
description: 'Pricing changed from $9 to $12'
confidence: 0.92
reason: 'Numeric price text changed in hero section'
matched_feedback_rule: null
console_analysis: null
created_at: '2025-01-01 13:37:00'
properties:
data:
type: object
properties:
id:
type: string
example: 21cf8800-f906-4fa3-b1db-ed3d2977354d
screenshot_1:
type: string
example: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
screenshot_1_created_at:
type: string
example: '2025-01-01 13:37:00'
screenshot_1_updated_at:
type: string
example: '2025-01-01 13:37:01'
screenshot_1_link:
type: string
example: 'https://storage.webchangedetector.com/folder/screenshot1.png'
screenshot_2:
type: string
example: 958dce2c-8468-47d3-8bc2-7dc6bf0aadaf
screenshot_2_created_at:
type: string
example: '2025-01-01 13:37:00'
screenshot_2_updated_at:
type: string
example: '2025-01-01 13:37:01'
screenshot_2_link:
type: string
example: 'https://storage.webchangedetector.com/folder/screenshot2.png'
html_title:
type: string
example: Foobar
device:
type: string
example: mobile
monitoring:
type: boolean
example: true
group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
group_name:
type: string
example: Barfoo
queue:
type: string
example: 8ea7b88d-b5c6-4fad-8e9d-1497a54d9266
link:
type: string
example: 'https://storage.webchangedetector.com/folder/comparison.png'
batch:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
batch_name:
type: string
example: 'Auto Update Checks'
batch_source:
type: string
example: monitoring
batch_trigger_type:
type: string
example: null
nullable: true
difference_percent:
type: number
example: 0.4
threshold:
type: number
example: 0.2
status:
type: string
example: new
public_link:
type: string
example: 'https://www.webchangedetector.com/show-change-detection?token=f00b4r'
token:
type: string
example: f00b4r
url:
type: string
example: 'https://example.com'
url_id:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
cms:
type: string
example: wordpress
browser_console_added:
type: string
example: null
nullable: true
browser_console_removed:
type: string
example: null
nullable: true
browser_console_change:
type: string
example: null
nullable: true
ai_regions:
type: array
example:
-
id: 0
bbox:
x: 120
'y': 340
w: 280
h: 64
pixel_count: 1840
items:
type: object
properties:
id:
type: integer
example: 0
bbox:
type: object
properties:
x:
type: integer
example: 120
'y':
type: integer
example: 340
w:
type: integer
example: 280
h:
type: integer
example: 64
pixel_count:
type: integer
example: 1840
ai_verification_status:
type: string
example: verified
ai_verification_result:
type: object
properties:
capture_issue:
type: string
example: null
nullable: true
summary:
type: string
example: 'Pricing text updated, may need review.'
processing_time_ms:
type: integer
example: 1234
total_regions:
type: integer
example: 1
all_good:
type: integer
example: 0
not_sure:
type: integer
example: 0
alerts:
type: integer
example: 1
regions:
type: array
example:
-
region_id: 0
category: alert
description: 'Pricing changed from $9 to $12'
confidence: 0.92
reason: 'Numeric price text changed in hero section'
matched_feedback_rule: null
items:
type: object
properties:
region_id:
type: integer
example: 0
category:
type: string
example: alert
description:
type: string
example: 'Pricing changed from $9 to $12'
confidence:
type: number
example: 0.92
reason:
type: string
example: 'Numeric price text changed in hero section'
matched_feedback_rule:
type: string
example: null
nullable: true
console_analysis:
type: string
example: null
nullable: true
created_at:
type: string
example: '2025-01-01 13:37:00'
tags:
- Comparison
put:
summary: 'Update Comparison'
operationId: updateComparison
description: "Updates the specified `Comparison` by setting the values of the parameters passed.\nAny parameters not provided will be left unchanged.\n\n`batch_source` is one of `manual`, `monitoring`, `auto_update`. `batch_trigger_type` is `post_save` (a saved page started the monitoring run), `manual_trigger` (\"run monitoring now\") or `null` (scheduled monitoring and all non-monitoring runs). `browser_console_*` fields are `null` unless the account has the `browser-console-comparisons` feature. `ai_regions`, `ai_verification_status`, and `ai_verification_result` are `null` unless the account has the `ai-verification` feature; `ai_verification_status` is one of `pending`, `verified`, `failed`, `skipped`. A comparison whose before or after screenshot came back as a completely blank page is decided automatically, without AI analysis: it carries an `ai_verification_result` with the marker `capture_issue` (`after_blank`, `before_blank` or `both_blank`), a `summary` and `alerts`, and no `regions`. Only `after_blank` (the page went blank) is an alert: it sets `status = new` and `alerts = 1`. A page recovering (`before_blank`) or staying blank (`both_blank`) is recorded the same way but resolves to `status = ok` with `alerts = 0`, because there is no valid comparison to judge against a blank baseline."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
id: 21cf8800-f906-4fa3-b1db-ed3d2977354d
screenshot_1: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
screenshot_1_created_at: '2025-01-01 13:37:00'
screenshot_1_updated_at: '2025-01-01 13:37:01'
screenshot_1_link: 'https://storage.webchangedetector.com/folder/screenshot1.png'
screenshot_2: 958dce2c-8468-47d3-8bc2-7dc6bf0aadaf
screenshot_2_created_at: '2025-01-01 13:37:00'
screenshot_2_updated_at: '2025-01-01 13:37:01'
screenshot_2_link: 'https://storage.webchangedetector.com/folder/screenshot2.png'
html_title: Foobar
device: mobile
monitoring: true
group: 023c282c-6513-420a-a36b-a654312ab229
group_name: Barfoo
queue: 8ea7b88d-b5c6-4fad-8e9d-1497a54d9266
link: 'https://storage.webchangedetector.com/folder/comparison.png'
batch: 0d5f8108-51f1-4961-939a-2d33c7145918
batch_name: 'Auto Update Checks'
batch_source: monitoring
batch_trigger_type: null
difference_percent: 0.4
threshold: 0.2
status: new
public_link: 'https://www.webchangedetector.com/show-change-detection?token=f00b4r'
token: f00b4r
url: 'https://example.com'
url_id: 418e0748-a9cf-480b-86d6-88b00bac00b9
cms: wordpress
browser_console_added: null
browser_console_removed: null
browser_console_change: null
ai_regions:
-
id: 0
bbox:
x: 120
'y': 340
w: 280
h: 64
pixel_count: 1840
ai_verification_status: verified
ai_verification_result:
capture_issue: null
summary: 'Pricing text updated, may need review.'
processing_time_ms: 1234
total_regions: 1
all_good: 0
not_sure: 0
alerts: 1
regions:
-
region_id: 0
category: alert
description: 'Pricing changed from $9 to $12'
confidence: 0.92
reason: 'Numeric price text changed in hero section'
matched_feedback_rule: null
console_analysis: null
created_at: '2025-01-01 13:37:00'
properties:
id:
type: string
example: 21cf8800-f906-4fa3-b1db-ed3d2977354d
screenshot_1:
type: string
example: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
screenshot_1_created_at:
type: string
example: '2025-01-01 13:37:00'
screenshot_1_updated_at:
type: string
example: '2025-01-01 13:37:01'
screenshot_1_link:
type: string
example: 'https://storage.webchangedetector.com/folder/screenshot1.png'
screenshot_2:
type: string
example: 958dce2c-8468-47d3-8bc2-7dc6bf0aadaf
screenshot_2_created_at:
type: string
example: '2025-01-01 13:37:00'
screenshot_2_updated_at:
type: string
example: '2025-01-01 13:37:01'
screenshot_2_link:
type: string
example: 'https://storage.webchangedetector.com/folder/screenshot2.png'
html_title:
type: string
example: Foobar
device:
type: string
example: mobile
monitoring:
type: boolean
example: true
group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
group_name:
type: string
example: Barfoo
queue:
type: string
example: 8ea7b88d-b5c6-4fad-8e9d-1497a54d9266
link:
type: string
example: 'https://storage.webchangedetector.com/folder/comparison.png'
batch:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
batch_name:
type: string
example: 'Auto Update Checks'
batch_source:
type: string
example: monitoring
batch_trigger_type:
type: string
example: null
nullable: true
difference_percent:
type: number
example: 0.4
threshold:
type: number
example: 0.2
status:
type: string
example: new
public_link:
type: string
example: 'https://www.webchangedetector.com/show-change-detection?token=f00b4r'
token:
type: string
example: f00b4r
url:
type: string
example: 'https://example.com'
url_id:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
cms:
type: string
example: wordpress
browser_console_added:
type: string
example: null
nullable: true
browser_console_removed:
type: string
example: null
nullable: true
browser_console_change:
type: string
example: null
nullable: true
ai_regions:
type: array
example:
-
id: 0
bbox:
x: 120
'y': 340
w: 280
h: 64
pixel_count: 1840
items:
type: object
properties:
id:
type: integer
example: 0
bbox:
type: object
properties:
x:
type: integer
example: 120
'y':
type: integer
example: 340
w:
type: integer
example: 280
h:
type: integer
example: 64
pixel_count:
type: integer
example: 1840
ai_verification_status:
type: string
example: verified
ai_verification_result:
type: object
properties:
capture_issue:
type: string
example: null
nullable: true
summary:
type: string
example: 'Pricing text updated, may need review.'
processing_time_ms:
type: integer
example: 1234
total_regions:
type: integer
example: 1
all_good:
type: integer
example: 0
not_sure:
type: integer
example: 0
alerts:
type: integer
example: 1
regions:
type: array
example:
-
region_id: 0
category: alert
description: 'Pricing changed from $9 to $12'
confidence: 0.92
reason: 'Numeric price text changed in hero section'
matched_feedback_rule: null
items:
type: object
properties:
region_id:
type: integer
example: 0
category:
type: string
example: alert
description:
type: string
example: 'Pricing changed from $9 to $12'
confidence:
type: number
example: 0.92
reason:
type: string
example: 'Numeric price text changed in hero section'
matched_feedback_rule:
type: string
example: null
nullable: true
console_analysis:
type: string
example: null
nullable: true
created_at:
type: string
example: '2025-01-01 13:37:00'
tags:
- Comparison
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
status:
type: string
description: 'Mark the comparison as a false positive, as fixed or simply ok.'
example: false_positive
enum:
- false_positive
- ok
- to_fix
required:
- status
parameters:
-
in: path
name: id
description: 'The ID of the Comparison.'
example: 21cf8800-f906-4fa3-b1db-ed3d2977354d
required: true
schema:
type: string
/api/v2/groups:
get:
summary: 'List Groups'
operationId: listGroups
description: "Returns a list of all Groups. The Groups are sorted by creation date, with\nthe most recent Groups appearing first."
parameters:
-
in: query
name: per_page
description: 'Maximum number of Groups per page.'
example: 15
required: false
schema:
type: integer
description: 'Maximum number of Groups per page.'
example: 15
-
in: query
name: monitoring
description: 'Filter to monitoring (`true`) or manual-checks (`false`) groups only. Omit to return both.'
example: true
required: false
schema:
type: boolean
description: 'Filter to monitoring (`true`) or manual-checks (`false`) groups only. Omit to return both.'
example: true
-
in: query
name: ids
description: ''
example:
- autem
required: false
schema:
type: array
description: ''
example:
- autem
items:
type: string
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
id: 023c282c-6513-420a-a36b-a654312ab229
name: 'Example Group'
monitoring: true
enabled: true
hour_of_day: 0
interval_in_h: 24
alert_emails: 'hello@example.com,test@foobar.com'
css: null
js: null
cms: wordpress
threshold: 0.2
urls_count: 42
selected_urls_count: 37
basic_auth_user: null
has_basic_auth: false
proxy_type: none
proxy_country: us
links:
first: 'http://api.webchangedetector.test/api/v2/groups?page=1'
last: 'http://api.webchangedetector.test/api/v2/groups?page=1'
prev: null
next: null
meta:
current_page: 1
from: 1
last_page: 1
links:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/groups?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
path: 'http://api.webchangedetector.test/api/v2/groups'
per_page: 15
to: 1
total: 1
properties:
data:
type: array
example:
-
id: 023c282c-6513-420a-a36b-a654312ab229
name: 'Example Group'
monitoring: true
enabled: true
hour_of_day: 0
interval_in_h: 24
alert_emails: 'hello@example.com,test@foobar.com'
css: null
js: null
cms: wordpress
threshold: 0.2
urls_count: 42
selected_urls_count: 37
basic_auth_user: null
has_basic_auth: false
proxy_type: none
proxy_country: us
items:
type: object
properties:
id:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
name:
type: string
example: 'Example Group'
monitoring:
type: boolean
example: true
enabled:
type: boolean
example: true
hour_of_day:
type: integer
example: 0
interval_in_h:
type: integer
example: 24
alert_emails:
type: string
example: 'hello@example.com,test@foobar.com'
css:
type: string
example: null
nullable: true
js:
type: string
example: null
nullable: true
cms:
type: string
example: wordpress
threshold:
type: number
example: 0.2
urls_count:
type: integer
example: 42
selected_urls_count:
type: integer
example: 37
basic_auth_user:
type: string
example: null
nullable: true
has_basic_auth:
type: boolean
example: false
proxy_type:
type: string
example: none
proxy_country:
type: string
example: us
links:
type: object
properties:
first:
type: string
example: 'http://api.webchangedetector.test/api/v2/groups?page=1'
last:
type: string
example: 'http://api.webchangedetector.test/api/v2/groups?page=1'
prev:
type: string
example: null
nullable: true
next:
type: string
example: null
nullable: true
meta:
type: object
properties:
current_page:
type: integer
example: 1
from:
type: integer
example: 1
last_page:
type: integer
example: 1
links:
type: array
example:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/groups?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
items:
type: object
properties:
url:
type: string
example: null
nullable: true
label:
type: string
example: '« Previous'
active:
type: boolean
example: false
path:
type: string
example: 'http://api.webchangedetector.test/api/v2/groups'
per_page:
type: integer
example: 15
to:
type: integer
example: 1
total:
type: integer
example: 1
tags:
- Group
post:
summary: 'Create Group'
operationId: createGroup
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 023c282c-6513-420a-a36b-a654312ab229
name: 'Example Group'
monitoring: true
enabled: true
hour_of_day: 0
interval_in_h: 24
schedule_type: interval
schedule_days: null
quiet_hours_start: null
quiet_hours_end: null
triggers: []
alert_emails: 'hello@example.com,test@foobar.com'
css: '.btn {visibility: none;}'
js: ''
cms: wordpress
threshold: 0.2
urls_count: 42
selected_urls_count: 37
basic_auth_user: null
has_basic_auth: false
proxy_type: none
proxy_country: us
properties:
data:
type: object
properties:
id:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
name:
type: string
example: 'Example Group'
monitoring:
type: boolean
example: true
enabled:
type: boolean
example: true
hour_of_day:
type: integer
example: 0
interval_in_h:
type: integer
example: 24
schedule_type:
type: string
example: interval
schedule_days:
type: string
example: null
nullable: true
quiet_hours_start:
type: string
example: null
nullable: true
quiet_hours_end:
type: string
example: null
nullable: true
triggers:
type: array
example: []
alert_emails:
type: string
example: 'hello@example.com,test@foobar.com'
css:
type: string
example: '.btn {visibility: none;}'
js:
type: string
example: ''
cms:
type: string
example: wordpress
threshold:
type: number
example: 0.2
urls_count:
type: integer
example: 42
selected_urls_count:
type: integer
example: 37
basic_auth_user:
type: string
example: null
nullable: true
has_basic_auth:
type: boolean
example: false
proxy_type:
type: string
example: none
proxy_country:
type: string
example: us
tags:
- Group
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'Name of the Group.'
example: 'Example Group'
monitoring:
type: boolean
description: 'Defaults to false.'
example: true
enum:
- 'true'
- 'false'
enabled:
type: boolean
description: 'Defaults to true.'
example: true
enum:
- 'true'
- 'false'
hour_of_day:
type: integer
description: 'Which hour of the day are the auto updates executed. Defaults to 0'
example: 0
interval_in_h:
type: number
description: 'One of the following intervals of the hour. Defaults to 24'
example: 24
enum:
- 0.25
- 0.5
- 3
- 6
- 12
- 24
schedule_type:
type: string
description: 'Schedule type: interval (default), weekly, monthly, or off (no scheduled runs, only triggers)'
example: interval
enum:
- interval
- weekly
- monthly
- 'off'
schedule_days:
type: array
description: 'Days for weekly (1=Mon..7=Sun) or monthly (1-30 or "last") schedules'
example:
- 1
- 3
- 5
items:
type: string
quiet_hours_start:
type: integer
description: 'Hour (0-23) when quiet period starts. No checks during quiet hours.'
example: 22
quiet_hours_end:
type: integer
description: 'Hour (0-23) when quiet period ends'
example: 6
alert_emails:
type: array
description: 'A list of emails to notify. Defaults to the account email.'
example:
- hello@example.com
- mail@example.com
items:
type: string
cms:
type: string
description: 'Optional CMS hint used by the screenshot pipeline (e.g. `wordpress`). Allowed values: see `config/enums.cms`.'
example: wordpress
enum:
- wordpress
nullable: true
basic_auth_user:
type: string
description: 'Username for HTTP Basic Authentication'
example: admin
basic_auth_password:
type: string
description: 'Password for HTTP Basic Authentication'
example: secret123
proxy_type:
type: string
description: 'Proxy type to use for screenshots'
example: none
enum:
- none
- static
- residential
proxy_country:
type: string
description: 'Location code for residential proxy (2-letter). Defaults to the screenshot region when unset; reserved for future country-specific proxies.'
example: enim
screenshot_region:
type: string
description: "Region this group's screenshots are taken from. `auto` (default) auto-geolocates the target domain to the nearest region, then stores the resolved concrete value back in this field. `us`/`eu` pin the region explicitly (`eu` renders from an EU IP with lower latency for EU sites). Reading this field returns `auto` transiently right after create, then the resolved `us`/`eu`. Allowed values: see `config/enums.screenshot_region`."
example: auto
enum:
- us
- eu
- auto
screenshot_delay:
type: integer
description: 'Minimum seconds between consecutive screenshot dispatches for this group, per user (7-60). Higher values reduce load on the screenshoter and target site, useful for groups with many URLs. Must be at least 7. Must not be greater than 60.'
example: 10
nullable: true
default_desktop:
type: boolean
description: 'Activate newly synced URLs for desktop screenshots by default in this group. Applied only to URLs the next sync first assigns; existing assignments keep their flags.'
example: false
default_mobile:
type: boolean
description: 'Activate newly synced URLs for mobile screenshots by default in this group. Applied only to URLs the next sync first assigns; existing assignments keep their flags.'
example: false
triggers:
type: array
description: 'Events that start a monitoring check in addition to the schedule, e.g. saving a post in WordPress. Objects with `type` (post_save) and optional `scope` (url). Monitoring groups only.'
example:
-
type: post_save
scope: url
items:
type: object
properties:
type:
type: string
description: ''
example: post_save
enum:
- post_save
scope:
type: string
description: 'What the trigger checks: `url` = only the reported URLs. Defaults to `url`.'
example: url
enum:
- url
required:
- type
css:
type: string
description: 'CSS to be injected before the screenshot is taken for all URLs in this group'
example: '.btn {visibility: none;}'
js:
type: string
description: 'JavaScript to be injected before the screenshot is taken for all URLs in this group'
example: ''
threshold:
type: numeric
description: 'Difference in percent of when this counts as a change detection for all URLs in this group'
example: 0.4
required:
- name
'/api/v2/groups/{id}':
get:
summary: 'Get Group'
operationId: getGroup
description: 'Retrieves a Group object identfied by their ID'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 023c282c-6513-420a-a36b-a654312ab229
name: 'Example Group'
monitoring: true
enabled: true
hour_of_day: 0
interval_in_h: 24
alert_emails: 'hello@example.com,test@foobar.com'
css: null
js: null
cms: wordpress
threshold: 0.2
urls_count: 42
selected_urls_count: 37
basic_auth_user: null
has_basic_auth: false
proxy_type: none
proxy_country: us
properties:
data:
type: object
properties:
id:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
name:
type: string
example: 'Example Group'
monitoring:
type: boolean
example: true
enabled:
type: boolean
example: true
hour_of_day:
type: integer
example: 0
interval_in_h:
type: integer
example: 24
alert_emails:
type: string
example: 'hello@example.com,test@foobar.com'
css:
type: string
example: null
nullable: true
js:
type: string
example: null
nullable: true
cms:
type: string
example: wordpress
threshold:
type: number
example: 0.2
urls_count:
type: integer
example: 42
selected_urls_count:
type: integer
example: 37
basic_auth_user:
type: string
example: null
nullable: true
has_basic_auth:
type: boolean
example: false
proxy_type:
type: string
example: none
proxy_country:
type: string
example: us
tags:
- Group
put:
summary: 'Update Group'
operationId: updateGroup
description: "Updates the specified `Group` by setting the values of the parameters passed.\nAny parameters not provided will be left unchanged."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 023c282c-6513-420a-a36b-a654312ab229
name: 'Example Group'
monitoring: true
enabled: true
hour_of_day: 0
interval_in_h: 24
schedule_type: interval
schedule_days: null
quiet_hours_start: null
quiet_hours_end: null
triggers: []
alert_emails: 'hello@example.com,test@foobar.com'
css: '.btn {visibility: none;}'
js: ''
cms: wordpress
threshold: 0.2
urls_count: 42
selected_urls_count: 37
basic_auth_user: admin
has_basic_auth: true
proxy_type: static
proxy_country: us
properties:
data:
type: object
properties:
id:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
name:
type: string
example: 'Example Group'
monitoring:
type: boolean
example: true
enabled:
type: boolean
example: true
hour_of_day:
type: integer
example: 0
interval_in_h:
type: integer
example: 24
schedule_type:
type: string
example: interval
schedule_days:
type: string
example: null
nullable: true
quiet_hours_start:
type: string
example: null
nullable: true
quiet_hours_end:
type: string
example: null
nullable: true
triggers:
type: array
example: []
alert_emails:
type: string
example: 'hello@example.com,test@foobar.com'
css:
type: string
example: '.btn {visibility: none;}'
js:
type: string
example: ''
cms:
type: string
example: wordpress
threshold:
type: number
example: 0.2
urls_count:
type: integer
example: 42
selected_urls_count:
type: integer
example: 37
basic_auth_user:
type: string
example: admin
has_basic_auth:
type: boolean
example: true
proxy_type:
type: string
example: static
proxy_country:
type: string
example: us
tags:
- Group
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
name:
type: string
description: 'Name of the Group.'
example: 'Example Group'
monitoring:
type: boolean
description: 'Defaults to false.'
example: true
enum:
- 'true'
- 'false'
enabled:
type: boolean
description: 'Defaults to true.'
example: true
enum:
- 'true'
- 'false'
hour_of_day:
type: integer
description: 'Which hour of the day are the auto updates executed. Defaults to 0'
example: 0
interval_in_h:
type: number
description: 'One of the following intervals of the hour. Defaults to 24'
example: 24
enum:
- 0.25
- 0.5
- 3
- 6
- 12
- 24
schedule_type:
type: string
description: 'Schedule type: interval (default), weekly, monthly, or off (no scheduled runs, only triggers)'
example: interval
enum:
- interval
- weekly
- monthly
- 'off'
schedule_days:
type: array
description: 'Days for weekly (1=Mon..7=Sun) or monthly (1-30 or "last") schedules'
example:
- 1
- 3
- 5
items:
type: string
quiet_hours_start:
type: integer
description: 'Hour (0-23) when quiet period starts. No checks during quiet hours.'
example: 22
quiet_hours_end:
type: integer
description: 'Hour (0-23) when quiet period ends'
example: 6
alert_emails:
type: array
description: 'A list of emails to notify. Defaults to the account email.'
example:
- hello@example.com
- mail@example.com
items:
type: string
css:
type: string
description: 'CSS to be injected before the screenshot is taken for all URLs in this group'
example: '.btn {visibility: none;}'
js:
type: string
description: 'JavaScript to be injected before the screenshot is taken for all URLs in this group'
example: ''
threshold:
type: numeric
description: 'Difference in percent of when this counts as a change detection for all URLs in this group'
example: 0.4
basic_auth_user:
type: string
description: 'Username for HTTP Basic Authentication'
example: admin
basic_auth_password:
type: string
description: 'Password for HTTP Basic Authentication'
example: secret123
proxy_type:
type: string
description: 'Proxy type to use for screenshots'
example: none
enum:
- none
- static
- residential
proxy_country:
type: string
description: 'Location code for residential proxy (2-letter). Defaults to the screenshot region when unset; reserved for future country-specific proxies.'
example: facilis
screenshot_region:
type: string
description: "Region this group's screenshots are taken from. `auto` (default) auto-geolocates the target domain to the nearest region, then stores the resolved concrete value back in this field. `us`/`eu` pin the region explicitly (`eu` renders from an EU IP with lower latency for EU sites). Setting `auto` re-triggers detection; the API mirrors any region change onto the website's sibling detection group automatically. Allowed values: see `config/enums.screenshot_region`."
example: auto
enum:
- us
- eu
- auto
screenshot_delay:
type: integer
description: 'Minimum seconds between consecutive screenshot dispatches for this group, per user (7-60). Higher values reduce load on the screenshoter and target site, useful for groups with many URLs. Must be at least 7. Must not be greater than 60.'
example: 10
nullable: true
default_desktop:
type: boolean
description: 'Activate newly synced URLs for desktop screenshots by default in this group. Applied only to URLs the next sync first assigns; existing assignments keep their flags.'
example: false
default_mobile:
type: boolean
description: 'Activate newly synced URLs for mobile screenshots by default in this group. Applied only to URLs the next sync first assigns; existing assignments keep their flags.'
example: false
triggers:
type: array
description: 'Events that start a monitoring check in addition to the schedule, e.g. saving a post in WordPress. Objects with `type` (post_save) and optional `scope` (url). Monitoring groups only.'
example:
-
type: post_save
scope: url
items:
type: object
properties:
type:
type: string
description: ''
example: post_save
enum:
- post_save
scope:
type: string
description: 'What the trigger checks: `url` = only the reported URLs. Defaults to `url`.'
example: url
enum:
- url
required:
- type
delete:
summary: 'Delete Group'
operationId: deleteGroup
description: "Permanently deletes a `Group`. This cannot be undone.\n"
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: '{ID} deleted'
properties:
message:
type: string
example: '{ID} deleted'
tags:
- Group
parameters:
-
in: path
name: id
description: 'The ID of the Group.'
example: 023c282c-6513-420a-a36b-a654312ab229
required: true
schema:
type: string
'/api/v2/groups/{id}/add-urls':
post:
summary: 'Add Urls To Group'
operationId: addUrlsToGroup
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
count: '{Amount of URLs added}'
properties:
count:
type: string
example: '{Amount of URLs added}'
tags:
- Group
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
urls:
type: array
description: 'Array of URLs with their settings in this Group'
example:
-
id: 418e0748-a9cf-480b-86d6-88b00bac00b9
desktop: true
-
id: 418e0748-a9cf-480b-86d6-88b00bac00c1
mobile: false
items:
type: string
required:
- urls
parameters:
-
in: path
name: id
description: 'The ID of the Group.'
example: 023c282c-6513-420a-a36b-a654312ab229
required: true
schema:
type: string
'/api/v2/groups/{id}/remove-urls':
post:
summary: 'Remove Urls From Group'
operationId: removeUrlsFromGroup
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
count: '{Amount of URLs removed}'
properties:
count:
type: string
example: '{Amount of URLs removed}'
tags:
- Group
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
urls:
type: array
description: 'Array of URL IDs'
example:
- 418e0748-a9cf-480b-86d6-88b00bac00b9
- 418e0748-a9cf-480b-86d6-88b00bac00c1
items:
type: string
required:
- urls
parameters:
-
in: path
name: id
description: 'The ID of the Group.'
example: 023c282c-6513-420a-a36b-a654312ab229
required: true
schema:
type: string
'/api/v2/groups/{id}/urls':
get:
summary: 'List Urls For Group'
operationId: listUrlsForGroup
description: 'Returns a list of all `Urls`. The `Urls` are sorted by creation date, with the most recent `Urls` appearing first.'
parameters:
-
in: query
name: per_page
description: 'Maximum number of URLs per page.'
example: 25
required: false
schema:
type: integer
description: 'Maximum number of URLs per page.'
example: 25
-
in: query
name: type
description: 'Filter by post-type slug (e.g. `posts`, `pages`, `products`).'
example: posts
required: false
schema:
type: string
description: 'Filter by post-type slug (e.g. `posts`, `pages`, `products`).'
example: posts
-
in: query
name: category
description: 'Filter by URL category (e.g. `types`, `taxonomies`, `frontpage`).'
example: types
required: false
schema:
type: string
description: 'Filter by URL category (e.g. `types`, `taxonomies`, `frontpage`).'
example: types
-
in: query
name: search
description: 'Substring match against the URL or its title.'
example: about
required: false
schema:
type: string
description: 'Substring match against the URL or its title.'
example: about
-
in: query
name: url_ids
description: 'Comma-separated list of URL UUIDs to restrict the result to.'
example: '91e9c9fd-b86f-4269-a3f4-f02810167a6d,b3a9d2e5-2c64-4a16-8f1c-9e3b21f8a4e7'
required: false
schema:
type: string
description: 'Comma-separated list of URL UUIDs to restrict the result to.'
example: '91e9c9fd-b86f-4269-a3f4-f02810167a6d,b3a9d2e5-2c64-4a16-8f1c-9e3b21f8a4e7'
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
id: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title: 'Example Title'
url: example.com/foobar
last_crawled_at: '2025-01-01 13:37:42'
desktop: true
mobile: true
css: null
js: null
threshold: null
group: 023c282c-6513-420a-a36b-a654312ab229
links:
first: 'http://api.webchangedetector.test/api/v2/groups/023c282c-6513-420a-a36b-a654312ab229/urls?page=1'
last: 'http://api.webchangedetector.test/api/v2/groups/023c282c-6513-420a-a36b-a654312ab229/urls?page=1'
prev: null
next: null
meta:
current_page: 1
from: 1
last_page: 1
links:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/groups/023c282c-6513-420a-a36b-a654312ab229/urls?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
path: 'http://api.webchangedetector.test/api/v2/groups/023c282c-6513-420a-a36b-a654312ab229/urls'
per_page: 15
to: 1
total: 1
selected_urls_count: 1
properties:
data:
type: array
example:
-
id: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title: 'Example Title'
url: example.com/foobar
last_crawled_at: '2025-01-01 13:37:42'
desktop: true
mobile: true
css: null
js: null
threshold: null
group: 023c282c-6513-420a-a36b-a654312ab229
items:
type: object
properties:
id:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title:
type: string
example: 'Example Title'
url:
type: string
example: example.com/foobar
last_crawled_at:
type: string
example: '2025-01-01 13:37:42'
desktop:
type: boolean
example: true
mobile:
type: boolean
example: true
css:
type: string
example: null
nullable: true
js:
type: string
example: null
nullable: true
threshold:
type: string
example: null
nullable: true
group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
links:
type: object
properties:
first:
type: string
example: 'http://api.webchangedetector.test/api/v2/groups/023c282c-6513-420a-a36b-a654312ab229/urls?page=1'
last:
type: string
example: 'http://api.webchangedetector.test/api/v2/groups/023c282c-6513-420a-a36b-a654312ab229/urls?page=1'
prev:
type: string
example: null
nullable: true
next:
type: string
example: null
nullable: true
meta:
type: object
properties:
current_page:
type: integer
example: 1
from:
type: integer
example: 1
last_page:
type: integer
example: 1
links:
type: array
example:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/groups/023c282c-6513-420a-a36b-a654312ab229/urls?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
items:
type: object
properties:
url:
type: string
example: null
nullable: true
label:
type: string
example: '« Previous'
active:
type: boolean
example: false
path:
type: string
example: 'http://api.webchangedetector.test/api/v2/groups/023c282c-6513-420a-a36b-a654312ab229/urls'
per_page:
type: integer
example: 15
to:
type: integer
example: 1
total:
type: integer
example: 1
selected_urls_count:
type: integer
example: 1
tags:
- Group
parameters:
-
in: path
name: id
description: 'The ID of the Group.'
example: 023c282c-6513-420a-a36b-a654312ab229
required: true
schema:
type: string
-
in: path
name: type
description: 'URL Type.'
example: foobar
required: true
schema:
type: string
-
in: path
name: category
description: Category.
example: barfoo
required: true
schema:
type: string
-
in: path
name: search
description: 'Search in html_title and url.'
example: loremipsum
required: true
schema:
type: string
-
in: path
name: url_ids
description: 'Comma separated list of URL UUIDs'
example: eos
required: true
schema:
type: string
'/api/v2/groups/{group_id}/urls/select-all':
put:
summary: 'Select All Urls In Group'
operationId: selectAllUrlsInGroup
description: "Enables or disables one viewport (desktop or mobile) for ALL URLs of a group in a single\noperation. Use this instead of sending thousands of individual URL ids when toggling a whole\ncolumn (\"select all\" / \"deselect all\"). Only the given device column changes; the other viewport\nis left untouched."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'All desktop URLs in Group 023c282c-6513-420a-a36b-a654312ab229 updated'
selected_urls_count: 42
selected_checks_count: 80
properties:
message:
type: string
example: 'All desktop URLs in Group 023c282c-6513-420a-a36b-a654312ab229 updated'
selected_urls_count:
type: integer
example: 42
selected_checks_count:
type: integer
example: 80
tags:
- Group
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
device:
type: string
description: 'Which viewport to toggle for every URL.'
example: desktop
enum:
- desktop
- mobile
enabled:
type: boolean
description: 'Whether screenshots of that viewport should be taken.'
example: true
enum:
- 'true'
- 'false'
required:
- device
- enabled
parameters:
-
in: path
name: group_id
description: 'The ID of the Group.'
example: 023c282c-6513-420a-a36b-a654312ab229
required: true
schema:
type: string
'/api/v2/groups/{group_id}/urls/{url_id}':
put:
summary: 'Update Url In Group'
operationId: updateUrlInGroup
description: 'Updates a URL within a group.'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title: 'Example Title'
url: example.com/foobar
last_crawled_at: '2025-01-01 13:37:42'
desktop: true
mobile: true
css: '.btn {visibility: none;}'
js: null
threshold: null
group: 023c282c-6513-420a-a36b-a654312ab229
meta:
selected_urls_count: 1
properties:
data:
type: object
properties:
id:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title:
type: string
example: 'Example Title'
url:
type: string
example: example.com/foobar
last_crawled_at:
type: string
example: '2025-01-01 13:37:42'
desktop:
type: boolean
example: true
mobile:
type: boolean
example: true
css:
type: string
example: '.btn {visibility: none;}'
js:
type: string
example: null
nullable: true
threshold:
type: string
example: null
nullable: true
group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
meta:
type: object
properties:
selected_urls_count:
type: integer
example: 1
tags:
- Group
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
desktop:
type: boolean
description: 'Should a desktop screenshot be taken'
example: true
enum:
- 'true'
- 'false'
mobile:
type: boolean
description: 'Should a mobile screenshot be taken'
example: true
enum:
- 'true'
- 'false'
css:
type: string
description: 'CSS to be injected before the screenshot is taken'
example: '.btn {visibility: none;}'
js:
type: string
description: 'JavaScript to be injected before the screenshot is taken'
example: illum
threshold:
type: numeric
description: 'Difference in percent of when this counts as a change detection'
example: 0.4
parameters:
-
in: path
name: group_id
description: 'The ID of the Group.'
example: 023c282c-6513-420a-a36b-a654312ab229
required: true
schema:
type: string
-
in: path
name: url_id
description: 'The ID of the URL in that Group.'
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
required: true
schema:
type: string
'/api/v2/groups/{group_id}/urls':
put:
summary: 'Update All Urls In Group'
operationId: updateAllUrlsInGroup
description: 'Updates all URLs within a group.'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: '42 URLs in Group 023c282c-6513-420a-a36b-a654312ab229 changed'
properties:
message:
type: string
example: '42 URLs in Group 023c282c-6513-420a-a36b-a654312ab229 changed'
tags:
- Group
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
urls:
type: array
description: 'Array of URLs with settings'
example:
-
id: 418e0748-a9cf-480b-86d6-88b00bac00b9
desktop: true
mobile: true
css: null
js: null
threshold: 0.4
items:
type: string
parameters:
-
in: path
name: group_id
description: 'The ID of the Group.'
example: 023c282c-6513-420a-a36b-a654312ab229
required: true
schema:
type: string
/api/v2/monitoring/trigger:
post:
summary: 'Trigger Monitoring Check'
operationId: triggerMonitoringCheck
description: "Reports changed pages of a monitoring `Group`. After a short wait (so caches serve the new\nversion) a monitoring check runs for exactly these pages and compares them against their last\nmonitoring screenshot, with the Group's usual alerts and webhooks. Further triggers for the same\npage during the wait are merged into one check.\n\nThe Group must be an enabled monitoring Group with the trigger `type` in its `triggers`.\nOnly URLs that are active in the Group are checked, the others are listed under `ignored`\n(`not_in_group`, `not_active`, `rate_limited`). Nothing is charged for ignored URLs.\nAt most 60 pages per Group and hour are accepted; a request with only pages over that\ncap gets 429.\n\n**`type` = `manual_trigger` (\"run monitoring now\")** starts the monitoring check immediately,\nwithout the wait, the hourly cap or the merging described above. The check runs as soon as\nthe request returns, so clear or warm the page caches first, then call this endpoint.\nSend `scope` = `all` (and no `urls`) to check every active URL of the Group, or `scope` =\n`url` with `urls`. The Group only has to be an enabled monitoring Group; `manual_trigger` is\nnot configured in `triggers`. All URLs are checked in one monitoring run (`batch_id`, with\n`trigger_context.type` = `manual_trigger`); `run_at` is its start. URLs with a monitoring\ncheck in progress are listed under `ignored` (`already_running`). Waiting `post_save`\nchecks of the started URLs are replaced by this run.\nErrors carry a `reason`: 409 `already_running` (every URL is already being checked, or a\nrun for this Group is being started right now), 402 `not_enough_credits` (the checks do\nnot fit into the remaining checks; nothing is started), 422 `unsupported` (none of the URLs\ncan be checked), 422 `trigger_not_enabled` (not an enabled monitoring Group)."
parameters: []
responses:
202:
description: ''
content:
application/json:
schema:
oneOf:
-
description: post_save
type: object
example:
data:
group_id: 023c282c-6513-420a-a36b-a654312ab229
type: post_save
accepted:
- example.com/about
ignored:
-
url: 'https://example.com/new-post/'
reason: not_in_group
run_at: '2026-09-25T10:05:00.000000Z'
properties:
data:
type: object
properties:
group_id:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
type:
type: string
example: post_save
accepted:
type: array
example:
- example.com/about
items:
type: string
ignored:
type: array
example:
-
url: 'https://example.com/new-post/'
reason: not_in_group
items:
type: object
properties:
url:
type: string
example: 'https://example.com/new-post/'
reason:
type: string
example: not_in_group
run_at:
type: string
example: '2026-09-25T10:05:00.000000Z'
-
description: manual_trigger
type: object
example:
data:
group_id: 023c282c-6513-420a-a36b-a654312ab229
type: manual_trigger
accepted:
- example.com/about
- example.com/contact
ignored:
-
url: example.com/news
reason: already_running
run_at: '2026-09-25T10:00:03.000000Z'
batch_id: 0d5f8108-51f1-4961-939a-2d33c7145918
properties:
data:
type: object
properties:
group_id:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
type:
type: string
example: manual_trigger
accepted:
type: array
example:
- example.com/about
- example.com/contact
items:
type: string
ignored:
type: array
example:
-
url: example.com/news
reason: already_running
items:
type: object
properties:
url:
type: string
example: example.com/news
reason:
type: string
example: already_running
run_at:
type: string
example: '2026-09-25T10:00:03.000000Z'
batch_id:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
402:
description: 'manual_trigger, not enough checks left'
content:
application/json:
schema:
type: object
example:
message: 'Bummer, you used your credit already. Please upgrade your account to a bigger plan.'
reason: not_enough_credits
properties:
message:
type: string
example: 'Bummer, you used your credit already. Please upgrade your account to a bigger plan.'
reason:
type: string
example: not_enough_credits
409:
description: 'manual_trigger, every URL already being checked'
content:
application/json:
schema:
type: object
example:
message: 'A monitoring check is already running for these pages.'
reason: already_running
properties:
message:
type: string
example: 'A monitoring check is already running for these pages.'
reason:
type: string
example: already_running
tags:
- 'Monitoring Trigger'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
group_id:
type: string
description: 'ID of the monitoring Group the URLs belong to. The Group must have the trigger `type` in its `triggers`. Must not be greater than 36 characters.'
example: 023c282c-6513-420a-a36b-a654312ab229
type:
type: string
description: 'What happened. Allowed values: see `config/enums.trigger_type`: `post_save` (a page was saved; checked after a short wait) or `manual_trigger` (run the monitoring now; the check starts immediately).'
example: post_save
enum:
- post_save
- manual_trigger
scope:
type: string
description: 'What to check: `url` (default) = only the given `urls`; `all` = every active URL of the Group, without `urls`. `all` is allowed with `type` = `manual_trigger` only.'
example: url
enum:
- url
- all
urls:
type: array
description: 'The changed pages, max. 50 per request. Only URLs that are active in the Group are checked; others are returned under `ignored`. Required unless `scope` is `all`; not allowed with `scope` = `all`.'
example:
-
url: 'https://example.com/about/'
title: 'About us'
post_id: 42
items:
type: object
properties:
url:
type: string
description: 'The page URL, with or without protocol and trailing slash. Must not be greater than 2048 characters.'
example: 'https://example.com/about/'
title:
type: string
description: "Optional page title, shown in the run's `trigger_context`. Must not be greater than 255 characters."
example: 'About us'
nullable: true
post_id:
type: integer
description: 'Optional CMS id of the page (e.g. the WordPress post ID), stored in `trigger_context`. Must be at least 1.'
example: 42
nullable: true
required:
- url
editor:
type: string
description: 'Optional display name of the person who made the change. Do not send email addresses. Must not be greater than 100 characters.'
example: Anna
nullable: true
required:
- group_id
- type
/api/v2/monitoring/trigger/extend:
post:
summary: 'Extend Monitoring Trigger'
operationId: extendMonitoringTrigger
description: "Reports pages of a monitoring `Group` that are still being edited without being saved, e.g. a\nWordPress autosave. For each page that already waits for its trigger check, the wait is restarted\n(7 minutes from now), so the check runs only once the editing has stopped.\n\nAn extension never starts a check: pages without a waiting check are listed under `ignored`\n(`not_waiting`) and nothing happens for them. Extensions do not count towards the hourly cap of\nthe trigger endpoint and cost nothing. The Group must be an enabled monitoring Group with the\ntrigger `type` in its `triggers`."
parameters: []
responses:
202:
description: ''
content:
application/json:
schema:
type: object
example:
data:
group_id: 023c282c-6513-420a-a36b-a654312ab229
type: post_save
accepted:
- example.com/about
ignored:
-
url: 'https://example.com/contact/'
reason: not_waiting
run_at: '2026-09-25T10:07:00.000000Z'
properties:
data:
type: object
properties:
group_id:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
type:
type: string
example: post_save
accepted:
type: array
example:
- example.com/about
items:
type: string
ignored:
type: array
example:
-
url: 'https://example.com/contact/'
reason: not_waiting
items:
type: object
properties:
url:
type: string
example: 'https://example.com/contact/'
reason:
type: string
example: not_waiting
run_at:
type: string
example: '2026-09-25T10:07:00.000000Z'
tags:
- 'Monitoring Trigger'
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
group_id:
type: string
description: 'ID of the monitoring Group the URLs belong to. The Group must have the trigger `type` in its `triggers`. Must not be greater than 36 characters.'
example: 023c282c-6513-420a-a36b-a654312ab229
type:
type: string
description: 'The trigger type of the waiting check. Allowed values: `post_save`.'
example: post_save
enum:
- post_save
urls:
type: array
description: 'The pages that are still being edited, max. 50 per request. Only pages with a waiting check are extended; others are returned under `ignored`.'
example:
-
url: 'https://example.com/about/'
items:
type: object
properties:
url:
type: string
description: 'The page URL, with or without protocol and trailing slash. Must not be greater than 2048 characters.'
example: 'https://example.com/about/'
required:
- url
required:
- group_id
- type
- urls
/api/v2/monitoring/running:
get:
summary: 'Get Running Monitoring'
operationId: getRunningMonitoring
description: "Tells for each requested monitoring `Group` whether a monitoring run is in progress, and which\none. Counts every monitoring run of the Group: scheduled, trigger-based and manual\n(`manual_trigger`), including its comparisons.\n\nEvery requested Group that is one of your monitoring Groups is listed, with `batch_id` = the\nrunning Batch or `null` when nothing runs. Unknown Groups, Groups of other accounts and manual\nGroups are left out (no 404); treat a missing Group as not running. With several running\nBatches the newest one is returned. Checks open or processing for more than 60 minutes are\nconsidered stuck and do not count.\n\nWhether the run is finished, and its result, comes from `GET /batches/{id}`: the Batch is\nfinished when `finished_at` is set, which can be a few minutes after the Group stopped running."
parameters:
-
in: query
name: group_ids
description: 'Comma separated list of monitoring Group IDs, max. 50.'
example: '023c282c-6513-420a-a36b-a654312ab229,023c282c-6513-420a-a36b-a654312ab230'
required: true
schema:
type: string
description: 'Comma separated list of monitoring Group IDs, max. 50.'
example: '023c282c-6513-420a-a36b-a654312ab229,023c282c-6513-420a-a36b-a654312ab230'
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
group_id: 023c282c-6513-420a-a36b-a654312ab229
batch_id: 0d5f8108-51f1-4961-939a-2d33c7145918
-
group_id: 023c282c-6513-420a-a36b-a654312ab230
batch_id: null
properties:
data:
type: array
example:
-
group_id: 023c282c-6513-420a-a36b-a654312ab229
batch_id: 0d5f8108-51f1-4961-939a-2d33c7145918
-
group_id: 023c282c-6513-420a-a36b-a654312ab230
batch_id: null
items:
type: object
properties:
group_id:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
batch_id:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
tags:
- 'Monitoring Trigger'
/api/v2/queues:
get:
summary: 'List Queues'
operationId: listQueues
description: "Returns a list of all `Queues`. The `Queues` are sorted by creation date, with the most recent `Queues` appearing first.\n\nWhen filtering by `batch` or `batches` parameter, the response includes additional metadata:\n- `meta.status_counts`: Aggregated status counts across all filtered batches\n- `meta.status_counts.by_type`: Status counts grouped by screenshot type (pre, post, comparison)\n- `meta.status_counts_by_batch`: Status counts for each individual batch, including a per-batch `by_type` breakdown"
parameters:
-
in: query
name: status
description: 'Comma separated list of status to filter for.'
example: 'done,failed'
required: false
schema:
type: string
description: 'Comma separated list of status to filter for.'
example: 'done,failed'
-
in: query
name: groups
description: 'Comma separated list of Group UUIDs to filter for.'
example: '023c282c-6513-420a-a36b-a654312ab229,023c282c-6513-420a-a36b-a654312ab230'
required: false
schema:
type: string
description: 'Comma separated list of Group UUIDs to filter for.'
example: '023c282c-6513-420a-a36b-a654312ab229,023c282c-6513-420a-a36b-a654312ab230'
-
in: query
name: batches
description: 'Comma separated list of Batch UUIDs to filter for.'
example: '0d5f8108-51f1-4961-939a-2d33c7145918,1d5f8108-51f1-4961-939a-2d33c7145918'
required: false
schema:
type: string
description: 'Comma separated list of Batch UUIDs to filter for.'
example: '0d5f8108-51f1-4961-939a-2d33c7145918,1d5f8108-51f1-4961-939a-2d33c7145918'
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
id: 3bf0cec1-e8ee-49ba-804e-0db5ed93a7e3
url: 418e0748-a9cf-480b-86d6-88b00bac00b9
batch: 0d5f8108-51f1-4961-939a-2d33c7145918
group: 023c282c-6513-420a-a36b-a654312ab229
device: desktop
status: open
error_msg: null
sc_type: pre
css: null
js: null
monitoring: true
url_link: 'https://example.com'
html_title: 'Example Title'
image_link: 'https://images.webchangedetector.com/image.jpg'
created_at: '2024-08-08 13:37:42'
updated_at: '2024-08-08 13:37:42'
links:
first: 'http://api.webchangedetector.test/api/v2/queues?page=1'
last: 'http://api.webchangedetector.test/api/v2/queues?page=1'
prev: null
next: null
meta:
current_page: 1
from: 1
last_page: 1
links:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/queues?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
path: 'http://api.webchangedetector.test/api/v2/queues'
per_page: 15
to: 1
total: 1
status_counts:
open: 15
processing: 3
done: 42
failed: 2
by_type:
pre:
open: 5
processing: 1
done: 14
failed: 0
post:
open: 5
processing: 1
done: 14
failed: 1
comparison:
open: 5
processing: 1
done: 14
failed: 1
status_counts_by_batch:
0d5f8108-51f1-4961-939a-2d33c7145918:
open: 10
processing: 2
done: 30
failed: 1
by_type:
pre:
open: 0
processing: 0
done: 15
failed: 0
post:
open: 10
processing: 2
done: 3
failed: 0
compare:
open: 0
processing: 0
done: 12
failed: 1
properties:
data:
type: array
example:
-
id: 3bf0cec1-e8ee-49ba-804e-0db5ed93a7e3
url: 418e0748-a9cf-480b-86d6-88b00bac00b9
batch: 0d5f8108-51f1-4961-939a-2d33c7145918
group: 023c282c-6513-420a-a36b-a654312ab229
device: desktop
status: open
error_msg: null
sc_type: pre
css: null
js: null
monitoring: true
url_link: 'https://example.com'
html_title: 'Example Title'
image_link: 'https://images.webchangedetector.com/image.jpg'
created_at: '2024-08-08 13:37:42'
updated_at: '2024-08-08 13:37:42'
items:
type: object
properties:
id:
type: string
example: 3bf0cec1-e8ee-49ba-804e-0db5ed93a7e3
url:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
batch:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
device:
type: string
example: desktop
status:
type: string
example: open
error_msg:
type: string
example: null
nullable: true
sc_type:
type: string
example: pre
css:
type: string
example: null
nullable: true
js:
type: string
example: null
nullable: true
monitoring:
type: boolean
example: true
url_link:
type: string
example: 'https://example.com'
html_title:
type: string
example: 'Example Title'
image_link:
type: string
example: 'https://images.webchangedetector.com/image.jpg'
created_at:
type: string
example: '2024-08-08 13:37:42'
updated_at:
type: string
example: '2024-08-08 13:37:42'
links:
type: object
properties:
first:
type: string
example: 'http://api.webchangedetector.test/api/v2/queues?page=1'
last:
type: string
example: 'http://api.webchangedetector.test/api/v2/queues?page=1'
prev:
type: string
example: null
nullable: true
next:
type: string
example: null
nullable: true
meta:
type: object
properties:
current_page:
type: integer
example: 1
from:
type: integer
example: 1
last_page:
type: integer
example: 1
links:
type: array
example:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/queues?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
items:
type: object
properties:
url:
type: string
example: null
nullable: true
label:
type: string
example: '« Previous'
active:
type: boolean
example: false
path:
type: string
example: 'http://api.webchangedetector.test/api/v2/queues'
per_page:
type: integer
example: 15
to:
type: integer
example: 1
total:
type: integer
example: 1
status_counts:
type: object
properties:
open:
type: integer
example: 15
processing:
type: integer
example: 3
done:
type: integer
example: 42
failed:
type: integer
example: 2
by_type:
type: object
properties:
pre:
type: object
properties:
open:
type: integer
example: 5
processing:
type: integer
example: 1
done:
type: integer
example: 14
failed:
type: integer
example: 0
post:
type: object
properties:
open:
type: integer
example: 5
processing:
type: integer
example: 1
done:
type: integer
example: 14
failed:
type: integer
example: 1
comparison:
type: object
properties:
open:
type: integer
example: 5
processing:
type: integer
example: 1
done:
type: integer
example: 14
failed:
type: integer
example: 1
status_counts_by_batch:
type: object
properties:
0d5f8108-51f1-4961-939a-2d33c7145918:
type: object
properties:
open:
type: integer
example: 10
processing:
type: integer
example: 2
done:
type: integer
example: 30
failed:
type: integer
example: 1
by_type:
type: object
properties:
pre:
type: object
properties:
open: { type: integer, example: 0 }
processing: { type: integer, example: 0 }
done: { type: integer, example: 15 }
failed: { type: integer, example: 0 }
post:
type: object
properties:
open: { type: integer, example: 10 }
processing: { type: integer, example: 2 }
done: { type: integer, example: 3 }
failed: { type: integer, example: 0 }
compare:
type: object
properties:
open: { type: integer, example: 0 }
processing: { type: integer, example: 0 }
done: { type: integer, example: 12 }
failed: { type: integer, example: 1 }
tags:
- Queue
'/api/v2/queues/{id}':
get:
summary: 'Get Queue'
operationId: getQueue
description: 'Retrieves a `Queue` object identfied by their ID'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 3bf0cec1-e8ee-49ba-804e-0db5ed93a7e3
url: 418e0748-a9cf-480b-86d6-88b00bac00b9
batch: 0d5f8108-51f1-4961-939a-2d33c7145918
group: 023c282c-6513-420a-a36b-a654312ab229
device: desktop
status: open
sc_type: pre
css: null
js: null
monitoring: true
url_link: 'https://example.com'
html_title: 'Example Title'
image_link: 'https://images.webchangedetector.com/image.jpg'
created_at: '2024-08-08 13:37:42'
updated_at: '2024-08-08 13:37:42'
properties:
data:
type: object
properties:
id:
type: string
example: 3bf0cec1-e8ee-49ba-804e-0db5ed93a7e3
url:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
batch:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
device:
type: string
example: desktop
status:
type: string
example: open
sc_type:
type: string
example: pre
css:
type: string
example: null
nullable: true
js:
type: string
example: null
nullable: true
monitoring:
type: boolean
example: true
url_link:
type: string
example: 'https://example.com'
html_title:
type: string
example: 'Example Title'
image_link:
type: string
example: 'https://images.webchangedetector.com/image.jpg'
created_at:
type: string
example: '2024-08-08 13:37:42'
updated_at:
type: string
example: '2024-08-08 13:37:42'
tags:
- Queue
parameters:
-
in: path
name: id
description: 'The ID of the Queue.'
example: 3bf0cec1-e8ee-49ba-804e-0db5ed93a7e3
required: true
schema:
type: string
/api/v2/screenshots:
get:
summary: 'List Screenshots'
operationId: listScreenshots
description: "Returns a list of all `Screenshots`. The `Screenshots` are sorted by creation date, with\nthe most recent `Screenshots` appearing first."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
id: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
queue: 8ea7b88d-b5c6-4fad-8e9d-1497a54d9266
domain: example.com
url: example.com/foobar
link: 'https://images.webchangedetector.com/example.jpg'
device: desktop
sc_type: pre
monitoring: true
browser_console:
text: 'Failed to load resource: the server responded with a status of 404 ()'
type: error
location:
url: 'https://example.com.com/favicon.ico'
links:
first: 'http://api.webchangedetector.test/api/v2/screenshots?page=1'
last: 'http://api.webchangedetector.test/api/v2/screenshots?page=1'
prev: null
next: null
meta:
current_page: 1
from: 1
last_page: 1
links:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/screenshots?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
path: 'http://api.webchangedetector.test/api/v2/screenshots'
per_page: 15
to: 1
total: 1
properties:
data:
type: array
example:
-
id: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
queue: 8ea7b88d-b5c6-4fad-8e9d-1497a54d9266
domain: example.com
url: example.com/foobar
link: 'https://images.webchangedetector.com/example.jpg'
device: desktop
sc_type: pre
monitoring: true
browser_console:
text: 'Failed to load resource: the server responded with a status of 404 ()'
type: error
location:
url: 'https://example.com.com/favicon.ico'
items:
type: object
properties:
id:
type: string
example: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
queue:
type: string
example: 8ea7b88d-b5c6-4fad-8e9d-1497a54d9266
domain:
type: string
example: example.com
url:
type: string
example: example.com/foobar
link:
type: string
example: 'https://images.webchangedetector.com/example.jpg'
device:
type: string
example: desktop
sc_type:
type: string
example: pre
monitoring:
type: boolean
example: true
browser_console:
type: object
properties:
text:
type: string
example: 'Failed to load resource: the server responded with a status of 404 ()'
type:
type: string
example: error
location:
type: object
properties:
url:
type: string
example: 'https://example.com.com/favicon.ico'
links:
type: object
properties:
first:
type: string
example: 'http://api.webchangedetector.test/api/v2/screenshots?page=1'
last:
type: string
example: 'http://api.webchangedetector.test/api/v2/screenshots?page=1'
prev:
type: string
example: null
nullable: true
next:
type: string
example: null
nullable: true
meta:
type: object
properties:
current_page:
type: integer
example: 1
from:
type: integer
example: 1
last_page:
type: integer
example: 1
links:
type: array
example:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/screenshots?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
items:
type: object
properties:
url:
type: string
example: null
nullable: true
label:
type: string
example: '« Previous'
active:
type: boolean
example: false
path:
type: string
example: 'http://api.webchangedetector.test/api/v2/screenshots'
per_page:
type: integer
example: 15
to:
type: integer
example: 1
total:
type: integer
example: 1
tags:
- Screenshot
'/api/v2/screenshots/{id}':
get:
summary: 'Get Screenshot'
operationId: getScreenshot
description: 'Retrieves a `Screenshot` object identfied by their ID'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
queue: 8ea7b88d-b5c6-4fad-8e9d-1497a54d9266
domain: example.com
url: example.com/foobar
link: 'https://images.webchangedetector.com/example.jpg'
device: desktop
sc_type: pre
monitoring: true
browser_console:
text: 'Failed to load resource: the server responded with a status of 404 ()'
type: error
location:
url: 'https://example.com.com/favicon.ico'
properties:
data:
type: object
properties:
id:
type: string
example: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
queue:
type: string
example: 8ea7b88d-b5c6-4fad-8e9d-1497a54d9266
domain:
type: string
example: example.com
url:
type: string
example: example.com/foobar
link:
type: string
example: 'https://images.webchangedetector.com/example.jpg'
device:
type: string
example: desktop
sc_type:
type: string
example: pre
monitoring:
type: boolean
example: true
browser_console:
type: object
properties:
text:
type: string
example: 'Failed to load resource: the server responded with a status of 404 ()'
type:
type: string
example: error
location:
type: object
properties:
url:
type: string
example: 'https://example.com.com/favicon.ico'
tags:
- Screenshot
parameters:
-
in: path
name: id
description: 'The ID of the Screenshot.'
example: 958dce2c-8468-47d3-8bc2-7dc6bf0aadae
required: true
schema:
type: string
/api/v2/screenshots/take:
post:
summary: 'Take Screenshot'
operationId: takeScreenshot
description: "Adds screenshots of URLs in the passed groups to the queue. The parameter sc_type indicates if\npre-update screenshots are taken (pre) or post-update screenshots and comparisons are taken (post).\nWhen post-update screenshots are done, a comparison is automatically triggered.\n\nBy default all groups share ONE batch. With `batch_per_group=true` each group gets its own batch\nand the response additionally contains a `batches` map (group UUID => batch UUID)."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
oneOf:
-
description: Success
type: object
example:
batch: 0d5f8108-51f1-4961-939a-2d33c7145918
amount_screenshots: 42
groups:
- 023c282c-6513-420a-a36b-a654312ab229
- 023c282c-6513-420a-a36b-a654312ab230
properties:
batch:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
amount_screenshots:
type: integer
example: 42
groups:
type: array
example:
- 023c282c-6513-420a-a36b-a654312ab229
- 023c282c-6513-420a-a36b-a654312ab230
items:
type: string
-
description: 'Success (batch_per_group=true)'
type: object
example:
batch: 0d5f8108-51f1-4961-939a-2d33c7145918
amount_screenshots: 42
groups:
- 023c282c-6513-420a-a36b-a654312ab229
- 023c282c-6513-420a-a36b-a654312ab230
batches:
023c282c-6513-420a-a36b-a654312ab229: 0d5f8108-51f1-4961-939a-2d33c7145918
023c282c-6513-420a-a36b-a654312ab230: 1e6f9219-62f2-5a72-a4ab-3e44d8256a29
properties:
batch:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
amount_screenshots:
type: integer
example: 42
groups:
type: array
example:
- 023c282c-6513-420a-a36b-a654312ab229
- 023c282c-6513-420a-a36b-a654312ab230
items:
type: string
batches:
type: object
properties:
023c282c-6513-420a-a36b-a654312ab229:
type: string
example: 0d5f8108-51f1-4961-939a-2d33c7145918
023c282c-6513-420a-a36b-a654312ab230:
type: string
example: 1e6f9219-62f2-5a72-a4ab-3e44d8256a29
402:
description: 'Not enough credits'
content:
application/json:
schema:
type: object
example:
message: 'Bummer, you used your credit already. Please upgrade your account to a bigger plan.'
properties:
message:
type: string
example: 'Bummer, you used your credit already. Please upgrade your account to a bigger plan.'
422:
description: 'All selected URLs are unsupported content (batch_per_group=true)'
content:
application/json:
schema:
type: object
example:
message: 'None of the selected URLs can be checked. Only HTML pages are supported (not PDFs, images, or other files).'
properties:
message:
type: string
example: 'None of the selected URLs can be checked. Only HTML pages are supported (not PDFs, images, or other files).'
tags:
- Screenshot
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
group_ids:
type: array
description: 'A list of Groups.'
example: '["023c282c-6513-420a-a36b-a654312ab229", "023c282c-6513-420a-a36b-a654312ab230"]'
items:
type: string
sc_type:
type: string
description: 'Screenshot phase. `pre` captures the baseline before changes; `post` captures after changes and triggers comparisons against the matching `pre` screenshots in the same Batch.'
example: pre
enum:
- pre
- post
source:
type: string
description: 'Optional batch source tag for filtering / reporting. Allowed values: see `Batch::SOURCE_ALL` (e.g. `manual`, `auto_update`, `monitoring`).'
example: manual
enum:
- manual
- monitoring
- auto_update
batch_per_group:
type: boolean
description: 'When `true`, one Batch is created PER group instead of a single shared batch. The response then additionally contains a `batches` object mapping each started group UUID to its batch UUID; groups that could not be started (no credits, nothing to check) are omitted from the map. Defaults to `false` (unchanged single-batch behavior and response). Send as JSON boolean or `0`/`1` — the strings `"true"`/`"false"` are rejected with 422.'
example: false
required:
- group_ids
/api/v2/invitations/verify:
post:
summary: 'Verify Invitation'
operationId: verifyInvitation
description: "Returns subaccount details for a valid invitation token, including the decrypted API token.\nIdempotent: can be called multiple times until the invitation is accepted or expires.\nDoes NOT consume the token. Use POST /invitations/accept after the user has finished\nsetting up their account to mark the invitation as consumed.\nThis endpoint does not require authentication."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 17482316-2398-4374-9f70-e0e3e2bf292a
name_first: Jane
name_last: Doe
email: mail@example.com
api_token: V82abQfqPA3hBXL9ZHfMAt94Ta23VUdYt691D7GO
properties:
data:
type: object
properties:
id:
type: string
example: 17482316-2398-4374-9f70-e0e3e2bf292a
name_first:
type: string
example: Jane
name_last:
type: string
example: Doe
email:
type: string
example: mail@example.com
api_token:
type: string
example: V82abQfqPA3hBXL9ZHfMAt94Ta23VUdYt691D7GO
tags:
- Subaccount
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
invitation_token:
type: string
description: 'The invitation token from the email'
example: ducimus
required:
- invitation_token
/api/v2/invitations/accept:
post:
summary: 'Accept Invitation'
operationId: acceptInvitation
description: "Marks a subaccount invitation as accepted, consuming the token. Should be called by the\nwebapp AFTER the local user account has been successfully created — calling this before\nis a self-DoS because the token is cleared and cannot be re-verified afterwards.\nThis endpoint does not require authentication."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Invitation accepted'
properties:
message:
type: string
example: 'Invitation accepted'
tags:
- Subaccount
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
invitation_token:
type: string
description: 'The invitation token from the email'
example: reprehenderit
required:
- invitation_token
/api/v2/subaccounts:
get:
summary: 'List Subaccounts'
operationId: listSubaccounts
description: "Returns a list of all `Subaccounts`. The `Subaccounts` are sorted by creation date, with\nthe most recent `Subaccounts` appearing first."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
id: 17482316-2398-4374-9f70-e0e3e2bf292a
name_first: Jane
name_last: Doe
email: mail@example.com
checks_done: 42
checks_left: 1337
timezone: UTC
is_subaccount: true
links:
first: 'http://api.webchangedetector.test/api/v2/subaccounts?page=1'
last: 'http://api.webchangedetector.test/api/v2/subaccounts?page=1'
prev: null
next: null
meta:
current_page: 1
from: 1
last_page: 1
links:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/subaccounts?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
path: 'http://api.webchangedetector.test/api/v2/subaccounts'
per_page: 15
to: 1
total: 1
properties:
data:
type: array
example:
-
id: 17482316-2398-4374-9f70-e0e3e2bf292a
name_first: Jane
name_last: Doe
email: mail@example.com
checks_done: 42
checks_left: 1337
timezone: UTC
is_subaccount: true
items:
type: object
properties:
id:
type: string
example: 17482316-2398-4374-9f70-e0e3e2bf292a
name_first:
type: string
example: Jane
name_last:
type: string
example: Doe
email:
type: string
example: mail@example.com
checks_done:
type: integer
example: 42
checks_left:
type: integer
example: 1337
timezone:
type: string
example: UTC
is_subaccount:
type: boolean
example: true
links:
type: object
properties:
first:
type: string
example: 'http://api.webchangedetector.test/api/v2/subaccounts?page=1'
last:
type: string
example: 'http://api.webchangedetector.test/api/v2/subaccounts?page=1'
prev:
type: string
example: null
nullable: true
next:
type: string
example: null
nullable: true
meta:
type: object
properties:
current_page:
type: integer
example: 1
from:
type: integer
example: 1
last_page:
type: integer
example: 1
links:
type: array
example:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/subaccounts?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
items:
type: object
properties:
url:
type: string
example: null
nullable: true
label:
type: string
example: '« Previous'
active:
type: boolean
example: false
path:
type: string
example: 'http://api.webchangedetector.test/api/v2/subaccounts'
per_page:
type: integer
example: 15
to:
type: integer
example: 1
total:
type: integer
example: 1
tags:
- Subaccount
post:
summary: 'Create Subaccount'
operationId: createSubaccount
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 17482316-2398-4374-9f70-e0e3e2bf292a
name_first: Jane
name_last: Doe
email: mail@example.com
checks_done: 42
checks_left: 1337
timezone: UTC
api_token: V82abQfqPA3hBXL9ZHfMAt94Ta23VUdYt691D7GO
is_subaccount: true
properties:
data:
type: object
properties:
id:
type: string
example: 17482316-2398-4374-9f70-e0e3e2bf292a
name_first:
type: string
example: Jane
name_last:
type: string
example: Doe
email:
type: string
example: mail@example.com
checks_done:
type: integer
example: 42
checks_left:
type: integer
example: 1337
timezone:
type: string
example: UTC
api_token:
type: string
example: V82abQfqPA3hBXL9ZHfMAt94Ta23VUdYt691D7GO
is_subaccount:
type: boolean
example: true
tags:
- Subaccount
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name_first:
type: string
description: 'First Name'
example: Hans
name_last:
type: string
description: 'Last Name'
example: Hacker
email:
type: string
description: 'Must be a valid email'
example: mail@example.com
limit_checks:
type: number
description: "Maximum number of checks per renewal period this subaccount may consume. Capped at the parent account's plan limit (not remaining quota). Must be at least 0."
example: 1000.0
plan_label:
type: string
description: 'Optional display label shown in the subaccount UI (e.g. "Agency Starter"). No billing semantics — purely cosmetic. Must not be greater than 255 characters.'
example: 'Agency Starter'
nullable: true
can_create_subaccounts:
type: boolean
description: 'Allow this subaccount to itself manage subaccounts (level-1 reseller). Defaults to `false`.'
example: false
required:
- name_first
- name_last
- email
- limit_checks
'/api/v2/subaccounts/{id}':
get:
summary: 'Get Subaccount'
operationId: getSubaccount
description: 'Retrieves a `Subaccount` object identfied by their ID'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 17482316-2398-4374-9f70-e0e3e2bf292a
name_first: Jane
name_last: Doe
email: mail@example.com
checks_done: 42
checks_left: 1337
timezone: UTC
is_subaccount: true
properties:
data:
type: object
properties:
id:
type: string
example: 17482316-2398-4374-9f70-e0e3e2bf292a
name_first:
type: string
example: Jane
name_last:
type: string
example: Doe
email:
type: string
example: mail@example.com
checks_done:
type: integer
example: 42
checks_left:
type: integer
example: 1337
timezone:
type: string
example: UTC
is_subaccount:
type: boolean
example: true
tags:
- Subaccount
put:
summary: 'Update Subaccount'
operationId: updateSubaccount
description: "Updates the specified `Subaccount` by setting the values of the parameters passed.\nAny parameters not provided will be left unchanged.\n"
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 17482316-2398-4374-9f70-e0e3e2bf292a
name_first: Jane
name_last: Doe
email: mail@example.com
checks_done: 42
checks_left: 1337
timezone: UTC
is_subaccount: true
properties:
data:
type: object
properties:
id:
type: string
example: 17482316-2398-4374-9f70-e0e3e2bf292a
name_first:
type: string
example: Jane
name_last:
type: string
example: Doe
email:
type: string
example: mail@example.com
checks_done:
type: integer
example: 42
checks_left:
type: integer
example: 1337
timezone:
type: string
example: UTC
is_subaccount:
type: boolean
example: true
tags:
- Subaccount
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
name_first:
type: string
description: 'First Name'
example: Hans
name_last:
type: string
description: 'Last Name'
example: Hacker
limit_checks:
type: number
description: "New per-renewal-period check quota. Capped at the parent account's plan limit. Email is immutable on update. Must be at least 0."
example: 1500.0
plan_label:
type: string
description: 'Optional display label shown in the subaccount UI. No billing semantics. Must not be greater than 255 characters.'
example: 'Agency Pro'
nullable: true
can_create_subaccounts:
type: boolean
description: 'Toggle subaccount-management permission for this user.'
example: false
required:
- name_first
- name_last
delete:
summary: 'Delete Subaccount'
operationId: deleteSubaccount
description: "Permanently deletes a `Subaccount`. This cannot be undone.\n"
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Subaccount deleted'
properties:
message:
type: string
example: 'Subaccount deleted'
tags:
- Subaccount
parameters:
-
in: path
name: id
description: 'The ID of the Subaccount.'
example: 17482316-2398-4374-9f70-e0e3e2bf292a
required: true
schema:
type: string
'/api/v2/subaccounts/{id}/invite':
post:
summary: 'Invite Subaccount'
operationId: inviteSubaccount
description: "Sends an invitation email to a `Subaccount` user, allowing them to create their own webapp login.\nWorks for both new and existing subaccounts."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Invitation sent'
properties:
message:
type: string
example: 'Invitation sent'
tags:
- Subaccount
parameters:
-
in: path
name: id
description: 'The UUID of the Subaccount.'
example: 17482316-2398-4374-9f70-e0e3e2bf292a
required: true
schema:
type: string
/api/v2/urls:
get:
summary: 'List Urls'
operationId: listUrls
description: "Returns a list of all `Urls`. The `Urls` are sorted by creation date, with\nthe most recent `Urls` appearing first."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
id: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title: 'Example Title'
url: example.com/foobar
last_crawled_at: '2025-01-01 13:37:42'
type: types
category: Seiten
website: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
groups:
- 023c282c-6513-420a-a36b-a654312ab229
- 023c282c-6513-420a-a36b-a654312ab230
status_code: 200
error_count: 0
links:
first: 'http://api.webchangedetector.test/api/v2/urls?page=1'
last: 'http://api.webchangedetector.test/api/v2/urls?page=1'
prev: null
next: null
meta:
current_page: 1
from: 1
last_page: 1
links:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/urls?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
path: 'http://api.webchangedetector.test/api/v2/urls'
per_page: 15
to: 1
total: 1
properties:
data:
type: array
example:
-
id: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title: 'Example Title'
url: example.com/foobar
last_crawled_at: '2025-01-01 13:37:42'
type: types
category: Seiten
website: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
groups:
- 023c282c-6513-420a-a36b-a654312ab229
- 023c282c-6513-420a-a36b-a654312ab230
status_code: 200
error_count: 0
items:
type: object
properties:
id:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title:
type: string
example: 'Example Title'
url:
type: string
example: example.com/foobar
last_crawled_at:
type: string
example: '2025-01-01 13:37:42'
type:
type: string
example: types
category:
type: string
example: Seiten
website:
type: string
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
groups:
type: array
example:
- 023c282c-6513-420a-a36b-a654312ab229
- 023c282c-6513-420a-a36b-a654312ab230
items:
type: string
status_code:
type: integer
example: 200
error_count:
type: integer
example: 0
links:
type: object
properties:
first:
type: string
example: 'http://api.webchangedetector.test/api/v2/urls?page=1'
last:
type: string
example: 'http://api.webchangedetector.test/api/v2/urls?page=1'
prev:
type: string
example: null
nullable: true
next:
type: string
example: null
nullable: true
meta:
type: object
properties:
current_page:
type: integer
example: 1
from:
type: integer
example: 1
last_page:
type: integer
example: 1
links:
type: array
example:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/urls?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
items:
type: object
properties:
url:
type: string
example: null
nullable: true
label:
type: string
example: '« Previous'
active:
type: boolean
example: false
path:
type: string
example: 'http://api.webchangedetector.test/api/v2/urls'
per_page:
type: integer
example: 15
to:
type: integer
example: 1
total:
type: integer
example: 1
tags:
- Url
post:
summary: 'Create Url'
operationId: createUrl
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title: 'Example Title'
url: example.com/foobar
last_crawled_at: '2025-01-01 13:37:42'
type: null
category: null
website: null
groups: []
status_code: 200
error_count: 0
properties:
data:
type: object
properties:
id:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title:
type: string
example: 'Example Title'
url:
type: string
example: example.com/foobar
last_crawled_at:
type: string
example: '2025-01-01 13:37:42'
type:
type: string
example: null
nullable: true
category:
type: string
example: null
nullable: true
website:
type: string
example: null
nullable: true
groups:
type: array
example: []
status_code:
type: integer
example: 200
error_count:
type: integer
example: 0
tags:
- Url
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
url:
type: string
description: 'Must be a valid URL'
example: 'https://example.com'
required:
- url
'/api/v2/urls/{id}':
get:
summary: 'Get Url'
operationId: getUrl
description: 'Retrieves a `Url` object identfied by their ID'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title: 'Example Title'
url: example.com/foobar
last_crawled_at: '2025-01-01 13:37:42'
type: types
category: Seiten
website: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
groups:
- 023c282c-6513-420a-a36b-a654312ab229
- 023c282c-6513-420a-a36b-a654312ab230
status_code: 200
error_count: 0
properties:
data:
type: object
properties:
id:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title:
type: string
example: 'Example Title'
url:
type: string
example: example.com/foobar
last_crawled_at:
type: string
example: '2025-01-01 13:37:42'
type:
type: string
example: types
category:
type: string
example: Seiten
website:
type: string
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
groups:
type: array
example:
- 023c282c-6513-420a-a36b-a654312ab229
- 023c282c-6513-420a-a36b-a654312ab230
items:
type: string
status_code:
type: integer
example: 200
error_count:
type: integer
example: 0
tags:
- Url
put:
summary: 'Update Url'
operationId: updateUrl
description: "Updates the specified `Url` by setting the values of the parameters passed.\nAny parameters not provided will be left unchanged.\n"
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title: 'Example Title'
url: example.com/foobar
last_crawled_at: '2025-01-01 13:37:42'
type: types
category: Seiten
website: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
status_code: 200
error_count: 0
groups:
- 023c282c-6513-420a-a36b-a654312ab229
- 023c282c-6513-420a-a36b-a654312ab230
properties:
data:
type: object
properties:
id:
type: string
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
html_title:
type: string
example: 'Example Title'
url:
type: string
example: example.com/foobar
last_crawled_at:
type: string
example: '2025-01-01 13:37:42'
type:
type: string
example: types
category:
type: string
example: Seiten
website:
type: string
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
status_code:
type: integer
example: 200
error_count:
type: integer
example: 0
groups:
type: array
example:
- 023c282c-6513-420a-a36b-a654312ab229
- 023c282c-6513-420a-a36b-a654312ab230
items:
type: string
tags:
- Url
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
url:
type: string
description: 'Must be a valid URL'
example: 'https://example.com'
required:
- url
delete:
summary: 'Delete Url'
operationId: deleteUrl
description: "Permanently deletes a `Url`. This cannot be undone.\n"
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'URL deleted'
properties:
message:
type: string
example: 'URL deleted'
tags:
- Url
parameters:
-
in: path
name: id
description: 'The ID of the Url.'
example: 418e0748-a9cf-480b-86d6-88b00bac00b9
required: true
schema:
type: string
/api/v2/urls/add-from-sitemap:
post:
summary: 'Add From Sitemap'
operationId: addFromSitemap
description: "Adds all the URLs found in a sitemap for a given domain.\n"
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: 'Sitemap parsing started.'
properties:
message:
type: string
example: 'Sitemap parsing started.'
tags:
- Url
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
domain:
type: string
description: 'The domain to parse the sitemap from'
example: example.com
required:
- domain
/api/v2/webhooks:
get:
summary: 'List Webhooks'
operationId: listWebhooks
description: "Returns a list of all Webhooks. The Webhooks are sorted by creation date, with\nthe most recent Webhooks appearing first."
parameters:
-
in: query
name: event
description: 'Event of the Queue.'
example: comparison_status_new
required: false
schema:
type: string
description: 'Event of the Queue.'
example: comparison_status_new
enum:
- batch_finished
- comparison_status_new
- queue_status_done
- queue_status_failed
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
id: d86e9245-3524-4f8d-b5d9-e4a472136d27
event: comparison_status_new
url: 'https://example.com'
links:
first: 'http://api.webchangedetector.test/api/v2/webhooks?page=1'
last: 'http://api.webchangedetector.test/api/v2/webhooks?page=1'
prev: null
next: null
meta:
current_page: 1
from: 1
last_page: 1
links:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/webhooks?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
path: 'http://api.webchangedetector.test/api/v2/webhooks'
per_page: 15
to: 1
total: 1
properties:
data:
type: array
example:
-
id: d86e9245-3524-4f8d-b5d9-e4a472136d27
event: comparison_status_new
url: 'https://example.com'
items:
type: object
properties:
id:
type: string
example: d86e9245-3524-4f8d-b5d9-e4a472136d27
event:
type: string
example: comparison_status_new
url:
type: string
example: 'https://example.com'
links:
type: object
properties:
first:
type: string
example: 'http://api.webchangedetector.test/api/v2/webhooks?page=1'
last:
type: string
example: 'http://api.webchangedetector.test/api/v2/webhooks?page=1'
prev:
type: string
example: null
nullable: true
next:
type: string
example: null
nullable: true
meta:
type: object
properties:
current_page:
type: integer
example: 1
from:
type: integer
example: 1
last_page:
type: integer
example: 1
links:
type: array
example:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/webhooks?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
items:
type: object
properties:
url:
type: string
example: null
nullable: true
label:
type: string
example: '« Previous'
active:
type: boolean
example: false
path:
type: string
example: 'http://api.webchangedetector.test/api/v2/webhooks'
per_page:
type: integer
example: 15
to:
type: integer
example: 1
total:
type: integer
example: 1
tags:
- Webhook
post:
summary: 'Create Webhook'
operationId: createWebhook
description: ''
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: d86e9245-3524-4f8d-b5d9-e4a472136d27
event: comparison_status_new
url: 'https://example.com'
properties:
data:
type: object
properties:
id:
type: string
example: d86e9245-3524-4f8d-b5d9-e4a472136d27
event:
type: string
example: comparison_status_new
url:
type: string
example: 'https://example.com'
tags:
- Webhook
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
url:
type: string
description: 'HTTPS endpoint that receives the webhook POST. Requests are signed with HMAC-SHA256 in the `Signature` header — verify against your account webhook secret (GET /api/v2/account). Must be a valid URL.'
example: 'https://example.com/webhooks/wcd'
event:
type: string
description: 'Event to subscribe to. Allowed values for the v2 API: `batch_finished` (all Screenshots in a Batch complete; the payload carries the Batch `source` and `trigger_context`, see List Batches), `comparison_status_new` (a change was detected), `queue_status_done`, `queue_status_failed`. See `Webhook::EVENTS_ALL_API_V2`.'
example: batch_finished
enum:
- batch_finished
- comparison_status_new
- comparison_status_new_collection
- comparison_summary
- queue_status_done
- queue_status_failed
- wordpress_cron
- wordpress_single_call
required:
- url
- event
'/api/v2/webhooks/{id}':
get:
summary: 'Get Webhook'
operationId: getWebhook
description: 'Retrieves a Webhook object identfied by their ID'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: d86e9245-3524-4f8d-b5d9-e4a472136d27
event: comparison_status_new
url: 'https://example.com'
properties:
data:
type: object
properties:
id:
type: string
example: d86e9245-3524-4f8d-b5d9-e4a472136d27
event:
type: string
example: comparison_status_new
url:
type: string
example: 'https://example.com'
tags:
- Webhook
put:
summary: 'Update Webhook'
operationId: updateWebhook
description: "Updates the specified `Webhook` by setting the values of the parameters passed.\n"
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
id: d86e9245-3524-4f8d-b5d9-e4a472136d27
event: comparison_status_new
url: 'https://example.com'
properties:
data:
type: object
properties:
id:
type: string
example: d86e9245-3524-4f8d-b5d9-e4a472136d27
event:
type: string
example: comparison_status_new
url:
type: string
example: 'https://example.com'
tags:
- Webhook
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
url:
type: string
description: 'Must be a valid URL'
example: 'https://example.com'
required:
- url
delete:
summary: 'Delete Webhook'
operationId: deleteWebhook
description: 'Permanently deletes a `Webhook`. This cannot be undone.'
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: '{ID} deleted'
properties:
message:
type: string
example: '{ID} deleted'
tags:
- Webhook
parameters:
-
in: path
name: id
description: 'The ID of the Webhook.'
example: d86e9245-3524-4f8d-b5d9-e4a472136d27
required: true
schema:
type: string
/api/v2/websites:
get:
summary: 'List Websites'
operationId: listWebsites
description: "Returns a list of all `Website`. The `Websites` are sorted by creation date, with\nthe most recent `Websites` appearing first.\n"
parameters:
-
in: query
name: domain
description: 'Filter websites by domain. Must not be greater than 253 characters.'
example: example.com
required: false
schema:
type: string
description: 'Filter websites by domain. Must not be greater than 253 characters.'
example: example.com
nullable: true
-
in: query
name: managed_by
description: 'Filter websites by owning integration (e.g. native, mainwp). Omit for all.'
example: mainwp
required: false
schema:
type: string
description: 'Filter websites by owning integration (e.g. native, mainwp). Omit for all.'
example: mainwp
enum:
- native
- mainwp
nullable: true
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
data:
-
id: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
manual_detection_group: 023c282c-6513-420a-a36b-a654312ab229
auto_detection_group: 023c282c-6513-420a-a36b-a654312ab230
domain: example.com
last_seen_at: '2025-07-14T16:19:30Z'
plugin_version: 4.0.3
is_multisite_subsite: false
parent_multisite_website: null
sync_url_types:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
auto_update_settings:
auto_update_checks_enabled: false
auto_update_checks_from: '13:37'
auto_update_checks_to: '13:42'
auto_update_checks_monday: true
auto_update_checks_tuesday: true
auto_update_checks_wednesday: true
auto_update_checks_thursday: true
auto_update_checks_friday: true
auto_update_checks_saturday: false
auto_update_checks_sunday: false
auto_update_checks_emails: mail@example.com
allow_core_security_updates: true
allowances:
change_detections_view: true
ai_rules_view: true
manual_checks_view: true
manual_checks_start: true
manual_checks_settings: true
manual_checks_urls: true
monitoring_checks_view: true
monitoring_checks_settings: true
monitoring_checks_urls: true
logs_view: true
settings_view: true
settings_add_urls: true
settings_account_settings: true
upgrade_account: true
wizard_start: true
only_frontpage: false
plugin_view: true
links:
first: 'http://api.webchangedetector.test/api/v2/websites?page=1'
last: 'http://api.webchangedetector.test/api/v2/websites?page=1'
prev: null
next: null
meta:
current_page: 1
from: 1
last_page: 1
links:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/websites?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
path: 'http://api.webchangedetector.test/api/v2/websites'
per_page: 15
to: 1
total: 1
properties:
data:
type: array
example:
-
id: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
manual_detection_group: 023c282c-6513-420a-a36b-a654312ab229
auto_detection_group: 023c282c-6513-420a-a36b-a654312ab230
domain: example.com
last_seen_at: '2025-07-14T16:19:30Z'
plugin_version: 4.0.3
is_multisite_subsite: false
parent_multisite_website: null
sync_url_types:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
auto_update_settings:
auto_update_checks_enabled: false
auto_update_checks_from: '13:37'
auto_update_checks_to: '13:42'
auto_update_checks_monday: true
auto_update_checks_tuesday: true
auto_update_checks_wednesday: true
auto_update_checks_thursday: true
auto_update_checks_friday: true
auto_update_checks_saturday: false
auto_update_checks_sunday: false
auto_update_checks_emails: mail@example.com
allow_core_security_updates: true
allowances:
change_detections_view: true
ai_rules_view: true
manual_checks_view: true
manual_checks_start: true
manual_checks_settings: true
manual_checks_urls: true
monitoring_checks_view: true
monitoring_checks_settings: true
monitoring_checks_urls: true
logs_view: true
settings_view: true
settings_add_urls: true
settings_account_settings: true
upgrade_account: true
wizard_start: true
only_frontpage: false
plugin_view: true
items:
type: object
properties:
id:
type: string
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
manual_detection_group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
auto_detection_group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab230
domain:
type: string
example: example.com
last_seen_at:
type: string
example: '2025-07-14T16:19:30Z'
plugin_version:
type: string
example: 4.0.3
is_multisite_subsite:
type: boolean
example: false
parent_multisite_website:
type: string
example: null
nullable: true
sync_url_types:
type: array
example:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
items:
type: object
properties:
url_type_slug:
type: string
example: types
url_type_name:
type: string
example: 'Post Types'
post_type_slug:
type: string
example: posts
post_type_name:
type: string
example: Posts
auto_update_settings:
type: object
properties:
auto_update_checks_enabled:
type: boolean
example: false
auto_update_checks_from:
type: string
example: '13:37'
auto_update_checks_to:
type: string
example: '13:42'
auto_update_checks_monday:
type: boolean
example: true
auto_update_checks_tuesday:
type: boolean
example: true
auto_update_checks_wednesday:
type: boolean
example: true
auto_update_checks_thursday:
type: boolean
example: true
auto_update_checks_friday:
type: boolean
example: true
auto_update_checks_saturday:
type: boolean
example: false
auto_update_checks_sunday:
type: boolean
example: false
auto_update_checks_emails:
type: string
example: mail@example.com
allow_core_security_updates:
type: boolean
example: true
allowances:
type: object
properties:
change_detections_view:
type: boolean
example: true
ai_rules_view:
type: boolean
example: true
manual_checks_view:
type: boolean
example: true
manual_checks_start:
type: boolean
example: true
manual_checks_settings:
type: boolean
example: true
manual_checks_urls:
type: boolean
example: true
monitoring_checks_view:
type: boolean
example: true
monitoring_checks_settings:
type: boolean
example: true
monitoring_checks_urls:
type: boolean
example: true
logs_view:
type: boolean
example: true
settings_view:
type: boolean
example: true
settings_add_urls:
type: boolean
example: true
settings_account_settings:
type: boolean
example: true
upgrade_account:
type: boolean
example: true
wizard_start:
type: boolean
example: true
only_frontpage:
type: boolean
example: false
plugin_view:
type: boolean
example: true
links:
type: object
properties:
first:
type: string
example: 'http://api.webchangedetector.test/api/v2/websites?page=1'
last:
type: string
example: 'http://api.webchangedetector.test/api/v2/websites?page=1'
prev:
type: string
example: null
nullable: true
next:
type: string
example: null
nullable: true
meta:
type: object
properties:
current_page:
type: integer
example: 1
from:
type: integer
example: 1
last_page:
type: integer
example: 1
links:
type: array
example:
-
url: null
label: '« Previous'
active: false
-
url: 'http://api.webchangedetector.test/api/v2/websites?page=1'
label: '1'
active: true
-
url: null
label: 'Next »'
active: false
items:
type: object
properties:
url:
type: string
example: null
nullable: true
label:
type: string
example: '« Previous'
active:
type: boolean
example: false
path:
type: string
example: 'http://api.webchangedetector.test/api/v2/websites'
per_page:
type: integer
example: 15
to:
type: integer
example: 1
total:
type: integer
example: 1
tags:
- Website
post:
summary: 'Create Website'
operationId: createWebsite
description: "Creates a `Website` by setting the values of the parameters passed.\nTypically only done by the WordPress plugin.\n"
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
id: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
domain: example.com
last_seen_at: '2025-07-14T16:19:30Z'
plugin_version: 4.0.3
manual_detection_group: 023c282c-6513-420a-a36b-a654312ab229
auto_detection_group: 023c282c-6513-420a-a36b-a654312ab230
is_multisite_subsite: false
parent_multisite_website: null
allowances:
change_detections_view: true
ai_rules_view: true
manual_checks_view: true
manual_checks_start: true
manual_checks_settings: true
manual_checks_urls: true
monitoring_checks_view: true
monitoring_checks_settings: true
monitoring_checks_urls: true
logs_view: true
settings_view: true
settings_add_urls: true
settings_account_settings: true
upgrade_account: true
wizard_start: true
only_frontpage: false
plugin_view: true
sync_url_types:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: pages
post_type_name: Pages
-
url_type_slug: taxonomies
url_type_name: Taxonomies
post_type_slug: category
post_type_name: Category
auto_update_settings:
auto_update_checks_enabled: false
auto_update_checks_from: '13:37'
auto_update_checks_to: '13:42'
auto_update_checks_monday: true
auto_update_checks_tuesday: true
auto_update_checks_wednesday: true
auto_update_checks_thursday: true
auto_update_checks_friday: true
auto_update_checks_saturday: false
auto_update_checks_sunday: false
auto_update_checks_emails: mail@example.com
allow_core_security_updates: true
properties:
id:
type: string
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
domain:
type: string
example: example.com
last_seen_at:
type: string
example: '2025-07-14T16:19:30Z'
plugin_version:
type: string
example: 4.0.3
manual_detection_group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
auto_detection_group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab230
is_multisite_subsite:
type: boolean
example: false
parent_multisite_website:
type: string
example: null
nullable: true
allowances:
type: object
properties:
change_detections_view:
type: boolean
example: true
ai_rules_view:
type: boolean
example: true
manual_checks_view:
type: boolean
example: true
manual_checks_start:
type: boolean
example: true
manual_checks_settings:
type: boolean
example: true
manual_checks_urls:
type: boolean
example: true
monitoring_checks_view:
type: boolean
example: true
monitoring_checks_settings:
type: boolean
example: true
monitoring_checks_urls:
type: boolean
example: true
logs_view:
type: boolean
example: true
settings_view:
type: boolean
example: true
settings_add_urls:
type: boolean
example: true
settings_account_settings:
type: boolean
example: true
upgrade_account:
type: boolean
example: true
wizard_start:
type: boolean
example: true
only_frontpage:
type: boolean
example: false
plugin_view:
type: boolean
example: true
sync_url_types:
type: array
example:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: pages
post_type_name: Pages
-
url_type_slug: taxonomies
url_type_name: Taxonomies
post_type_slug: category
post_type_name: Category
items:
type: object
properties:
url_type_slug:
type: string
example: types
url_type_name:
type: string
example: 'Post Types'
post_type_slug:
type: string
example: posts
post_type_name:
type: string
example: Posts
auto_update_settings:
type: object
properties:
auto_update_checks_enabled:
type: boolean
example: false
auto_update_checks_from:
type: string
example: '13:37'
auto_update_checks_to:
type: string
example: '13:42'
auto_update_checks_monday:
type: boolean
example: true
auto_update_checks_tuesday:
type: boolean
example: true
auto_update_checks_wednesday:
type: boolean
example: true
auto_update_checks_thursday:
type: boolean
example: true
auto_update_checks_friday:
type: boolean
example: true
auto_update_checks_saturday:
type: boolean
example: false
auto_update_checks_sunday:
type: boolean
example: false
auto_update_checks_emails:
type: string
example: mail@example.com
allow_core_security_updates:
type: boolean
example: true
tags:
- Website
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
domain:
type: string
description: 'The domain of the Website.'
example: example.com
manual_detection_group_id:
type: string
description: 'The ID of the Manual Detection Group.'
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
auto_detection_group_id:
type: string
description: 'The ID of the Auto Detection Group.'
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
managed_by:
type: string
description: ''
example: native
enum:
- native
- mainwp
nullable: true
parent_multisite_website_id:
type: string
description: 'UUID of the multisite main Website if this Website is a subsite. Must belong to the same user and not itself be a subsite. Subsites inherit the Schedule from the main; only their own auto_update_checks_enabled takes effect.'
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
allowances:
type: array
description: 'The allowances of the Website.'
example:
change_detections_view: true
ai_rules_view: true
manual_checks_view: true
manual_checks_start: true
manual_checks_settings: true
manual_checks_urls: true
monitoring_checks_view: true
monitoring_checks_settings: true
monitoring_checks_urls: true
logs_view: true
settings_view: true
settings_add_urls: true
settings_account_settings: true
upgrade_account: true
wizard_start: true
only_frontpage: false
plugin_view: true
items:
type: string
sync_url_types:
type: array
description: 'The sync url types of the Website.'
example:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: pages
post_type_name: Pages
-
url_type_slug: taxonomies
url_type_name: Taxonomies
post_type_slug: category
post_type_name: Category
items:
type: string
auto_update_settings:
type: array
description: 'The auto update settings of the Website.'
example:
auto_update_checks_enabled: false
auto_update_checks_monday: true
auto_update_checks_tuesday: true
auto_update_checks_wednesday: true
auto_update_checks_thursday: true
auto_update_checks_friday: true
auto_update_checks_saturday: false
auto_update_checks_sunday: false
auto_update_checks_from: null
auto_update_checks_to: null
auto_update_checks_emails: null
allow_core_security_updates: true
items:
type: string
required:
- domain
- manual_detection_group_id
- auto_detection_group_id
'/api/v2/websites/{id}':
get:
summary: 'Get Website'
operationId: getWebsite
description: "Retrieves a `Website` object identified by its ID.\n\nOn Multisite Subsites the returned `auto_update_settings` reflects the **effective (inherited)** values: Schedule fields (timeframe, weekdays, notification emails) come from the parent main Website, while `auto_update_checks_enabled` reflects this Subsite's own toggle. The `is_multisite_subsite` boolean and the nested `parent_multisite_website` object indicate the link.\n"
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
oneOf:
-
description: ''
type: object
example:
data:
id: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
manual_detection_group: 023c282c-6513-420a-a36b-a654312ab229
auto_detection_group: 023c282c-6513-420a-a36b-a654312ab230
domain: example.com
last_seen_at: '2025-07-14T16:19:30Z'
plugin_version: 4.0.3
is_multisite_subsite: false
parent_multisite_website: null
sync_url_types:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
auto_update_settings:
auto_update_checks_enabled: false
auto_update_checks_from: '13:37'
auto_update_checks_to: '13:42'
auto_update_checks_monday: true
auto_update_checks_tuesday: true
auto_update_checks_wednesday: true
auto_update_checks_thursday: true
auto_update_checks_friday: true
auto_update_checks_saturday: false
auto_update_checks_sunday: false
auto_update_checks_emails: mail@example.com
allow_core_security_updates: true
allowances:
change_detections_view: true
ai_rules_view: true
manual_checks_view: true
manual_checks_start: true
manual_checks_settings: true
manual_checks_urls: true
monitoring_checks_view: true
monitoring_checks_settings: true
monitoring_checks_urls: true
logs_view: true
settings_view: true
settings_add_urls: true
settings_account_settings: true
upgrade_account: true
wizard_start: true
only_frontpage: false
plugin_view: true
properties:
data:
type: object
properties:
id:
type: string
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
manual_detection_group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
auto_detection_group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab230
domain:
type: string
example: example.com
last_seen_at:
type: string
example: '2025-07-14T16:19:30Z'
plugin_version:
type: string
example: 4.0.3
is_multisite_subsite:
type: boolean
example: false
parent_multisite_website:
type: string
example: null
nullable: true
sync_url_types:
type: array
example:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
items:
type: object
properties:
url_type_slug:
type: string
example: types
url_type_name:
type: string
example: 'Post Types'
post_type_slug:
type: string
example: posts
post_type_name:
type: string
example: Posts
auto_update_settings:
type: object
properties:
auto_update_checks_enabled:
type: boolean
example: false
auto_update_checks_from:
type: string
example: '13:37'
auto_update_checks_to:
type: string
example: '13:42'
auto_update_checks_monday:
type: boolean
example: true
auto_update_checks_tuesday:
type: boolean
example: true
auto_update_checks_wednesday:
type: boolean
example: true
auto_update_checks_thursday:
type: boolean
example: true
auto_update_checks_friday:
type: boolean
example: true
auto_update_checks_saturday:
type: boolean
example: false
auto_update_checks_sunday:
type: boolean
example: false
auto_update_checks_emails:
type: string
example: mail@example.com
allow_core_security_updates:
type: boolean
example: true
allowances:
type: object
properties:
change_detections_view:
type: boolean
example: true
ai_rules_view:
type: boolean
example: true
manual_checks_view:
type: boolean
example: true
manual_checks_start:
type: boolean
example: true
manual_checks_settings:
type: boolean
example: true
manual_checks_urls:
type: boolean
example: true
monitoring_checks_view:
type: boolean
example: true
monitoring_checks_settings:
type: boolean
example: true
monitoring_checks_urls:
type: boolean
example: true
logs_view:
type: boolean
example: true
settings_view:
type: boolean
example: true
settings_add_urls:
type: boolean
example: true
settings_account_settings:
type: boolean
example: true
upgrade_account:
type: boolean
example: true
wizard_start:
type: boolean
example: true
only_frontpage:
type: boolean
example: false
plugin_view:
type: boolean
example: true
-
description: 'Multisite Subsite (auto_update_settings reflect effective inherited values from the parent main Website)'
type: object
example:
data:
id: b3a9d2e5-2c64-4a16-8f1c-9e3b21f8a4e7
manual_detection_group: d4d2af0b-7a35-4b99-aa46-5c4f2bb9f1a1
auto_detection_group: d4d2af0b-7a35-4b99-aa46-5c4f2bb9f1a2
domain: shop.example.com
last_seen_at: '2025-07-14T16:19:30Z'
plugin_version: 4.0.3
is_multisite_subsite: true
parent_multisite_website:
id: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
domain: example.com
sync_url_types:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
auto_update_settings:
auto_update_checks_enabled: true
auto_update_checks_from: '13:37'
auto_update_checks_to: '13:42'
auto_update_checks_monday: true
auto_update_checks_tuesday: true
auto_update_checks_wednesday: true
auto_update_checks_thursday: true
auto_update_checks_friday: true
auto_update_checks_saturday: false
auto_update_checks_sunday: false
auto_update_checks_emails: mail@example.com
allow_core_security_updates: true
allowances:
change_detections_view: true
ai_rules_view: true
manual_checks_view: true
manual_checks_start: true
manual_checks_settings: true
manual_checks_urls: true
monitoring_checks_view: true
monitoring_checks_settings: true
monitoring_checks_urls: true
logs_view: true
settings_view: true
settings_add_urls: true
settings_account_settings: true
upgrade_account: true
wizard_start: true
only_frontpage: false
plugin_view: true
properties:
data:
type: object
properties:
id:
type: string
example: b3a9d2e5-2c64-4a16-8f1c-9e3b21f8a4e7
manual_detection_group:
type: string
example: d4d2af0b-7a35-4b99-aa46-5c4f2bb9f1a1
auto_detection_group:
type: string
example: d4d2af0b-7a35-4b99-aa46-5c4f2bb9f1a2
domain:
type: string
example: shop.example.com
last_seen_at:
type: string
example: '2025-07-14T16:19:30Z'
plugin_version:
type: string
example: 4.0.3
is_multisite_subsite:
type: boolean
example: true
parent_multisite_website:
type: object
properties:
id:
type: string
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
domain:
type: string
example: example.com
sync_url_types:
type: array
example:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
items:
type: object
properties:
url_type_slug:
type: string
example: types
url_type_name:
type: string
example: 'Post Types'
post_type_slug:
type: string
example: posts
post_type_name:
type: string
example: Posts
auto_update_settings:
type: object
properties:
auto_update_checks_enabled:
type: boolean
example: true
auto_update_checks_from:
type: string
example: '13:37'
auto_update_checks_to:
type: string
example: '13:42'
auto_update_checks_monday:
type: boolean
example: true
auto_update_checks_tuesday:
type: boolean
example: true
auto_update_checks_wednesday:
type: boolean
example: true
auto_update_checks_thursday:
type: boolean
example: true
auto_update_checks_friday:
type: boolean
example: true
auto_update_checks_saturday:
type: boolean
example: false
auto_update_checks_sunday:
type: boolean
example: false
auto_update_checks_emails:
type: string
example: mail@example.com
allow_core_security_updates:
type: boolean
example: true
allowances:
type: object
properties:
change_detections_view:
type: boolean
example: true
ai_rules_view:
type: boolean
example: true
manual_checks_view:
type: boolean
example: true
manual_checks_start:
type: boolean
example: true
manual_checks_settings:
type: boolean
example: true
manual_checks_urls:
type: boolean
example: true
monitoring_checks_view:
type: boolean
example: true
monitoring_checks_settings:
type: boolean
example: true
monitoring_checks_urls:
type: boolean
example: true
logs_view:
type: boolean
example: true
settings_view:
type: boolean
example: true
settings_add_urls:
type: boolean
example: true
settings_account_settings:
type: boolean
example: true
upgrade_account:
type: boolean
example: true
wizard_start:
type: boolean
example: true
only_frontpage:
type: boolean
example: false
plugin_view:
type: boolean
example: true
tags:
- Website
put:
summary: 'Update Website'
operationId: updateWebsite
description: "Updates the specified `Website` by setting the values of the parameters passed.\nAny parameters not provided will be left unchanged.\n"
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
id: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
domain: example.com
last_seen_at: '2025-07-14T16:19:30Z'
plugin_version: 4.0.3
manual_detection_group: 023c282c-6513-420a-a36b-a654312ab229
auto_detection_group: 023c282c-6513-420a-a36b-a654312ab230
is_multisite_subsite: false
parent_multisite_website: null
allowances:
change_detections_view: true
ai_rules_view: true
manual_checks_view: true
manual_checks_start: true
manual_checks_settings: true
manual_checks_urls: true
monitoring_checks_view: true
monitoring_checks_settings: true
monitoring_checks_urls: true
logs_view: true
settings_view: true
settings_add_urls: true
settings_account_settings: true
upgrade_account: true
wizard_start: true
only_frontpage: false
plugin_view: true
sync_url_types:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: pages
post_type_name: Pages
auto_update_settings:
auto_update_checks_enabled: false
auto_update_checks_from: '13:37'
auto_update_checks_to: '13:42'
auto_update_checks_monday: true
auto_update_checks_tuesday: true
auto_update_checks_wednesday: true
auto_update_checks_thursday: true
auto_update_checks_friday: true
auto_update_checks_saturday: false
auto_update_checks_sunday: false
auto_update_checks_emails: mail@example.com
allow_core_security_updates: true
properties:
id:
type: string
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
domain:
type: string
example: example.com
last_seen_at:
type: string
example: '2025-07-14T16:19:30Z'
plugin_version:
type: string
example: 4.0.3
manual_detection_group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab229
auto_detection_group:
type: string
example: 023c282c-6513-420a-a36b-a654312ab230
is_multisite_subsite:
type: boolean
example: false
parent_multisite_website:
type: string
example: null
nullable: true
allowances:
type: object
properties:
change_detections_view:
type: boolean
example: true
ai_rules_view:
type: boolean
example: true
manual_checks_view:
type: boolean
example: true
manual_checks_start:
type: boolean
example: true
manual_checks_settings:
type: boolean
example: true
manual_checks_urls:
type: boolean
example: true
monitoring_checks_view:
type: boolean
example: true
monitoring_checks_settings:
type: boolean
example: true
monitoring_checks_urls:
type: boolean
example: true
logs_view:
type: boolean
example: true
settings_view:
type: boolean
example: true
settings_add_urls:
type: boolean
example: true
settings_account_settings:
type: boolean
example: true
upgrade_account:
type: boolean
example: true
wizard_start:
type: boolean
example: true
only_frontpage:
type: boolean
example: false
plugin_view:
type: boolean
example: true
sync_url_types:
type: array
example:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: pages
post_type_name: Pages
items:
type: object
properties:
url_type_slug:
type: string
example: types
url_type_name:
type: string
example: 'Post Types'
post_type_slug:
type: string
example: posts
post_type_name:
type: string
example: Posts
auto_update_settings:
type: object
properties:
auto_update_checks_enabled:
type: boolean
example: false
auto_update_checks_from:
type: string
example: '13:37'
auto_update_checks_to:
type: string
example: '13:42'
auto_update_checks_monday:
type: boolean
example: true
auto_update_checks_tuesday:
type: boolean
example: true
auto_update_checks_wednesday:
type: boolean
example: true
auto_update_checks_thursday:
type: boolean
example: true
auto_update_checks_friday:
type: boolean
example: true
auto_update_checks_saturday:
type: boolean
example: false
auto_update_checks_sunday:
type: boolean
example: false
auto_update_checks_emails:
type: string
example: mail@example.com
allow_core_security_updates:
type: boolean
example: true
tags:
- Website
requestBody:
required: false
content:
application/json:
schema:
type: object
properties:
parent_multisite_website_id:
type: string
description: 'UUID of the multisite main Website. Pass null to detach. On subsites only auto_update_checks_enabled takes effect in auto_update_settings; Schedule fields are inherited from the main at read time.'
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
allowances:
type: array
description: 'The allowances of the Website.'
example:
change_detections_view: true
ai_rules_view: true
manual_checks_view: true
manual_checks_start: true
manual_checks_settings: true
manual_checks_urls: true
monitoring_checks_view: true
monitoring_checks_settings: true
monitoring_checks_urls: true
logs_view: true
settings_view: true
settings_add_urls: true
settings_account_settings: true
upgrade_account: true
wizard_start: true
only_frontpage: false
plugin_view: true
items:
type: string
sync_url_types:
type: array
description: 'The sync url types of the Website.'
example:
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: posts
post_type_name: Posts
-
url_type_slug: types
url_type_name: 'Post Types'
post_type_slug: pages
post_type_name: Pages
-
url_type_slug: taxonomies
url_type_name: Taxonomies
post_type_slug: category
post_type_name: Category
items:
type: string
auto_update_settings:
type: array
description: 'The auto update settings of the Website.'
example:
auto_update_checks_enabled: false
auto_update_checks_monday: true
auto_update_checks_tuesday: true
auto_update_checks_wednesday: true
auto_update_checks_thursday: true
auto_update_checks_friday: true
auto_update_checks_saturday: false
auto_update_checks_sunday: false
auto_update_checks_from: null
auto_update_checks_to: null
auto_update_checks_emails: null
allow_core_security_updates: true
items:
type: string
domain:
type: string
description: ''
example: null
delete:
summary: 'Delete Website'
operationId: deleteWebsite
description: "Soft-deletes a `Website` together with both of its detection groups (monitoring\nand on-demand). The underlying screenshot/comparison history is retained so\ncheck-usage counting stays correct."
parameters: []
responses:
200:
description: ''
content:
application/json:
schema:
type: object
example:
message: '{ID} deleted'
properties:
message:
type: string
example: '{ID} deleted'
tags:
- Website
parameters:
-
in: path
name: id
description: 'The ID of the Website.'
example: 91e9c9fd-b86f-4269-a3f4-f02810167a6d
required: true
schema:
type: string