{
  "openapi": "3.0.1",
  "info": {
    "title": "Viator Scraper – Tours, Activities, Prices & Availability",
    "description": "Collect Viator.com tour and activity results from destinations, categories, search pages, or pasted URLs. Returns product codes, prices, ratings, reviews, images, availability, source context, and optional detail fields.",
    "version": "0.1",
    "x-build-id": "QraMmSOvenqIBsppv"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~viator-com-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-viator-com-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~viator-com-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-viator-com-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~viator-com-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-viator-com-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",
          "maxItems"
        ],
        "properties": {
          "mode": {
            "title": "Mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "Choose destination/category search or URL list mode.",
            "default": "search"
          },
          "destination": {
            "title": "Destination",
            "enum": [
              "boston",
              "new_york",
              "las_vegas",
              "london",
              "paris",
              "rome",
              "sydney"
            ],
            "type": "string",
            "description": "Search mode destination preset. It selects the Viator listing page that search mode walks, so it applies in search mode only and is ignored in URL mode.",
            "default": "boston"
          },
          "destinationQuery": {
            "title": "Destination (type a name)",
            "type": "string",
            "description": "Optional. Type a destination name (for example Lisbon) instead of using the list above. The name is looked up on Viator and used only when it resolves to a destination page with a matching name; otherwise the run stops with a clear message. Leave empty to use the destination list. Search mode only; ignored in URL mode. Category still applies.",
            "default": ""
          },
          "category": {
            "title": "Category",
            "enum": [
              "tours_sightseeing",
              "bus_tours",
              "day_trips",
              "walking_tours",
              "food_drink",
              "attractions_tickets"
            ],
            "type": "string",
            "description": "Search mode category preset. It selects the Viator listing page that search mode walks, so it applies in search mode only and is ignored in URL mode.",
            "default": "tours_sightseeing"
          },
          "urls": {
            "title": "URLs",
            "type": "array",
            "description": "Viator destination page, category listing, or single product URLs (a product URL returns one row for that exact product, with description, images, reviews and itinerary only when Fetch details is on). A search-results link works only when Viator redirects it to a destination page; free-text activity searches are not supported. Used only in URL mode; left untouched it scrapes one example of each supported shape. The filter and sort fields in the next section still apply to every row a pasted URL returns.",
            "items": {
              "type": "string"
            },
            "default": [
              "https://www.viator.com/Boston-tours/Bus-and-Minivan-Tours/d678-g12-c98",
              "https://www.viator.com/Boston/d678-ttd",
              "https://www.viator.com/tours/Boston/Boston-Hop-On-Hop-Off-All-Day-Sightseeing-Tour/d678-358782P2"
            ]
          },
          "keyword": {
            "title": "Keyword",
            "type": "string",
            "description": "Optional keyword that must appear in the activity name, URL, destination, or category text. Leave empty to keep all results. Applies in both search mode and URL mode, including a pasted listing URL."
          },
          "minPrice": {
            "title": "Min price",
            "minimum": 0,
            "type": "number",
            "description": "Minimum listed price. Leave empty for no minimum. Applies in both search mode and URL mode, including a pasted listing URL."
          },
          "maxPrice": {
            "title": "Max price",
            "minimum": 0,
            "type": "number",
            "description": "Maximum listed price. Leave empty for no maximum. Applies in both search mode and URL mode, including a pasted listing URL."
          },
          "currency": {
            "title": "Currency",
            "enum": [
              "",
              "USD",
              "AUD",
              "EUR",
              "GBP",
              "CAD",
              "NZD",
              "SGD"
            ],
            "type": "string",
            "description": "Keep only rows with this currency, or Any to keep all returned currencies. Applies in both search mode and URL mode, including a pasted listing URL.",
            "default": ""
          },
          "minRating": {
            "title": "Min rating",
            "minimum": 0,
            "maximum": 5,
            "type": "number",
            "description": "Minimum aggregate rating. Applies in both search mode and URL mode, including a pasted listing URL."
          },
          "minReviews": {
            "title": "Min reviews",
            "minimum": 0,
            "type": "integer",
            "description": "Minimum review count. Applies in both search mode and URL mode, including a pasted listing URL."
          },
          "availability": {
            "title": "Availability",
            "enum": [
              "",
              "InStock"
            ],
            "type": "string",
            "description": "Filter by availability value. Applies in both search mode and URL mode, including a pasted listing URL.",
            "default": ""
          },
          "sortBy": {
            "title": "Sort",
            "enum": [
              "source",
              "price_asc",
              "price_desc",
              "rating_desc",
              "reviews_desc"
            ],
            "type": "string",
            "description": "Choose the result order: price, rating, review count, or original source order. Applies in both search mode and URL mode, including a pasted listing URL. A price, rating or review-count sort is applied across all crawled pages: the run keeps crawling until it holds Max items matching rows (or reaches Max pages or the end of the results), then sorts them together. Source order saves each page as it is read.",
            "default": "source"
          },
          "fetchDetails": {
            "title": "Fetch details",
            "type": "boolean",
            "description": "Try product pages for additional fields when available. Results are still saved if detail pages are unavailable.",
            "default": false
          },
          "maxReviewsPerProduct": {
            "title": "Max reviews per product",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "Most reviews to keep per product when Fetch details is on (newest first across all sources, each with its language). If the full review list cannot be read, up to 30 reviews from the product page are kept instead.",
            "default": 20
          },
          "maxItems": {
            "title": "Max items",
            "minimum": 1,
            "maximum": 100000,
            "type": "integer",
            "description": "Maximum matching rows to save. Fewer rows can be returned when the selected source and filters match fewer live records.",
            "default": 20
          },
          "maxPages": {
            "title": "Max pages",
            "minimum": 0,
            "type": "integer",
            "description": "No page limit when set to 0. The run stops at Max items, or earlier if the results end.",
            "default": 0
          },
          "proxy": {
            "title": "Proxy",
            "type": "object",
            "description": "Residential proxy is recommended for this site. Cheaper proxy tiers can return fewer usable pages or block.",
            "default": {
              "useApifyProxy": true,
              "apifyProxyGroups": [
                "RESIDENTIAL"
              ]
            }
          },
          "resumeFromRunId": {
            "title": "Resume from a previous run (delta)",
            "type": "string",
            "description": "Optional. ID of a previous run of this actor (or a dataset ID). Products already in that dataset are skipped, so this run returns only products it did not have. Combine both datasets for the full set. For recurring monitoring of the same search, use Incremental mode below."
          },
          "incrementalMode": {
            "title": "Incremental changes for scheduled runs",
            "type": "boolean",
            "description": "Turn on for daily or recurring monitoring. The first run returns every matching product as NEW. Later runs return only NEW, UPDATED and REAPPEARED products; each row gets changeType, changedFields, firstSeenAt and lastSeenAt. A product is UPDATED when a real field changes (price, rating, review count, name and similar); scrapedAt, the listing rank (position) and the review bodies never count as changes (review count and rating do). Prices are shown in the local currency of the connection used, so a run that lands on a different country can read as UPDATED on offerPrice and offerCurrency; pick a Currency filter or add those two fields to the ignore list below if that is not wanted. State is kept separately for each mode, destination, category, URL set and filter setup; use State key to name or deliberately share a campaign. Unchanged and expired rows are only returned (and billed as result rows) when you turn those options on.",
            "default": false
          },
          "stateKey": {
            "title": "State key (optional, 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 from the mode, destination, category, URLs and filters, so 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 did not change since the last run, marked UNCHANGED. This returns and bills extra rows you already have.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired products (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return products that were seen in an earlier run but are no longer found, marked EXPIRED. Only produced when the run scanned every source to a confirmed end of results: not when Max items or Max pages cut it short, and not when Resume was used. This returns and bills extra rows.",
            "default": false
          },
          "ignoreFieldsForChanges": {
            "title": "Ignore fields when detecting changes (incremental mode only)",
            "type": "array",
            "description": "Output field names that should NOT make a product count as UPDATED, for example image or locationName. Use a dotted path to ignore a field inside a nested object. Ignored fields are still returned in the output.",
            "default": [],
            "items": {
              "type": "string"
            }
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send the scraped tours into the apps you already use, via Model Context Protocol (MCP) connectors. Authorize a connector once under Apify → Settings → Integrations, then select it here. The connector receives a condensed, human-readable summary per tour (name + key fields), not the full JSON. The complete record stays in the dataset. Leave empty to skip. 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 tour 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 items 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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}