Skip to content

POST /v1/concierge ​

Returns the concierge result set for a stay: the resolved hotel, nearby food and beverage venues, nearby attractions, and events happening during the stay. The response is a single JSON document.

http
POST /v1/concierge
Authorization: Bearer <token>
Content-Type: application/json

Request body ​

Send exactly the fields below. Any unknown field is rejected with 400 so typos surface immediately.

FieldTypeRequiredDefaultNotes
hotelPlaceIdstringno—Bare Overlook place id. When present, the hotel name fields are optional.
hotelNamestringyes*—Name of the hotel. *Required unless hotelPlaceId is supplied.
hotelAddressstringno""Street address; helps disambiguate resolution.
hotelCitystringyes*—City. *Required unless hotelPlaceId is supplied.
hotelStatestringyes*—State/region code, e.g. "ME". *Required unless hotelPlaceId is supplied.
checkinDatestringyes—Date the stay begins. Must parse as a date.
checkoutDatestringyes—Date the stay ends; must be on or after checkinDate.
roomRateintegerno0Nightly rate in USD. Used as a price/quality signal.
adultsintegerno1Number of adults.
childrenintegerno0Number of children.
accessibleRoomstringno"no"Accessible-room flag, e.g. "yes" / "no".
loyaltyProgramstringno"no"Loyalty-program flag, e.g. "yes" / "no".
guestZipstringno""Guest ZIP code.
packageNamestringno""Rate package name, if any.
specialNotesstringno""Free-text guest preferences; used as a relevance signal.
externalGuestIdstringnonullYour own opaque identifier for the guest. Echoed back unchanged; to be used for cross-booking personalization.
resultsCountsobjectno{}Per-section result counts. Keys are foodAndBeverage, attractions, and events; each is an integer 0–5 (default 3). A count of 0 skips that section.
radiusMilesnumberno15Search radius around the hotel, in miles (5–30).

Numeric fields (roomRate, adults, children, radiusMiles, and each value inside resultsCounts) are parsed as numbers. A missing or empty field uses the default above; a value that is present but not a number is rejected with 400 invalid_request ("<field> must be a number").

externalGuestId is an opaque identifier that you assign to the guest — a CRM id, loyalty number, email address, or any other stable value. Send the same value on each of that guest's bookings; it is to be used for cross-booking personalization. Omit it when you do not track guests.

Validation ​

  • Hotel identity: either hotelPlaceId, or all of hotelName/hotelCity/hotelState.
  • Missing or empty required fields → 400 invalid_request.
  • An unknown field → 400 invalid_request ("Unknown field: <name>").
  • An unparseable checkinDate or checkoutDate → 400 invalid_request.
  • checkoutDate earlier than checkinDate → 400 invalid_request.
  • A resultsCounts that is not an object, has an unknown section key, has a count outside 0–5, or asks for zero results in every section → 400 invalid_request.
  • radiusMiles outside 5–30 → 400 invalid_request.
  • roomRate below 0, adults below 1, or children below 0 → 400 invalid_request.
  • A non-string externalGuestId → 400 invalid_request ("externalGuestId must be a string").
  • A body that is not valid JSON → 400 invalid_request.

Example request ​

json
{
  "hotelName": "Portland Regency Hotel & Spa",
  "hotelAddress": "20 Milk St",
  "hotelCity": "Portland",
  "hotelState": "ME",
  "checkinDate": "2026-10-05",
  "checkoutDate": "2026-10-10",
  "roomRate": 300,
  "adults": 1,
  "children": 0,
  "accessibleRoom": "no",
  "loyaltyProgram": "no",
  "guestZip": "04101",
  "packageName": "",
  "specialNotes": "",
  "externalGuestId": "acme-guest-42",
  "resultsCounts": { "foodAndBeverage": 3, "attractions": 3, "events": 3 }
}
bash
curl -s https://api.overlookhospitality.com/v1/concierge \
  -H "Authorization: Bearer $OVERLOOK_TOKEN" \
  -H "Content-Type: application/json" \
  -d @request.json

Response 200 OK ​

json
{
  "requestId": "0f2f6c1e-3b6a-4b0e-9d0a-2c1f6b9e8a44",
  "externalGuestId": "acme-guest-42",
  "generatedAt": "2026-10-05T23:16:22.193Z",
  "hotel": {
    "placeId": "1a2b3c4d5e6f",
    "name": "Portland Regency Hotel & Spa",
    "label": "Portland Regency Hotel & Spa, Portland, ME",
    "address": "20 Milk St",
    "locality": "Portland",
    "region": "ME",
    "latitude": 43.657,
    "longitude": -70.253
  },
  "foodAndBeverage": [
    {
      "placeId": "4484774505543785",
      "name": "Scales Food",
      "section": "foodAndBeverage",
      "blurb": "Waterfront seafood house with a raw bar and harbor views.",
      "why": "A special-occasion seafood dinner within a short walk of the hotel.",
      "reasons": ["Date night", "Walkable", "Local favorite"],
      "imageUrls": ["https://…"],
      "imageUrl": "https://…",
      "layers": ["michelin"],
      "layerIcons": [{ "name": "Michelin Guides", "iconUrl": "https://…" }],
      "latitude": 43.6567,
      "longitude": -70.2531,
      "aggregateRating": 4.5,
      "reviewCount": 2103,
      "address": "2 Portland Pier",
      "locality": "Portland",
      "region": "ME",
      "priceRange": "$$$",
      "website": "https://scalesfood.com/",
      "reservationUrl": "https://www.opentable.com/r/scales-food-portland",
      "distanceFromHotel": 0.1
    }
  ],
  "attractions": [
    {
      "placeId": "…",
      "name": "Portland Museum of Art",
      "section": "attractions",
      "blurb": "…",
      "why": "A compact, high-quality art museum that suits a rainy afternoon.",
      "reasons": ["Rainy day", "Walkable"],
      "imageUrls": ["https://…"],
      "imageUrl": "https://…",
      "layers": null,
      "layerIcons": [],
      "latitude": 43.6537,
      "longitude": -70.2625,
      "aggregateRating": 4.7,
      "reviewCount": 812,
      "address": "7 Congress Square",
      "locality": "Portland",
      "region": "ME",
      "priceRange": null,
      "distanceFromHotel": 0.4
    }
  ],
  "events": [
    {
      "eventId": "…",
      "venuePlaceId": "…",
      "title": "…",
      "date": "2026-10-07",
      "time": "19:30",
      "venue": "…",
      "blurb": "…",
      "why": "Live music during your stay, a short ride from the hotel.",
      "reasons": ["In your dates", "Free"],
      "latitude": 43.65,
      "longitude": -70.25,
      "locality": "Portland",
      "region": "ME",
      "timezone": "America/New_York",
      "address": "…",
      "neighborhood": "Old Port",
      "category": "music",
      "url": "https://www.tixr.com/groups/example/events/live-jazz",
      "isFree": false,
      "ticketPrice": { "min": 25, "max": 45, "currency": "USD" },
      "distanceFromHotel": 0.3
    }
  ]
}

The example above is abridged: with the default counts each section can contain up to 3 food and beverage venues, 3 attractions, and 3 events.

How results are chosen ​

Each section has its own count in the request's resultsCounts map: foodAndBeverage, attractions, and events (each 0–5, default 3). A count of 0 skips that section entirely — it is neither fetched nor selected, so the response section comes back empty. Each count is an upper bound: a section returns up to the number of items you ask for. Candidates are gathered from a search box of radiusMiles around the hotel, and distanceFromHotel is the straight-line distance in miles.

How pricing is blended ​

priceRange on a place is a relative band, never a dollar amount: $, $$, $$$, or $$$$. It is a single band and it is always Overlook's own blend, or null when we have no price signal for the place.

It is never a range, never an average, and never a third-party fallback.

Event list items carry isFree (true, false, or null for unknown) and a ticketPrice range ({ min, max, currency } or null), the same shape the event detail returns.

Top-level fields ​

FieldTypeDescription
requestIdstringA UUID that identifies this request in logs.
externalGuestIdstring|nullThe externalGuestId you sent, echoed back; null when you did not send one.
generatedAtstringISO-8601 timestamp of when the result was produced.
durationMsintegerTotal server-side processing time in milliseconds.
hotelHotelThe resolved hotel reference.
foodAndBeveragePlace[]Ranked food and beverage venues.
attractionsPlace[]Ranked attractions.
eventsEvent[]Ranked events occurring during the stay.

See Data types for the shape of each item.

why / reasons

why and reasons are authored for each selected item by our concierge model and are always present, so clients can render them unconditionally.

Errors ​

All errors use the shared envelope and codes; see Errors for the full matrix. This endpoint's own code is 422 hotel_not_resolved, returned when the hotel cannot be confidently resolved to a place with coordinates.

Overlook Hospitality API