{
  "openapi": "3.0.1",
  "info": {
    "title": "OpenTable Reviews Scraper – Restaurants, Ratings & Diner Data",
    "description": "Scrape full OpenTable.com restaurant reviews by keyword, area, or restaurant profile URLs. Collect every available review with text, ratings, diner profile data, tags, photos, restaurant metadata, cuisines, neighborhood, and profile links in structured rows.",
    "version": "0.2",
    "x-build-id": "dimniAgevRZ3eYFhg"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/abotapi~opentable-reviews-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-abotapi-opentable-reviews-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~opentable-reviews-scraper/runs": {
      "post": {
        "operationId": "runs-sync-abotapi-opentable-reviews-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~opentable-reviews-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-abotapi-opentable-reviews-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": "Input mode",
            "enum": [
              "search",
              "url"
            ],
            "type": "string",
            "description": "Search mode discovers restaurants around the selected coordinates and collects their full review history. URL mode takes pasted restaurant profile links and collects every review for each one.",
            "default": "search"
          },
          "keywords": {
            "title": "Keywords",
            "type": "array",
            "description": "Restaurant, cuisine, or dining terms to search. Examples: sushi, steakhouse, rooftop, vegan.",
            "items": {
              "type": "string"
            }
          },
          "location": {
            "title": "Location",
            "type": "string",
            "description": "City, neighborhood, or address to search around (keyword search mode). For example: New York, Chelsea Manhattan, or 90210. The actor resolves this to map coordinates automatically.",
            "default": "New York"
          },
          "latitude": {
            "title": "Latitude (advanced)",
            "type": "number",
            "description": "Optional. Exact latitude to search around. When both latitude and longitude are set they override Location."
          },
          "longitude": {
            "title": "Longitude (advanced)",
            "type": "number",
            "description": "Optional. Exact longitude to search around. When both latitude and longitude are set they override Location."
          },
          "startUrls": {
            "title": "OpenTable restaurant URLs",
            "type": "array",
            "description": "Paste OpenTable restaurant profile URLs such as https://www.opentable.com/r/yakiniku-shodai-san-francisco.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "maxItems": {
            "title": "Max items",
            "minimum": 1,
            "maximum": 1000000,
            "type": "integer",
            "description": "Maximum review rows to save across the whole run. The run can return fewer rows when OpenTable has fewer matching reviews.",
            "default": 20
          },
          "maxReviewsPerRestaurant": {
            "title": "Max reviews per restaurant",
            "minimum": 1,
            "maximum": 1000000,
            "type": "integer",
            "description": "Optional cap on how many reviews to collect from each restaurant. Leave empty to collect every available review for each restaurant (bounded only by Max items)."
          },
          "maxRestaurants": {
            "title": "Max restaurants per keyword",
            "minimum": 1,
            "maximum": 100,
            "type": "integer",
            "description": "Keyword search only. How many restaurants around the coordinates to collect reviews from per keyword.",
            "default": 50
          },
          "reviewSort": {
            "title": "Review sort order",
            "enum": [
              "highestRated",
              "newest",
              "lowestRated"
            ],
            "type": "string",
            "description": "Order of reviews returned for each restaurant.",
            "default": "highestRated"
          },
          "minOverallRating": {
            "title": "Minimum overall rating",
            "minimum": 1,
            "maximum": 5,
            "type": "number",
            "description": "Only keep reviews with at least this overall review rating."
          },
          "minFoodRating": {
            "title": "Minimum food rating",
            "minimum": 1,
            "maximum": 5,
            "type": "number",
            "description": "Only keep reviews with at least this food rating."
          },
          "minServiceRating": {
            "title": "Minimum service rating",
            "minimum": 1,
            "maximum": 5,
            "type": "number",
            "description": "Only keep reviews with at least this service rating."
          },
          "minAmbienceRating": {
            "title": "Minimum ambience rating",
            "minimum": 1,
            "maximum": 5,
            "type": "number",
            "description": "Only keep reviews with at least this ambience rating."
          },
          "minValueRating": {
            "title": "Minimum value rating",
            "minimum": 1,
            "maximum": 5,
            "type": "number",
            "description": "Only keep reviews with at least this value rating."
          },
          "cuisines": {
            "title": "Cuisine filter",
            "type": "array",
            "description": "Only keep restaurants whose primary or secondary cuisine contains at least one value.",
            "items": {
              "type": "string"
            }
          },
          "neighborhoods": {
            "title": "Neighborhood filter",
            "type": "array",
            "description": "Only keep restaurants whose neighborhood contains at least one value.",
            "items": {
              "type": "string"
            }
          },
          "fromDinedDate": {
            "title": "Dined from",
            "type": "string",
            "description": "Only keep reviews with a dined date on or after this YYYY-MM-DD date."
          },
          "toDinedDate": {
            "title": "Dined to",
            "type": "string",
            "description": "Only keep reviews with a dined date on or before this YYYY-MM-DD date."
          },
          "vipOnly": {
            "title": "VIP reviewers only",
            "type": "boolean",
            "description": "Only keep reviews where OpenTable marks the reviewer as VIP.",
            "default": false
          },
          "requireReviewPhotos": {
            "title": "Require review photos",
            "type": "boolean",
            "description": "Only keep reviews that include diner photos.",
            "default": false
          },
          "resumeFromRunId": {
            "title": "Resume from a previous run",
            "type": "string",
            "description": "Paste a previous run ID or dataset ID to continue a large review pull without returning or charging for reviews already collected there. Use this after an interrupted run, or when continuing a large restaurant's review history in another run. For recurring monitoring of the same search or restaurants, 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 all matching reviews as NEW. Later runs normally return only NEW, UPDATED, and REAPPEARED reviews. Turn on \"Emit unchanged\" or \"Emit expired\" only when you also want those reviews returned (and billed). State is kept separately for each search/URL and filter setup; use State key when you want to name or deliberately share a monitoring campaign. To continue one specific interrupted run instead, use Resume from a previous run above.",
            "default": false
          },
          "emitUnchanged": {
            "title": "Emit unchanged reviews (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return reviews 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 specifically want the full snapshot every run.",
            "default": false
          },
          "emitExpired": {
            "title": "Emit expired reviews (incremental mode only)",
            "type": "boolean",
            "description": "Off by default. Turn on to also return reviews that were present in a previous run but are no longer found, marked EXPIRED. Only produced once a run has fully scanned the tracked restaurants — not when Max items capped it, when Resume was used, or when a keyword search may have been truncated. This returns — and bills — extra synthetic rows, so leave it off unless you need expiry tracking.",
            "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 let the actor derive a key automatically from the search/URL and filter settings — different searches then never mix state with each other."
          },
          "proxy": {
            "title": "Proxy configuration",
            "type": "object",
            "description": "Connection routing for the run. The default is the right one for OpenTable and works on every Apify plan; only change it if your environment requires a specific route.",
            "default": {
              "useApifyProxy": true
            }
          },
          "mcpConnectors": {
            "title": "Pipe results into your apps (optional)",
            "type": "array",
            "description": "Optionally send scraped review rows into connected apps via Model Context Protocol connectors. Authorize a connector under Apify > Settings > API & Integrations, then select it here. Supported: Notion, Linear, Airtable, and Apify."
          },
          "notionParentPageUrl": {
            "title": "Notion parent page",
            "type": "string",
            "description": "URL or id of the Notion page under which review pages are created. Required for Notion export; ignored by other connectors."
          },
          "maxNotifyListings": {
            "title": "Max reviews to export per connector",
            "minimum": 1,
            "maximum": 1000,
            "type": "integer",
            "description": "Cap on how many review rows are written to each selected 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
                  }
                }
              },
              "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}