Skip to main content
Glama

Ticker: Live Event Ticket Market

Screen Events by Market Data

screen_events
Read-only

Finds upcoming ticketed events whose market data meets conditions (prices and their changes, listings and tickets, demand and sales, performer rank and odds, sale dates, venue, location and date) and ranks them by any of those columns. Use it when the person asks for events that match such criteria, or for a ranked list across many events, such as the games with the largest price drop this week. Write the predicate over the columns list_screen_columns names, with the grammar the predicate input gives; preset or view_id runs a preset screen or a saved View instead. To find one event by name, performer or venue, use search_events; for every number on one event, use get_event_analytics.

Tool call template

This tool declares no required parameters. Add optional parameters from the input schema as needed.

{
  "id": 1,
  "jsonrpc": "2.0",
  "method": "tools/call",
  "params": {
    "arguments": {},
    "name": "screen_events"
  }
}

Input Schema

NameRequiredDescriptionDefault
pageNoThe page to read, from 1. Default 1.
sortNoServer-side ranking: sorts the FULL match set by `col` (NULLS LAST, event_id tiebreak) so the page is the true top-N, not an event_id slice. Omit for default event_id ASC. Fast on the ranking primitives (`ea.price_self_z_7d_pct_rank_subcat_tte`, `ea.price_self_z_7d_xs_z_subcat_tte`, `ea.inventory_velocity_1d_xs_z_subcat_tte`, `ea.pace_z_3d_vs_14d_xs_z_subcat_tte`); sorting other columns over a broad predicate may time out; narrow the predicate.
countNoCompute the total number of matches (up to 10,000, surfaced as `total`; `countCapped` true means at least that many). Default false: counting roughly DOUBLES query cost and is usually not needed to answer with a page of events. Set true ONLY when the user's ask is about how many events match ("how many…", "count the…") or you must paginate exhaustively. When false, `total`, `totalPages` and `countCapped` are null.
limitNoRows per page. A page too large for one tool result comes back as the first rows plus `meta.truncated` and `meta.total_rows`; narrow the predicate, project fewer columns, or page, rather than repeating the call.
presetNoA preset screen's key, from list_screen_columns with view presets (e.g. top_selling_24h): runs that preset's predicate in its order, the same rows the app's preset shows. Send it instead of predicate and sort.
columnsNoSnapshot columns to return, as namespaced refs (e.g. ["ea.median_price_current","e.event_name"]). A bare namespace ("ea") returns that whole bag; ["*"] returns the full ea+e+pa snapshot. Omit for a compact default (identity + headline signals) that keeps the payload small. Request more only when you need them. Names must come from list_screen_columns, spelled exactly; an unknown one is REJECTED by name, not dropped, so fix it and call again. EVERY ROW IS ALREADY LINKED: `event_id` and `event_url` are on every row already and do not need projecting.
parkingNoParking events: a parking pass that is its own event (sub_category_id 75 or 'Parking' in the name). `hide` (the default) leaves them out; `only` returns parking alone; `include` returns parking beside every other event. Set `only` when the user asks for parking, `include` when they want both; leave it at `hide` otherwise. With view_id the View's own parking choice runs and this is ignored.hide
view_idNoA saved View's id, from list_views: runs that View's predicate with the View's own economic floor setting, the events the app shows for it now. Send it instead of predicate and preset; sort, columns and paging still apply.
predicateNoA pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: "ea." = event_analytics, "e." = events, "pa." = performer_analytics, "p." = performers (p.name, the act the row is about), "v." = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {"all":[{"col":"ea.price_self_z_7d_xs_z_subcat_tte","op":">=","val":2},{"col":"ea.days_to_event","op":"between","val":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {"col":"ea.last_price_snapshot_date","op":">=","val":{"days_ago":1}}, which means "priced within the last day" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {"days_ago": N} value form is valid on any date/timestamp column. A weekend is {"col":"e.local_date","op":"between","val":{"weekend":"this","tz":"America/New_York"}} ("next" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN KEEPS THE ROWS PRICED WITHIN 3 DAYS OF THE MARKET BY DEFAULT (ea.last_price_snapshot_date, exclude_stale), so a screen adds the leg only for a tighter window. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. PARKING IS HIDDEN BY DEFAULT: parking passes that are their own event (sub_category_id 75, or 'Parking' in the name) appear only with parking 'only' or 'include'; under the default 'hide' a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest (the most people viewing in an hour, whole numbers, with its changes, ea.interest*) and Sales (tickets bought in the last 24 hours, 7 and 30 days, ea.sales_24h / ea.sales_7d / ea.sales_30d, with orders beside them, ea.orders_*); gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {"all":[{"col":"e.onsale_date","op":">=","val":{"days_ago":0}},{"col":"e.onsale_date","op":"<=","val":{"days_ago":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' sorts ea.sales_24h desc and 'top selling this week' ea.sales_7d desc (tickets bought, whole numbers; ea.orders_24h / ea.orders_7d count the orders). 0 = checked and no sale; null = no sales record for the event. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION COUNTS TICKETS THAT LEFT THE MARKETPLACE: ea.absorption_count_1d/7d, ea.absorption_settled_7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace, whether a buyer took them or the seller withdrew, moved or let them expire. Say 'absorbed' / 'delisted'; completed sales are ea.sales_* and ea.orders_*. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is the last full day (UTC) the block reading covers; an event without listing-level coverage is NULL in every absorption column, never 0, and absorption_count_1d is also NULL when the event was not captured the day before. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality; lower values warrant more caution when comparing activity. Every absorption value is 0 or more. A ticket that comes back on sale comes off the counts, and an exit that takes longer to confirm is added to the 7d count later, on the day it left, so the 7d count and the rate can rise as well as fall after they are published. ea.absorption_settled_7d counts only confirmed exits and leaves out the newest days of the window: quote it as the settled figure and absorption_count_7d as the latest.
active_onlyNoRestrict to the active event universe (status='active'). Only events dated today or later are screened either way; false adds inactive events in that window, whose rows can be frozen at the last computation or hollow (partial_row true: treat their nulls as unknown). Default true: inactive/closed events are stale and should not rank as live signals. Set false to include them.
apply_floorNoApply the economic floor (listings_current >= 25 AND median_price_current >= 40). Default true. Set false only when explicitly screening the raw universe.
diagnosticsNoExplain the result set. EMPTY RESULTS ARE EXPLAINED, NOT GUESSED AT: the block carries `rows_evaluated` (events the predicate was measured against, after the active, parking, economic floor and freshness gates; the freshness gate is exclude_stale, on by default), `system_gates` (how many survived each gate), `root` and a per-leg `passed`/`failed`/`null` breakdown. Read the `warnings` before answering: ALL_NULL means that column is NULL for EVERY row evaluated, so the screen is broken, NOT a real no-match; say the signal is not computed for these events and offer another column, never 'no events match'. A real no-match has legs with non-zero `passed`: loosen the thresholds. HIGH_NULL_RATE (>50% NULL): the results are real but cover part of the universe, so say so. NO_ROWS_EVALUATED: the scope flags, not the predicate, are the problem. A leg's `marginal` is how many more rows dropping that leg adds. If `diagnostics.status` is "unavailable" the events are still correct. "on_empty" (the default) runs the analysis only when this page came back with zero rows, so an empty screen is never reported as a plain 'no matches' when it is really an ALL_NULL column. true runs it always (useful to check how much of the universe a signal actually covers); false never runs it. The analysis is a second aggregate query over the whole candidate universe and adds ~5s, so don't set true routinely.on_empty
include_pastNoScreen events that have already taken place too. Default false. Reading past events takes the plan that includes them.
exclude_staleNoKeep the rows priced within 3 days of the market frontier (last_price_snapshot_date). Default true. Set false only when the user explicitly wants older rows included.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • addedInput schema / properties / parking
      Added value: +{
      +  "default": "hide",
      +  "description": "Parking events: a parking pass that is its own event (sub_category_id 75 or 'Parking' in the name). `hide` (the default) leaves them out; `only` returns parking alone; `include` returns parking beside every other event. Set `only` when the user asks for parking, `include` when they want both; leave it at `hide` otherwise. With view_id the View's own parking choice runs and this is ignored.",
      +  "enum": [
      +    "hide",
      +    "include",
      +    "only"
      +  ],
      +  "type": "string"
      +}
    • changedInput schema / properties / predicate / description
      Previous value: -"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}}, which means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN KEEPS THE ROWS PRICED WITHIN 3 DAYS OF THE MARKET BY DEFAULT (ea.last_price_snapshot_date, exclude_stale), so a screen adds the leg only for a tighter window. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest (the most people viewing in an hour, whole numbers, with its changes, ea.interest*) and Sales (tickets bought in the last 24 hours, 7 and 30 days, ea.sales_24h / ea.sales_7d / ea.sales_30d, with orders beside them, ea.orders_*); gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' sorts ea.sales_24h desc and 'top selling this week' ea.sales_7d desc (tickets bought, whole numbers; ea.orders_24h / ea.orders_7d count the orders). 0 = checked and no sale; null = no sales record for the event. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION COUNTS TICKETS THAT LEFT THE MARKETPLACE: ea.absorption_count_1d/7d, ea.absorption_settled_7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace, whether a buyer took them or the seller withdrew, moved or let them expire. Say 'absorbed' / 'delisted'; completed sales are ea.sales_* and ea.orders_*. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is the last full day (UTC) the block reading covers; an event without listing-level coverage is NULL in every absorption column, never 0, and absorption_count_1d is also NULL when the event was not captured the day before. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality; lower values warrant more caution when comparing activity. Every absorption value is 0 or more. A ticket that comes back on sale comes off the counts, and an exit that takes longer to confirm is added to the 7d count later, on the day it left, so the 7d count and the rate can rise as well as fall after they are published. ea.absorption_settled_7d counts only confirmed exits and leaves out the newest days of the window: quote it as the settled figure and absorption_count_7d as the latest."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}}, which means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN KEEPS THE ROWS PRICED WITHIN 3 DAYS OF THE MARKET BY DEFAULT (ea.last_price_snapshot_date, exclude_stale), so a screen adds the leg only for a tighter window. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. PARKING IS HIDDEN BY DEFAULT: parking passes that are their own event (sub_category_id 75, or 'Parking' in the name) appear only with parking 'only' or 'include'; under the default 'hide' a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest (the most people viewing in an hour, whole numbers, with its changes, ea.interest*) and Sales (tickets bought in the last 24 hours, 7 and 30 days, ea.sales_24h / ea.sales_7d / ea.sales_30d, with orders beside them, ea.orders_*); gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' sorts ea.sales_24h desc and 'top selling this week' ea.sales_7d desc (tickets bought, whole numbers; ea.orders_24h / ea.orders_7d count the orders). 0 = checked and no sale; null = no sales record for the event. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION COUNTS TICKETS THAT LEFT THE MARKETPLACE: ea.absorption_count_1d/7d, ea.absorption_settled_7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace, whether a buyer took them or the seller withdrew, moved or let them expire. Say 'absorbed' / 'delisted'; completed sales are ea.sales_* and ea.orders_*. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is the last full day (UTC) the block reading covers; an event without listing-level coverage is NULL in every absorption column, never 0, and absorption_count_1d is also NULL when the event was not captured the day before. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality; lower values warrant more caution when comparing activity. Every absorption value is 0 or more. A ticket that comes back on sale comes off the counts, and an exit that takes longer to confirm is added to the 7d count later, on the day it left, so the 7d count and the rate can rise as well as fall after they are published. ea.absorption_settled_7d counts only confirmed exits and leaves out the newest days of the window: quote it as the settled figure and absorption_count_7d as the latest."
  2. Changed1 schema field changed
    • changedInput schema / properties / predicate / description
      Previous value: -"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}}, which means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN KEEPS THE ROWS PRICED WITHIN 3 DAYS OF THE MARKET BY DEFAULT (ea.last_price_snapshot_date, exclude_stale), so a screen adds the leg only for a tighter window. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest (the most people viewing in an hour, whole numbers, with its changes, ea.interest*) and Sales (tickets bought in the last 24 hours, 7 and 30 days, ea.sales_24h / ea.sales_7d / ea.sales_30d, with orders beside them, ea.orders_*); gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' sorts ea.sales_24h desc and 'top selling this week' ea.sales_7d desc (tickets bought, whole numbers; ea.orders_24h / ea.orders_7d count the orders). 0 = checked and no sale; null = no sales record for the event. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION COUNTS TICKETS THAT LEFT THE MARKETPLACE: ea.absorption_count_1d/7d, ea.absorption_settled_7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace, whether a buyer took them or the seller withdrew, moved or let them expire. Say 'absorbed' / 'delisted'; completed sales are ea.sales_* and ea.orders_*. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without listing-level coverage is NULL in every absorption column, never 0, and absorption_count_1d is also NULL when the event was not captured the day before. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality; lower values warrant more caution when comparing activity. Every absorption value is 0 or more. A ticket that comes back on sale comes off the counts, and an exit that takes longer to confirm is added to the 7d count later, on the day it left, so the 7d count and the rate can rise as well as fall after they are published. ea.absorption_settled_7d counts only confirmed exits and leaves out the newest days of the window: quote it as the settled figure and absorption_count_7d as the latest."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}}, which means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN KEEPS THE ROWS PRICED WITHIN 3 DAYS OF THE MARKET BY DEFAULT (ea.last_price_snapshot_date, exclude_stale), so a screen adds the leg only for a tighter window. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest (the most people viewing in an hour, whole numbers, with its changes, ea.interest*) and Sales (tickets bought in the last 24 hours, 7 and 30 days, ea.sales_24h / ea.sales_7d / ea.sales_30d, with orders beside them, ea.orders_*); gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' sorts ea.sales_24h desc and 'top selling this week' ea.sales_7d desc (tickets bought, whole numbers; ea.orders_24h / ea.orders_7d count the orders). 0 = checked and no sale; null = no sales record for the event. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION COUNTS TICKETS THAT LEFT THE MARKETPLACE: ea.absorption_count_1d/7d, ea.absorption_settled_7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace, whether a buyer took them or the seller withdrew, moved or let them expire. Say 'absorbed' / 'delisted'; completed sales are ea.sales_* and ea.orders_*. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is the last full day (UTC) the block reading covers; an event without listing-level coverage is NULL in every absorption column, never 0, and absorption_count_1d is also NULL when the event was not captured the day before. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality; lower values warrant more caution when comparing activity. Every absorption value is 0 or more. A ticket that comes back on sale comes off the counts, and an exit that takes longer to confirm is added to the 7d count later, on the day it left, so the 7d count and the rate can rise as well as fall after they are published. ea.absorption_settled_7d counts only confirmed exits and leaves out the newest days of the window: quote it as the settled figure and absorption_count_7d as the latest."
  3. Changed4 schema fields changed
    • addedInput schema / properties / include_past
      Added value: +{
      +  "default": false,
      +  "description": "Screen events that have already taken place too. Default false. Reading past events takes the plan that includes them.",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / page / description
      Added value: +"The page to read, from 1. Default 1."
    • changedInput schema / properties / predicate / description
      Previous value: -"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN KEEPS THE ROWS PRICED WITHIN 3 DAYS OF THE MARKET BY DEFAULT (ea.last_price_snapshot_date, exclude_stale), so a screen adds the leg only for a tighter window. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest (the most people viewing in an hour, whole numbers, with its changes, ea.interest*) and Sales (tickets bought in the last 24 hours, 7 and 30 days, ea.sales_24h / ea.sales_7d / ea.sales_30d, with orders beside them, ea.orders_*); gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' sorts ea.sales_24h desc and 'top selling this week' ea.sales_7d desc (tickets bought, whole numbers; ea.orders_24h / ea.orders_7d count the orders). 0 = checked and no sale; null = no sales record for the event. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION COUNTS TICKETS THAT LEFT THE MARKETPLACE: ea.absorption_count_1d/7d, ea.absorption_settled_7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace, whether a buyer took them or the seller withdrew, moved or let them expire. Say 'absorbed' / 'delisted'; completed sales are ea.sales_* and ea.orders_*. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without listing-level coverage is NULL in every absorption column, never 0, and absorption_count_1d is also NULL when the event was not captured the day before. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality; lower values warrant more caution when comparing activity. Every absorption value is 0 or more. A ticket that comes back on sale comes off the counts, and an exit that takes longer to confirm is added to the 7d count later, on the day it left, so the 7d count and the rate can rise as well as fall after they are published. ea.absorption_settled_7d counts only confirmed exits and leaves out the newest days of the window: quote it as the settled figure and absorption_count_7d as the latest."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}}, which means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN KEEPS THE ROWS PRICED WITHIN 3 DAYS OF THE MARKET BY DEFAULT (ea.last_price_snapshot_date, exclude_stale), so a screen adds the leg only for a tighter window. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest (the most people viewing in an hour, whole numbers, with its changes, ea.interest*) and Sales (tickets bought in the last 24 hours, 7 and 30 days, ea.sales_24h / ea.sales_7d / ea.sales_30d, with orders beside them, ea.orders_*); gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' sorts ea.sales_24h desc and 'top selling this week' ea.sales_7d desc (tickets bought, whole numbers; ea.orders_24h / ea.orders_7d count the orders). 0 = checked and no sale; null = no sales record for the event. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION COUNTS TICKETS THAT LEFT THE MARKETPLACE: ea.absorption_count_1d/7d, ea.absorption_settled_7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace, whether a buyer took them or the seller withdrew, moved or let them expire. Say 'absorbed' / 'delisted'; completed sales are ea.sales_* and ea.orders_*. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without listing-level coverage is NULL in every absorption column, never 0, and absorption_count_1d is also NULL when the event was not captured the day before. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality; lower values warrant more caution when comparing activity. Every absorption value is 0 or more. A ticket that comes back on sale comes off the counts, and an exit that takes longer to confirm is added to the 7d count later, on the day it left, so the 7d count and the rate can rise as well as fall after they are published. ea.absorption_settled_7d counts only confirmed exits and leaves out the newest days of the window: quote it as the settled figure and absorption_count_7d as the latest."
    • addedInput schema / properties / sort / properties / dir / description
      Added value: +"desc (default) ranks the highest values first, asc the lowest."
  4. Changed2 schema fields changed
    • changedInput schema / properties / exclude_stale / description
      Previous value: -"Drop stale rows: events last priced more than 3 days behind the market frontier (last_price_snapshot_date). Default true; a 4-day-old snapshot is not a live signal. Set false only when the user explicitly wants stale rows included."New value: +"Keep the rows priced within 3 days of the market frontier (last_price_snapshot_date). Default true. Set false only when the user explicitly wants older rows included."
    • changedInput schema / properties / predicate / description
      Previous value: -"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN LEAVES OUT STALE ROWS BY DEFAULT: rows more than 3 days behind the market (ea.last_price_snapshot_date), or never priced, are left out (exclude_stale), so a screen adds the leg only for fresher rows. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest (the most people viewing in an hour, whole numbers, with its changes, ea.interest*) and Sales (tickets bought in the last 24 hours, 7 and 30 days, ea.sales_24h / ea.sales_7d / ea.sales_30d, with orders beside them, ea.orders_*); gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' sorts ea.sales_24h desc and 'top selling this week' ea.sales_7d desc (tickets bought, whole numbers; ea.orders_24h / ea.orders_7d count the orders). 0 = checked and no sale; null = not covered. No column averages sale prices. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_settled_7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a seller withdrawing a listing, moving it to another exchange, or letting it expire counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without listing-level coverage is NULL in every absorption column, never 0, and absorption_count_1d is also NULL when the event was not captured the day before. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality; lower values warrant more caution when comparing activity. Every absorption value is 0 or more. A ticket that comes back on sale comes off the counts, and an exit that takes longer to confirm is added to the 7d count later, on the day it left, so the 7d count and the rate can rise as well as fall after they are published. ea.absorption_settled_7d counts only confirmed exits and leaves out the newest days of the window: quote it as the settled figure and absorption_count_7d as the latest."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN KEEPS THE ROWS PRICED WITHIN 3 DAYS OF THE MARKET BY DEFAULT (ea.last_price_snapshot_date, exclude_stale), so a screen adds the leg only for a tighter window. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest (the most people viewing in an hour, whole numbers, with its changes, ea.interest*) and Sales (tickets bought in the last 24 hours, 7 and 30 days, ea.sales_24h / ea.sales_7d / ea.sales_30d, with orders beside them, ea.orders_*); gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' sorts ea.sales_24h desc and 'top selling this week' ea.sales_7d desc (tickets bought, whole numbers; ea.orders_24h / ea.orders_7d count the orders). 0 = checked and no sale; null = no sales record for the event. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION COUNTS TICKETS THAT LEFT THE MARKETPLACE: ea.absorption_count_1d/7d, ea.absorption_settled_7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace, whether a buyer took them or the seller withdrew, moved or let them expire. Say 'absorbed' / 'delisted'; completed sales are ea.sales_* and ea.orders_*. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without listing-level coverage is NULL in every absorption column, never 0, and absorption_count_1d is also NULL when the event was not captured the day before. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality; lower values warrant more caution when comparing activity. Every absorption value is 0 or more. A ticket that comes back on sale comes off the counts, and an exit that takes longer to confirm is added to the 7d count later, on the day it left, so the 7d count and the rate can rise as well as fall after they are published. ea.absorption_settled_7d counts only confirmed exits and leaves out the newest days of the window: quote it as the settled figure and absorption_count_7d as the latest."
  5. Changed1 schema field changed
    • changedInput schema / properties / predicate / description
      Previous value: -"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN LEAVES OUT STALE ROWS BY DEFAULT: rows more than 3 days behind the market (ea.last_price_snapshot_date), or never priced, are left out (exclude_stale), so a screen adds the leg only for fresher rows. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest (the most people viewing in an hour, whole numbers, with its changes, ea.interest*) and Sales (tickets bought in the last 24 hours, 7 and 30 days, ea.sales_24h / ea.sales_7d / ea.sales_30d, with orders beside them, ea.orders_*); gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' sorts ea.sales_24h desc and 'top selling this week' ea.sales_7d desc (tickets bought, whole numbers; ea.orders_24h / ea.orders_7d count the orders). 0 = checked and no sale; null = not covered. No column averages sale prices. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN LEAVES OUT STALE ROWS BY DEFAULT: rows more than 3 days behind the market (ea.last_price_snapshot_date), or never priced, are left out (exclude_stale), so a screen adds the leg only for fresher rows. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest (the most people viewing in an hour, whole numbers, with its changes, ea.interest*) and Sales (tickets bought in the last 24 hours, 7 and 30 days, ea.sales_24h / ea.sales_7d / ea.sales_30d, with orders beside them, ea.orders_*); gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' sorts ea.sales_24h desc and 'top selling this week' ea.sales_7d desc (tickets bought, whole numbers; ea.orders_24h / ea.orders_7d count the orders). 0 = checked and no sale; null = not covered. No column averages sale prices. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_settled_7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a seller withdrawing a listing, moving it to another exchange, or letting it expire counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without listing-level coverage is NULL in every absorption column, never 0, and absorption_count_1d is also NULL when the event was not captured the day before. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality; lower values warrant more caution when comparing activity. Every absorption value is 0 or more. A ticket that comes back on sale comes off the counts, and an exit that takes longer to confirm is added to the 7d count later, on the day it left, so the 7d count and the rate can rise as well as fall after they are published. ea.absorption_settled_7d counts only confirmed exits and leaves out the newest days of the window: quote it as the settled figure and absorption_count_7d as the latest."
  6. Changed2 schema fields changed
    • changedInput schema / properties / predicate / description
      Previous value: -"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN LEAVES OUT STALE ROWS BY DEFAULT: rows more than 3 days behind the market (ea.last_price_snapshot_date), or never priced, are left out (exclude_stale), so a screen adds the leg only for fresher rows. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest and Sales per hour and their changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' and 'top selling this week' sort ea.sales desc (Sales: orders per hour over the day); ea.sales_d1 and ea.sales_d7 are its change since yesterday and over a week. No column counts sales in a window or averages their prices. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN LEAVES OUT STALE ROWS BY DEFAULT: rows more than 3 days behind the market (ea.last_price_snapshot_date), or never priced, are left out (exclude_stale), so a screen adds the leg only for fresher rows. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest (the most people viewing in an hour, whole numbers, with its changes, ea.interest*) and Sales (tickets bought in the last 24 hours, 7 and 30 days, ea.sales_24h / ea.sales_7d / ea.sales_30d, with orders beside them, ea.orders_*); gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' sorts ea.sales_24h desc and 'top selling this week' ea.sales_7d desc (tickets bought, whole numbers; ea.orders_24h / ea.orders_7d count the orders). 0 = checked and no sale; null = not covered. No column averages sale prices. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."
    • addedInput schema / properties / view_id
      Added value: +{
      +  "description": "A saved View's id, from list_views: runs that View's predicate with the View's own economic floor setting, the events the app shows for it now. Send it instead of predicate and preset; sort, columns and paging still apply.",
      +  "format": "uuid",
      +  "type": "string"
      +}
  7. Changed3 schema fields changed
    • changedInput schema / properties / diagnostics / description
      Previous value: -"Explain the result set. EMPTY RESULTS ARE EXPLAINED, NOT GUESSED AT: the block carries `rows_evaluated` (events the predicate was measured against, after the active, parking, economic floor and freshness gates), `system_gates` (how many survived each gate), `root` and a per-leg `passed`/`failed`/`null` breakdown. Read the `warnings` before answering: ALL_NULL means that column is NULL for EVERY row evaluated, so the screen is broken, NOT a real no-match; say the signal is not computed for these events and offer another column, never 'no events match'. A real no-match has legs with non-zero `passed`: loosen the thresholds. HIGH_NULL_RATE (>50% NULL): the results are real but cover part of the universe, so say so. NO_ROWS_EVALUATED: the scope flags, not the predicate, are the problem. A leg's `marginal` is how many more rows dropping that leg adds. If `diagnostics.status` is \"unavailable\" the events are still correct. \"on_empty\" (the default) runs the analysis only when this page came back with zero rows, so an empty screen is never reported as a plain 'no matches' when it is really an ALL_NULL column. true runs it always (useful to check how much of the universe a signal actually covers); false never runs it. The analysis is a second aggregate query over the whole candidate universe and adds ~5s, so don't set true routinely."New value: +"Explain the result set. EMPTY RESULTS ARE EXPLAINED, NOT GUESSED AT: the block carries `rows_evaluated` (events the predicate was measured against, after the active, parking, economic floor and freshness gates; the freshness gate is exclude_stale, on by default), `system_gates` (how many survived each gate), `root` and a per-leg `passed`/`failed`/`null` breakdown. Read the `warnings` before answering: ALL_NULL means that column is NULL for EVERY row evaluated, so the screen is broken, NOT a real no-match; say the signal is not computed for these events and offer another column, never 'no events match'. A real no-match has legs with non-zero `passed`: loosen the thresholds. HIGH_NULL_RATE (>50% NULL): the results are real but cover part of the universe, so say so. NO_ROWS_EVALUATED: the scope flags, not the predicate, are the problem. A leg's `marginal` is how many more rows dropping that leg adds. If `diagnostics.status` is \"unavailable\" the events are still correct. \"on_empty\" (the default) runs the analysis only when this page came back with zero rows, so an empty screen is never reported as a plain 'no matches' when it is really an ALL_NULL column. true runs it always (useful to check how much of the universe a signal actually covers); false never runs it. The analysis is a second aggregate query over the whole candidate universe and adds ~5s, so don't set true routinely."
    • changedInput schema / properties / predicate / description
      Previous value: -"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Gate a movement ask on ea.last_price_snapshot_date with a relative date. The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. A freshness gate is NOT applied by default, so supply it yourself: {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest and Sales per hour and their changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' and 'top selling this week' sort ea.sales desc (Sales: orders per hour over the day); ea.sales_d1 and ea.sales_d7 are its change since yesterday and over a week. No column counts sales in a window or averages their prices. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Views and alerts do not gate freshness: when a View is about movement, add a relative-date leg on ea.last_price_snapshot_date (days_ago 1). The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. Views and alerts do not gate freshness: a View about movement adds the leg {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A SCREEN LEAVES OUT STALE ROWS BY DEFAULT: rows more than 3 days behind the market (ea.last_price_snapshot_date), or never priced, are left out (exclude_stale), so a screen adds the leg only for fresher rows. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest and Sales per hour and their changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' and 'top selling this week' sort ea.sales desc (Sales: orders per hour over the day); ea.sales_d1 and ea.sales_d7 are its change since yesterday and over a week. No column counts sales in a window or averages their prices. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."
    • addedInput schema / properties / preset
      Added value: +{
      +  "description": "A preset screen's key, from list_screen_columns with view presets (e.g. top_selling_24h): runs that preset's predicate in its order, the same rows the app's preset shows. Send it instead of predicate and sort.",
      +  "type": "string"
      +}
  8. Changed1 schema field changed
    • changedInput schema / properties / predicate / description
      Previous value: -"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Gate a movement ask on ea.last_price_snapshot_date with a relative date. The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. A freshness gate is NOT applied by default, so supply it yourself: {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest and Sales per hour and their changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Gate a movement ask on ea.last_price_snapshot_date with a relative date. The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. A freshness gate is NOT applied by default, so supply it yourself: {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest and Sales per hour and their changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. TOP SELLING IS SALES, NOT ABSORPTION: 'top selling today' and 'top selling this week' sort ea.sales desc (Sales: orders per hour over the day); ea.sales_d1 and ea.sales_d7 are its change since yesterday and over a week. No column counts sales in a window or averages their prices. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."
  9. Changed1 schema field changed
    • changedInput schema / properties / predicate / description
      Previous value: -"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Gate a movement ask on ea.last_price_snapshot_date with a relative date. The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. A freshness gate is NOT applied by default, so supply it yourself: {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest and Sales per hour and their changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. COMPLETED SALES ARE NOT ABSORPTION: ea.completed_sales_1d/_3d/_7d/_30d count completed resale sales in the last 24 h, 3, 7 or 30 days (sales, not tickets; NULL = not covered), so 'top selling today' sorts ea.completed_sales_1d desc. ea.completed_sale_avg_aip_price_* is the average last listed all-in of those sales, never a confirmed price paid. ea.tm_tickets_pct_1d/_7d are the primary market's 1 and 7 day percent changes in tickets. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Gate a movement ask on ea.last_price_snapshot_date with a relative date. The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. A freshness gate is NOT applied by default, so supply it yourself: {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest and Sales per hour and their changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."
  10. Changed1 schema field changed
    • changedInput schema / properties / predicate / description
      Previous value: -"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Gate a movement ask on ea.last_price_snapshot_date with a relative date. The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. A freshness gate is NOT applied by default, so supply it yourself: {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace demand levels/changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.demand_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. COMPLETED SALES ARE NOT ABSORPTION: ea.completed_sales_1d/_3d/_7d/_30d count completed resale sales in the last 24 h, 3, 7 or 30 days (sales, not tickets; NULL = not covered), so 'top selling today' sorts ea.completed_sales_1d desc. ea.completed_sale_avg_aip_price_* is the average last listed all-in of those sales, never a confirmed price paid. ea.tm_tickets_pct_1d/_7d are the primary market's 1 and 7 day percent changes in tickets. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Gate a movement ask on ea.last_price_snapshot_date with a relative date. The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. A freshness gate is NOT applied by default, so supply it yourself: {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace Interest and Sales per hour and their changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.interest* / ea.sales* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. COMPLETED SALES ARE NOT ABSORPTION: ea.completed_sales_1d/_3d/_7d/_30d count completed resale sales in the last 24 h, 3, 7 or 30 days (sales, not tickets; NULL = not covered), so 'top selling today' sorts ea.completed_sales_1d desc. ea.completed_sale_avg_aip_price_* is the average last listed all-in of those sales, never a confirmed price paid. ea.tm_tickets_pct_1d/_7d are the primary market's 1 and 7 day percent changes in tickets. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."
  11. Changed1 schema field changed
    • changedInput schema / properties / predicate / description
      Previous value: -"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Gate a movement ask on ea.last_price_snapshot_date with a relative date. The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. A freshness gate is NOT applied by default, so supply it yourself: {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace demand levels/changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.demand_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Gate a movement ask on ea.last_price_snapshot_date with a relative date. The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. A freshness gate is NOT applied by default, so supply it yourself: {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace demand levels/changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.demand_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. COMPLETED SALES ARE NOT ABSORPTION: ea.completed_sales_1d/_3d/_7d/_30d count completed resale sales in the last 24 h, 3, 7 or 30 days (sales, not tickets; NULL = not covered), so 'top selling today' sorts ea.completed_sales_1d desc. ea.completed_sale_avg_aip_price_* is the average last listed all-in of those sales, never a confirmed price paid. ea.tm_tickets_pct_1d/_7d are the primary market's 1 and 7 day percent changes in tickets. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."
  12. Changed1 schema field changed
    • changedInput schema / properties / predicate / description
      Previous value: -"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Gate a movement ask on ea.last_price_snapshot_date with a relative date. The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. A freshness gate is NOT applied by default, so supply it yourself: {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace demand levels/changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.demand_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Gate a movement ask on ea.last_price_snapshot_date with a relative date. The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. A freshness gate is NOT applied by default, so supply it yourself: {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. A weekend is {\"col\":\"e.local_date\",\"op\":\"between\",\"val\":{\"weekend\":\"this\",\"tz\":\"America/New_York\"}} (\"next\" for the one after): the coming Friday to Sunday in tz, from today on a Friday to Sunday, resolved on every run. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace demand levels/changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.demand_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."
  13. Changed5 schema fields changed
    • changedInput schema / properties / active_only / description
      Previous value: -"Restrict to the active event universe (status='active'). Default true: inactive/closed events are stale and should not rank as live signals. Set false to include them."New value: +"Restrict to the active event universe (status='active'). Only events dated today or later are screened either way; false adds inactive events in that window, whose rows can be frozen at the last computation or hollow (partial_row true: treat their nulls as unknown). Default true: inactive/closed events are stale and should not rank as live signals. Set false to include them."
    • changedInput schema / properties / columns / description
      Previous value: -"Snapshot columns to return, as namespaced refs (e.g. [\"ea.median_price_current\",\"e.event_name\"]). A bare namespace (\"ea\") returns that whole bag; [\"*\"] returns the full ea+e+pa snapshot. Omit for a compact default (identity + headline signals) that keeps the payload small. Request more only when you need them. Names must come from list_screen_columns, spelled exactly; an unknown one is rejected by name rather than dropped. `event_id` and `event_url` are on every row already and do not need projecting."New value: +"Snapshot columns to return, as namespaced refs (e.g. [\"ea.median_price_current\",\"e.event_name\"]). A bare namespace (\"ea\") returns that whole bag; [\"*\"] returns the full ea+e+pa snapshot. Omit for a compact default (identity + headline signals) that keeps the payload small. Request more only when you need them. Names must come from list_screen_columns, spelled exactly; an unknown one is REJECTED by name, not dropped, so fix it and call again. EVERY ROW IS ALREADY LINKED: `event_id` and `event_url` are on every row already and do not need projecting."
    • changedInput schema / properties / diagnostics / description
      Previous value: -"Explain the result set (see EMPTY RESULTS in the tool description). \"on_empty\" (the default) runs the analysis only when this page came back with zero rows, so an empty screen is never reported as a plain 'no matches' when it is really an ALL_NULL column. true runs it always (useful to check how much of the universe a signal actually covers); false never runs it. The analysis is a second aggregate query over the whole candidate universe and adds ~5s, so don't set true routinely."New value: +"Explain the result set. EMPTY RESULTS ARE EXPLAINED, NOT GUESSED AT: the block carries `rows_evaluated` (events the predicate was measured against, after the active, parking, economic floor and freshness gates), `system_gates` (how many survived each gate), `root` and a per-leg `passed`/`failed`/`null` breakdown. Read the `warnings` before answering: ALL_NULL means that column is NULL for EVERY row evaluated, so the screen is broken, NOT a real no-match; say the signal is not computed for these events and offer another column, never 'no events match'. A real no-match has legs with non-zero `passed`: loosen the thresholds. HIGH_NULL_RATE (>50% NULL): the results are real but cover part of the universe, so say so. NO_ROWS_EVALUATED: the scope flags, not the predicate, are the problem. A leg's `marginal` is how many more rows dropping that leg adds. If `diagnostics.status` is \"unavailable\" the events are still correct. \"on_empty\" (the default) runs the analysis only when this page came back with zero rows, so an empty screen is never reported as a plain 'no matches' when it is really an ALL_NULL column. true runs it always (useful to check how much of the universe a signal actually covers); false never runs it. The analysis is a second aggregate query over the whole candidate universe and adds ~5s, so don't set true routinely."
    • addedInput schema / properties / limit / description
      Added value: +"Rows per page. A page too large for one tool result comes back as the first rows plus `meta.truncated` and `meta.total_rows`; narrow the predicate, project fewer columns, or page, rather than repeating the call."
    • changedInput schema / properties / predicate / description
      Previous value: -"Predicate DSL object (see tool description), a pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering."New value: +"A pure boolean FILTER, not an ordering. Omit or pass {} to screen the whole live universe. To surface the most interesting rows first, use the `sort` parameter; the predicate cannot express ordering. Predicate DSL (recursive JSON): a leaf is {col, op, val}; composites are {all:[...]} (AND) or {any:[...]} (OR). Columns are prefixed: \"ea.\" = event_analytics, \"e.\" = events, \"pa.\" = performer_analytics, \"p.\" = performers (p.name, the act the row is about), \"v.\" = venues (v.venue_name, the venue's name; v.city, v.state, v.country_code, v.capacity). Ops: =, !=, >, >=, <, <=, between (val=[lo,hi]), in (val=[...]), contains (case-insensitive substring on a TEXT column; val is a plain string), not_contains (removes the rows whose TEXT column holds val as a case-insensitive substring; a row with no value stays; % and _ in val match themselves, while contains reads them as wildcards). Example: {\"all\":[{\"col\":\"ea.price_self_z_7d_xs_z_subcat_tte\",\"op\":\">=\",\"val\":2},{\"col\":\"ea.days_to_event\",\"op\":\"between\",\"val\":[7,60]}]}. NAMED ACTS / TEAMS / PERFORMERS, use p.name. When the user names the act the events are BY (a musician like 'Taylor Swift', a team like 'Lakers', a comedian, a touring show), filter the performer column: {col:'p.name', op:'contains', val:'Taylor Swift'}. p.name is the act the row is KEYED on. e.event_name is the TITLE, which reads 'A at B' for a sports event and so also returns the opponent's home games, and for a concert also returns parking and support billings. A performer or team ask NEVER goes to e.event_name. Keep writing 'contains' for an act name. When what was typed IS a whole act name in the catalog, the server rewrites that leaf to op '=' and says so; anything else stays a substring. REMOVING ROWS BY A WORD. 'NOT Little', 'not the Lakers', 'without Taylor', 'excluding Hamilton' remove every row whose title contains the word: {col:'e.event_name', op:'not_contains', val:'Little'}. Never write '!=' for a word: '!=' compares the WHOLE value, so e.event_name != 'Manilow' removes nothing. A MISSPELLED superlative is still a superlative. 'htotest', 'hotest', 'bigest movers', 'chepest', 'lowset price' read as the word they intend and take the ordering that word takes. A ranking word is NEVER a name: never put it in a 'contains' leaf on e.event_name or p.name, and never answer with sort null because the spelling was odd. ECONOMIC FLOOR. The server already ANDs ea.listings_current >= 25 AND ea.median_price_current >= 40 into every screen. Do NOT add a listings-depth floor of your own. A column whose name ends in d1 or 1d is a ONE-DAY CHANGE, not yesterday's value. 'Inventory dropping' or 'listings falling' is a SEVEN-DAY change or an absorption column, never a one-day ratio. A stale row, or an event that is not active, is NEVER a move: its numbers describe the last day it was priced. Gate a movement ask on ea.last_price_snapshot_date with a relative date. The economic floor CAN be turned off at the call site (apply_floor=false, or apply_economic_floor=false on a rule), only when you explicitly want the raw universe. A freshness gate is NOT applied by default, so supply it yourself: {\"col\":\"ea.last_price_snapshot_date\",\"op\":\">=\",\"val\":{\"days_ago\":1}} means \"priced within the last day\" and compiles to CURRENT_DATE - 1, re-evaluated every tick, where a literal date string silently rots. The {\"days_ago\": N} value form is valid on any date/timestamp column. e.event_id, e.venue_id and e.performer_id take the ids rows carry (ev..., vn..., pf...). Authoritative validation runs in SQL; an invalid predicate returns a clear error. A window of event dates from today ('the next week', 'the next 30 days') is ea.days_to_event between [0, N]. NON-ADMISSION SKUs ARE ALWAYS EXCLUDED: parking and shuttle / no-admission passes (sub_category_id 75, or an event_name matching '%parking%') never appear in a screen, and a screen that asks for sub_category_id 75 alone is refused. Also screenable: marketplace demand levels/changes (ea.interest*, ea.sales*; young series, gate freshness on ea.demand_asof_date), PERFORMER-grain demand (pa.interest*, pa.sales*, pa.demand_asof_date; a separate performer-resource reading, NOT a rollup of that performer's events; filtering on it selects every event of a matching performer, so use it to find hot performers and ea.demand_* to pick among their events; gate on pa.demand_asof_date), performer popularity-rank momentum (pa.popularity_rank*; positive change = climbing), and sale-timing/ops columns: e.presale1_date and e.onsale_date (timestamptz; NULL = unknown/TBD and NULL never matches a range predicate; negative days_ago means the FUTURE: 'on sale in the next 7 days' is {\"all\":[{\"col\":\"e.onsale_date\",\"op\":\">=\",\"val\":{\"days_ago\":0}},{\"col\":\"e.onsale_date\",\"op\":\"<=\",\"val\":{\"days_ago\":-7}}]}) and e.monitoring_priority (monitoring priority from P1, highest, to P10, lowest, stored as 1 to 10). Count changes come as counts (ea.listings_delta_*, ea.tickets_delta_*) AND as percents (ea.listings_pct_1d/_7d, ea.tickets_pct_1d/_7d): 'listings down 10%' is ea.listings_pct_7d <= -10, never a count of 10. ea.median_price_7d_ago is the median of 7 days earlier, a past level. ea.tm_tickets_pct_3d is the primary market's 3-day percent change (-100 = none left after some 3 days ago), and e.tm_sells is true when TM sells the event as its own primary sale ('not on TM' is false); both are primary-market columns. ONLY EVENTS DATED TODAY OR LATER (UTC) ARE SCREENED, whatever active_only says: a screen whose e.local_date range ended two or more days ago is refused. ABSORPTION IS DELISTING, NOT SALES: ea.absorption_count_1d/7d, ea.absorption_rate_7d and ea.listings_added_count_* count listings that LEFT (or joined) the marketplace: a broker withdrawal, a move to another exchange, or an expiry counts the same as a sale. NEVER report them as tickets bought or as sales volume; say 'absorbed' / 'delisted'. A predicate or sort on an absorption column adds ea.absorption_data_quality, ea.absorption_grain and ea.absorption_asof_date to the projection; quote the quality and the as-of day with any absorption number. The as-of day is yesterday (UTC) for every covered event; an event without seat block ledger coverage is NULL in every absorption column, never 0. Quality ranges from 0 to 1 and reflects observation coverage and listing-tracking quality. Lower values warrant more caution when comparing activity. Published counts can decrease after revisions and can be negative when returns exceed departures."
  14. Changed1 schema field changed
    • removedInput schema / properties / limit / maximum
      Removed value: -100
  15. First observed

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, destructiveHint=false and openWorldHint=false, so safety is covered; the description adds that only 'upcoming' events are screened and that results can be ranked by any returned column. It does not itself disclose the economic floor, freshness gates, parking default or the extra cost of counting/diagnostics — those live in the schema, not this text. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, front-loaded with purpose, then when-to-use, then how to construct input, then alternatives. Every sentence earns its place and nothing is repeated from the schema's parameter text.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 14-parameter, nested-schema read tool, the description covers purpose, triggers, input construction and alternatives adequately. The return shape (rows of projected columns, paging/truncation metadata) is only implied via schema parameter text and there is no output schema, so a sentence on the result payload would make it fully complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema coverage the baseline is 3, and the schema already documents every parameter in depth, including the full predicate DSL. The description adds meaningful linkage by telling the agent to build the predicate from columns 'list_screen_columns' names and that 'preset' or 'view_id' is an alternative to predicate/sort — routing semantics not obvious from the schema alone.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource — 'Finds upcoming ticketed events whose market data meets conditions' — plus the ranking capability, so scope is unambiguous. It also names the two sibling tools it is not ('search_events' for one event, 'get_event_analytics' for one event's numbers), letting an agent route without opening another schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit trigger conditions ('asks for events that match such criteria, or for a ranked list across many events, such as the games with the largest price drop this week') and names the alternative for each other need. The preset/view_id clause tells the agent when not to hand-write a predicate.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources