{
  "openapi": "3.0.1",
  "info": {
    "title": "OpenTable Scraper — Restaurants, Availability & Reviews",
    "description": "Scrape OpenTable restaurants, available reservation times and reviews from any city search or restaurant URL: ratings, price band, bookings today, address, hours, awards.",
    "version": "0.1",
    "x-build-id": "0K70YaJ0XbsaBrnIH"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/tortuga~opentable-scraper/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-tortuga-opentable-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/tortuga~opentable-scraper/runs": {
      "post": {
        "operationId": "runs-sync-tortuga-opentable-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/tortuga~opentable-scraper/run-sync": {
      "post": {
        "operationId": "run-sync-tortuga-opentable-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",
        "properties": {
          "mode": {
            "title": "What to scrape",
            "enum": [
              "restaurants",
              "reviews"
            ],
            "type": "string",
            "description": "restaurants: one item per restaurant (cuisine, price band, rating, review count, 'booked today', address, coordinates, phone, awards, photos and the reservation times free for your date, time and party size). reviews: one item per review (overall and food / service / ambience / value ratings, text, visit date, reviewer name, city and VIP flag, restaurant reply).",
            "default": "restaurants"
          },
          "searchQueries": {
            "title": "Search (city, neighbourhood, cuisine + city)",
            "type": "array",
            "description": "What you would type into OpenTable's search box: a city (\"Chicago\"), a neighbourhood (\"SoHo New York\"), a cuisine and a place (\"Italian San Francisco\") or a restaurant name. Works for every country OpenTable covers (US, UK, Canada, Australia, Germany, Mexico, Japan ...).",
            "items": {
              "type": "string"
            }
          },
          "startUrls": {
            "title": "OpenTable URLs",
            "type": "array",
            "description": "Any OpenTable domain. Search result pages (opentable.com/s?... - filters such as cuisine, price, neighbourhood in the URL are kept), city / neighbourhood pages (opentable.com/metro/chicago-restaurants) and restaurant pages (opentable.com/r/..., opentable.com/<name>, opentable.com/restaurant/profile/<id>). Restaurant pages always return full details.",
            "items": {
              "type": "object",
              "required": [
                "url"
              ],
              "properties": {
                "url": {
                  "type": "string",
                  "title": "URL of a web page",
                  "format": "uri"
                }
              }
            }
          },
          "date": {
            "title": "Reservation date",
            "type": "string",
            "description": "Date to check available times for: YYYY-MM-DD, 'today', 'tomorrow' or '+7 days' (relative dates keep a scheduled run current). Empty = tomorrow. A search URL with its own dateTime keeps it."
          },
          "time": {
            "title": "Reservation time",
            "type": "string",
            "description": "Time to check, e.g. 19:00 or 7:30 pm (restaurant local time). OpenTable returns the bookable slots around it, as on its search page. Empty = 19:00."
          },
          "partySize": {
            "title": "Party size",
            "minimum": 1,
            "maximum": 20,
            "type": "integer",
            "description": "Number of guests for the availability check (and the search).",
            "default": 2
          },
          "priceBands": {
            "title": "Price filter",
            "type": "array",
            "description": "Only restaurants in these OpenTable price bands (applies to searches). Empty = all prices.",
            "items": {
              "type": "string",
              "enum": [
                "2",
                "3",
                "4"
              ],
              "enumTitles": [
                "$$ ($30 and under)",
                "$$$ ($31 to $50)",
                "$$$$ ($50 and over)"
              ]
            }
          },
          "includeAvailability": {
            "title": "Add available reservation times",
            "type": "boolean",
            "description": "Restaurants mode: add the bookable times for the date, time and party size above (availableTimes, slot types such as bar / counter / experience). One extra request per 50 restaurants, no extra charge.",
            "default": true
          },
          "includeDetails": {
            "title": "Add restaurant details",
            "type": "boolean",
            "description": "Restaurants mode: open each restaurant found in a search for website, food / service / ambience / value ratings, rating histogram, hours, dress code, payment options, parking, executive chef, menu link, amenities and Diner's Choice awards. One extra request and the 'detail' event per restaurant. Restaurant URLs always include them.",
            "default": false
          },
          "maxItems": {
            "title": "Max items",
            "minimum": 1,
            "type": "integer",
            "description": "Stop after this many items in total (restaurants or reviews). You pay per item, so this caps the cost.",
            "default": 100
          },
          "maxRestaurantsPerSearch": {
            "title": "Max restaurants per search",
            "minimum": 1,
            "type": "integer",
            "description": "Take at most this many restaurants (OpenTable's order) from each search. Empty = no per-search cap in restaurants mode, 10 in reviews mode (reviews of the top 10 restaurants of each search)."
          },
          "maxReviewsPerRestaurant": {
            "title": "Max reviews per restaurant",
            "minimum": 1,
            "type": "integer",
            "description": "Reviews mode: newest reviews per restaurant (OpenTable orders them by visit date, 10 per page).",
            "default": 100
          },
          "reviewsNewerThan": {
            "title": "Only reviews newer than",
            "type": "string",
            "description": "Only reviews newer than: a date (YYYY-MM-DD) or a period such as '7 days' or '24 hours' (the date the review was written). Reading stops once a page's visits are more than 14 days older than this."
          },
          "onlyNewOrChanged": {
            "title": "Only new or changed items",
            "type": "boolean",
            "description": "Remember what earlier runs of this search returned and output only new items or items whose price/status changed. Use with a Schedule; unchanged items are not charged. Restaurants: compared on rating and review count; Max items is then the number of restaurants watched. Reviews: each run checks the newest 'Max reviews per restaurant' reviews and saves only reviews not seen before.",
            "default": false
          },
          "monitoringKey": {
            "title": "Monitoring key",
            "type": "string",
            "description": "Name for this watch, so several schedules on the same search stay separate; defaults to a key derived from the search input."
          },
          "proxyConfiguration": {
            "title": "Proxy",
            "type": "object",
            "description": "Apify datacenter proxy (default) is enough most of the time: every blocked attempt is retried on a fresh IP. Choose RESIDENTIAL for large runs if your datacenter IPs keep getting refused.",
            "default": {
              "useApifyProxy": true
            }
          },
          "residentialFallback": {
            "title": "Retry blocked pages through residential proxy",
            "type": "boolean",
            "description": "With Apify datacenter proxy: when OpenTable's bot protection refuses a page 4 times, retry it through Apify RESIDENTIAL proxy (Apify bills it per GB, about $0.0008 per restaurant page or per 10 reviews). Off = datacenter only.",
            "default": 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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}