Table Pricing Routing

How VIP table pricing is fetched from urvenue APIs

Three Data Sources

Each venue ecosystem uses a different endpoint or data mechanism:

XS Nightclub

Embedded in Page

Source: JavaScript variable

Data: uv_tablesitems on event page

Extra API: No, extracted during scrape

LIV / LIV Beach

urvenue AJAX API

Endpoint: livnightclub.com/wp-admin/admin-ajax.php

Codes: VEN1121561 (LIV), VEN1214881 (Beach)

Header: Requires User-Agent (403 without)

TAO Group

Booketing Proxy

Proxy: booketing.com/uws/house/proxy

Venues: Hakkasan (VEN1085), Omnia (VEN1089), Marquee (VEN1108)

Extra: Param manageentid=61

Routing Logic

The _build_pricing_url() function in src/pricing.py determines which endpoint to call:

Both routes return identical response format

Response Format

Both urvenue and booketing APIs return the same JSON structure with three key objects:

sections
Pricing tier definitions (e.g., "VIP", "Gold", "Silver") with min spend amounts
items
Individual menu items (e.g., "Dom Pérignon", "Beluga Caviar") with pricing by tier
secitems
Mapping that links each item to its section(s), determining which menu a bottle appears in

The TablePricing and TablePricingTier Pydantic models parse and normalize this data. Items are deduplicated and grouped by tier.

Never hardcode VEN1121562

The LIV map page at /las-vegas/map/?eid= has a hardcoded venue code in its JavaScript: VEN1121562. This is incorrect and points to an alternate/test venue.

Always use event.venue_id when calling the pricing API. Venue IDs are scraped from each event's detail page and are venue-specific.

Wrong:

url = f"https://livnightclub.com/wp-admin/admin-ajax.php?venuecode=VEN1121562&date={date}"

Right:

url = _build_pricing_url(event.venue_id, date)
# Uses event.venue_id from the scraped event object
Output Model

Pricing data is normalized into this Pydantic structure:

TablePricing
  ├─ venue_id: str
  ├─ scraped_at: datetime
  ├─ date: date
  └─ tiers: List[TablePricingTier]
      ├─ name: str
      ├─ min_spend: float
      ├─ item_ids: List[str]  # Links to items
      └─ items: List[TableItem]
          ├─ id: str
          ├─ name: str
          ├─ category: str
          └─ price: float

This model is stored in the master database and exported to D1 for the Astro site to display pricing ranges and tier details.

CLI Usage

Scraping automatically fetches table pricing for LIV and TAO venues:

$ vinny scrape --venue xs

XS data is embedded in the page HTML.
No separate pricing API call is made.

Fetch pricing for all venues on a specific date:

$ vinny pricing --date 2026-03-15

Fetches pricing for LIV, LIV Beach, and all TAO venues.
Outputs in JSON or updates master database.

Fetch pricing for a single venue:

$ vinny pricing --venue hakkasan --date 2026-03-15

Targets TAO's booketing proxy for Hakkasan (VEN1085).
Returns pricing for that date and venue.

Venue shortnames: Use xs, liv, livbeach, hakkasan, omnia, marquee

Run vinny scrape --help or vinny pricing --help to see all available options.