From a5b57cdf7843bcd23e34e40ffe98c5fd8f589086 Mon Sep 17 00:00:00 2001 From: zachary king Date: Thu, 11 Jun 2026 12:26:10 +1000 Subject: [PATCH 1/2] Add close_tab() helper: agents clean up their tabs in the user's Chrome Co-Authored-By: Claude Fable 5 --- helpers.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/helpers.py b/helpers.py index 428ebfbc..bbb091b3 100644 --- a/helpers.py +++ b/helpers.py @@ -143,6 +143,14 @@ def new_tab(url="about:blank"): goto(url) return tid +def close_tab(target_id=None): + # Close a tab (default: the agent's current one) and clean up after + # yourself in the user's Chrome. Target.closeTarget must get the page + # targetId — the attached session's id is not closable directly. + tid = target_id or current_tab()["targetId"] + cdp("Target.closeTarget", targetId=tid) + ensure_real_tab() + def ensure_real_tab(): """Switch to a real user tab if current is chrome:// / internal / stale.""" tabs = list_tabs(include_chrome=False) From ced64224614072d030713b77271de56c99b5d340 Mon Sep 17 00:00:00 2001 From: zachary king Date: Fri, 12 Jun 2026 21:26:19 +1000 Subject: [PATCH 2/2] Add Luma domain skill: internal admin API for events and guest lists Cookie-authed api.luma.com endpoints (must fetch from a luma.com tab), period=past|future trap, approval_status semantics, pagination, and the invited-vs-registered 10x list-size trap. Co-Authored-By: Claude Opus 4.8 --- domain-skills/luma/admin-api.md | 58 +++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 domain-skills/luma/admin-api.md diff --git a/domain-skills/luma/admin-api.md b/domain-skills/luma/admin-api.md new file mode 100644 index 00000000..d6e2413f --- /dev/null +++ b/domain-skills/luma/admin-api.md @@ -0,0 +1,58 @@ +# Luma (luma.com) — calendar admin & guest lists + +Event platform. Public event pages scrape fine; anything admin (guest lists with +emails, full event management) needs the **internal cookie-authed API** described here. +The official API (`public-api.luma.com`, `x-luma-api-key` header) requires a paid +Luma Plus subscription per calendar — the internal API below works with any +logged-in host session. + +## Internal API: `https://api.luma.com` + +Cookie auth with SameSite cookies, so **fetches must run from a luma.com page +context** — `js("fetch(...)", ...)` from any other origin returns 400. Ensure a +luma.com tab first: + +```python +if "luma.com" not in (page_info().get("url") or ""): + tabs = [t for t in list_tabs(include_chrome=False) if "luma.com" in t["url"]] + switch_tab(tabs[0]["targetId"]) if tabs else (new_tab("https://luma.com/home"), wait_for_load()) +``` + +A 400 right after opening/navigating the tab can also just be the page still +settling — wait ~3s and retry once before concluding auth is broken. + +### List a calendar's events + +``` +GET /calendar/admin/get-events?calendar_api_id=cal-XXXX&pagination_limit=20&period=past +``` + +- `period` is `past` or `future`. **`upcoming` is invalid and returns 400** (easy trap). +- Returns `{entries: [{api_id: "calev-...", event: {api_id: "evt-...", name, start_at, + end_at, url, geo_address_info, ...}, guest_count}], has_more, next_cursor}`. +- Paginate with `&pagination_cursor=`. +- Calendar id is in the manage URL: `luma.com/calendar/manage/cal-XXXX`. + +### Full guest list with emails (host only) + +``` +GET /event/admin/get-guests?event_api_id=evt-XXXX&pagination_limit=100 +``` + +- Returns `{entries: [...], has_more, next_cursor}`; paginate with `pagination_cursor`. +- Each guest: `name`, `email`, `approval_status`, `registered_at`, `checked_in_at`, + `registration_answers`, social handles, `user_api_id`. +- **`approval_status` semantics:** `approved` / `going` = actually registered; + `invited` = host sent an invite, never registered (these dominate the list — + a 24-guest event can return 238 rows, 210 of them `invited`); `declined` = declined. + Filter on status or your "guest list" will be 10x the real size. +- `checked_in_at` is null unless the host scanned people in — for casual events, + registered ≠ attended. + +## Traps + +- The event page UI count ("24 guests") = approved only, not the raw entries count. +- Email notifications to hosts (`noreply@luma-mail.com`) contain per-guest + register/cancel updates — usable as a fallback data source but not complete. +- CSV export exists at Manage Event → Guests → ⋯ → Download if you only need a + one-off list and don't want the API.