{
  "openapi": "3.0.1",
  "info": {
    "title": "Price Tracker & Monitor — Any Retailer's Prices & Stock",
    "description": "Paste product URLs from any store and get the price, currency, stock, list price and discount for each, read from the page's own structured data. Monitor mode remembers the last run and returns price drops, rises, restocks and sell-outs with a price history. No browser, no key.",
    "version": "0.1",
    "x-build-id": "cmjcg9yLpNRNgVkb8"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/insight.solutions~price-tracker-api/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-insight.solutions-price-tracker-api",
        "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/insight.solutions~price-tracker-api/runs": {
      "post": {
        "operationId": "runs-sync-insight.solutions-price-tracker-api",
        "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/insight.solutions~price-tracker-api/run-sync": {
      "post": {
        "operationId": "run-sync-insight.solutions-price-tracker-api",
        "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": "Product URLs",
            "type": "array",
            "description": "Product page URLs, one per line, on any retailer — up to 2,000. A missing scheme becomes `https://`; a `#fragment` and tracking parameters (`utm_*`, `gclid`, `fbclid`, …) are ignored when matching a URL to its earlier observations, and `?variant=` is kept, because on Shopify it is a different price. The same product written twice is read once. Category, search and home pages are recognised and returned as free `not-a-product-page` rows.",
            "items": {
              "type": "string"
            }
          },
          "mode": {
            "title": "Mode",
            "enum": [
              "snapshot",
              "monitor"
            ],
            "type": "string",
            "description": "**snapshot** reads each page and returns its price, stock and list price. **monitor** does the same and also remembers each URL's last observation in a named key-value store: the first run is the baseline, and every later run adds a `change` row for each price move, stock flip or discount it finds, plus `previousPrice` and a `priceHistory[]` on every product row. Schedule it (hourly, daily) and the dataset is your price-drop feed.",
            "default": "snapshot"
          },
          "watch": {
            "title": "Changes to report (monitor)",
            "type": "array",
            "description": "Monitor mode only. `price`: a `price-up` / `price-down` row when the price moves by at least *Minimum price change*. `availability`: `back-in-stock` / `out-of-stock` when the product flips between buyable and not (an unreadable stock state is never a flip). `discount`: `discount-started` / `discount-ended` when a list (\"was\") price appears or disappears.",
            "items": {
              "type": "string",
              "enum": [
                "price",
                "availability",
                "discount"
              ],
              "enumTitles": [
                "Price moves",
                "Stock flips",
                "Discounts starting and ending"
              ]
            },
            "default": [
              "price",
              "availability"
            ]
          },
          "minChangePct": {
            "title": "Minimum price change (%)",
            "minimum": 0,
            "maximum": 1000,
            "type": "number",
            "description": "Monitor mode only. A price move smaller than this many percent of the previous price is not a change row (the product row still carries the new price and `changePct`). `0` reports every move, down to a cent.",
            "default": 0
          },
          "historyDays": {
            "title": "Price history on each row (days)",
            "minimum": 1,
            "maximum": 90,
            "type": "integer",
            "description": "Monitor mode only. How many days of `priceHistory[]` — one point per UTC day: date, price, availability — each product row carries, so a chart needs nothing else. Up to 90 days are stored per URL.",
            "default": 30
          },
          "stateKey": {
            "title": "Watchlist name (monitor)",
            "type": "string",
            "description": "Monitor mode only. Leave empty to keep observations in the store `price-tracker-api-state`. Give each independent watchlist its own name (`competitors`, `client-acme`) so they keep separate histories and two schedules can run at the same time: the store becomes `price-tracker-api-state-<name>`.",
            "default": ""
          },
          "includeVariants": {
            "title": "Return every variant",
            "type": "boolean",
            "description": "Also return one `variant` row per priced variant — size, colour — with its own price, list price, SKU and stock, on Shopify products and on pages whose JSON-LD is a `ProductGroup`. Each variant row is billed as a product.",
            "default": false
          },
          "allowTextFallback": {
            "title": "Read the visible price when there is no structured data",
            "type": "boolean",
            "description": "The last rung: the first currency amount inside an element marked as a price, skipping struck-through, \"was\", \"compare at\" and per-month amounts. Such rows say `extractionMethod: \"visible-text\"` and `confidence: \"low\"`. Switch off to get structured-data prices only.",
            "default": true
          },
          "currencyHint": {
            "title": "Currency when the page does not say",
            "type": "string",
            "description": "An ISO 4217 code (`USD`, `EUR`, `GBP`) used only when the page itself names no currency. Without it, the domain decides (`.co.uk` → GBP, `/us/en/` → USD); with neither, `currency` is null.",
            "default": ""
          },
          "requestTimeoutSecs": {
            "title": "Request timeout (seconds)",
            "minimum": 5,
            "maximum": 120,
            "type": "integer",
            "description": "How long one page may take to answer. 5–120.",
            "default": 30
          },
          "maxConcurrency": {
            "title": "Pages at once",
            "minimum": 1,
            "maximum": 32,
            "type": "integer",
            "description": "How many pages are read in parallel, each through its own proxy session. 1–32.",
            "default": 8
          },
          "maxRunSecs": {
            "title": "Time budget (seconds)",
            "minimum": 30,
            "maximum": 3600,
            "type": "integer",
            "description": "The run stops reading new pages after this long; rows already returned are kept, and billed. URLs not reached get a free `timeout` row. 30–3,600.",
            "default": 240
          },
          "proxyConfiguration": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Every page goes through this proxy. Apify datacenter (the default) reads Shopify and WooCommerce stores, Apple, Staples, Gymshark, Brooklinen and most brand sites. Some sites behind Cloudflare need the RESIDENTIAL group — LEGO always, IKEA when its challenge is up (it comes and goes on datacenter). The big-box retailers in the README's *unsupported* column refuse both, and this Actor never bypasses a bot wall.",
            "default": {
              "useApifyProxy": true
            }
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}