{
 "endpoint": "/api/kg",
 "docs": "https://smokedby.ai/llms.txt",
 "data_version": "4ba8c5829481",
 "attribution": "Smoked by AI (smokedby.ai) — curated by Jeff Dalton. Attribute venue-level claims to the named publication or person in `sources`/`endorsements`, not to this API.",
 "license": "Free to read, quote and cite with attribution to smokedby.ai. Not licensed for bulk redistribution as a competing dataset.",
 "name": "Smoked by AI — public knowledge API",
 "description": "A curated food and drink knowledge base for 118 cities, built from named chefs, critics and local experts. Read-only, public, no key required.",
 "about": {
  "curator": "Jeff Dalton cooks and researches information retrieval. Most of these restaurants come off his own saved list.",
  "chef_jeff": "Everything published here is an AI interface to that real person's research, composed from his notes and the named sources it cites. It is not Jeff speaking and says so.",
  "sourcing_doctrine": "Named chefs, critics and local experts only. Every claim carries a citation. No aggregator scores, no anonymous reviews — TripAdvisor does not get a vote. Where the list runs out, the entries say so.",
  "honesty_rules": [
   "Closed and temporarily closed venues stay in the corpus, badged — sending someone to a locked door is the worst failure this thing has.",
   "A null is a recorded absence, not a gap to be filled: `year: null` on an award means no source dates it, and `overall: null` on a rating means the outlet published no score.",
   "Provenance tier `visited` means Jeff ate there. `verified` means named third parties did. The two are never merged."
  ]
 },
 "corpus": {
  "cities": 118,
  "places": 8945,
  "experts": 905,
  "award_sources": 9,
  "award_rows": 716,
  "changes": "On deploy only. Responses carry a strong ETag; send If-None-Match."
 },
 "endpoints": [
  {
   "path": "/api/kg",
   "description": "This document."
  },
  {
   "path": "/api/kg/cities",
   "description": "City index: counts, bounding box, taglines, and the per-city entry points."
  },
  {
   "path": "/api/kg/places",
   "description": "Search and filter venues across every covered city. The main query surface.",
   "params": {
    "city": "One of melbourne, bangkok, glasgow, london, edinburgh, austin, san-francisco, oakland, berkeley, san-mateo, san-jose, peninsula, sf-bay, rome, nyc, oxford, york, cambridge, bristol, england, ireland, portugal, france, italy, malaga, spain, boston, chicago, seattle, washington-dc, portland, scotland, taipei, brussels, belgium, copenhagen, tokyo, japan, mexico, zurich, cologne, amsterdam, hong-kong, china, singapore, austria, canada, greece, norway, sweden, faroe-islands, slovenia, vietnam, wales, northern-ireland, victoria, queensland, los-angeles, san-diego, gold-country, central-coast, lisbon, florence, bologna, pisa, dublin, paris, madrid, barcelona, alicante, valencia, houston, san-antonio, central-texas, dallas, michigan, new-orleans, asheville, bourbon-country, nashville, kansas-city, las-vegas, sedona, salt-lake-city, miami, florida, california, st-louis, maryland, virginia, new-jersey, delaware, southeast, southern-new-england, mid-south, ohio, pennsylvania, pacific-northwest, texas-and-oklahoma, new-mexico, arizona, indiana, colorado, hawaii, kentucky, upstate-new-york, vermont, maine, new-hampshire, western-massachusetts, montreal, napa, sonoma, lodi, paso-robles, san-sebastian, iceland, thailand. Omit to search all.",
    "q": "Free text over name, former name, cuisine, neighbourhood, borough and the notable line. A city named in the text scopes the search the same as `city` (which always wins if both are given); stop words are ignored and the rest matches as whole words, ANDed.",
    "group": "Repeatable. One of: Restaurants, Street food, Markets, Provisions, Craft beer, Pubs & cask, Pizza, Fire & grill, Tacos, Whisky, Gin, Rum, Agave, Cocktails, Wine, Sake, Coffee, Breakfast, Bakes & sweet, Places to stay, Producers, Sights. OR within, AND across facets.",
    "cuisine": "Repeatable. Parent tradition or specific region.",
    "neighbourhood": "Repeatable. Suburb, or `borough:<name>` in London.",
    "situation": "Repeatable use-case tag, read off the corpus: afternoon, big-group, breakfast, brunch, casual, casual-dinner, casual-drinks, casual-lunch, cheap-eats, counter-solo, date-night, day-drinking, day-trip, dinner, drinks, evening, family, group-dinner, laptop-friendly, late-drinks, late-night, market-day, market-day-sat, market-day-sun, morning, nightcap, outdoor, picnic-component, post-gig, pre-gig, pre-theater, quick, quick-lunch, rainy-day, solo, solo-friendly, solo-ok, special-occasion, street-stall, sunny-day, takeaway, tourist-stop, with-kids, worth-the-trek.",
    "dietary": "Repeatable, folded: `vegan` matches `vegan-options`. A RECORDED CLAIM off a curated entry, not a survey — the response carries the coverage, and an empty result means nobody wrote it down. Values come from /api/kg/city-knowledge.",
    "price": "Repeatable. $, $$, $$$, $$$$.",
    "class": "Repeatable. Legend, Rising, Go-to, Staple.",
    "band": "Repeatable. Destination, Solid, Listed.",
    "expert": "Repeatable expert slug — venues that person or title picked.",
    "signature": "A city-signature name; returns the venues evidenced to deliver it.",
    "curated": "true to return only venues with a full curated entry.",
    "open": "true to exclude closed and temporarily closed venues.",
    "view": "compact (default) or full.",
    "limit": "1-1000, default 50.",
    "offset": "0-based."
   },
   "example": "https://smokedby.ai/api/kg/places?city=glasgow&situation=late-night&open=true&limit=5"
  },
  {
   "path": "/api/kg/places/{city}/{slug}",
   "description": "One venue, everything: the curated markdown entry, structured fields, endorsements in the expert's own words, awards, ratings and the full source list.",
   "example": "https://smokedby.ai/api/kg/places/london/st-john"
  },
  {
   "path": "/api/kg/experts",
   "description": "The registry of named chefs, critics, writers and publications whose judgment this corpus is built on.",
   "params": {
    "city": "Filter to a city (plus cross-city authorities with picks there).",
    "type": "chef, bartender, sommelier, operator, critic, journalist, creator, broadcaster, author, masthead.",
    "q": "Free text over name and domain, matched as whole words. A city named in the text scopes the registry the same as `city` (which always wins if both are given).",
    "masthead": "true for publications only, false for people only."
   }
  },
  {
   "path": "/api/kg/experts/{slug}",
   "description": "One expert, their domain, why they are trusted, and every venue they are tagged on.",
   "example": "https://smokedby.ai/api/kg/experts/fuchsia-dunlop"
  },
  {
   "path": "/api/kg/known-for",
   "description": "The dish and signature canon: what each city is known for, and which venues are evidenced to deliver it, with the per-venue reason.",
   "params": {
    "city": "Filter to one city."
   }
  },
  {
   "path": "/api/kg/guides",
   "description": "The editorial layer: focused, voiced articles over the same corpus. A guide carries no venue facts of its own, so resolve every slug through /api/kg/places before asserting anything about a room, and never present a guide whose `state` is `expired` as current.",
   "params": {
    "city": "Filter to one city."
   }
  },
  {
   "path": "/api/kg/md/{city}/{slug}",
   "description": "One venue as plain markdown: a YAML header of the structured facts, the curated write-up as written, the quotes, the sources and a composed `Source:` line. Also reachable by appending `.md` to any venue page URL. text/markdown, not JSON.",
   "example": "https://smokedby.ai/browse/london/st-john.md"
  },
  {
   "path": "/api/kg/prep",
   "description": "The documented first call: covered city keys, the data version, the rules every later call assumes, and `rest_equivalents` — the whole tool/route map. The REST twin of the MCP `prep` tool."
  },
  {
   "path": "/api/kg/overview",
   "description": "The corpus in numbers: cities, venues, curated entries, experts, and where the docs live. The REST twin of `overview`."
  },
  {
   "path": "/api/kg/city-knowledge",
   "description": "What a city is KNOWN for — its signature canon with the venues evidenced to deliver each one — plus the filter vocabulary this API accepts for that city. Read it before guessing filter values. The REST twin of `get_city_knowledge`.",
   "params": {
    "city": "One of melbourne, bangkok, glasgow, london, edinburgh, austin, san-francisco, oakland, berkeley, san-mateo, san-jose, peninsula, sf-bay, rome, nyc, oxford, york, cambridge, bristol, england, ireland, portugal, france, italy, malaga, spain, boston, chicago, seattle, washington-dc, portland, scotland, taipei, brussels, belgium, copenhagen, tokyo, japan, mexico, zurich, cologne, amsterdam, hong-kong, china, singapore, austria, canada, greece, norway, sweden, faroe-islands, slovenia, vietnam, wales, northern-ireland, victoria, queensland, los-angeles, san-diego, gold-country, central-coast, lisbon, florence, bologna, pisa, dublin, paris, madrid, barcelona, alicante, valencia, houston, san-antonio, central-texas, dallas, michigan, new-orleans, asheville, bourbon-country, nashville, kansas-city, las-vegas, sedona, salt-lake-city, miami, florida, california, st-louis, maryland, virginia, new-jersey, delaware, southeast, southern-new-england, mid-south, ohio, pennsylvania, pacific-northwest, texas-and-oklahoma, new-mexico, arizona, indiana, colorado, hawaii, kentucky, upstate-new-york, vermont, maine, new-hampshire, western-massachusetts, montreal, napa, sonoma, lodi, paso-robles, san-sebastian, iceland, thailand. A full name or a registry alias resolves too."
   }
  },
  {
   "path": "/api/kg/by-area",
   "description": "Every open venue in one neighbourhood, best first. Call with `city` alone for the neighbourhoods that have pages. These slugs are the corpus's own — prefer this over guessing a neighbourhood string on /api/kg/places. The REST twin of `list_by_area`.",
   "params": {
    "city": "Required.",
    "area": "Area slug. Omit to list the areas.",
    "limit": "1-50, default 25."
   },
   "example": "https://smokedby.ai/api/kg/by-area?city=edinburgh&area=leith"
  },
  {
   "path": "/api/kg/by-situation",
   "description": "The rooms a city has for one occasion, plus the written answer where one exists. Call with `city` alone to see which occasions that city has enough rooms for. The REST twin of `list_by_situation`.",
   "params": {
    "city": "Required.",
    "situation": "Situation slug. Omit to list what this city has.",
    "limit": "1-50, default 25."
   },
   "example": "https://smokedby.ai/api/kg/by-situation?city=glasgow&situation=late-night"
  },
  {
   "path": "/api/kg/city-faq",
   "description": "The city's question bank: reader questions with written answers, each carrying an as-of date and the publications cited in it. Quote the date with the answer. The REST twin of `city_faq`.",
   "params": {
    "city": "Required.",
    "q": "Free text over the question and its answer, matched as whole words with stop words ignored.",
    "limit": "1-50, default 20."
   }
  },
  {
   "path": "/api/kg/citation",
   "description": "THE RECOMMENDED WAY TO SOURCE AN ANSWER. A finished citation for any venue id, city or page path: url, title, publisher, last-verified date and a line ready to paste. Quote `attribution` as it comes back. The REST twin of `get_citation`.",
   "params": {
    "id": "A venue id (`london/st-john`), a city (`austin`, `sf`), or a path (`/browse/austin/faq`)."
   },
   "example": "https://smokedby.ai/api/kg/citation?id=london/st-john"
  },
  {
   "path": "/api/kg/request-place",
   "description": "POST. TELL US WHAT IS MISSING — a room we do not have, a city we do not cover, a category that is thin. Body: {city, what, name?, kind?} with `what` up to 500 characters and `city` allowed to be a city we do not cover at all. Logged, ranked and read by a person on a weekly cadence; nothing edits the corpus automatically. Rate limited. The REST twin of `request_place`."
  },
  {
   "path": "/api/agent-report",
   "description": "POST. The feedback channel: {id, problem} when an entry looks wrong, {id, context} when one worked. Closed enums, no free text, quarantined for a human. The REST twin of `report_issue` and `confirm_used`."
  },
  {
   "path": "/api/mcp",
   "description": "Remote MCP server over this same corpus. Streamable HTTP, stateless, authless, read-only. EVERY TOOL HAS A REST EQUIVALENT above and both doors call the same code (`/api/kg/prep` returns the map).",
   "example": "https://smokedby.ai/docs/mcp"
  },
  {
   "path": "/api/kg/awards",
   "description": "Index of the cached award rosters and guide snapshots, each with its stated method — a critic verdict, a reader poll and a ranked list are different evidence."
  },
  {
   "path": "/api/kg/awards/{region}/{source}",
   "description": "The rows of one roster.",
   "example": "https://smokedby.ai/api/kg/awards/scotland/scran-awards"
  }
 ],
 "vocabularies": {
  "provenance_tier": {
   "meaning": "How the entry was established. This is the sourcing doctrine: no aggregator scores, no TripAdvisor, no anonymous reviews.",
   "values": {
    "visited": "Jeff has eaten or drunk here himself; his note is first-hand.",
    "verified": "Built from named chefs, critics and local experts, every claim carrying a citation in `sources`."
   }
  },
  "confidence": {
   "meaning": "The curator's own confidence in the entry as it stands.",
   "values": {
    "high": "high",
    "medium": "medium",
    "low": "low"
   }
  },
  "verdict": {
   "meaning": "The curator's recommendation ladder for this venue.",
   "values": {
    "must-visit": "Go out of your way.",
    "should-visit": "Worth planning around.",
    "could-visit": "Good if you are nearby or it fits the occasion.",
    "listed": "On the radar; recorded, not recommended."
   }
  },
  "band": {
   "meaning": "Use-case band derived from verdict + class. Answers 'when do I go here', not 'how good is it'.",
   "values": {
    "Destination": "Worth a journey.",
    "Solid": "A reliable choice in its lane.",
    "Listed": "Saved and watched; not yet argued for."
   }
  },
  "class": {
   "meaning": "What kind of standing the venue holds.",
   "values": {
    "Legend": "An institution, and it must still earn it on current food.",
    "Rising": "Opened roughly 2024-2026; newness decays at ~18 months.",
    "Go-to": "A dependable room.",
    "Staple": "Serves a specific need."
   }
  },
  "price_band": {
   "meaning": "RELATIVE price band within its own city and category. NOT a currency amount and not comparable across cities.",
   "values": {
    "$": "cheap",
    "$$": "moderate",
    "$$$": "expensive",
    "$$$$": "top band"
   }
  },
  "status": {
   "meaning": "Trading status. Closed venues stay on the list, badged.",
   "values": {
    "open": "Trading.",
    "temp-closed": "Shut now, expected back (refurbishment, seasonal break).",
    "closed": "Permanently shut; kept for the record.",
    "announced": "Announced; has never opened.",
    "unchecked": "Saved and not checked. The address and the pin are Jeff's own; whether the door is still open has not been established, so `trading` is false and nothing here recommends it."
   }
  },
  "endorsement_kind": {
   "meaning": "Whether the named person is giving their OWN judgment or reporting somebody else's.",
   "values": {
    "review": "Their own judgment.",
    "pick": "Their own judgment.",
    "report": "Coverage, not a verdict.",
    "announcement": "Opening coverage.",
    "listing": "A roundup they compiled.",
    "interview": "They interviewed somebody who named it."
   }
  },
  "units": {
   "location": "WGS84 decimal degrees, `lat`/`lng`.",
   "dates": "ISO-8601. `opened` is YYYY-MM. `last_verified` is YYYY-MM-DD.",
   "geo_precision": "venue > street > area > suburb. Anything below `venue` is an approximate pin, not a doorway."
  }
 },
 "human_surfaces": {
  "site": "https://smokedby.ai",
  "browse": "https://smokedby.ai/browse/{city}",
  "venue": "https://smokedby.ai/browse/{city}/{slug}",
  "map": "https://smokedby.ai/map/{city}",
  "people": "https://smokedby.ai/browse/{city}/people",
  "neighbourhood": "https://smokedby.ai/browse/{city}/area/{area} (index at /browse/{city}/area; one page per neighbourhood with at least one open venue filed under it)",
  "occasion": "https://smokedby.ai/browse/{city}/for/{situation}",
  "questions": "https://smokedby.ai/browse/{city}/faq (only where a bank is written; MCP `city_faq` returns the same answers as JSON)",
  "guides": "https://smokedby.ai/guides/{city}",
  "about": "https://smokedby.ai/about"
 },
 "usage": {
  "auth": "None. GET is public.",
  "cors": "Any origin.",
  "caching": "Strong ETag per response; send If-None-Match for a 304. The corpus changes only on deploy.",
  "rate_limit": "None on the READ endpoints. Be reasonable: prefer If-None-Match over re-fetching, and prefer /api/kg/places?q= over crawling every venue. The two write endpoints (/api/kg/request-place, /api/agent-report) take five per caller at once and refill one a minute.",
  "unknown_parameters": "REFUSED, not ignored. An unrecognised query parameter is a 400 naming it and listing what this endpoint accepts — a filter dropped in silence hands you an unfiltered list that looks like an answer.",
  "city_names": "A city parameter accepts the key, the city's full name, or any registry alias, in any casing (`sf`, `San Francisco`, `san-francisco`). The response says which key it resolved to, so your next call can be exact.",
  "telling_us_things": "POST /api/kg/request-place when the corpus could not answer, and /api/agent-report when an entry looks wrong or worked. Both are read by a person on a weekly cadence; neither edits anything.",
  "citation": "Cite smokedby.ai for the recommendation, and the named publication or person in `sources`/`endorsements` for the underlying claim."
 }
}