{
  "openapi": "3.0.1",
  "info": {
    "title": "SaaS Pricing & Changelog Monitor",
    "description": "Reads public SaaS pricing and changelog pages into plans, prices and release notes, then reports what changed since the last run. Not a sitemap diff. Obeys robots.txt. JavaScript-only tables are flagged, not guessed.",
    "version": "1.0",
    "x-build-id": "II2bcqJCxNEdfIAa4"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/mmdincer~saas-pricing-changelog-monitor/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-mmdincer-saas-pricing-changelog-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/mmdincer~saas-pricing-changelog-monitor/runs": {
      "post": {
        "operationId": "runs-sync-mmdincer-saas-pricing-changelog-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/mmdincer~saas-pricing-changelog-monitor/run-sync": {
      "post": {
        "operationId": "run-sync-mmdincer-saas-pricing-changelog-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",
        "required": [
          "pages"
        ],
        "properties": {
          "pages": {
            "title": "Pages",
            "minItems": 1,
            "maxItems": 25,
            "type": "array",
            "description": "Public pricing, changelog or features pages, one per line. A full URL such as <code>https://buttondown.com/pricing</code> is fetched as that page. A domain such as <code>buttondown.com</code> checks only the usual paths for the page types you selected. Up to 25 per run.",
            "items": {
              "type": "string"
            }
          },
          "pageTypes": {
            "title": "Page types",
            "type": "array",
            "description": "What to read. <b>Pricing</b> is plans and prices. <b>Changelog</b> is dated release notes. <b>Features</b> is a feature list on a page that has no plan table. A URL whose path is <code>/pricing</code> is not also mined for stray changelog dates, and a <code>/changelog</code> path is not mined for stray prices.",
            "items": {
              "type": "string",
              "enum": [
                "pricing",
                "changelog",
                "features"
              ],
              "enumTitles": [
                "Pricing",
                "Changelog",
                "Features"
              ]
            },
            "default": [
              "pricing",
              "changelog"
            ]
          },
          "mode": {
            "title": "Mode",
            "enum": [
              "changes",
              "snapshot"
            ],
            "type": "string",
            "description": "<b>Changes</b> compares each page with the previous run of the same watchlist. The first run only saves a baseline. <b>Snapshot</b> returns the plans and changelog entries as they are now and does not save anything.",
            "default": "changes"
          },
          "onlyChanged": {
            "title": "Only changed pages",
            "type": "boolean",
            "description": "In changes mode, skip dataset rows for pages that match the previous run. The first run still returns the baseline. Pages that cannot be read are still returned. The quick start leaves this off, so a repeat returns the page with status unchanged and the plans or changelog that were read, and no change row. Turn it on when a scheduled watchlist should stay empty until something changes.",
            "default": true
          },
          "changeTypes": {
            "title": "Change types to report",
            "type": "array",
            "description": "Which changes become rows. Changes you leave out are not charged. The new reading is still saved, so a left-out change is not reported on a later run either. <b>extraction_failed</b> means the page could not be read and the previous baseline was kept.",
            "items": {
              "type": "string",
              "enum": [
                "plan_added",
                "plan_removed",
                "price_changed",
                "features_changed",
                "changelog_added",
                "changelog_removed",
                "feature_added",
                "feature_removed",
                "extraction_failed"
              ],
              "enumTitles": [
                "Plan added",
                "Plan removed",
                "Price changed",
                "Plan features changed",
                "Changelog entry added",
                "Changelog entry removed",
                "Feature added",
                "Feature removed",
                "Could not read the page"
              ]
            },
            "default": [
              "plan_added",
              "plan_removed",
              "price_changed",
              "features_changed",
              "changelog_added",
              "changelog_removed",
              "feature_added",
              "feature_removed",
              "extraction_failed"
            ]
          },
          "monitorName": {
            "title": "Watchlist name",
            "type": "string",
            "description": "Name of the saved baseline (changes mode). Runs with the same name compare against each other. Use different names to keep separate watchlists, for example <code>competitors</code> and <code>ours</code>.",
            "default": "default"
          },
          "maxChangelogEntries": {
            "title": "Max changelog entries",
            "minimum": 1,
            "maximum": 40,
            "type": "integer",
            "description": "How many of the newest changelog entries to keep per page. Older entries that slide out of this window are not reported as removed.",
            "default": 25
          },
          "respectRobotsTxt": {
            "title": "Respect robots.txt",
            "type": "boolean",
            "description": "Read each site's <code>robots.txt</code> and skip pages it disallows. Recommended. Skipped pages are not charged. Sitemap addresses inside robots.txt are ignored.",
            "default": true
          },
          "requestsPerSecond": {
            "title": "Requests per second (per site)",
            "minimum": 0.2,
            "maximum": 3,
            "type": "number",
            "description": "How fast pages are requested from one site. The Actor also waits for a crawl-delay of up to 10 seconds.",
            "default": 1
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Optional. Direct requests work for most public marketing pages. Turn on Apify Proxy only if a site refuses requests from the Apify platform. Proxy traffic is billed by Apify separately.",
            "default": {
              "useApifyProxy": 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
                  },
                  "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}