{
  "openapi": "3.0.1",
  "info": {
    "title": "Website Change Detection: Page Diff Alerts",
    "description": "Watch many web pages for changes and get the exact lines or links that were added or removed. Scope it to one part of a page, ignore timestamps, render JavaScript when needed, and get alerts by email, Slack, Discord or webhook. Failed checks are free.",
    "version": "0.1",
    "x-build-id": "Gnt2KQ4FowTmrspaW"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/fernandosord~website-change-monitor/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-fernandosord-website-change-monitor",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/acts/fernandosord~website-change-monitor/runs": {
      "post": {
        "operationId": "runs-sync-fernandosord-website-change-monitor",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor and returns information about the initiated run in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/runsResponseSchema"
                }
              }
            }
          }
        }
      }
    },
    "/acts/fernandosord~website-change-monitor/run-sync": {
      "post": {
        "operationId": "run-sync-fernandosord-website-change-monitor",
        "x-openai-isConsequential": false,
        "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
        "tags": [
          "Run Actor"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/inputSchema"
              }
            }
          }
        },
        "parameters": [
          {
            "name": "token",
            "in": "query",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Enter your Apify token here"
          }
        ],
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "inputSchema": {
        "type": "object",
        "properties": {
          "urls": {
            "title": "Pages to watch",
            "type": "array",
            "description": "Full URLs of the pages to check, for example a pricing page, a changelog, a terms page or a product page. Each run compares every page with the version saved by the previous run under the same watch list name. The first run saves a baseline.",
            "items": {
              "type": "string"
            }
          },
          "selector": {
            "title": "Part of the page to watch (CSS selector)",
            "type": "string",
            "description": "Only this part of each page is compared, for example <code>main</code>, <code>#pricing</code> or <code>.release-list</code>. Leave empty to watch the whole page body. Watching a smaller part avoids alerts from menus, footers and rotating banners."
          },
          "compareMode": {
            "title": "What to compare",
            "enum": [
              "text",
              "links"
            ],
            "type": "string",
            "description": "<b>Visible text</b> reports lines that were added or removed. <b>Links only</b> reports new and removed links, which suits listing pages such as blogs, job pages, product catalogs and RSS or Atom feeds.",
            "default": "text"
          },
          "ignoreSelectors": {
            "title": "Ignore elements (CSS selectors)",
            "type": "array",
            "description": "Elements removed before comparing, for example <code>.ad</code>, <code>#related-posts</code> or <code>time</code>. Scripts, styles, hidden elements and common cookie banners are always ignored.",
            "items": {
              "type": "string"
            }
          },
          "ignorePatterns": {
            "title": "Ignore text matching (regular expressions)",
            "type": "array",
            "description": "Text that matches is deleted before comparing, so it can't trigger an alert. Useful for counters and timestamps, for example <code>\\d+ (minutes|hours) ago</code> or <code>Updated: .*</code>. Matching ignores case.",
            "items": {
              "type": "string"
            }
          },
          "minChangedCharacters": {
            "title": "Minimum change size (characters)",
            "minimum": 1,
            "type": "integer",
            "description": "A change smaller than this many added plus removed characters is not reported. The saved version is kept, so small edits add up until they reach the limit.",
            "default": 1
          },
          "renderJavaScript": {
            "title": "Render JavaScript",
            "type": "boolean",
            "description": "Load pages in a real Chrome browser. Turn this on for pages that build their content with JavaScript (the result shows \"no text\" or a missing selector without it). It is slower and has a higher per-page price.",
            "default": false
          },
          "waitForSelector": {
            "title": "Wait for element (browser only)",
            "type": "string",
            "description": "With \"Render JavaScript\" on, wait up to 20 s for this CSS selector to appear before reading the page."
          },
          "waitSecs": {
            "title": "Extra wait (browser only)",
            "minimum": 0,
            "maximum": 30,
            "type": "integer",
            "description": "With \"Render JavaScript\" on, wait this many seconds after the page loads before reading it.",
            "default": 0
          },
          "screenshotOnChange": {
            "title": "Screenshot changed pages",
            "type": "boolean",
            "description": "When a page changes, save a JPEG of the watched part (or of the top of the page) and add its link to the result. Works with or without \"Render JavaScript\". Charged per screenshot.",
            "default": false
          },
          "screenshotSelector": {
            "title": "Screenshot area (CSS selector)",
            "type": "string",
            "description": "Element to capture in the screenshot. Leave empty to use the watched part."
          },
          "notificationEmails": {
            "title": "Email alerts to",
            "type": "array",
            "description": "Up to 5 email addresses, one per line. When at least one page changed, the run sends one email with each changed page, its change summary, the first added and removed lines and the screenshot link. No email is sent when nothing changed. Emails go out through Apify's free <code>apify/send-mail</code> Actor from your account; on the Apify free plan it can only send to your account's own email address.",
            "items": {
              "type": "string"
            }
          },
          "emailSubjectPrefix": {
            "title": "Email subject prefix",
            "type": "string",
            "description": "Optional text put in front of the email subject, for example <code>[Competitors]</code>, so you can filter the alerts. Up to 60 characters."
          },
          "webhookUrl": {
            "title": "Webhook URL",
            "type": "string",
            "description": "Optional. When at least one page changed, the run sends a POST to this https URL: a Slack or Discord incoming-webhook URL, or any endpoint that accepts JSON (Zapier, Make, n8n, your own server)."
          },
          "webhookFormat": {
            "title": "Webhook format",
            "enum": [
              "json",
              "slack",
              "discord"
            ],
            "type": "string",
            "description": "<b>JSON</b> sends the full change rows. <b>Slack</b> and <b>Discord</b> send a readable message with the added and removed lines.",
            "default": "json"
          },
          "notifyOnErrors": {
            "title": "Also notify about pages that failed",
            "type": "boolean",
            "description": "Also send the email and webhook message when pages could not be checked (blocked, missing selector, not found), and list those pages in it.",
            "default": false
          },
          "onlyChanges": {
            "title": "Only output changed pages",
            "type": "boolean",
            "description": "Leave off to get one row per page every run (changed, unchanged, baseline or failed). Turn on to get rows only for pages that changed, which suits integrations that act on every new dataset row.",
            "default": false
          },
          "stateKey": {
            "title": "Watch list name",
            "type": "string",
            "description": "Saved versions are kept per watch list. Use a different name for each task, so separate lists don't share history. Renaming starts a fresh baseline.",
            "default": "default"
          },
          "pages": {
            "title": "Pages with their own settings",
            "type": "array",
            "description": "Optional JSON list for pages that need different settings, for example <code>[{\"url\": \"https://example.com/pricing\", \"selector\": \"#plans\", \"label\": \"Pricing\"}]</code>. Each item can set <code>url</code>, <code>label</code>, <code>selector</code>, <code>compareMode</code>, <code>ignoreSelectors</code>, <code>ignorePatterns</code>, <code>renderJavaScript</code>, <code>waitForSelector</code>, <code>waitSecs</code> and <code>screenshotSelector</code>. Anything left out uses the settings above."
          },
          "respectRobotsTxt": {
            "title": "Respect robots.txt",
            "type": "boolean",
            "description": "Skip pages that the site's robots.txt asks automated visitors not to open. Turn off only for sites you own or have permission to monitor.",
            "default": true
          },
          "maxConcurrency": {
            "title": "Pages checked at once",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Requests to the same site are always spaced at least 1 s apart (or by the site's Crawl-delay). At most 2 pages render in Chrome at a time.",
            "default": 5
          },
          "timeoutSecs": {
            "title": "Page timeout",
            "minimum": 5,
            "maximum": 120,
            "type": "integer",
            "description": "How long to wait for each page before reporting it as failed.",
            "default": 30
          }
        }
      },
      "runsResponseSchema": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "id": {
                "type": "string"
              },
              "actId": {
                "type": "string"
              },
              "userId": {
                "type": "string"
              },
              "startedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "finishedAt": {
                "type": "string",
                "format": "date-time",
                "example": "2025-01-08T00:00:00.000Z"
              },
              "status": {
                "type": "string",
                "example": "READY"
              },
              "meta": {
                "type": "object",
                "properties": {
                  "origin": {
                    "type": "string",
                    "example": "API"
                  },
                  "userAgent": {
                    "type": "string"
                  }
                }
              },
              "stats": {
                "type": "object",
                "properties": {
                  "inputBodyLen": {
                    "type": "integer",
                    "example": 2000
                  },
                  "rebootCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "restartCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "resurrectCount": {
                    "type": "integer",
                    "example": 0
                  },
                  "computeUnits": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "options": {
                "type": "object",
                "properties": {
                  "build": {
                    "type": "string",
                    "example": "latest"
                  },
                  "timeoutSecs": {
                    "type": "integer",
                    "example": 300
                  },
                  "memoryMbytes": {
                    "type": "integer",
                    "example": 1024
                  },
                  "diskMbytes": {
                    "type": "integer",
                    "example": 2048
                  }
                }
              },
              "buildId": {
                "type": "string"
              },
              "defaultKeyValueStoreId": {
                "type": "string"
              },
              "defaultDatasetId": {
                "type": "string"
              },
              "defaultRequestQueueId": {
                "type": "string"
              },
              "buildNumber": {
                "type": "string",
                "example": "1.0.0"
              },
              "containerUrl": {
                "type": "string"
              },
              "usage": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "integer",
                    "example": 1
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              },
              "usageTotalUsd": {
                "type": "number",
                "example": 0.00005
              },
              "usageUsd": {
                "type": "object",
                "properties": {
                  "ACTOR_COMPUTE_UNITS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATASET_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "KEY_VALUE_STORE_WRITES": {
                    "type": "number",
                    "example": 0.00005
                  },
                  "KEY_VALUE_STORE_LISTS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_READS": {
                    "type": "integer",
                    "example": 0
                  },
                  "REQUEST_QUEUE_WRITES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_INTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "DATA_TRANSFER_EXTERNAL_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_SERPS": {
                    "type": "integer",
                    "example": 0
                  },
                  "PROXY_UNBLOCKER_UNITS": {
                    "type": "integer",
                    "example": 0
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}