{
  "openapi": "3.0.1",
  "info": {
    "title": "Website Change Monitor — Learns What to Ignore",
    "description": "Website change monitor that learns which parts of a page are noise — clocks, counters, A/B tests — and never alerts or bills you for them.",
    "version": "1.0",
    "x-build-id": "np0cLCuz67GJNZPvE"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/drkiwi~website-change-detection/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-drkiwi-website-change-detection",
        "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/drkiwi~website-change-detection/runs": {
      "post": {
        "operationId": "runs-sync-drkiwi-website-change-detection",
        "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/drkiwi~website-change-detection/run-sync": {
      "post": {
        "operationId": "run-sync-drkiwi-website-change-detection",
        "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",
        "required": [
          "urls"
        ],
        "properties": {
          "urls": {
            "title": "URLs to monitor",
            "type": "array",
            "description": "Pages to watch. Either a plain list of addresses, or objects with url, an optional label used in output and webhooks, and an optional per-page CSS selector. Duplicate URLs are removed so one page is never charged twice in a run.",
            "default": [
              {
                "url": "https://news.ycombinator.com/",
                "label": "Hacker News front page"
              }
            ]
          },
          "mode": {
            "title": "What to compare",
            "enum": [
              "text",
              "selector",
              "html"
            ],
            "type": "string",
            "description": "text compares visible page text and is the right default for almost everything. selector compares only the part matching your CSS selector. html compares raw markup and is the most sensitive — use it only when you need to catch attribute or tag changes.",
            "default": "text"
          },
          "selector": {
            "title": "CSS selector",
            "type": "string",
            "description": "Required when mode is 'selector'. The part of the page to compare, e.g. '.pricing-table' or 'main'. If it matches nothing the page is reported as an error rather than silently compared as empty."
          },
          "ignoreSelectors": {
            "title": "Ignore these elements",
            "type": "array",
            "description": "CSS selectors removed before comparing — ad slots, cookie banners, 'related posts' rails. Optional: the Actor learns recurring noise by itself, this just skips the learning period for regions you already know about.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "ignorePatterns": {
            "title": "Ignore text matching these patterns",
            "type": "array",
            "description": "JavaScript regular expressions whose matches are blanked before comparing, e.g. 'Last updated: .*' or 'Visitors: \\d+'. Timestamps, clocks, UUIDs, session tokens and cache-busting URLs are already handled automatically and do not need to be listed.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "learningRuns": {
            "title": "Comparisons before noise suppression kicks in",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "How many comparisons the Actor observes before it will judge a region as noise. Lower learns faster but risks silencing a region that only looked noisy; higher is more cautious. These comparisons are free — you are not charged for changes reported during the learning window.",
            "default": 3
          },
          "volatilityThreshold": {
            "title": "How often a region must change to count as noise",
            "minimum": 0.1,
            "maximum": 1,
            "type": "number",
            "description": "Share of observed comparisons in which a region must change before it is treated as noise. 0.6 means 'changes in at least 6 of every 10 checks'. Raise it towards 1 to suppress only relentlessly noisy regions; lower it to be more aggressive.",
            "default": 0.6
          },
          "minChangedWords": {
            "title": "Minimum changed words to report",
            "minimum": 0,
            "maximum": 10000,
            "type": "integer",
            "description": "Changes smaller than this are treated as noise: not reported, not charged. Leave at 1 to catch single-word edits such as a price. Raise it if you only care about substantial rewrites.",
            "default": 1
          },
          "confirmRuns": {
            "title": "Consecutive checks a change must survive",
            "minimum": 1,
            "maximum": 10,
            "type": "integer",
            "description": "Set above 1 to require a change to appear identically on this many consecutive checks before it is reported. This is how you filter A/B tests and rotating content, which otherwise flip back and forth. Costs you one check of delay per extra run.",
            "default": 1
          },
          "webhookUrl": {
            "title": "Webhook URL",
            "type": "string",
            "description": "If set, a POST fires for each confirmed change. Never fires for noise, baselines or unchanged pages."
          },
          "webhookSecret": {
            "title": "Webhook signing secret",
            "type": "string",
            "description": "If set, each POST carries an x-wcm-signature header: sha256 HMAC over '<timestamp>.<body>' using this secret, with the timestamp in x-wcm-timestamp. Lets your endpoint prove the request came from this Actor and has not been replayed."
          },
          "includeUnchanged": {
            "title": "Also write a row for unchanged pages",
            "type": "boolean",
            "description": "Off by default so the dataset contains only things that happened. Turn on if you want a complete audit trail of every check, including the quiet ones.",
            "default": false
          },
          "stateStoreName": {
            "title": "Named key-value store for snapshots",
            "type": "string",
            "description": "Where page snapshots and learned noise are kept between runs. Every schedule that should share memory must use the same name. Use different names to keep separate watchlists independent.",
            "default": "website-change-state"
          },
          "maxConcurrency": {
            "title": "Pages fetched in parallel",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Raise for large watchlists, lower if a target site rate-limits you.",
            "default": 5
          },
          "timeoutSecs": {
            "title": "Per-page timeout (seconds)",
            "minimum": 5,
            "maximum": 300,
            "type": "integer",
            "description": "How long to wait for one page before giving up on it. A timed-out page is reported as an error and leaves its baseline untouched, so nothing is lost.",
            "default": 45
          },
          "disableUniversalNoise": {
            "title": "Disable built-in noise patterns",
            "type": "boolean",
            "description": "Advanced. Turns off automatic handling of timestamps, clocks, relative times, UUIDs, CSRF tokens and cache-busting URLs. Only enable if you specifically need to detect changes in those values.",
            "default": false
          }
        }
      },
      "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
                  }
                }
              },
              "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}