{"version":"1","policy_version":"public-2026-10-03","routes":{"schema":"GET /v1/public/intelligence/schema","query":"GET /v1/public/intelligence/query","query_post":"POST /v1/public/intelligence/query"},"execution_classes":["interactive"],"read_only":"No read fetches, collects, refreshes, runs a model or exposes SQL.","get_syntax":{"grain":"required; one of business, domain_record, location, menu_item, relationship, offer","select":"comma-separated registered fields; default is the grain's default_select","where":"where[<field>][<op>]=<literal>; `in` takes comma-separated values (a value containing a comma must use eq); predicates combine with AND","body":"GET has no body; a request body is refused","aliases":"flat per-grain aliases expand to where[<field>][eq]","order_by":"<field> (ascending) or -<field> (descending), registered directions only; the identity breaks ties","limit":"1..100, default 50","cursor":"meta.next_cursor from the previous page of the same query","version":"1","origin":"grain=location only: origin[<label>]=<lat>,<lng>, repeated, with where[distance_miles][lte]=<miles>; see grains.location.spatial"},"operators":{"eq":"Equals one literal value.","in":"Equals any of up to 100 comma-separated literal values.","gte":"Greater than or equal (range-capable indexed fields only).","lte":"Less than or equal (range-capable indexed fields only).","contains":"Contains one literal substring, case-insensitive, on trigram-indexed text fields only. At least 3 characters including 3 consecutive letters or digits; `%`, `_` and `\\` are data, never wildcards. No synonyms, stemming or spelling variants.","none_since":"Absence of a STORED, ACCEPTED event on or after one ISO date (YYYY-MM-DD; a value with a time is read as its UTC calendar date). Registered on inspection.latest_failure_at only: the location has no inspection stored with outcome 'failed' (the authority's own word, classed by GI) and attribution 'accepted' on or after the date. Stored visits with no declared outcome never exclude a location (it stays, with inspection.state visits_without_declared_outcome), and visits whose attribution is unknown or candidate never count as the Place's failure. Not a pass or safety claim."},"limits":{"default_limit":50,"max_limit":100,"max_selected_fields":30,"max_predicates":50,"max_in_values":100,"max_query_string_bytes":4096,"max_response_bytes":131072,"statement_timeout_ms":2000,"database_allowance_ms":3000},"budgets":"statement_timeout_ms bounds each database statement; database_allowance_ms is the total statement allowance of one request's database statements (a spent allowance is refused with 503 query_unavailable, never extended). Neither is a whole-request deadline: connection acquisition, admission and response serialization are not yet bounded (open release gap).","pagination":"Live keyset pagination, not a snapshot. A cursor binds the normalized filters, grain, order, limit and policy version; only the projection (select) may change within a traversal. Cursors are scoped, not signed: altering one can only move the start position within the same public result set; every decoded value is re-validated against the grain, normalized filters, order, limit and policy version.","errors":{"invalid_query":422,"unsupported_capability":422,"invalid_cursor":422,"projection_too_large":422,"query_unavailable":503},"grains":{"business":{"description":"One canonical business identity with a public page.","row_meaning":"One business_identities row: the durable canonical business (a domain record is where evidence was observed, not the business).","eligibility":"A business is listed iff it has a public page by the rule every public read uses (canonical_records): a business_identity_sources binding 'represents', not retired (retired_at IS NULL), on an indexable web_domains record; AND merged_into_id IS NULL (a merged identity is served by its survivor). An identity with no such record has no page and is not listed; no business is manufactured from an unresolved domain. Stored corpus only; not a complete national census.","identity":"id","ref":"public_page","fields":{"id":{"type":"uuid","description":"Canonical business identity UUID (never moves on a rename).","source":"business_identities.id","operators":["eq","in"],"sortable":["asc"],"selectable":true,"filterable":true,"visibility":"public","normalizer":"uuid","null_semantics":"never null","negatable":true},"name":{"type":"string","description":"The resolved name, display only. Not filterable or sortable: a name is not an identifier.","source":"business_identities.name","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when the resolver elected no name; reported as unknown."},"site_domain":{"type":"string","description":"The registrable domain of the official site GI elected, as stored. Display only: business_identities has no index on it, so a filter would be an unproven public scan; the exact lookup is the indexed `domain` filter.","source":"business_identities.site_domain","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"domain","null_semantics":"Stored as '' when GI elected no official site; reported as unknown."},"first_seen_at":{"type":"datetime","description":"When the identity was first allocated.","source":"business_identities.first_seen_at","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"never null"},"last_confirmed_at":{"type":"datetime","description":"When a readable record of the business last confirmed it.","source":"business_identities.last_confirmed_at","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"never null"},"materially_changed_at":{"type":"datetime","description":"When the published profile last materially changed. Display only: business_identities has no index on it, so a global sort or range over every eligible business would be an unproven public cost; the admitted order is id.","source":"business_identities.materially_changed_at","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"never null"},"domain":{"type":"string","description":"Filter: an indexable record on this domain currently represents the business (the public page rule; a non-indexable representing record does not match).","source":"business_identity_sources(represents, not retired) JOIN web_domains.domain (indexable)","operators":["eq"],"sortable":[],"selectable":false,"filterable":true,"visibility":"public","normalizer":"domain","null_semantics":"null means unknown for this row"},"location_count":{"type":"integer","description":"SCOPE full_footprint: the number of DISTINCT publicly eligible (at least one current source) stored Places reached through the exact join restaurant_location_sources(current).web_domain_id -> web_domains.business_identity_id, over the business's WHOLE stored footprint. Maintained per business when evidence changes, independent of any other predicate of the query: menu, geography or row filters (e.g. location-grain having businesses) narrow ROWS, never this count. This field does not count a filtered territory. Not a worldwide footprint or claim about unread records: read it with locations.coverage (whose `scope` names the same scope). Filter and sort operate on the full matched set before pagination. Coverage, not proof: a count of 0 with nothing read means 'not represented', never 'none exist'; not_having means no qualifying STORED accepted evidence under this coverage.","source":"business_intelligence_summaries.location_count, maintained from distinct current restaurant_location_sources joined through web_domains.business_identity_id","operators":["eq","gte","lte"],"sortable":["asc","desc"],"selectable":true,"filterable":true,"visibility":"public","normalizer":"integer","null_semantics":"never null; 0 is 'no stored eligible Place', read with locations.coverage","negatable":true,"post_only":true},"locations.coverage":{"type":"object","description":"{scope, records, read, sources_current}: scope = full_footprint (the location_count scope, named on the row); records = indexable records currently representing the business (canonical_records' rule); read = how many of those records store a location-lane read status of complete or partial (web_domains.collector_record['restaurant_locations'].status; failed, unattempted or absent are not read); sources_current = current location sources on records belonging to the business. location_count = 0 with read = 0 is 'not represented', not 'no locations'. Coverage, not proof: a count of 0 with nothing read means 'not represented', never 'none exist'; not_having means no qualifying STORED accepted evidence under this coverage.","source":"business_intelligence_summaries, maintained from current representing business_identity_sources, indexable web_domains and their location-read status, and current restaurant_location_sources","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"never null","post_only":true},"relationships.coverage":{"type":"object","description":"{records, current_edges}: records = indexable records currently representing the business; current_edges = current, keyed, admitted-predicate edges stated by records that currently belong to it (the relationship grain's eligibility). No stored per-record relationship read status exists, so no 'read' count is published: zero edges means none STORED, never none exist. Coverage, not proof: a count of 0 with nothing read means 'not represented', never 'none exist'; not_having means no qualifying STORED accepted evidence under this coverage.","source":"computed: business_identity_sources(represents) JOIN web_domains (indexable); business_identity_relationships (current) JOIN web_domains (stated_by)","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"never null","post_only":true}},"default_select":["id","name","site_domain","materially_changed_at"],"default_order":{"field":"id","direction":"asc"},"aliases":{"domain":"domain"},"rules":["ref.href is the business's public page, decided in SQL with canonical_records' own precedence (its official site's own indexable record, else the earliest bound, one row per business); never a link built from site_domain.","Admitted paths are the primary key (id eq/in, ordered by id) and the indexed exact `domain` lookup; no name, site_domain or material-change filter or sort is served until its plan is measured.","A business's locations are not a column of this grain: grain=location&where[business.id][eq]=<id>."],"children":{"locations":{"grain":"location","description":"Places of the business through the exact join (restaurant_location_sources(current).web_domain_id -> web_domains.business_identity_id), each an eligible location row. location_count counts them.","countable":true,"include_limit":20,"parent_filter":"business.id","coverage_field":"locations.coverage","not_having":true},"relationships":{"grain":"relationship","description":"Current typed edges whose subject is the business, exactly the relationship grain's rows (stated by a record that currently belongs to it). Every predicate in one having group binds the SAME edge.","countable":false,"include_limit":20,"parent_filter":"subject.business_id","coverage_field":"relationships.coverage","not_having":true}}},"domain_record":{"description":"One stored domain-level public collection record.","row_meaning":"One web_domains row that is its business's public page.","eligibility":"Public indexable business pages exactly as /v1/public/company-intelligence: web_domains.indexable AND web_domains.business_page. Stored corpus only; not a complete national census.","identity":"domain","ref":"public_page","fields":{"domain":{"type":"string","description":"Registrable domain, lowercase.","source":"web_domains.domain","operators":["eq","in"],"sortable":["asc"],"selectable":true,"filterable":true,"visibility":"public","normalizer":"domain","null_semantics":"never null","negatable":true},"collected_at":{"type":"datetime","description":"When the collection this record reflects finished.","source":"web_domains.collected_at","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"null means unknown for this row"},"materially_changed_at":{"type":"datetime","description":"When the record's content last materially changed.","source":"web_domains.materially_changed_at","operators":["gte","lte"],"sortable":["desc"],"selectable":true,"filterable":true,"visibility":"public","normalizer":"datetime","null_semantics":"null means unknown for this row"},"observation_count":{"type":"integer","description":"Observations the collector reported for the record.","source":"web_domains.observation_count","operators":["eq","gte","lte"],"sortable":["desc"],"selectable":true,"filterable":true,"visibility":"public","normalizer":"integer","null_semantics":"never null"},"name":{"type":"string","description":"Stored canonical business name, unknown if unresolved.","source":"business_identities.name via web_domains.business_identity_id","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"null means unknown for this row","post_only":true},"domain.search":{"type":"string","description":"Literal domain substring, backed by the existing public directory trigram index. Case-insensitive; wildcards are data.","source":"web_domains.domain","operators":["contains"],"sortable":[],"selectable":false,"filterable":true,"visibility":"public","normalizer":"lowercase","null_semantics":"null means unknown for this row","post_only":true},"location_count":{"type":"integer","description":"Whole stored canonical business footprint, independent of matching-location filters. Unknown without identity or any represented location read/evidence; not exhaustive worldwide chain size.","source":"business location_count with locations.coverage knownness","operators":["gte","lte"],"sortable":["asc","desc"],"selectable":true,"filterable":true,"visibility":"public","normalizer":"integer","null_semantics":"null means unknown for this row","post_only":true},"contacts.summary":{"type":"object","description":"Recorded public contact availability, not deliverability or buyer qualification.","source":"accepted company and location routes; published people","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"null means unknown for this row","post_only":true},"contacts.any":{"type":"integer","description":"1 when any evidence is stored on this report; 0 means not recorded, never absent in reality.","source":"accepted company and location routes; published people","operators":["eq"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"integer","null_semantics":"null means unknown for this row","post_only":true},"contacts.email":{"type":"integer","description":"1 when email evidence is stored on this report; 0 means not recorded, never absent in reality.","source":"accepted company and location routes; published people","operators":["eq"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"integer","null_semantics":"null means unknown for this row","post_only":true},"contacts.phone":{"type":"integer","description":"1 when phone evidence is stored on this report; 0 means not recorded, never absent in reality.","source":"accepted company and location routes; published people","operators":["eq"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"integer","null_semantics":"null means unknown for this row","post_only":true},"contacts.form":{"type":"integer","description":"1 when form evidence is stored on this report; 0 means not recorded, never absent in reality.","source":"accepted company and location routes; published people","operators":["eq"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"integer","null_semantics":"null means unknown for this row","post_only":true},"contacts.person_email":{"type":"integer","description":"1 when person_email evidence is stored on this report; 0 means not recorded, never absent in reality.","source":"accepted company and location routes; published people","operators":["eq"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"integer","null_semantics":"null means unknown for this row","post_only":true},"contacts.people":{"type":"integer","description":"1 when people evidence is stored on this report; 0 means not recorded, never absent in reality.","source":"accepted company and location routes; published people","operators":["eq"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"integer","null_semantics":"null means unknown for this row","post_only":true},"locations.coverage":{"type":"object","description":"Business footprint coverage; read counts complete or partial stored location reads. Unknown without a resolved business.","source":"business locations.coverage","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"null means unknown for this row","post_only":true}},"default_select":["domain","materially_changed_at","observation_count"],"default_order":{"field":"domain","direction":"asc"},"aliases":{"domain":"domain"},"rules":[],"children":{"locations":{"grain":"location","description":"Current locations stored on this published report. Every predicate qualifies the same location, including cuisine and provider presence.","countable":true,"include_limit":20,"parent_filter":"domain","coverage_field":null,"not_having":false},"relationships":{"grain":"relationship","description":"Current typed edges this record states about the business it currently belongs to. Every predicate in one having group binds the SAME edge. No stored per-record relationship read status exists, so not_having is not served on this path.","countable":false,"include_limit":20,"parent_filter":"subject.domain","coverage_field":null,"not_having":false}}},"location":{"description":"One canonical physical Place in the restaurant-location corpus. The source's own declared type is `declared_type` (unknown when it declared none): on the local corpus 8,194 eligible Places were 3,865 Restaurant, 2,822 unknown, 532 LocalBusiness, 524 FastFoodRestaurant, 271 FoodEstablishment, 103 Place and a tail of others, so a row of this grain is a Place, not necessarily a restaurant.","row_meaning":"One restaurant_locations row (accepted membership, not one row per source).","eligibility":"Locations with at least one CURRENT source, exactly as /v1/public/restaurant-locations (a location every source of which was retired leaves the directory). Stored corpus only; not a complete national census. Locations without a stored valid point are not evaluated by distance.","identity":"id","ref":"api_resource","fields":{"id":{"type":"uuid","description":"Canonical location UUID.","source":"restaurant_locations.id","operators":["eq","in"],"sortable":["asc"],"selectable":true,"filterable":true,"visibility":"public","normalizer":"uuid","null_semantics":"never null","negatable":true},"name":{"type":"string","description":"The location's resolved name.","source":"restaurant_locations.name","operators":[],"sortable":["asc"],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when no source stated it; reported as unknown."},"address.street":{"type":"string","description":"First address line.","source":"restaurant_locations.address_line_1","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when no source stated it; reported as unknown."},"address.city":{"type":"string","description":"City; filters compare case-insensitively.","source":"restaurant_locations.city","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"lowercase","null_semantics":"Stored as '' when no source stated it; reported as unknown.","negatable":true,"groupable":true},"address.region":{"type":"string","description":"Region or state; filters compare case-insensitively.","source":"restaurant_locations.region","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"lowercase","null_semantics":"Stored as '' when no source stated it; reported as unknown.","negatable":true,"groupable":true},"address.postal_code":{"type":"string","description":"Postal code.","source":"restaurant_locations.postal_code","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when no source stated it; reported as unknown."},"address.country":{"type":"string","description":"Country; filters compare case-insensitively.","source":"restaurant_locations.country","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"lowercase","null_semantics":"Stored as '' when no source stated it; reported as unknown.","negatable":true,"groupable":true},"cuisines":{"type":"array","description":"Typed cuisines stored on this Place. Exact case-insensitive array membership (any selected cuisine); not inferred from its menu or name. An empty array is unknown. Membership uses a normalized text-array expression with a GIN index and retains the statement timeout.","source":"restaurant_locations.cuisines","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"lowercase","null_semantics":"[] means no stored cuisine statement, not no cuisine","post_only":true},"identifier.providers":{"type":"array","description":"Stored non-conflicted provider identifier presence at this same Place. Listing evidence only; not current service availability or sales.","source":"restaurant_location_identifiers (status != conflicted)","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"null means unknown for this row","post_only":true},"operating_status":{"type":"string","description":"The stored operational status, matched literally. Not indexed: combine with a geography or domain filter.","source":"restaurant_locations.operational_status","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when no source stated it; reported as unknown.","negatable":true},"declared_type":{"type":"string","description":"The type the SOURCE declared for this Place, exactly as filed (schema.org-style words such as Restaurant, FastFoodRestaurant, Bakery, LocalBusiness, Place, Organization; case kept), matched literally. Unknown when the source declared none -- unknown is not a type and no name or text is read to supply one, so a filter on Restaurant leaves every unknown row out and says nothing about it. No hierarchy is inferred: FastFoodRestaurant is not matched by Restaurant. Access path, measured on the local corpus (9,134 rows, 20 distinct values, 3,487 unknown): a sequential scan, 6-41 ms; with origins the (latitude, longitude) index serves the radius first and the type is applied to those candidates. No index until the measurement asks for one.","source":"restaurant_locations.declared_type","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when the source declared no type; reported as unknown"},"domain":{"type":"string","description":"Filter: the location is listed by this domain (a current source).","source":"restaurant_location_sources(current) JOIN web_domains.domain","operators":["eq"],"sortable":[],"selectable":false,"filterable":true,"visibility":"public","normalizer":"domain","null_semantics":"null means unknown for this row"},"identifier.provider":{"type":"string","description":"Filter: a registered, non-conflicted provider identifier is present (case-insensitive provider name). Presence only; no identifier values.","source":"restaurant_location_identifiers.provider (status != 'conflicted')","operators":["eq","in"],"sortable":[],"selectable":false,"filterable":true,"visibility":"public","normalizer":"lowercase","null_semantics":"null means unknown for this row"},"business.id":{"type":"uuid","description":"Filter: the location has a CURRENT source whose record currently belongs to this canonical business (grain=business id). The stored path is the source's record, not a location column; no name matching. Current source membership and the record's business binding have supporting indexes.","source":"restaurant_location_sources(current) JOIN web_domains.business_identity_id","operators":["eq"],"sortable":[],"selectable":false,"filterable":true,"visibility":"public","normalizer":"uuid","null_semantics":"null means unknown for this row"},"menu.name":{"type":"string","description":"Filter, CANDIDATE Places: a published menu item bound to this location has this literal in its NAME (name only; description is not indexed). Case-insensitive substring, trigram-indexed; no synonyms or spelling variants. Items are bound to their record's representative Place, and whether that menu page applies to this Place is not stored on the rows (the surface scope lives in the record), so a match is a candidate, not proof the dish is served here. Only representative Places have menu rows: a location that does not match may simply not have been collected, never 'not on the menu'.","source":"EXISTS restaurant_menu_items (current accepted source) ON restaurant_location_id = restaurant_locations.id AND lower(name) LIKE '%' || :term || '%'","operators":["contains"],"sortable":[],"selectable":false,"filterable":true,"visibility":"public","normalizer":"literal","null_semantics":"null means unknown for this row"},"coordinates.latitude":{"type":"float","description":"Latitude (degrees) of the location's one stored point, shown only when the point is valid (both coordinates present, finite, in range). Provenance of the point (the venue's own, a directory's, an authority's or a Census address geocode) is not stored yet: unknown.","source":"restaurant_locations.latitude","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"null means no stored valid point; provenance not yet stored — unknown"},"coordinates.longitude":{"type":"float","description":"Longitude (degrees) of the location's one stored point, shown only when the point is valid (both coordinates present, finite, in range). Provenance of the point is not stored yet: unknown.","source":"restaurant_locations.longitude","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"null means no stored valid point; provenance not yet stored — unknown"},"distance_miles":{"type":"float","description":"Radius filter and sort over the query's prepared origins: the great-circle (haversine) straight-line distance on a sphere of R = 6,371,000 m, in statute miles (1,609.344 m), from the location's stored point to an origin. lte only, inclusive, 0 < r <= 100 (provisional); required with origin[<label>]=<lat>,<lng> and refused without one. Not selectable: each returned row carries near {origin, distance_miles} and within.","source":"computed: restaurant_locations.latitude/longitude and the query's origins","operators":["lte"],"sortable":["asc"],"selectable":false,"filterable":true,"visibility":"public","normalizer":"miles","null_semantics":"never null on a returned row; a location without a stored valid point is not evaluated (neither inside nor outside)"},"inspection":{"type":"object","description":"One object per location over its stored inspection visits (GI's 5-year read horizon at most): visits, undated_visits, declared_outcomes (failed | passed | passed_with_conditions), latest_at, latest_outcome ('' = not classed by GI; ties on one date by the authority's record number, descending), latest_declared_at, latest_failure_at -- all over visits GI attributed 'accepted' to this Place only -- plus candidate_visits and attribution_unknown (visits that are NOT this Place's own outcome, counted so nothing is erased), window_since and state. window_since is the date the query's own predicate bound (none_since, else latest_failure_at gte, else latest_at gte) -- in the flat where or directly inside a top-level `and` group, a conjunct of the whole query; under `or` a window predicate is refused, since no single window would hold for every row; on an included Place, the include's own where; null = every stored visit. state is one of failed_in_window, assessed_no_failure, visits_without_declared_outcome, no_visit_in_window (first that holds): an accepted failed visit on/after window_since; an accepted declared outcome there and no failure; accepted visits there with no declared outcome (26 of 33 stored authorities file no result word: never a pass); none. register_read_no_record, not_yet_inspected and not_covered are not served: register coverage and sentinels are not stored. Absence of a known failure is not a pass or a safety claim.","source":"restaurant_location_inspections (typed projection of the location's health_inspection licence rows) ON restaurant_location_id = restaurant_locations.id","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"never null: a location with no stored visit reports visits 0 and state no_visit_in_window; unknown outcomes and attributions are counted inside it"},"inspection.latest_failure_at":{"type":"date","description":"Filter: the newest stored visit with outcome 'failed' (the authority's own result word, classed by GI) and attribution 'accepted' (this Place's own). gte: one on or after the date; lte: one on or before it and none after; none_since: none on or after it -- Q2's exclusion. Visits with no declared outcome and visits of unknown or candidate attribution are never a failure here. An ISO date; a value with a time is read as its UTC calendar date.","source":"NOT EXISTS / EXISTS restaurant_location_inspections (attribution 'accepted', outcome 'failed', inspected_at vs :date), index (restaurant_location_id, inspected_at DESC) and (outcome, inspected_at DESC)","operators":["gte","lte","none_since"],"sortable":[],"selectable":false,"filterable":true,"visibility":"public","normalizer":"datetime","null_semantics":"null means unknown for this row"},"inspection.latest_at":{"type":"date","description":"Filter: the newest stored visit attributed 'accepted' to this Place, whatever its outcome. gte: one on or after the date; lte: one on or before it and none after. Undated visits never match. An ISO date; a value with a time is read as its UTC calendar date.","source":"EXISTS restaurant_location_inspections (attribution 'accepted', inspected_at vs :date), index (restaurant_location_id, inspected_at DESC)","operators":["gte","lte"],"sortable":[],"selectable":false,"filterable":true,"visibility":"public","normalizer":"datetime","null_semantics":"null means unknown for this row"}},"default_select":["id","name","address.city","address.region","address.country"],"default_order":{"field":"name","direction":"asc"},"aliases":{"country":"address.country","region":"address.region","city":"address.city","domain":"domain","provider":"identifier.provider","operating_status":"operating_status"},"rules":["Radius over prepared origins: origin[<label>]=<lat>,<lng> repeated (1 to 100 origins, provisional; labels 1 to 64 characters, unique; two finite decimals, latitude -90..90, longitude -180..180) together with where[distance_miles][lte]=<miles> (0 < r <= 100, provisional). Each requires the other. Points only: no address strings, no geocoding, no fetch.","A location qualifies iff it has a stored valid point and its great-circle distance (haversine, R = 6,371,000 m, statute miles, straight line) to AT LEAST ONE origin is <= r (inclusive). Locations without a stored valid point are not evaluated: never reported inside or outside, and not counted.","One row per location id over the union of origins; locations sharing premises or a point are distinct rows. Each row carries near {origin, distance_miles} for its nearest origin (ties by the order the origins were given) and within: every origin within r, in the order given. distance_miles is rounded to 3 decimals for display only; ordering and cursors use the full-precision distance.","With origins the default order is distance_miles then id; order_by=name or id stays available. The cursor binds the origins (labels, points and their order), the radius and the policy. order_by=distance_miles without origins is unsupported.","Inspection exclusion: where[inspection.latest_failure_at][none_since]=<YYYY-MM-DD> keeps every location with no stored, accepted, authority-declared failure on or after the date -- including locations whose stored visits declare no outcome, whose visits are attribution-unknown or candidate, and locations with no stored visit at all; select `inspection` for each row's state. It compiles to NOT EXISTS over the typed, indexed inspection rows, never over the licence JSON."],"spatial":{"inputs":{"origin":"origin[<label>]=<latitude>,<longitude>, repeated; a prepared point (two finite decimals), never an address","radius":"where[distance_miles][lte]=<miles>, required with origins","post":"POST body: origins [{label, latitude, longitude}] with the radius {field: distance_miles, op: lte, value} as a top-level ANDed where predicate (see post.keys.origins); the same canonical query as the GET form"},"limits":{"max_origins":100,"max_radius_miles":100.0,"max_origin_label_chars":64,"basis":"Provisional, measured on 9,134 stored rows with no spatial index: 1 origin at 10 mi 5.8 ms, 25 at 10 mi 28.8 ms, 100 at 10 mi 50.6 ms, 100 at 50 mi 70.6 ms. Inline GET origins are also bounded by the 4096-byte query string."},"distance":{"model":"haversine great-circle, straight line (not road distance)","earth_radius_m":6371000.0,"meters_per_mile":1609.344,"radius":"inclusive (<=)","display":"near.distance_miles rounded to 3 decimals; order and cursor use the full-precision distance"},"row":{"near":"{origin, distance_miles}: the nearest origin; ties by the order given","within":"every origin within the radius, in the order given"},"default_order":{"field":"distance_miles","direction":"asc","then":"id"},"not_evaluated":"locations without a stored valid point (no corpus-wide count is computed per query)"},"children":{"menu_items":{"grain":"menu_item","description":"Published dishes bound to this Place (its record's representative Place; place_scope applies: a candidate, never proof the dish is served here). No per-Place menu read status is stored on the rows, so not_having is not served on this path.","countable":false,"include_limit":20,"parent_filter":"place.id","coverage_field":null,"not_having":false},"businesses":{"grain":"business","description":"The eligible businesses (public page, not merged) that own this Place through the exact join (a CURRENT source of the Place on a record that belongs to the business). A having group here qualifies the Place by its business's own fields: location_count is that business's WHOLE footprint (scope full_footprint), never narrowed by this query's menu, geography or other row predicates. A Place shared by two businesses qualifies when either does.","countable":false,"include_limit":20,"parent_filter":null,"coverage_field":null,"not_having":false}}},"menu_item":{"description":"One published menu item: one dish at one Place, as stored.","row_meaning":"One restaurant_menu_items row: a dish bound to one Place, with its purchase variants and their offers carried on the row (never one row per offer, surface or menu).","eligibility":"Published dishes exactly as the record menu read (menu_items_for): at least one restaurant_menu_item_sources row with current AND status 'accepted'; AND bound to a Place (restaurant_location_id) the location grain lists (at least one CURRENT restaurant_location_sources row). A brand menu bound to no Place is not a row. Only each record's representative Place has menu rows; a Place without rows was not collected, which is never 'not on the menu'. Stored corpus only; not a complete national census.","identity":"id","ref":"place","fields":{"id":{"type":"uuid","description":"Canonical menu item UUID (identity is held by its source rows).","source":"restaurant_menu_items.id","operators":["eq","in"],"sortable":["asc"],"selectable":true,"filterable":true,"visibility":"public","normalizer":"uuid","null_semantics":"never null"},"name":{"type":"string","description":"The dish name as stored. `contains`: literal, case-insensitive substring of the NAME only (trigram index on lower(name)); the description is not searched. No synonyms or spellings: 'filet' does not match 'fillet'. `eq`: the exact stored string. Not sortable.","source":"restaurant_menu_items.name","operators":["eq","contains"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when no name was read; reported as unknown."},"description":{"type":"string","description":"The dish description as stored. Display only: no index covers it, so it is not searchable.","source":"restaurant_menu_items.description","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when no source stated one; reported as unknown."},"categories":{"type":"array","description":"The category labels the sources stated, as stored (strings).","source":"restaurant_menu_items.categories (jsonb)","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as [] when no source stated it; reported as unknown."},"listing_status":{"type":"string","description":"The stored listing status (listed | withdrawn | unknown), literal.","source":"restaurant_menu_items.listing_status","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"never null"},"place.id":{"type":"uuid","description":"The Place the dish is bound to (restaurant_locations.id): its record's representative Place, never proof the menu applies there (place_scope).","source":"restaurant_menu_items.restaurant_location_id","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"uuid","null_semantics":"never null for an eligible row"},"variants":{"type":"array","description":"Purchase variants and their offers EXACTLY as stored: [{id, label, offers: [{surface_id, amount_cents, currency, source_price, kind, condition, availability, menu_context, observed_at}]}]. Each offer names the surface it was read from and carries serving {type, volume_ml} when the source's structure stated it. There is no item-level price: offers are never picked, compared or ranked here (grain=offer ranks stored offers), amounts are as the source printed them and are not validated, and publisher-menu offers carry no currency. Bounded by the response byte budget, never truncated.","source":"restaurant_menu_items.variants (jsonb)","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as [] when no offer was read; reported as unknown. An unpriced dish is still a row and still matches a name filter."},"first_seen_at":{"type":"datetime","description":"When the dish was first stored.","source":"restaurant_menu_items.first_seen_at","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"never null"},"last_confirmed_at":{"type":"datetime","description":"When a read last confirmed the dish; a dish whose surfaces all went unread keeps its earlier clock. Item-level: offers carry no clock of their own.","source":"restaurant_menu_items.last_confirmed_at","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"never null"},"materially_changed_at":{"type":"datetime","description":"When the dish's stored content (name, prices, attributes) last materially changed.","source":"restaurant_menu_items.materially_changed_at","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"never null"},"kind":{"type":"string","description":"What the item is (wine | beer | cocktail | spirit | beverage | food), as GI read it from the section heading the source filed it under; never derived by the API from categories or the name. Each offer in `variants` carries its own `serving` {type, volume_ml} when the source stated one, and none when it did not. Display here; filter and rank on grain=offer.","source":"restaurant_menu_items.item_kind ('unknown' = not stated)","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"unknown: the source stated none (stored as 'unknown')."}},"default_select":["id","name","place.id","categories","variants","last_confirmed_at"],"default_order":{"field":"id","direction":"asc"},"aliases":{"place":"place.id"},"rules":["`contains` searches the NAME only, as a literal case-insensitive substring: at least 3 characters including 3 consecutive letters or digits; `%`, `_` and `\\` are data. It is not content search: descriptions, categories and spelling variants are not searched.","place_scope is {binding: representative_place, applicability: unverified} on every row: GI binds a record's menu to its representative Place, and whether a menu page applies to that Place is held in the record's surface scope, not on the row. A row is a candidate dish at the Place, never proof it is served there.","Prices are the offers inside `variants`, exactly as stored. No offer is chosen as the item's price and nothing is ranked by amount; a dish with no offer is still a row.","Admitted order: id. No name or price sort is served.","Places with a dish: grain=location&where[menu.name][contains]=<term> (candidate Places, composable with geography, provider and business.id filters)."],"unsupported_fields":{"price.amount":"menu_item:price","price.currency":"menu_item:price","price":"menu_item:price","serving":"menu_item:serving","serving.unit":"menu_item:serving","serving.kind":"menu_item:serving","unit":"menu_item:serving","item_kind":"menu_item:serving","offer.kind":"menu_item:serving","offer.condition":"menu_item:serving","offer.observed_at":"menu_item:serving"}},"relationship":{"description":"One current, typed, declared provider-account edge with its exact source key.","row_meaning":"One business_identity_relationships row: the subject business, the predicate, and the exact {namespace, object_type, key} it declares.","eligibility":"The public record identity's shared-with rule (/company-intelligence/{domain}/identity): current edges (ended_at IS NULL) with a stated exact key (to_key != ''), predicate declares_provider_account, stated by the record that currently represents the subject business. One row per stated association: two surfaces of one business stating the same key are two rows, never two businesses. A stored association, not ownership, executed tracking, an active commercial account or market coverage; a group/account key never implies unique Place or company membership.","identity":"id","ref":"subject","fields":{"id":{"type":"uuid","description":"Relationship UUID.","source":"business_identity_relationships.id","operators":["eq","in"],"sortable":["asc"],"selectable":true,"filterable":true,"visibility":"public","normalizer":"uuid","null_semantics":"never null"},"subject.business_id":{"type":"uuid","description":"The canonical business identity that declares the key.","source":"business_identity_relationships.from_identity_id","operators":["eq"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"uuid","null_semantics":"never null"},"subject.domain":{"type":"string","description":"The stored domain record that states the relationship.","source":"web_domains.domain (stated_by)","operators":["eq"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"domain","null_semantics":"never null"},"predicate":{"type":"string","description":"The typed relationship predicate.","source":"business_identity_relationships.predicate","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"literal","null_semantics":"never null","allowed_values":["declares_provider_account"],"negatable":true},"state":{"type":"string","description":"GI's state for the edge: supported | candidate (matched literally).","source":"business_identity_relationships.state","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"literal","null_semantics":"null means unknown for this row","negatable":true},"source_key.namespace":{"type":"string","description":"Exact key namespace (literal). Part of the whole tuple.","source":"business_identity_relationships.to_namespace","operators":["eq"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"literal","null_semantics":"null means unknown for this row","negatable":true,"groupable":true},"source_key.object_type":{"type":"string","description":"Exact key object type (literal). Part of the whole tuple.","source":"business_identity_relationships.to_object_type","operators":["eq"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"literal","null_semantics":"null means unknown for this row","negatable":true,"groupable":true},"source_key.key":{"type":"string","description":"Exact key value: a literal string; case and leading zeros are kept; no substring or numeric matching. Part of the whole tuple.","source":"business_identity_relationships.to_key","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"literal","null_semantics":"null means unknown for this row"},"witness.source_url":{"type":"string","description":"The witness URL GI recorded; evidence link only, never fetched. Richer surface classification is not stored and is not inferred.","source":"business_identity_relationships.witness_url","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"null means unknown for this row"},"first_observed_at":{"type":"datetime","description":"The relationship's own first-observed clock.","source":"business_identity_relationships.first_observed_at","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"null when stored before relationships kept their own clocks"},"last_confirmed_at":{"type":"datetime","description":"The relationship's own last-confirmed clock.","source":"business_identity_relationships.last_confirmed_at","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"null when stored before relationships kept their own clocks"}},"default_select":["id","subject.business_id","subject.domain","predicate","state","source_key.namespace","source_key.object_type","source_key.key","witness.source_url","first_observed_at","last_confirmed_at"],"default_order":{"field":"id","direction":"asc"},"aliases":{"namespace":"source_key.namespace","object_type":"source_key.object_type","key":"source_key.key","predicate":"predicate","state":"state","subject_domain":"subject.domain"},"rules":["A source_key filter must name the whole tuple: namespace, object_type and key together. All three qualify the same stored association; a value alone is not globally unique across platforms or object types.","Keys are literal strings: case, leading zeros and wildcard characters are data.","subject.href is the business's public page when one is published (kind public_page); a business with no public page has href null (kind no_public_page) and its stating record's domain stays data in subject.domain."],"shorthand":{"aliases":{"namespace":"source_key.namespace","object_type":"source_key.object_type","key":"source_key.key"},"defaults":{"predicate":"declares_provider_account","state":"supported"},"applies_when":"any of namespace, object_type, key is given; an explicit predicate or state overrides its default","example":"/v1/public/intelligence/query?grain=relationship&namespace=meta&object_type=meta_pixel_id&key=1234567890123456"}},"offer":{"description":"One stored offer: one price, on one surface, for one variant of one dish at one Place.","row_meaning":"One restaurant_menu_offers row: an offer of a dish the menu_item grain lists, with its serving, the item's kind, its currency, amount, surface and clock on the SAME row. Never one row per item: a dish with a glass and a bottle price is two rows.","eligibility":"Offers of published dishes exactly as grain=menu_item lists them: the dish has a restaurant_menu_item_sources row with current AND status 'accepted', is bound to a Place the location grain lists (a CURRENT restaurant_location_sources row), and is listed. A ranking describes the STORED offers that qualify, never every wine, bottle or price at those Places: only each record's representative Place has menu rows, and an offer whose source stated no serving, kind or currency cannot qualify on that field (meta.coverage.unknown counts them). Stored corpus only; not a complete national census.","identity":"id","ref":"place","fields":{"id":{"type":"uuid","description":"Offer UUID, stable across re-reads of an unchanged offer (derived from the dish and the offer's own stated coordinates, not its amount).","source":"restaurant_menu_offers.id","operators":["eq","in"],"sortable":["asc"],"selectable":true,"filterable":true,"visibility":"public","normalizer":"uuid","null_semantics":"never null"},"item.id":{"type":"uuid","description":"The dish (grain=menu_item id) this offer prices.","source":"restaurant_menu_offers.menu_item_id","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"uuid","null_semantics":"never null"},"item.name":{"type":"string","description":"The dish name as stored (copied from the item when the offer was written). Display only; search names on grain=menu_item.","source":"restaurant_menu_offers.item_name","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when no name was read; reported as unknown."},"kind":{"type":"string","description":"What the dish is (wine | beer | cocktail | spirit | beverage | food), as GI read it from the section heading the source filed it under. Never derived by the API from a name, category or price. `unknown` selects the offers whose source stated no kind.","source":"restaurant_menu_offers.item_kind (from restaurant_menu_items.item_kind)","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"lowercase","null_semantics":"unknown: the source stated none (stored as '').","allowed_values":["wine","beer","cocktail","spirit","beverage","food","unknown"]},"serving.type":{"type":"string","description":"What this price buys (bottle | half_bottle | glass | carafe | flight | pairing | bundle), as GI read it from the source's structure (the price cell's marker, the offer's own label, a column header, the section). An expensive wine with no stated serving is not a bottle. `unknown` selects the offers whose source stated none.","source":"restaurant_menu_offers.serving_type","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"lowercase","null_semantics":"unknown: the source stated none (stored as '').","allowed_values":["bottle","half_bottle","glass","carafe","flight","pairing","bundle","unknown"]},"serving.volume_ml":{"type":"integer","description":"The volume the same slot printed with the serving (750 for '750 ml'), in millilitres.","source":"restaurant_menu_offers.serving_volume_ml","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"unknown: the source stated no volume."},"amount_cents":{"type":"bigint","description":"The offer's amount in minor units, exactly as stored (int8): the price as the source printed it, not validated, converted or compared across currencies. Rank one currency at a time (where[currency][eq]). Sorted highest first; ties by id.","source":"restaurant_menu_offers.amount_cents","operators":["gte","lte"],"sortable":["desc"],"selectable":true,"filterable":true,"visibility":"public","normalizer":"int8","null_semantics":"never null"},"currency":{"type":"string","description":"The currency the source stated, literal (e.g. USD). Restaurant websites state none today. `unknown` selects the offers with no stated currency.","source":"restaurant_menu_offers.currency","operators":["eq"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"literal","null_semantics":"unknown: the source stated none (stored as '')."},"source_price":{"type":"string","description":"What was printed where the price sits: evidence only.","source":"restaurant_menu_offers.source_price","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when nothing printed was kept; reported as unknown."},"surface_id":{"type":"string","description":"The channel: the surface (provider storefront or the publisher's own menu) this price was read from, literal.","source":"restaurant_menu_offers.surface_id","operators":["eq"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when no surface was named; reported as unknown."},"variant.id":{"type":"string","description":"The purchase variant this offer prices (GI's variant id).","source":"restaurant_menu_offers.variant_id","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when none was stated; reported as unknown."},"variant.label":{"type":"string","description":"The variant's own label as the source printed it.","source":"restaurant_menu_offers.variant_label","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when none was printed; reported as unknown."},"price_kind":{"type":"string","description":"The PRICE kind GI stated (a base price, 'from', conditional), literal. Not the item kind.","source":"restaurant_menu_offers.price_kind","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when none was stated; reported as unknown."},"condition":{"type":"string","description":"A condition the source attached to this price, literal.","source":"restaurant_menu_offers.condition","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when none was stated; reported as unknown."},"availability":{"type":"string","description":"The source's own word on whether it can be bought; unknown is not available.","source":"restaurant_menu_offers.availability","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when none was stated; reported as unknown."},"menu_context":{"type":"string","description":"The source's name for the menu this price was printed on (daypart, set menu, list).","source":"restaurant_menu_offers.menu_context","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"Stored as '' when none was stated; reported as unknown."},"observed_at":{"type":"datetime","description":"When this price was observed, as the source read stated it.","source":"restaurant_menu_offers.observed_at","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"unknown: no clock was stated for this offer (the dish's last_confirmed_at is on grain=menu_item)."},"listing_status":{"type":"string","description":"The dish's listing status when the offer was written (always listed on this grain).","source":"restaurant_menu_offers.listing_status","operators":[],"sortable":[],"selectable":true,"filterable":false,"visibility":"public","normalizer":"literal","null_semantics":"never null"},"place.id":{"type":"uuid","description":"The Place the dish is bound to (restaurant_locations.id): its record's representative Place, never proof the menu applies there (place_scope).","source":"restaurant_menu_offers.restaurant_location_id","operators":["eq","in"],"sortable":[],"selectable":true,"filterable":true,"visibility":"public","normalizer":"uuid","null_semantics":"never null for an eligible row"},"place.address.city":{"type":"string","description":"Filter: the offer's Place has this city (case-insensitive), reached through restaurant_menu_offers.restaurant_location_id exactly as grain=menu_item reaches its Place.","source":"EXISTS restaurant_locations ON id = restaurant_menu_offers.restaurant_location_id AND lower(city) = :city","operators":["eq","in"],"sortable":[],"selectable":false,"filterable":true,"visibility":"public","normalizer":"lowercase","null_semantics":"null means unknown for this row"},"place.address.region":{"type":"string","description":"Filter: the offer's Place has this region or state (case-insensitive).","source":"EXISTS restaurant_locations ON id = restaurant_menu_offers.restaurant_location_id AND lower(region) = :region","operators":["eq","in"],"sortable":[],"selectable":false,"filterable":true,"visibility":"public","normalizer":"lowercase","null_semantics":"null means unknown for this row"}},"default_select":["id","item.id","item.name","kind","serving.type","serving.volume_ml","amount_cents","currency","source_price","surface_id","place.id","observed_at"],"default_order":{"field":"amount_cents","direction":"desc"},"aliases":{"kind":"kind","serving":"serving.type","currency":"currency","surface":"surface_id","place":"place.id","city":"place.address.city","region":"place.address.region"},"rules":["One row is one stored offer; there is no item-level price and no offer is chosen per dish. Admitted orders: -amount_cents (the default; ties by id) and id.","A ranking describes the eligible STORED offers that qualify, never every wine or bottle at those Places: 'the highest-priced stored offers typed bottle and wine at Chicago Places', with meta.coverage.unknown saying how many offers at the same Places carry no stated serving, kind or currency.","serving.type, kind and currency are typed by GI from the source's structure, never by the API from printed text; `unknown` (stored '') is queryable and counted, never erased or treated as absence.","Without a currency filter the order sorts the stored amounts as numbers across currencies, and each row states its own currency (unknown when the source stated none, as publisher websites do today): an amount is comparable only to amounts in the same currency. where[currency][eq]=<code> ranks one currency.","place_scope is {binding: representative_place, applicability: unverified} on every row, as on grain=menu_item.","Fastest path: where[kind][eq] and where[serving.type][eq] together (the ix_restaurant_menu_offers_rank prefix), ordered -amount_cents."]}},"unsupported":[{"capability":"grain:person","reason":"People are stored and served per record; this service has no row-query implementation over them yet.","alternative":"GET /v1/public/company-intelligence/{domain}/people"},{"capability":"menu_item:price","reason":"No item-level price is stored: prices are offers nested in variants[].offers[], one per surface and variant, and choosing one would be a decision the row does not record. Serving, kind and price ranking are served by grain=offer: one row per stored offer with its serving {type, volume_ml}, the item's kind, currency, surface and amount, ranked by amount with full-precision keyset paging, and meta.coverage.unknown disclosing how many offers of the same set state no serving, kind or currency. On menu_item these are not fields: offers stay nested in variants[].offers[] exactly as stored and are never picked, compared or ranked here. Not served anywhere yet: observed_at windows (no stored offer carries a clock). Offers read before GI typed serving and kind from the source's structure (slice 7e) stay unknown until the retained structure is re-projected (slice 7f); an unmarked four-digit amount is ambiguous and is not read as a price.","alternative":"grain=offer&where[kind][eq]=wine&where[serving.type][eq]=bottle (ordered by -amount_cents by default); or select=variants here to read every stored offer with its surface_id."},{"capability":"menu_item:serving","reason":"Serving, kind and price ranking are served by grain=offer: one row per stored offer with its serving {type, volume_ml}, the item's kind, currency, surface and amount, ranked by amount with full-precision keyset paging, and meta.coverage.unknown disclosing how many offers of the same set state no serving, kind or currency. On menu_item these are not fields: offers stay nested in variants[].offers[] exactly as stored and are never picked, compared or ranked here. Not served anywhere yet: observed_at windows (no stored offer carries a clock). Offers read before GI typed serving and kind from the source's structure (slice 7e) stay unknown until the retained structure is re-projected (slice 7f); an unmarked four-digit amount is ambiguous and is not read as a price.","alternative":"grain=offer with where[serving.type][eq]=<type> and/or where[kind][eq]=<kind>; on menu_item, select=kind,variants."},{"capability":"menu_item:description_search","reason":"Only the name is trigram-indexed (ix_restaurant_menu_items_name_trgm); a substring scan of every description is not an admitted plan.","alternative":"where[name][contains]=<term>; select=description to read it."},{"capability":"menu:place_applicability","reason":"Menu rows are bound to their record's representative Place, and whether the menu page applies to that Place (surface scope: resolved, why, region) is kept in the record envelope, not on item or offer rows. A menu match at a Place is a candidate until an applicability projection (per-offer surface scope joinable from rows) is stored.","alternative":"grain=location&where[menu.name][contains]=<term> returns candidate Places; /v1/public/company-intelligence/{domain}/menu shows the record's surfaces."},{"capability":"grain:fact","reason":"Generic facts are deleted and recreated on refresh; no durable fact reference exists yet (design section 8).","alternative":"GET /v1/public/company-intelligence/{domain}"},{"capability":"grain:provider_relationship","reason":"Target capability in the design; no stored representation or read implementation yet.","alternative":"grain=relationship (declares_provider_account) or grain=location with identifier.provider; the declaring business: grain=business&where[id][eq]=<subject.business_id>."},{"capability":"grain:web_surface","reason":"Target capability in the design; no stored representation or read implementation yet.","alternative":"grain=domain_record"},{"capability":"grain:identifier_occurrence","reason":"Target capability in the design; no stored representation or read implementation yet.","alternative":"grain=relationship with the whole source_key tuple."},{"capability":"grain:fingerprint","reason":"No versioned fingerprint attribution is persisted yet.","alternative":"grain=relationship with the whole source_key tuple returns the stored occurrences of an exact key."},{"capability":"predicate:participates_in_program","reason":"Only declares_provider_account is admitted to the relationship grain today.","alternative":"The record's published identity (shared_with)."},{"capability":"predicate:declares_app","reason":"Only declares_provider_account is admitted to the relationship grain today.","alternative":"The record's published identity (shared_with)."},{"capability":"having","reason":"GET serves flat AND predicates only; correlated child qualification (having / not_having over registered children) is a POST body capability.","alternative":"POST /v1/public/intelligence/query with having / not_having."},{"capability":"include","reason":"GET serves flat rows only; bounded child includes are a POST body capability.","alternative":"POST /v1/public/intelligence/query with include; or follow each item's ref."},{"capability":"aggregate","reason":"GET serves rows only; full-matched-set aggregates are a POST body capability.","alternative":"POST /v1/public/intelligence/query with aggregate."},{"capability":"lookup","reason":"The batch exact-lookup mode is not implemented.","alternative":"where[<identity>][in]=... with up to 100 values."},{"capability":"operators:ne,prefix,not_exists,or,not","reason":"Only eq, in, indexed ordered ranges and `contains` on trigram-indexed text are operators; no prefix or ne operator. OR and NOT are POST where GROUPS (not on negatable fields only, unknown never matching), never GET operators.","alternative":"eq / in with literal values; POST where {and|or|not} groups."},{"capability":"order_by:multiple","reason":"GET takes one registered sort field per query; the identity breaks ties.","alternative":"order_by=<field> or order_by=-<field>; POST order_by takes up to 5 {field, dir} entries."},{"capability":"distance_sort_without_origins","reason":"A distance is measured from the query's origins; with none there is nothing to measure from.","alternative":"grain=location&origin[<label>]=<lat>,<lng>&where[distance_miles][lte]=<miles> (ordered by distance by default)."},{"capability":"origins:addresses","reason":"The query takes prepared points only and never geocodes or fetches; turning a tenant's addresses into labelled points is the separate authenticated step POST /v1/intelligence/origins, whose matched points are then passed inline.","alternative":"origin[<label>]=<lat>,<lng> with points you already hold, or prepared through POST /v1/intelligence/origins (authenticated)."},{"capability":"aggregate:grouped_unbounded","reason":"A grouped aggregate or facet over a field no index can bound would be a corpus scan; only fields the schema marks groupable are grouped.","alternative":"aggregate.metrics without group_by (full matched set), or group by a groupable field."},{"capability":"not_having:uncovered_child","reason":"not_having is served only on a child whose coverage is stored and carried on every row; without it, no stored row would read as real-world absence.","alternative":"having on the same child; not_having on a child the schema lists with a coverage_field."},{"capability":"aggregate:cursor","reason":"Aggregate pages are bounded by limit and say whether they are complete; group pages have no cursor in v1.","alternative":"Narrow where, or raise limit up to max_limit."},{"capability":"views","reason":"Saved dataset views are not implemented.","alternative":"GET /v1/public/intelligence/query"},{"capability":"execution_class:dataset,export","reason":"Only interactive bounded reads exist; nothing is queued.","alternative":"Narrow the query."},{"capability":"mcp","reason":"MCP adapters are deferred by owner decision (design section 1.2).","alternative":"Ordinary HTTP GET."}],"post":{"route":"POST /v1/public/intelligence/query","body":"JSON object; unknown keys are refused. Same error codes and response byte budget as GET; GET forms are unchanged.","keys":{"version":"1","grain":"required","select":"registered selectable fields","where":"[{field, op, value}] (ANDed) OR a group {and: [...]} | {or: [...]} | {not: <group or leaf>}; `in` takes a JSON array","having":"{<child>: <where>}: EXISTS one child row matching the whole group (the same edge / Place / dish); {} = any child","not_having":"{<child>: <where>}: NOT EXISTS; no qualifying STORED accepted evidence under the stated coverage, never real-world absence; rows carry the child's coverage_field","include":"{<child>: {select, where, order_by, limit}}: bounded child rows per parent, membership unchanged, each with its own complete/continue","aggregate":"{metrics: ['count' | {op: count_distinct, field}], group_by: [groupable fields], facets: [{field, limit}]}: over the full matched set","order_by":"[{field, dir}] up to the limit; the identity is the final tie-break; nulls sort last in both directions","limit":"1..100","cursor":"meta.next_cursor of the same body","origins":"grain=location: [{label, latitude, longitude}], 1 to 100 PREPARED points (labels unique, 1 to 64 characters; numbers, never strings), the body form of GET origin[<label>]=<lat>,<lng>, kept in the order given. Requires the radius {field: distance_miles, op: lte, value: <miles>}} ONCE as a top-level ANDed predicate (a where list, or directly inside a top-level `and` group); refused under or / not or in a child's where. With origins the default order is distance_miles then id and order_by takes one entry; having / not_having / include / aggregate apply within the radius. Nothing here geocodes: prepare addresses first."},"limits":{"max_group_depth":5,"max_group_predicates":100,"max_sorts":5,"max_group_by":3,"max_facets":10,"max_facet_limit":50,"max_query_body_bytes":65536,"aggregate_metrics":["count","count_distinct"]},"transport":"The body is counted while it streams and refused past 65536 bytes as invalid_query (422, the error table's code; path body) before any parsing. Responses, success or error, are Cache-Control: no-store (one URI serves every body). GET is unchanged and serves no post_only field.","negation":"not applies only to fields marked negatable; NOT X never matches a row whose value is unknown (null, or '' where that stores unknown).","cursor":"A POST cursor binds grain, select, the whole where/having/not_having/include shape, the sorts, the origins (labels, points and order) and the policy version; limit may change between pages. A body using no engine capability is the same canonical query as its GET form and pages under the GET binding."}}