{
  "openapi": "3.0.1",
  "info": {
    "title": "Wayfair Scraper - Furniture, Prices, Stock & Reviews",
    "description": "Scrape Wayfair.com furniture and home products by keyword or URL, including product, category, brand and sitemap links. Extract prices, discounts, ratings, variants, stock, images, specifications, dimensions and reviews. Supports scheduled price and stock change tracking.",
    "version": "0.1",
    "x-build-id": "XAIDCk3c84sHbHgto"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~wayfair-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-wayfair-scraper",
        "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/abotapi~wayfair-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-wayfair-scraper",
        "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/abotapi~wayfair-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-wayfair-scraper",
        "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": [
          "mode"
        ],
        "properties": {
          "mode": {
            "title": "Mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "Choose 'search' for keywords plus filters, or 'url' to scrape pasted Wayfair links. Each mode reads only its own field below.",
            "default": "search"
          },
          "queries": {
            "title": "Search keywords",
            "type": "array",
            "description": "Only used when mode = search, ignored in URL mode. One or more keywords, for example 'standing desk', 'area rug 8x10' or 'bar stool'.",
            "items": {
              "type": "string"
            }
          },
          "urls": {
            "title": "Wayfair links",
            "type": "array",
            "description": "Only used when mode = url, ignored in search mode. Product links (/pdp/), search links (keyword.php?keyword=...), category, brand and curated-collection pages and the store's product sitemaps (seo-pdp-sitemap~N.xml) are all accepted; other store pages are skipped with a warning. A result-page link that already carries curpage=N starts at that page, and a sortby value written into a link is kept. Tracking parameters are ignored.",
            "default": [
              "https://www.wayfair.com/keyword.php?keyword=standing+desk",
              "https://www.wayfair.com/furniture/sb0/office-chairs-c478390.html",
              "https://www.wayfair.com/furniture/sb0/office-chairs-c478390.html?curpage=3",
              "https://www.wayfair.com/brand/bnd/lark-manor-b37152.html",
              "https://www.wayfair.com/furniture/pdp/lark-manor-asyra-wide-back-tufted-swivel-task-chair-w100057029.html?piid=729629132",
              "https://www.wayfair.com/seo-pdp-sitemap~3.xml"
            ],
            "items": {
              "type": "string"
            }
          },
          "sortBy": {
            "title": "Sort by",
            "enum": [
              "relevance",
              "priceAsc",
              "priceDesc",
              "rating"
            ],
            "type": "string",
            "description": "Order of the result pages. A sort order written into a pasted link wins over this setting. The store mixes sponsored products into every ordering, so the order is not strict.",
            "default": "relevance"
          },
          "minPrice": {
            "title": "Minimum price",
            "minimum": 0,
            "type": "number",
            "description": "Only return products priced at or above this value, in the store's currency (US dollars). Applied to the returned rows."
          },
          "maxPrice": {
            "title": "Maximum price",
            "minimum": 0,
            "type": "number",
            "description": "Only return products priced at or below this value, in the store's currency (US dollars). Applied to the returned rows."
          },
          "onSaleOnly": {
            "title": "Only discounted products",
            "type": "boolean",
            "description": "Only return products that currently show a was-price above the current price.",
            "default": false
          },
          "minRating": {
            "title": "Minimum rating",
            "minimum": 0,
            "maximum": 5,
            "type": "number",
            "description": "Only return products whose average customer rating is at least this value (0 to 5)."
          },
          "brands": {
            "title": "Brands",
            "type": "array",
            "description": "Only return products from these brands. Matching ignores case and trademark signs, for example 'Lark Manor'.",
            "items": {
              "type": "string"
            }
          },
          "skipSponsored": {
            "title": "Skip sponsored products",
            "type": "boolean",
            "description": "Result pages mix paid placements in with the organic products. Turn on to leave the sponsored ones out; each returned row carries an isSponsored flag either way.",
            "default": false
          },
          "fetchDetails": {
            "title": "Read each product's page",
            "type": "boolean",
            "description": "Read every product's own page for the full description, specifications, dimensions, materials, breadcrumbs, the rating breakdown, the full image and video gallery and in-stock status for every option. Off by default because it costs one extra page per product. A pasted product link always reads the product page, because there is no result card behind it, so a product link is always billed one 'Product page detail' event whatever this toggle says.",
            "default": false
          },
          "fetchReviews": {
            "title": "Fetch customer reviews",
            "type": "boolean",
            "description": "Also collect customer reviews for each product: rating, text, date, first name, location, verified-purchase flag and the options the reviewer bought. Also reads the product page, so it carries the same per-product surcharge as the toggle above, plus one 'Customer review' event per review returned. The average rating, review count and rating breakdown do not need this.",
            "default": false
          },
          "maxReviewsPerProduct": {
            "title": "Max reviews per product",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on how many individual reviews are collected for each product when 'Fetch customer reviews' is on. The first few come with the product page; further ones are read twenty at a time. Each review returned is billed, so keep this tight.",
            "default": 20
          },
          "reviewSort": {
            "title": "Review order",
            "enum": [
              "relevance",
              "newest",
              "highest",
              "lowest"
            ],
            "type": "string",
            "description": "Which reviews come first when a product has more than the cap.",
            "default": "relevance"
          },
          "includeReviewImages": {
            "title": "Include review photos",
            "type": "boolean",
            "description": "Add the links of the photos reviewers attached to each review.",
            "default": false
          },
          "maxItems": {
            "title": "Max products",
            "minimum": 0,
            "maximum": 100000,
            "type": "integer",
            "description": "Maximum number of products to return across the whole run, EXPIRED rows from Incremental mode included. This is the run's cap. Use 0 for the maximum of 100000 products per run.",
            "default": 20
          },
          "maxPages": {
            "title": "Max result pages per keyword or link",
            "minimum": 0,
            "type": "integer",
            "description": "Maximum number of result pages to take per keyword or link. Each page carries about 48 products. 0 = no page limit set; the run then stops at Max products, when there are no more results, when the store stops serving new products for the search, or at a safety limit of 4167 pages per keyword or link (far above what Max products can reach). When a limit you set here stops a search that still had results, the log says so.",
            "default": 0
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Connection used for every request. Leave the default; the run escalates on its own when the store refuses a page. Choose residential for the most reliable results.",
            "default": {
              "useApifyProxy": true
            }
          },
          "resumeFromRunId": {
            "title": "Resume from a previous run",
            "type": "string",
            "description": "Paste a previous run ID or dataset ID to continue a large catalogue pull without returning or charging for products already collected there. Use this after an interrupted run. For recurring monitoring of the same search, use Incremental mode below instead."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "Turn this on for daily or recurring monitoring. The first run returns every matching product as NEW. Later runs normally return only NEW, UPDATED and REAPPEARED products, which makes it a cheap way to watch price drops and restocks. What is compared: price, was-price, discount, on-sale flag, stock status, the option list with per-option stock, name, brand, description, specifications, dimensions and categories. What is excluded by default (still returned in the row, never a change): scrape timestamps, the product's rank and page in the results, the sponsored flag, delivery promise and arrival date, the live units-left message, how the product was found, image and video links, and ratings and reviews (average rating, review count, rating breakdown, review summary and the review sample). Option and material lists are compared regardless of the order the store returns them. 'Changes to watch' narrows this to price and stock only. Turn on 'Emit unchanged' or 'Emit expired' only when you also want those rows returned (and billed). State is kept separately for each search and filter setup; use State key to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.",
            "default": false
          },
          "stateKey": {
            "title": "State key (incremental mode only)",
            "type": "string",
            "description": "Optional. Name this monitoring campaign to keep its state stable, or to deliberately share state across differently configured runs. Leave empty to derive a key automatically from the search and filter settings, so two different searches never mix state."
          },
          "emitUnchanged": {
            "title": "Emit unchanged products (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return products that have not changed since the last run, marked UNCHANGED. This returns, and bills, extra rows you already have, so leave it off unless you want a full snapshot every run.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired products (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return products that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked search, never when Max products capped it or Resume was used. EXPIRED rows count against Max products: a run returns at most the room left under it, and the rest are returned on a later complete run. This returns, and bills, extra rows, so leave it off unless you need expiry tracking.",
            "default": false
          },
          "changeScope": {
            "title": "Changes to watch (incremental mode only)",
            "enum": [
              "all",
              "priceAndStock"
            ],
            "type": "string",
            "description": "All fields (default): any change to the compared product data marks a product UPDATED. Price and stock only: just price, was-price, discount, on-sale flag, stock status and per-option stock count, so name, description or specification edits never produce a billable UPDATED row. Changing this never starts a new baseline: the existing saved state is kept (under an automatic or a named State key) and each stored product is simply compared under the new setting.",
            "default": "all"
          },
          "compactUpdates": {
            "title": "Compact UPDATED rows (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. When on, UPDATED and EXPIRED rows are slim: ids, link, title, current price and stock, plus priceChanges (old and new value of each field that moved) and variantChanges (per-option ADDED, REMOVED or CHANGED). NEW rows stay full. A compact row does not carry product-page detail fields or reviews, so no detail or review charge applies to it.",
            "default": false
          },
          "expireAfterMissedScans": {
            "title": "Expire after missed scans (incremental mode only)",
            "minimum": 1,
            "maximum": 30,
            "type": "integer",
            "description": "Used with 'Emit expired'. A product is marked EXPIRED only after it was missing from this many CONSECUTIVE complete scans (default 1). EXPIRED means the product dropped out of the scanned results; it does not prove the product is unavailable, because no product page is opened. Check stockStatus for availability.",
            "default": 1
          },
          "ignoreFieldsForChanges": {
            "title": "Ignore fields when detecting changes (incremental mode only)",
            "type": "array",
            "description": "Field names that must not count as a change, for example name or promoFlag. Use a dotted path to ignore a key inside every element of a list, for example options.url. Ignored fields are still returned in the row. Rank, sponsored flag, delivery text, media links and ratings and reviews are already ignored by default. Changing this list never starts a new baseline: the saved state is kept and each stored product is re-compared under the new list, so no product comes back as NEW.",
            "items": {
              "type": "string"
            }
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send results into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize one under Apify, Settings, API & Integrations, then select it here. Notion gets a page per product; other connectors get a best-effort write or digest. Each connector receives a condensed summary per product, not the full record; the complete record always stays in the dataset. Leave empty to skip; this never changes the dataset output. Supported: Notion (https://mcp.notion.com/mcp), Linear (https://mcp.linear.app/sse), Airtable (https://mcp.airtable.com/mcp), Apify (https://mcp.apify.com)."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page (Notion connector only)",
            "type": "string",
            "description": "URL or id of the Notion page under which product pages are created. Required to enable the Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max items to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on products written to each connector per run. Does not affect the dataset.",
            "default": 50
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}