{
  "openapi": "3.0.1",
  "info": {
    "title": "Booking Hotel Finder & Scraper: AI best-value shortlist",
    "description": "First 10 hotels free. Booking hotel finder: runs the Booking Scraper, drops sold-out and over-budget hotels free, ranks a hotel shortlist by value per night with AI brief match and hotel price drop alerts. Pay per result, per qualified hotel. Free demo on any plan; live search on your Apify account.",
    "version": "0.1",
    "x-build-id": "Q7DFDszOdudUxtx14"
  },
  "servers": [
    {
      "url": "https://api.apify.com/v2"
    }
  ],
  "paths": {
    "/acts/rich_minds~booking-hotel-finder-ai/run-sync-get-dataset-items": {
      "post": {
        "operationId": "run-sync-get-dataset-items-rich_minds-booking-hotel-finder-ai",
        "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/rich_minds~booking-hotel-finder-ai/runs": {
      "post": {
        "operationId": "runs-sync-rich_minds-booking-hotel-finder-ai",
        "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/rich_minds~booking-hotel-finder-ai/run-sync": {
      "post": {
        "operationId": "run-sync-rich_minds-booking-hotel-finder-ai",
        "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": [
          "sourceMode"
        ],
        "properties": {
          "destination": {
            "title": "Destination",
            "type": "string",
            "description": "City, district or hotel name as on Booking.com, e.g. <code>Lisbon</code>. Typed next to the prefilled demo, it starts the live search for you (capped by <b>Max source spend</b>). The live search runs a Store Actor on your Apify plan — if your plan cannot run Store Actors, rank a Booking dataset with the <i>dataset</i> mode."
          },
          "sourceMode": {
            "title": "Where do the hotels come from?",
            "enum": [
              "actor",
              "dataset",
              "list"
            ],
            "type": "string",
            "description": "<b>Live search</b> runs the Booking scraper picked below on your account (≈ $0.002–0.005 per property, capped by <b>Max source spend</b>). <b>Dataset</b> ranks an existing Booking scraper run. <b>List</b> ranks records you paste. <code>{}</code> over the API runs the free demo; a destination typed next to the demo searches it live.",
            "default": "actor"
          },
          "checkIn": {
            "title": "Check-in date",
            "type": "string",
            "description": "<code>YYYY-MM-DD</code> or relative, e.g. <code>30 days</code> from today. Without dates Booking shows no prices and hotels are ranked on rating only. With relative dates a schedule tracks each hotel by hotel + nights + adults, so price drops still show; fixed dates track one exact stay.",
            "default": "30 days"
          },
          "checkOut": {
            "title": "Check-out date",
            "type": "string",
            "description": "<code>YYYY-MM-DD</code> or relative, e.g. <code>32 days</code> (= 2 nights after a <code>30 days</code> check-in). Price per night = Booking's stay price ÷ nights.",
            "default": "32 days"
          },
          "maxQualified": {
            "title": "Max hotels on the shortlist",
            "minimum": 1,
            "maximum": 10000,
            "type": "integer",
            "description": "The best-value hotels are delivered first, up to this many — and the ceiling of what <b>this Actor</b> charges: at most this many × $0.01 with AI on (× $0.004 with AI off), e.g. 25 × $0.01 = $0.25. The source's own spend has its cap right below.",
            "default": 25
          },
          "maxDiscoveryChargeUsd": {
            "title": "Max source spend (USD)",
            "minimum": 0.01,
            "maximum": 1000,
            "type": "number",
            "description": "Hard cap on what the Booking scraper run may charge your account in live mode — $0.50 (≈ 100 properties with the default scraper, ≈ 166 with the $0.003 one) in the form and for an API or agent call that leaves it out. Raise it for bigger searches.",
            "default": 0.5
          },
          "notifyEmail": {
            "title": "E-mail me the shortlist (optional)",
            "type": "string",
            "description": "After every run with at least one new hotel or price drop, the digest (top 10 with price per night, rating and links) is e-mailed here through Apify's send-mail Actor. Schedule the run daily or weekly (Actions → Schedule) for price-drop alerts. Never sent for the free demo."
          },
          "discoveryActorId": {
            "title": "Booking scraper for the live search",
            "enum": [
              "voyager/booking-scraper",
              "santamaria-automations/booking-com-scraper",
              "voyager/fast-booking-scraper"
            ],
            "type": "string",
            "description": "Which Store Actor searches Booking.com on your account — most of what a run costs. The default brings the full listing (facilities, fine print, review summary); the $0.003 and $0.002 scrapers bring the search-page row — price, rating, free cancellation, meal plan — at 40–60 % less.",
            "default": "voyager/booking-scraper"
          },
          "travellerBrief": {
            "title": "Traveller brief (AI)",
            "type": "string",
            "description": "Who is travelling and what matters, in plain words. The AI scores every hotel against it with verbatim evidence from the listing and writes a why-this-hotel line. Without AI, the amenities it names are matched against Booking's facility list."
          },
          "minScore": {
            "title": "Minimum value score (0–100)",
            "minimum": 0,
            "maximum": 100,
            "type": "integer",
            "description": "The field that decides what you pay: hotels whose value score (price per night vs rating, reviews, location, cancellation — AI-adjusted with your brief) is below this are dropped and <b>not charged</b>.",
            "default": 40
          },
          "enableAi": {
            "title": "AI brief match, pros/cons & fine print",
            "type": "boolean",
            "description": "Scores each hotel against your brief with evidence quotes, writes a why-this-hotel line and pros/cons, and flags fine-print risks (city tax, deposit, cash only). <b>On = $0.01 per qualified hotel + AI tokens; off = $0.004</b> (rule-based value score, Booking's pros/cons, regex fine-print flags).",
            "default": true
          },
          "adults": {
            "title": "Adults",
            "minimum": 1,
            "maximum": 30,
            "type": "integer",
            "description": "Guests per search. Part of the price and of the stay the price-drop memory tracks.",
            "default": 2
          },
          "minRating": {
            "title": "Minimum guest rating (0–10)",
            "minimum": 0,
            "maximum": 10,
            "type": "number",
            "description": "Booking guest rating. Passed to the scraper as its <code>minScore</code> and checked again here. Hotels without a rating yet are dropped while this is above 0.",
            "default": 7.5
          },
          "maxPricePerNight": {
            "title": "Max price per night",
            "minimum": 1,
            "type": "number",
            "description": "In the currency below. Passed to Booking's price filter and checked again on the computed price per night. Empty = no budget cap."
          },
          "mustHaveAmenities": {
            "title": "Must-have amenities",
            "type": "array",
            "description": "Matched against Booking's structured facility list with synonyms (wifi, parking, pool, air conditioning, pets allowed, gym, kitchen, airport shuttle, spa, elevator …). A hotel missing one is dropped free; one at extra charge stays and is named in <code>amenitiesExtraCharge</code>.",
            "items": {
              "type": "string"
            }
          },
          "freeCancellationOnly": {
            "title": "Free cancellation only",
            "type": "boolean",
            "description": "Keep only hotels with at least one room option that can be cancelled for free.",
            "default": false
          },
          "breakfastIncludedOnly": {
            "title": "Breakfast included only",
            "type": "boolean",
            "description": "Keep only hotels with a room option whose conditions say breakfast is included.",
            "default": false
          },
          "minReviews": {
            "title": "Minimum number of reviews",
            "minimum": 0,
            "type": "integer",
            "description": "Drops properties with too few reviews to trust their rating.",
            "default": 20
          },
          "minStars": {
            "title": "Minimum stars",
            "minimum": 0,
            "maximum": 5,
            "type": "integer",
            "description": "0 = any. Checked on each property (Booking's own star filter takes one exact value only).",
            "default": 0
          },
          "children": {
            "title": "Children",
            "minimum": 0,
            "maximum": 10,
            "type": "integer",
            "description": "Number of children.",
            "default": 0
          },
          "rooms": {
            "title": "Rooms",
            "minimum": 1,
            "maximum": 30,
            "type": "integer",
            "description": "Number of rooms.",
            "default": 1
          },
          "nearPoint": {
            "title": "Near this point (latitude,longitude)",
            "type": "string",
            "description": "Your venue, beach or old town, e.g. <code>38.7139,-9.1394</code> (right-click a place in Google Maps to copy it). Every hotel gets <code>distanceKm</code> and closer ones score higher."
          },
          "maxDistanceKm": {
            "title": "Max distance (km)",
            "minimum": 0.1,
            "type": "number",
            "description": "Drops hotels farther than this from <b>Near this point</b> (free). Needs that point."
          },
          "propertyTypes": {
            "title": "Property types",
            "type": "array",
            "description": "Empty = any. One type is passed to Booking's own filter; several are filtered here on each property's type.",
            "items": {
              "type": "string",
              "enum": [
                "Hotels",
                "Apartments",
                "Guest houses",
                "Hostels",
                "Bed and breakfasts",
                "Villas",
                "Holiday homes",
                "Resorts",
                "Motels",
                "Homestays",
                "Country houses",
                "Campsites"
              ],
              "enumTitles": [
                "Hotels",
                "Apartments",
                "Guest houses",
                "Hostels",
                "Bed and breakfasts",
                "Villas",
                "Holiday homes",
                "Resorts",
                "Motels",
                "Homestays",
                "Country houses",
                "Campsites"
              ]
            }
          },
          "currency": {
            "title": "Currency",
            "enum": [
              "USD",
              "EUR",
              "GBP",
              "CHF",
              "CAD",
              "AUD",
              "NZD",
              "JPY",
              "CNY",
              "HKD",
              "SGD",
              "INR",
              "AED",
              "SAR",
              "BRL",
              "MXN",
              "ARS",
              "ZAR",
              "SEK",
              "NOK",
              "DKK",
              "PLN",
              "CZK",
              "HUF",
              "RON",
              "TRY",
              "ILS",
              "THB",
              "KRW",
              "IDR",
              "MYR",
              "PHP"
            ],
            "type": "string",
            "description": "Currency Booking shows prices in (and of <code>maxPricePerNight</code>).",
            "default": "USD"
          },
          "language": {
            "title": "Listing language",
            "enum": [
              "en-gb",
              "en-us",
              "de",
              "fr",
              "es",
              "it",
              "pt-pt",
              "pt-br",
              "nl",
              "pl",
              "cs",
              "sv",
              "da",
              "no",
              "fi",
              "el",
              "tr",
              "ru",
              "ja",
              "zh-cn",
              "ko",
              "ar",
              "he",
              "hu",
              "ro"
            ],
            "type": "string",
            "description": "Language of descriptions, facilities and policies.",
            "default": "en-gb"
          },
          "startUrls": {
            "title": "Booking.com URLs (instead of a destination)",
            "type": "array",
            "description": "Booking search result, hotel or shared-list URLs, passed to the scraper as <code>startUrls</code>; typed next to the demo, they start the live search. The live search runs a Store Actor on your Apify plan — if your plan cannot run Store Actors, use the <i>dataset</i> mode.",
            "items": {
              "type": "string"
            }
          },
          "shortlistMemo": {
            "title": "Client-ready shortlist memo",
            "type": "boolean",
            "description": "Writes a memo comparing the top 5 into the <code>SHORTLIST_MEMO</code> record and <code>OUTPUT</code> — one AI call per run with AI on, a markdown table otherwise.",
            "default": false
          },
          "onlyNewOrPriceDrop": {
            "title": "Only new hotels or price drops",
            "type": "boolean",
            "description": "Price-drop monitoring: a hotel already delivered for the same stay comes back only when its price fell by at least the percentage below — with <code>previousPrice</code> and <code>priceChangePct</code>. The stay is dates + adults, or hotel + nights + adults when the dates are relative. Off = every run delivers the full shortlist, still marked new / price_drop / unchanged.",
            "default": true
          },
          "minPriceDropPct": {
            "title": "Minimum price drop (%)",
            "minimum": 0,
            "maximum": 90,
            "type": "number",
            "description": "A remembered hotel counts as a price drop when its stay price fell by at least this much.",
            "default": 5
          },
          "slackWebhookUrl": {
            "title": "Post the new hotels to Slack (optional)",
            "type": "string",
            "description": "A Slack incoming-webhook URL (<code>https://hooks.slack.com/services/…</code>). After every run with at least one new hotel or price drop, the digest is posted to that channel as a readable message. Never sent for the free demo."
          },
          "webhookUrl": {
            "title": "Webhook URL (optional)",
            "type": "string",
            "description": "Qualified hotels are POSTed here as JSON with a Slack-ready <code>text</code> line (Zapier, Make, n8n, your app). Stored encrypted, like a key."
          },
          "webhookHeaders": {
            "title": "Webhook headers (optional)",
            "type": "object",
            "description": "Extra HTTP headers for the webhook, e.g. <code>{\"Authorization\": \"Bearer …\"}</code>. Stored encrypted — never shown in the run input."
          },
          "webhookBatchSize": {
            "title": "Webhook batch size",
            "minimum": 1,
            "maximum": 500,
            "type": "integer",
            "description": "1 = one POST per hotel the moment it is ready. Higher = one POST per N hotels.",
            "default": 1
          },
          "dedupeAcrossRuns": {
            "title": "Remember delivered hotels and prices",
            "type": "boolean",
            "description": "Keeps every delivered hotel stay and its price in a named key-value store on your account — needed for price-drop alerts. Off = every run starts fresh.",
            "default": true
          },
          "dedupeStoreName": {
            "title": "Memory store name",
            "type": "string",
            "description": "Key-value store for the cross-run memory. Left at the default, the memory is kept per traveller brief, so two clients never hide hotels from each other. Type your own name to share one memory, or keep one per trip.",
            "default": "booking-hotel-finder-ai-seen"
          },
          "llmProvider": {
            "title": "AI model access",
            "enum": [
              "apify",
              "byok"
            ],
            "type": "string",
            "description": "<b>Apify (no keys)</b> — the AI runs through Apify's built-in OpenRouter proxy; tokens are billed to your Apify account at OpenRouter's rates. <b>My own key</b> — use your OpenAI / Anthropic / Gemini / Groq key instead; a free-tier key is slower (2 calls at a time, one after a rate limit).",
            "default": "apify"
          },
          "llmModel": {
            "title": "AI model",
            "type": "string",
            "description": "Leave empty for the default (<code>anthropic/claude-haiku-4.5</code>). Apify mode takes an OpenRouter slug such as <code>openai/gpt-4.1-mini</code>; own-key mode takes <code>provider:model</code>, e.g. <code>anthropic:claude-haiku-4-5-20251001</code>."
          },
          "llmApiKey": {
            "title": "Your API key (own-key mode only)",
            "type": "string",
            "description": "Required when <b>AI model access</b> is <i>My own API key</i>. Stored encrypted by Apify, never logged."
          },
          "aiCandidateMultiplier": {
            "title": "AI candidate pool (× max hotels)",
            "minimum": 1,
            "maximum": 5,
            "type": "integer",
            "description": "How many of the best rule-scored hotels get the AI pass, as a multiple of <b>Max hotels on the shortlist</b> — best first, every one at or above the minimum value score − 15. Higher = more thorough, more tokens.",
            "default": 2
          },
          "datasetId": {
            "title": "Dataset",
            "type": "string",
            "description": "Only for <b>dataset</b> mode: a dataset of <code>voyager/booking-scraper</code> (or another Booking scraper with name, url and price / rating). Pick it so the Actor is granted read access."
          },
          "itemsList": {
            "title": "Hotels to rank",
            "type": "array",
            "description": "Only for <b>list</b> mode. JSON array of Booking records (voyager/booking-scraper fields: <code>name</code>, <code>url</code>, <code>price</code>, <code>checkInDate</code>, <code>checkOutDate</code>, <code>rating</code>, <code>reviews</code>, <code>rooms</code>, <code>facilities</code> …). The prefill is the free demo's sample."
          },
          "discoveryInput": {
            "title": "Extra source input (advanced)",
            "type": "object",
            "description": "Merged over the scraper input this Actor builds (e.g. <code>{\"flexWindow\": \"1\"}</code>). The live search runs a Store Actor on your Apify plan — if your plan cannot run Store Actors, use the <i>dataset</i> mode."
          },
          "maxToProcess": {
            "title": "Max properties to scrape",
            "minimum": 1,
            "maximum": 20000,
            "type": "integer",
            "description": "The scraper's row limit — also cut by <b>Max source spend</b> ÷ the scraper's price per property.",
            "default": 100
          },
          "targetFlags": {
            "title": "Target flags (any of)",
            "type": "array",
            "description": "Only deliver hotels with at least one of these flags, e.g. <code>free_cancellation</code>, <code>price_drop</code>, <code>top_rated</code>, <code>great_value_for_money</code> (<code>freeCancellation</code> works too); an unknown name stops the run at once with the list of valid ones.",
            "items": {
              "type": "string"
            }
          },
          "suppressionList": {
            "title": "Exclude list",
            "type": "array",
            "description": "Hotel names, URLs or hotel ids to never output. Skipped before any processing and never charged.",
            "items": {
              "type": "string"
            }
          }
        }
      },
      "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
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}