@trillboards/api-client 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-U4ZLW5RR.mjs → chunk-BGQVFH2T.mjs} +2 -2
- package/dist/chunk-BGQVFH2T.mjs.map +1 -0
- package/dist/generated.d.mts +12 -0
- package/dist/generated.d.ts +12 -0
- package/dist/generated.js.map +1 -1
- package/dist/generated.mjs +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
- package/dist/chunk-U4ZLW5RR.mjs.map +0 -1
package/dist/generated.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/generated/index.ts"],"names":[],"mappings":";;;AA46NO,IAAM,cAAA,GAAiB;AAAA,EAC5B,WAAA,EAAa,GAAA;AAAA,EACb,cAAA,EAAgB,GAAA;AAAA,EAChB,OAAA,EAAS,CAAC,IAAA,EAAK,YAAA,EAAa,qBAAA,EAAsB,iBAAgB,2BAAA,EAA4B,6BAAA,EAA8B,cAAA,EAAe,wBAAA,EAAyB,4BAAA,EAA6B,yBAAA,EAA0B,mBAAkB,yBAAA,EAA0B,aAAA,EAAc,aAAA,EAAc,mBAAA,EAAoB,gBAAA,EAAiB,mBAAA,EAAoB,oBAAA,EAAqB,yBAAA,EAA0B,4BAAA,EAA6B,eAAA,EAAgB,kCAAA,EAAmC,wBAAA,EAAyB,mBAAA,EAAoB,2BAAA,EAA4B,wBAAuB,QAAA,EAAS,yBAAA,EAA0B,eAAA,EAAgB,sBAAA,EAAuB,yBAAA,EAA0B,2BAAA,EAA4B,gBAAe,kBAAA,EAAmB,OAAA,EAAQ,YAAA,EAAa,kBAAA,EAAmB,cAAA,EAAe,mBAAA,EAAoB,yBAAwB,iBAAA,EAAkB,YAAA,EAAa,mBAAA,EAAoB,wBAAA,EAAyB,YAAA,EAAa,SAAA,EAAU,0BAAA,EAA2B,yBAAA,EAA0B,sBAAA,EAAuB,4BAAA,EAA6B,4BAAA,EAA6B,qCAAA,EAAsC,4BAAA,EAA6B,gCAAA,EAAiC,2BAA0B,sBAAA,EAAuB,qCAAA,EAAsC,2BAAA,EAA4B,+BAAA,EAAgC,yBAAA,EAA0B,0BAAA,EAA2B,6BAA4B,oBAAA,EAAqB,+BAAA,EAAgC,qBAAA,EAAsB,iCAAA,EAAkC,sBAAA,EAAuB,4BAAA,EAA6B,eAAc,oCAAA,EAAqC,oBAAA,EAAqB,+BAAA,EAAgC,oBAAA,EAAqB,wBAAA,EAAyB,2BAAA,EAA4B,cAAA,EAAe,gBAAA,EAAiB,kBAAA,EAAmB,2BAAA,EAA4B,2BAAA,EAA4B,8BAAA,EAA+B,yBAAA,EAA0B,uBAAA,EAAwB,yBAAwB,iBAAA,EAAkB,WAAA,EAAY,QAAA,EAAS,yBAAA,EAA0B,aAAA,EAAc,0BAAA,EAA2B,+BAAA,EAAgC,kBAAA,EAAmB,0BAAA,EAA2B,+BAAA,EAAgC,wBAAA,EAAyB,cAAA,EAAe,oBAAA,EAAqB,uBAAA,EAAwB,2BAA0B,8BAAA,EAA+B,gBAAA,EAAiB,oBAAA,EAAqB,YAAA,EAAa,aAAA,EAAc,kCAAA,EAAmC,eAAA,EAAgB,qBAAA,EAAsB,SAAA,EAAU,iBAAA,EAAkB,cAAA,EAAe,yBAAA,EAA0B,gBAAgB,CAAA;AAAA,EAC79E,UAAA,EAAY,CAAC,yBAAA,EAA0B,0BAAA,EAA2B,kCAAiC,0BAAA,EAA2B,8BAAA,EAA+B,oBAAA,EAAqB,eAAA,EAAgB,cAAA,EAAe,uBAAA,EAAwB,sBAAqB,eAAA,EAAgB,uBAAA,EAAwB,uBAAA,EAAwB,mBAAA,EAAoB,oBAAA,EAAqB,8BAAA,EAA+B,2BAA0B,wBAAA,EAAyB,uBAAA,EAAwB,gBAAA,EAAiB,eAAA,EAAgB,iBAAA,EAAkB,mBAAA,EAAoB,mBAAkB,qBAAA,EAAsB,gCAAA,EAAiC,gBAAe,sBAAA,EAAuB,cAAA,EAAe,wBAAuB,oBAAA,EAAqB,oBAAA,EAAqB,iBAAA,EAAkB,qBAAA,EAAsB,uBAAA,EAAwB,2BAAA,EAA4B,wBAAuB,uBAAA,EAAwB,uBAAA,EAAwB,oBAAA,EAAqB,uBAAA,EAAwB,sBAAA,EAAuB,sBAAA,EAAuB,0BAAyB,kBAAA,EAAmB,2BAAA,EAA4B,iBAAA,EAAkB,sBAAA,EAAuB,kBAAA,EAAmB,cAAA,EAAe,6BAA4B,wBAAA,EAAyB,iBAAA,EAAkB,0BAAyB,uBAAA,EAAwB,qBAAA,EAAsB,2BAA0B,wBAAA,EAAyB,oBAAA,EAAqB,kBAAA,EAAmB,uBAAA,EAAwB,oBAAA,EAAqB,cAAA,EAAe,6BAA4B,sBAAA,EAAuB,eAAA,EAAgB,yBAAA,EAA0B,uBAAA,EAAwB,gBAAA,EAAiB,cAAA,EAAe,aAAY,cAAA,EAAe,iBAAA,EAAkB,kBAAA,EAAmB,oBAAA,EAAqB,WAAA,EAAY,yBAAA,EAA0B,eAAc,kBAAA,EAAmB,sBAAA,EAAuB,gCAA+B,kBAAA,EAAmB,oBAAA,EAAqB,eAAc,sBAAA,EAAuB,eAAA,EAAgB,iBAAA,EAAkB,yBAAA,EAA0B,mBAAA,EAAoB,iBAAA,EAAkB,qBAAoB,kBAAA,EAAmB,kBAAA,EAAmB,qBAAA,EAAsB,qBAAA,EAAsB,sBAAA,EAAuB,wBAAA,EAAyB,kBAAiB,sBAAA,EAAuB,mBAAA,EAAoB,kBAAA,EAAmB,2BAAA,EAA4B,+BAAA,EAAgC,kBAAA,EAAmB,sBAAqB,qBAAA,EAAsB,kBAAA,EAAmB,eAAc,iBAAA,EAAkB,mBAAA,EAAoB,2BAA0B,YAAA,EAAa,oCAAA,EAAqC,YAAA,EAAa,iBAAA,EAAkB,sBAAA,EAAuB,cAAA,EAAe,uBAAsB,kBAAA,EAAmB,kBAAA,EAAmB,mBAAA,EAAoB,mBAAA,EAAoB,gBAAA,EAAiB,mBAAA,EAAoB,2BAA0B,0BAAA,EAA2B,6BAAA,EAA8B,gCAAA,EAAiC,0BAAA,EAA2B,wBAAA,EAAyB,uBAAA,EAAwB,+BAA8B,gCAAA,EAAiC,2BAAA,EAA4B,iCAAgC,4BAAA,EAA6B,iCAAA,EAAkC,wBAAuB,oBAAA,EAAqB,4BAAA,EAA6B,8BAAA,EAA+B,8BAAA,EAA+B,yBAAA,EAA0B,qBAAA,EAAsB,sBAAqB,oBAAA,EAAqB,uBAAA,EAAwB,yBAAA,EAA0B,0BAAA,EAA2B,2BAAA,EAA4B,4BAAA,EAA6B,oCAAmC,8BAAA,EAA+B,kCAAA,EAAmC,4BAAA,EAA6B,4BAAA,EAA6B,uBAAA,EAAwB,oBAAA,EAAqB,wBAAuB,uBAAA,EAAwB,wBAAA,EAAyB,6BAA4B,8BAAA,EAA+B,yBAAA,EAA0B,6BAA4B,4BAAA,EAA6B,0BAAA,EAA2B,0BAAA,EAA2B,uBAAA,EAAwB,8BAAA,EAA+B,4BAAA,EAA6B,4BAA2B,6BAAA,EAA8B,0BAAA,EAA2B,2BAAA,EAA4B,2BAAA,EAA4B,wBAAA,EAAyB,2BAAA,EAA4B,8BAA6B,oBAAA,EAAqB,yBAAA,EAA0B,qBAAA,EAAsB,wBAAA,EAAyB,wBAAA,EAAyB,qBAAA,EAAsB,mBAAkB,kBAAA,EAAmB,kBAAA,EAAmB,wBAAuB,kBAAA,EAAmB,kBAAA,EAAmB,wBAAuB,sBAAA,EAAuB,qBAAA,EAAsB,iBAAA,EAAkB,mBAAA,EAAoB,oBAAA,EAAqB,gBAAA,EAAiB,oBAAmB,oBAAA,EAAqB,eAAA,EAAgB,iBAAA,EAAkB,oBAAA,EAAqB,iBAAA,EAAkB,sBAAA,EAAuB,gBAAe,eAAA,EAAgB,eAAA,EAAgB,eAAA,EAAgB,sBAAA,EAAuB,aAAa;AAC7sJ","file":"generated.js","sourcesContent":["/* eslint-disable */\n/**\n * AUTO-GENERATED. DO NOT EDIT.\n *\n * Generated from: trillboard-api/docs/openapi/merged/partner-api.json\n * Generator: trillboards-api-client/scripts/generate.js\n *\n * Re-emit via `npm run generate`.\n */\n\n// OpenAPI version: 3.0.3\n// API title: Trillboards Partner API\n// API version: 1.2.0\n// Schema count: 112\n// Operation count: 211\n\n// ─── Component schemas ───────────────────────────────────────────────────\n\nexport type Ad = {\n /** Placement/allocation ID used for delivery accounting, make-goods, and pacing. */\n allocation_id?: string;\n /** Duration in seconds */\n duration?: number;\n /** Advertisement ID */\n id?: string;\n /** Server-generated impression ID that must be echoed when reporting proof-of-play. */\n impression_id?: string;\n /** **Deprecated alias of `tracking.impression_url`.** These two fields are the same string, byte for byte, produced from one value server-side — they are not two different hooks and firing both records the same call twice. Read `tracking.impression_url`; this flat field is retained only for clients that predate the `tracking` object and will be removed once they are off it. */\n impression_url?: string;\n title?: string;\n /** Structured proof-of-play URLs for clients that prefer named tracking hooks over legacy flat fields. **Fire exactly one of `impression_url` / `complete_url` per play.** They resolve to the same endpoint and differ only by the `completed` query parameter, which that endpoint does not act on (see `GET /impression`) — calling both records the play twice. */\n tracking?: {\n /** Call when the ad completes playback/display dwell. This is `impression_url` plus `&completed=true`; the flag is inert server-side, so this is a delivery-accounting call, not proof of play. */\n complete_url?: string;\n /** Call when the ad is presented. Identical to the top-level `impression_url`. */\n impression_url?: string;\n /** **Server-signed proof of play. Present only on owner-billable direct bookings; absent on self-promo, house/QR, demo and fully-delivered placements.** When present, fire it VERBATIM — including the `sig`, `request_id` and `impid` parameters — once the ad has finished playing. Do not rewrite, re-sign, re-order, or drop any query parameter: the signature covers the values and any edit invalidates it. This is the only completion signal on the `data.ads` rail that settles; `complete_url` above is delivery accounting and is not billing-grade. Replays of the same play are collapsed on the SIGNED `request_id`, which carries this serve's `impression_id`. Because it is covered by `sig`, a replay that alters it to claim a fresh dedup key fails verification and records nothing — one served play can settle at most once. Firing it in addition to `complete_url` is correct and does not double-count — they land in different stores. */\n owned_direct_complete_url?: string;\n };\n type?: \"video\" | \"image\";\n /** Media URL (CDN) */\n url?: string;\n};\n\nexport type AdSettings = {\n /** Partner-configured ad rotation cadence in seconds, served from the screen display setting `ad_interval_seconds` when present and legacy display preferences only as fallback. */\n ad_interval?: number;\n content_fit?: ContentFitSettings;\n /** Seconds to display image ads; independent from ad rotation cadence. */\n image_duration?: number;\n max_ads_per_hour?: number;\n overlay_button_text?: string;\n sound_enabled?: boolean;\n};\n\n/**\n * Stateful resettable operating-system advertising identity. Send\n * `available` only with the current OS ID; send `limited`,\n * `consent_denied`, `unavailable`, `unsupported`, or `error` to clear a\n * previously observed identifier. UID2 and hashed email are audience\n * tokens, not OS advertising IDs, and do not belong in this envelope.\n *\n */\nexport type AdvertisingIdentity = {\n expires_at?: string | null;\n /** Present only when status is `available`. */\n id?: string | null;\n /** Resettable OS identifier type. GAID maps to OpenRTB `aaid`. */\n id_type?: \"gaid\" | \"aaid\" | \"afai\" | \"rida\" | \"tifa\" | \"idfa\" | null;\n /** Must be false for `available` and true for `limited`. */\n limit_ad_tracking: boolean | null;\n observed_at: string;\n source: \"google_play_services\" | \"amazon_fire_os\" | \"roku_os\" | \"samsung_tizen\" | \"lg_webos\" | \"apple_platform\" | \"host_supplied\";\n source_version?: string | null;\n status: \"available\" | \"limited\" | \"consent_denied\" | \"unavailable\" | \"unsupported\" | \"error\";\n};\n\n/**\n * Partner analytics summary (`@trillboards/api-client` `AnalyticsData`).\n *\n */\nexport type AnalyticsData = {\n average_cpm: number;\n /** Optional per-screen breakdown. */\n by_screen?: Array<{\n earnings: number;\n impressions: number;\n name: string;\n screen_id: string;\n }>;\n /** Fraction of ad opportunities filled, 0..1. */\n fill_rate: number;\n /** The window this summary covers (e.g. day, week, month). */\n period: string;\n screens_active: number;\n screens_total: number;\n total_earnings: number;\n total_impressions: number;\n};\n\nexport type AudienceAnalyticsResponse = {\n data?: {\n audience?: {\n avg_attention?: number;\n avg_face_count?: number;\n screens_with_data?: number;\n };\n overview?: {\n active_screens?: number;\n avg_impressions_per_screen?: number;\n total_impressions?: number;\n total_screens?: number;\n };\n period?: string;\n timestamp?: string;\n trends?: {\n audience_trend?: \"increasing\" | \"stable\" | \"decreasing\";\n impressions_trend?: \"increasing\" | \"stable\" | \"decreasing\";\n };\n };\n request_id?: string;\n success?: boolean;\n};\n\n/**\n * Backend-derived predictive attention signal + buyer-grade attentive-seconds. 1:1 with audience_metrics. Never null by contract; placeholder on row 1.\n */\nexport type AudienceAttentionPrediction = {\n /** attentive_face_count SMALLINT: distinct viewers meeting the >=1s threshold; the buyer-side CPMA denominator. NEVER NULL. */\n attentive_face_count: number;\n /** attentive_seconds_observed = SUM(per_face[].gaze_seconds >= 1.0), OpenOOH 2024 4.2. NEVER NULL by DDL, so 0.000 means 'no viewer met threshold' ONLY when per_face_observations[] was present. NUMERIC(6,3). */\n attentive_seconds_observed: number;\n /** attentive_seconds_predicted_15s: expected next-15s attentive seconds from per-screen history x attention-weight; bootstrap = linear extrapolation. No global tau. NUMERIC(6,3). */\n attentive_seconds_predicted_15s: number;\n next_state_abs_error?: number | null;\n next_state_attention_forecast?: number | null;\n next_state_attention_realized?: number | null;\n next_state_confidence?: number | null;\n next_state_forecast_at?: string | null;\n next_state_graded_at?: string | null;\n next_state_horizon_minutes?: number | null;\n next_state_method?: string | null;\n next_state_persist_abs_error?: number | null;\n next_state_sample_size?: number | null;\n next_state_xscreen_abs_error?: number | null;\n next_state_xscreen_method?: string | null;\n next_state_xscreen_sample_size?: number | null;\n next_state_xsv_abs_error?: number | null;\n next_state_xsv_sample_size?: number | null;\n /** predicted_attention_next_30s enum {high,medium,low,none}. 'none' is below 'low'; fires when rolling history converges to zero or on a trend down from 'low'. */\n predicted_attention_next_30s: \"high\" | \"medium\" | \"low\" | \"none\";\n /** predicted_disengagement_imminent needs elevated dwell AND a falling trend, so it is unreachable whenever the history vector is empty. A 0% fire rate is a HISTORY-PLUMBING alarm, not a quiet fleet. */\n predicted_disengagement_imminent: boolean;\n prediction_evidence: string;\n};\n\n/**\n * Live/aggregate audience data for a screen\n * (`@trillboards/api-client` `AudienceData`).\n *\n */\nexport type AudienceData = {\n /** Count of attentive viewers in the sample. */\n attention_count: number;\n /** Optional demographic breakdown. */\n demographics?: Record<string, unknown>;\n /** Average dwell time for the sample. */\n dwell_time_avg: number;\n screen_id: string;\n timestamp: string;\n};\n\nexport type AudienceExportResponse = {\n data?: Array<{\n audience?: {\n avg_attention?: number;\n avg_face_count?: number;\n demographics?: Record<string, unknown>;\n income_profile?: Record<string, unknown>;\n lifestyle_segments?: Array<string>;\n };\n country?: string;\n impressions?: number;\n location?: string;\n period?: {\n end?: string;\n start?: string;\n };\n screen_id?: string;\n screen_name?: string;\n }>;\n request_id?: string;\n success?: boolean;\n summary?: {\n aggregation?: string;\n period?: Record<string, unknown>;\n total_impressions?: number;\n total_screens?: number;\n };\n};\n\n/**\n * Per-device cross-day loyalty feature row emitted by the\n * `audience_loyalty_features` dataset. Keyed by a partner-scoped\n * pseudonymous ID — the same physical device yields a different ID\n * for each partner because the HMAC salt is partner-specific\n * (`partner_salt` on `platform_api_keys`).\n *\n */\nexport type AudienceLoyaltyFeaturesRow = {\n _match_disclosure?: {\n match_confidence?: \"high\" | \"medium\" | \"low\";\n primary_signal_source?: \"ble_continuity\" | \"ble_mac_stable\" | \"mdns_vendor_model\" | \"fixed_mac\";\n };\n demographic_inference?: {\n age_bracket?: string;\n attention_score_avg?: number;\n audience_attire_archetype?: string;\n audience_group_composition?: string;\n audience_intent_stage?: string;\n gender_distribution?: Record<string, unknown>;\n };\n /** Partner-scoped HMAC of cross-day device key (16 hex chars + tb_ prefix). Different partners get different IDs for the same physical device — preventing collusion. */\n device_id_pseudonymous: string;\n distinct_days_in_window: number;\n distinct_venues_in_window?: number;\n /** Days since this device was first observed at any of the partner-scoped screens. */\n first_seen_relative_days: number;\n last_seen_relative_days: number;\n manufacturer_class: \"premium\" | \"mainstream\" | \"audio_iot\" | \"other\";\n manufacturer_label?: string;\n /** Raw cross-day-stable identifiers when available (NULL for randomized phone MACs without Continuity). */\n raw_identifiers?: {\n ble_mac?: string | null;\n /** First 3 bytes of BLE MAC (IEEE OUI vendor lookup). */\n ble_mac_oui?: string | null;\n ble_mac_oui_vendor?: string | null;\n manufacturer_company_id?: number | null;\n mdns_hostname?: string | null;\n wifi_bssid?: string | null;\n };\n top_day_of_week?: number;\n top_hour_of_day?: number;\n /** List of venue_category labels (Bar, Restaurant, etc.) the device was observed at. */\n venue_archetypes?: Array<string>;\n visit_count_in_window: number;\n};\n\nexport type AudienceMetricsResponse = {\n data?: {\n aggregated?: {\n avgAttention?: number;\n avgDwellMs?: number;\n avgFaceCount?: number;\n groupComposition?: Record<string, unknown>;\n incomeProfile?: {\n high?: number;\n low?: number;\n medium?: number;\n premium?: number;\n };\n };\n history?: Array<Record<string, unknown>>;\n live?: {\n /** Average attention score (0-1) */\n avgAttention?: number;\n /** Average faces detected */\n avgFaceCount?: number;\n incomeLevel?: \"unknown\" | \"low\" | \"medium\" | \"high\" | \"premium\";\n /** Maximum faces detected in period */\n maxFaces?: number;\n mood?: string;\n screenEngagement?: string;\n };\n period?: string;\n screen_id?: string;\n screen_name?: string;\n timestamp?: string;\n };\n request_id?: string;\n success?: boolean;\n};\n\nexport type AudienceSegment = {\n created_at?: string;\n description?: string;\n id?: string;\n is_active?: boolean;\n last_matched_at?: string;\n last_matched_count?: number;\n name?: string;\n object?: string;\n request_id?: string;\n rules?: Array<{\n field?: string;\n operator?: string;\n value?: unknown;\n }>;\n updated_at?: string;\n};\n\n/**\n * Buyer-grade social amplification signal (5 typed columns). Cloud Vertex Gemini producer. 1 row per audience observation when cascade is observable.\n */\nexport type AudienceSocialAttention = {\n amplification_evidence: string;\n cascade_depth: number;\n /** All 5 columns NOT NULL except primary_attention_anchor_face_index (only legit NULL: no anchor or solo scene). */\n primary_attention_anchor_face_index?: number | null;\n /** NUMERIC(4,3). */\n social_amplification_factor: number;\n /** viral_attention_score is the headline number Viant/T-Vision license. Composite of social_amplification_factor × cascade_depth × emotional engagement. NUMERIC(4,3). */\n viral_attention_score: number;\n};\n\nexport type BatchResult = {\n /** Number that failed */\n failed_count?: number;\n failed_screens?: Array<{\n error?: string;\n screen_id?: string;\n }>;\n object?: string;\n request_id?: string;\n /** Number of screens requested to update */\n total_requested?: number;\n /** Number successfully updated */\n updated_count?: number;\n /** IDs of successfully updated screens */\n updated_screens?: Array<string>;\n};\n\n/**\n * Partner billing snapshot — plan, credits, and month-to-date usage\n * (`@trillboards/api-client` `BillingInfo`).\n *\n */\nexport type BillingInfo = {\n credits_remaining: number;\n credits_used: number;\n plan: string;\n /** Whether the partner has a connected Stripe account. */\n stripe_connected: boolean;\n /** Usage counters for the current billing month, keyed by metric. */\n usage_this_month: Record<string, number>;\n};\n\nexport type BleScanResultData = {\n appleContinuitySubtype?: number | null;\n deviceType?: number | null;\n ibeaconMajor?: number | null;\n ibeaconMinor?: number | null;\n ibeaconUuid?: string | null;\n manufacturerCompanyId?: number | null;\n rawAddress: string;\n rssi: number;\n serviceUuids?: Array<string> | null;\n stableManufacturerPayloadHex?: string | null;\n txPowerDbm?: number | null;\n [key: string]: unknown;\n};\n\nexport type ChangelogEntry = {\n /** ISO date string or null for unreleased */\n date: string | null;\n /** Human-readable change description */\n description: string;\n /** API surface: data, sdk, device, sensing, openrtb, partner, all */\n surface: string;\n /** Keepachangelog type: added, changed, deprecated, removed, fixed, security */\n type: string;\n /** \"unreleased\" or a date like \"2026-04-16\" */\n version: string;\n};\n\nexport type ChangelogResponse = {\n /** Matching changelog entries */\n data: Array<ChangelogEntry>;\n /** Always \"list\" */\n object: \"list\";\n /** Number of entries returned */\n total: number;\n};\n\n/**\n * Per-content-type sizing returned and accepted by the Partner API.\n * `fit` preserves the entire creative and may letterbox; `fill` covers\n * the screen and may crop edges. Omitting this object from a write leaves\n * the screen's current behavior unchanged.\n *\n */\nexport type ContentFitSettings = {\n /** Sizing for direct and programmatic advertisements. */\n advertisements?: \"fit\" | \"fill\";\n /** Sizing for default/background streams. */\n default_streams?: \"fit\" | \"fill\";\n /** Sizing for self-promotion and QR-code house ads. */\n self_promo?: \"fit\" | \"fill\";\n};\n\nexport type ContentPreferencesInput = {\n /** Specific advertiser IDs to block */\n blocked_advertisers?: Array<string>;\n /** Ad categories to block (e.g., \"alcohol\", \"gambling\", \"adult\") */\n blocked_categories?: Array<string>;\n /** Max times same ad can show per hour */\n max_ad_frequency?: number;\n /** Minimum ad content rating */\n min_ad_rating?: \"G\" | \"PG\" | \"PG-13\" | \"R\";\n /** Preferred ad categories (prioritized in auctions) */\n preferred_categories?: Array<string>;\n};\n\nexport type ContentPreferencesResponse = {\n blocked_advertisers?: Array<string>;\n blocked_categories?: Array<string>;\n max_ad_frequency?: number;\n min_ad_rating?: string;\n object?: string;\n preferred_categories?: Array<string>;\n request_id?: string;\n screen_id?: string;\n updated_at?: string;\n};\n\nexport type ContentPreset = {\n /** Advertiser IDs blocked */\n blocked_advertisers?: Array<string>;\n /** Categories blocked by this preset */\n blocked_categories?: Array<string>;\n /** Preset description */\n description?: string;\n /** Unique preset identifier */\n id?: string;\n /** Minimum ad rating allowed */\n min_ad_rating?: \"G\" | \"PG\" | \"PG-13\" | \"R\";\n /** Human-readable preset name */\n name?: string;\n /** Full preference object applied by this preset */\n preferences?: Record<string, unknown>;\n};\n\nexport type CreatePartnerSensingRouteRequest = {\n actions: Array<SensingRouteAction>;\n activeDaysMask?: number;\n activeEndMinute?: number;\n activeStartMinute?: number;\n activeTz?: string;\n condition?: SensingRouteCondition;\n debounceSeconds?: number;\n /** Required when mode=digest. `field` is required for avg/max. */\n digest?: {\n field?: string;\n intervalMinutes?: number;\n metric?: \"count\" | \"avg\" | \"max\";\n windowMinutes?: number;\n };\n enabled?: boolean;\n mode?: \"threshold\" | \"digest\";\n name: string;\n /** Bind to a named Sense Anything profile (stable across redeploys). */\n profileName?: string;\n /** Screens to watch — all owned by this partner (foreign → 403). Provide EITHER screenMongoIds OR targetGroupId, not both. */\n screenMongoIds?: Array<string>;\n sustainMinSamples?: number;\n sustainWindowSeconds?: number;\n /** A sg_ Screen Group id (owned by this partner) to target instead of an explicit screen set. The route fires on the group's live members. Requires SENSING_ROUTES_GROUP_TARGET_ENABLED. */\n targetGroupId?: string;\n};\n\n/**\n * Structured creative classification — the same shape the Trillboards venue portal renders for a served ad.\n */\nexport type CreativeClassification = {\n advertiser_name?: string | null;\n /** One of G, PG, PG-13, R, NC-17 (null until classified). */\n age_rating?: string | null;\n analysis?: {\n keywords?: Array<string>;\n mood?: string | null;\n quality?: string | null;\n setting?: string | null;\n subjects?: Array<string>;\n /** On-screen text (OCR). */\n text_content?: string | null;\n };\n categorization?: {\n brand?: string | null;\n category?: string | null;\n iab_categories?: Array<string>;\n };\n /** Classification confidence, 0..1. */\n confidence?: number | null;\n content_sha256?: string;\n /** Canonical reference — `sha256:<hex>` of the creative bytes. Use as `creative_ref` when posting plays. */\n id?: string;\n moderation?: {\n approved?: boolean;\n flags?: Array<string>;\n };\n object?: string;\n status?: \"pending\" | \"approved\" | \"flagged\" | \"blocked\";\n thumbnail_url?: string | null;\n};\n\nexport type DashboardResponse = {\n earnings?: {\n available_payout_cents?: number;\n next_payout_date?: string;\n pending_payout_cents?: number;\n revenue_share_percent?: number;\n total_earned_cents?: number;\n };\n partner?: {\n created_at?: string;\n name?: string;\n slug?: string;\n status?: \"pending\" | \"active\" | \"suspended\" | \"terminated\";\n };\n recent_activity?: Array<{\n ad_id?: string;\n screen_id?: string;\n timestamp?: string;\n type?: string;\n }>;\n stats?: {\n active_screens?: number;\n offline_screens?: number;\n pending_screens?: number;\n total_impressions_month?: number;\n total_impressions_today?: number;\n total_impressions_week?: number;\n total_screens?: number;\n };\n stripe_status?: {\n account_status?: string;\n connect_account_id?: string;\n };\n top_screens?: Array<{\n impressions_today?: number;\n location?: string;\n name?: string;\n screen_id?: string;\n }>;\n};\n\n/**\n * Per-dataset record counts + date ranges for the partner's screens.\n * Returned by `GET /data-export/summary`.\n *\n */\nexport type DataExportSummaryResponse = {\n data?: {\n /** Map of dataset name to record summary */\n datasets?: Record<string, {\n earliest?: string | null;\n latest?: string | null;\n total_records?: number;\n }>;\n k_anonymity_threshold?: number;\n lookback_days?: number;\n screen_count?: number;\n };\n success?: boolean;\n};\n\nexport type DemographicsResponse = {\n data?: {\n data_quality?: {\n confidence?: number;\n sample_size?: number;\n };\n demographics?: {\n age_distribution?: {\n \"18-25\"?: number;\n \"26-35\"?: number;\n \"36-50\"?: number;\n \"50+\"?: number;\n };\n gender_split?: {\n female?: number;\n male?: number;\n };\n group_composition?: {\n couples?: number;\n families?: number;\n friends?: number;\n solo?: number;\n work_groups?: number;\n };\n income_profile?: {\n high?: number;\n low?: number;\n medium?: number;\n premium?: number;\n };\n lifestyle_segments?: Array<string>;\n };\n period?: string;\n screen_id?: string;\n screen_name?: string;\n timestamp?: string;\n };\n request_id?: string;\n success?: boolean;\n};\n\nexport type Device = {\n created_at?: string;\n device_id?: string;\n device_type?: string;\n /** Screen display specification. `width`/`height` are pixel resolution; `width_in`/`height_in` are physical inches. Pixel-only inputs are NOT recorded as physical size — pass `width_in`/`height_in` (most accurate) or `ppi` so the server can derive inches from pixels. */\n display?: {\n /** Display resolution height in pixels */\n height?: number;\n /** Physical screen height in inches */\n height_in?: number;\n orientation?: string;\n /** Pixels per inch (required to derive physical size from width/height) */\n ppi?: number;\n /** Display resolution width in pixels */\n width?: number;\n /** Physical screen width in inches */\n width_in?: number;\n };\n embed_url?: string;\n enrichment?: Record<string, unknown>;\n external_device_id?: string;\n fingerprint?: string;\n location?: Record<string, unknown>;\n name?: string;\n screen_id?: string;\n status?: \"pending\" | \"active\" | \"offline\" | \"suspended\";\n updated_at?: string;\n venue?: Record<string, unknown>;\n};\n\nexport type DeviceCapabilityPayload = {\n agentType?: string | null;\n agentVersion?: string | null;\n audienceSensing?: {\n cameraAvailable?: boolean | null;\n cameraCount?: number | null;\n cameraHealth?: {\n lastFailureClass?: string | null;\n lastFailureMessage?: string | null;\n lastFrameAtMs?: number | null;\n retryCount?: number | null;\n state?: string | null;\n [key: string]: unknown;\n } | null;\n cameraType?: string | null;\n microphoneAvailable?: boolean | null;\n sensingMode?: string | null;\n [key: string]: unknown;\n } | null;\n audioControl?: {\n mute?: boolean | null;\n volume?: boolean | null;\n [key: string]: unknown;\n } | null;\n capabilitiesVersion?: number | null;\n environmentSensors?: {\n ambientLight?: boolean | null;\n temperature?: boolean | null;\n [key: string]: unknown;\n } | null;\n inputControl?: {\n appSwitch?: boolean | null;\n hdmi?: boolean | null;\n [key: string]: unknown;\n } | null;\n isDeviceOwner?: boolean | null;\n managementCapabilities?: {\n clearCache?: boolean | null;\n installApk?: boolean | null;\n kioskMode?: boolean | null;\n reboot?: boolean | null;\n restart?: boolean | null;\n screenshot?: boolean | null;\n wipe?: boolean | null;\n [key: string]: unknown;\n } | null;\n mlCapabilities?: {\n availableRamMb?: number | null;\n chipsetName?: string | null;\n chipsetVendor?: string | null;\n cpuAbi?: string | null;\n densityDpi?: number | null;\n gpuDelegateSupported?: boolean | null;\n gpuName?: string | null;\n hasNpu?: boolean | null;\n maxVlmSizeMb?: number | null;\n nnapiSupported?: boolean | null;\n npuName?: string | null;\n osApiLevel?: number | null;\n recommendedModelTier?: string | null;\n screenHeightPx?: number | null;\n screenWidthPx?: number | null;\n totalRamMb?: number | null;\n [key: string]: unknown;\n } | null;\n powerControl?: {\n cec?: boolean | null;\n softBlackout?: boolean | null;\n wol?: boolean | null;\n [key: string]: unknown;\n } | null;\n wifiCsiSensing?: {\n csiAvailable?: boolean | null;\n csiHardwareType?: string | null;\n csiNodeCount?: number | null;\n [key: string]: unknown;\n } | null;\n [key: string]: unknown;\n};\n\nexport type DeviceSummary = {\n created_at?: string;\n device_id?: string;\n device_type?: string;\n display?: Record<string, unknown>;\n embed_url?: string;\n enrichment?: Record<string, unknown>;\n external_device_id?: string;\n fingerprint?: string;\n location?: Record<string, unknown>;\n name?: string;\n screen_id?: string;\n status?: string;\n updated_at?: string;\n venue?: Record<string, unknown>;\n};\n\nexport type DisplaySettingsInput = {\n /** Default ad duration in seconds */\n ad_duration_default?: number;\n /** Screen brightness percentage */\n brightness?: number;\n content_fit?: ContentFitSettings;\n /** Ad display mode */\n display_mode?: \"fullscreen\" | \"l-bar\" | \"split\";\n /** What to show when no ads */\n idle_content?: \"default_stream\" | \"black\" | \"logo\";\n /** Mute audio */\n mute?: boolean;\n /** Screen orientation */\n orientation?: \"landscape\" | \"portrait\" | \"auto\";\n /** QR code position on screen */\n qr_code_position?: \"bottom-left\" | \"bottom-right\" | \"top-left\" | \"top-right\" | \"none\";\n /** Transition effect between ads */\n transition_effect?: \"fade\" | \"slide\" | \"none\";\n /** Audio volume percentage */\n volume?: number;\n};\n\nexport type DisplaySettingsResponse = {\n ad_duration_default?: number;\n ad_surfaces?: Array<{\n height_percent?: number;\n id?: string;\n position?: string;\n width_percent?: number;\n }>;\n brightness?: number;\n content_fit?: ContentFitSettings;\n display_mode?: string;\n idle_content?: string;\n mute?: boolean;\n object?: string;\n orientation?: string;\n playback_policy?: {\n allow_skip?: boolean;\n max_duration_seconds?: number;\n min_break_between_ads?: number;\n };\n qr_code_position?: string;\n request_id?: string;\n screen_id?: string;\n transition_effect?: string;\n updated_at?: string;\n volume?: number;\n};\n\nexport type EarningsBreakdownResponse = {\n breakdown?: Array<{\n /** Date or screen_id depending on group_by */\n date?: string;\n earnings_cents?: number;\n impressions?: number;\n /** Screen ID (when grouped by screen) */\n screen_id?: string;\n }>;\n pending_programmatic?: {\n confirmation_date?: string;\n estimated_cents?: number;\n };\n period?: {\n end?: string;\n group_by?: \"day\" | \"week\" | \"screen\";\n start?: string;\n };\n summary?: {\n direct_cents?: number;\n programmatic_cents?: number;\n total_cents?: number;\n total_impressions?: number;\n };\n};\n\n/**\n * Partner earnings summary with optional daily series\n * (`@trillboards/api-client` `EarningsData`).\n *\n */\nexport type EarningsData = {\n average_cpm: number;\n /** Optional per-day earnings/impressions series. */\n daily?: Array<{\n /** Day label (YYYY-MM-DD). */\n date: string;\n earnings: number;\n impressions: number;\n }>;\n last_payout_amount?: number;\n last_payout_date?: string;\n /** Balance not yet paid out. */\n pending_payout: number;\n period: string;\n total_earnings: number;\n total_impressions: number;\n};\n\nexport type EarningsResponse = {\n /** Amount available for immediate payout */\n available_for_payout_cents?: number;\n breakdown?: {\n direct_campaigns?: number;\n programmatic_floodgates?: number;\n programmatic_google?: number;\n };\n next_payout_estimate?: {\n amount_cents?: number;\n date?: string;\n stripe_status?: string;\n };\n /** Minimum amount required for payout */\n payout_threshold_cents?: number;\n /** Programmatic earnings pending Net-60 confirmation */\n pending_confirmation_cents?: number;\n /** Partner's revenue share percentage */\n revenue_share_percent?: number;\n /** Estimated earnings for current month */\n this_month_cents?: number;\n /** Total earnings since partner started */\n total_lifetime_cents?: number;\n};\n\nexport type Error = {\n error?: string;\n message?: string;\n success?: boolean;\n};\n\n/**\n * A single partner API error-log record\n * (`@trillboards/api-client` `ErrorEntry`) — one logged error occurrence\n * scoped to the partner. Distinct from the public error *catalog* entries\n * (`ErrorListItem` / `ErrorCodeResponse`), which describe error codes in\n * the abstract.\n *\n */\nexport type ErrorEntry = {\n /** Stable machine error code (e.g. not_found). */\n code: string;\n doc_url: string;\n /** The API path that produced the error. */\n endpoint: string;\n id: string;\n message: string;\n /** The HTTP method of the failing request. */\n method: string;\n /** The request parameter the error concerns, if any. */\n param?: string;\n request_id: string;\n timestamp: string;\n /** Stripe-style error taxonomy (matches the SDK's ApiErrorType). */\n type: \"invalid_request_error\" | \"authentication_error\" | \"permission_error\" | \"rate_limit_error\" | \"idempotency_error\" | \"api_error\";\n};\n\n/**\n * Exact DSP-matchable audience identity kept separate from the resettable\n * OS advertising ID. `hem_sha256` is an existing SHA-256 digest: send it\n * directly (the server lowercases hexadecimal once and never hashes it\n * again). `uid2_token` is an opaque, case-sensitive UID2 advertising\n * token: send it exactly as issued and include `expires_at` so it can be\n * refreshed; tokens contain no whitespace. Use `unavailable` with no\n * `id` to clear a prior value.\n *\n */\nexport type ExtendedIdentity = {\n /** OpenRTB person-based identifier type. */\n atype: 3;\n expires_at?: string | null;\n id?: string | null;\n id_type: \"hem_sha256\" | \"uid2_token\";\n observed_at: string;\n /** Canonical top-level domain for this identity system. */\n source: string;\n source_version?: string | null;\n status: \"available\" | \"unavailable\";\n};\n\n/**\n * A fleet-command job: one batch that fanned a device command across a screen group's\n * members. Poll via GET /fleet-commands/{id}.\n *\n */\nexport type FleetCommand = {\n command_type?: string;\n completed_at?: string | null;\n created_at?: string;\n error?: string | null;\n /** Screens that could not be enqueued */\n failed?: number;\n group_id?: string | null;\n /** Job id (fc_ prefix). */\n id?: string;\n object?: string;\n /** Screens the command was enqueued to */\n queued?: number;\n results?: Array<{\n device_command_id?: string | null;\n error?: string | null;\n screen_id?: string;\n status?: \"queued\" | \"failed\";\n }>;\n status?: \"queued\" | \"running\" | \"completed\" | \"failed\";\n /** Member screens resolved for this command */\n targeted?: number;\n updated_at?: string;\n};\n\n/**\n * Webhook body for a group fleet-command terminal state (`fleet_command.completed` |\n * `fleet_command.failed`). Standard `{ id, event, timestamp, data }` envelope; `data` is the\n * `fleet_command` job object (status, targeted/queued/failed counts, per-screen results; on\n * failure, an `error` message). The event type is also in the `X-Trillboards-Event` header —\n * verify the compound `X-Trillboards-Signature` over the raw body first.\n *\n */\nexport type FleetCommandEvent = {\n /** The fleet_command job object. */\n data?: Record<string, unknown>;\n event?: \"fleet_command.completed\" | \"fleet_command.failed\";\n id?: string;\n timestamp?: string;\n};\n\n/**\n * Programmatic header-bidding configuration and the resolved VAST waterfall for the screen. The `vast_waterfall.sources[]` array is the programmatic demand path — fetch each source's `vast_url` in priority order and hand the returned VAST to your IMA SDK. Source names are opaque public aliases. Source-health request-pressure governance does not remove SQL/Admin-enabled sources from this catalog.\n *\n */\nexport type HeaderBiddingSettings = {\n ad_buffering?: {\n enabled?: boolean;\n max_buffer?: number;\n max_cache_age_seconds?: number;\n min_buffer?: number;\n warmup_count?: number;\n } | null;\n ad_pod?: Record<string, unknown> | null;\n allocation?: number;\n auction_request_id?: string;\n enabled?: boolean;\n experiment_variant?: string | null;\n fast_loop?: Record<string, unknown> | null;\n fetch_mode?: string | null;\n force_request?: boolean;\n ima_profile?: Record<string, unknown> | null;\n min_interval_seconds?: number;\n prebid?: Record<string, unknown> | null;\n provider?: string;\n regional_config?: {\n ad_buffer_percentage?: number;\n enable_network_adaptation?: boolean;\n fallback_timeout_ms?: number;\n preferred_resolution?: string;\n timeout_ms?: number;\n vquality?: string;\n } | null;\n /** Per-request waterfall identifier; echo it back on programmatic-event reports. */\n request_id?: string;\n request_mode?: string;\n source_name?: string | null;\n source_priority?: number | null;\n variant_name?: string;\n vast_cache?: {\n enabled?: boolean;\n priority?: string;\n ttl_seconds?: number;\n } | null;\n vast_tag_url?: string;\n vast_waterfall?: VastWaterfall;\n} | null;\n\nexport type HttpProbeResult = {\n host: string;\n port?: number | null;\n server?: string | null;\n [key: string]: unknown;\n};\n\n/**\n * A recorded ad impression / play for a partner screen\n * (`@trillboards/api-client` `Impression`).\n *\n */\nexport type Impression = {\n /** Kind of ad served (e.g. direct, programmatic, self_promo). */\n ad_type?: string;\n advertiser_name?: string;\n /** Effective CPM for the impression, in the partner's currency. */\n cpm?: number;\n device_id: string;\n /** Play duration in seconds. */\n duration_seconds?: number;\n /** Earner revenue accrued for the impression. */\n earnings?: number;\n impression_id: string;\n played_at: string;\n screen_id: string;\n};\n\nexport type MdnsNetworkDevice = {\n host?: string | null;\n instanceName: string;\n mdnsModel?: string | null;\n mdnsSoftwareVersion?: string | null;\n mdnsVendor?: string | null;\n port?: number | null;\n serviceType: string;\n [key: string]: unknown;\n};\n\n/**\n * Versioned public disclosure of how audience measurement is produced.\n * Describes WHAT is measured and HOW IT IS QUALIFIED — deliberately never\n * names infrastructure or source locations.\n *\n */\nexport type MeasurementMethodology = {\n canonical_path?: string;\n /** What each screen observes and what is dropped at the edge. */\n capture_stack?: Record<string, unknown>;\n /** Cross-day identity, including measured coverage (1.6% of identifiable BLE rows). An earlier revision said ~31%; that graded the presence of stable_payload_hash and ignored the sanitizer the identity expression applies, and it is withdrawn. */\n cross_day_matching?: Record<string, unknown>;\n display_exposure_zone?: Record<string, unknown>;\n dwell_qualification_thresholds?: Record<string, unknown>;\n edge_confidence_model?: Record<string, unknown>;\n /** Evidence grades, which are decisionable, and person-grain resolution. */\n evidence_grade_ladder: Record<string, unknown>;\n fallback_path?: string;\n /** How identifiers are keyed, and what erasure means. */\n hashing?: Record<string, unknown>;\n /** The counting UNIT. Reach and unique-device counts are counts of BLE identifiers, not devices and not people; one device contributes several identifiers per window and the number grows with the window. Carries the measured identifiers-per-device per fleet type and the controlled comparison it was derived from. */\n identifier_inflation?: Record<string, unknown>;\n mrc_ooh_phase2_alignment: Record<string, unknown>;\n parser_versions?: Record<string, unknown>;\n /** k-anonymity floor and differential-privacy budget. */\n privacy_gates: Record<string, unknown>;\n /** Per-store retention in days. */\n retention: Record<string, unknown>;\n /** Tables a reviewer re-derives every published count from. */\n source_tables: Array<string>;\n /** Bumped on any disclosure change; drives the ETag. */\n version: string;\n};\n\nexport type Pagination = {\n /** Whether more items exist */\n has_more?: boolean;\n /** Items per page */\n limit?: number;\n /** Current offset */\n offset?: number;\n /** Total number of items */\n total?: number;\n};\n\nexport type Partner = {\n integration_tier?: string;\n name?: string;\n partner_id?: string;\n /** Legacy classification retained for existing integrations. New integrations should not branch on this field. */\n partner_type?: string;\n revenue_share_percent?: number;\n sdk_config?: SDKConfig;\n slug?: string;\n stats?: PartnerStats;\n status?: \"pending\" | \"active\" | \"suspended\" | \"terminated\";\n stripe_account_status?: string;\n};\n\nexport type PartnerAdDeliveryProfile = {\n android_api_level?: number | null;\n auto_recovery_enabled?: boolean;\n ima_integration?: \"android_native\" | \"html5_webview\" | \"disabled\" | \"unknown\";\n mode?: \"ima_sdk\" | \"vast_fallback\";\n notes?: Array<string>;\n reason?: string;\n webview_chromium_major?: number | null;\n};\n\n/**\n * Non-fatal advisories about the creative that was just accepted. The ad IS created and will serve — these describe problems only the uploader can fix. Empty when there is nothing to report. The most important one is an over-length video: a spot longer than the 30 second ad slot is cut off when the next ad starts, so it never reaches its completion event and its final seconds are never seen.\n */\nexport type PartnerCreativeWarnings = Array<string>;\n\nexport type PartnerDefaultStream = {\n _id?: string;\n canva_url?: string;\n createdAt?: string;\n description?: string;\n duration_seconds?: number;\n embed_url?: string;\n generic_iframe_url?: string;\n google_slides_url?: string;\n iframe_config?: Record<string, unknown>;\n image_duration?: number;\n images?: Array<string>;\n is_active?: boolean;\n is_currently_playing?: boolean;\n name?: string;\n partner_id?: string;\n playback_order?: number;\n screenId?: string;\n social_wall_url?: string;\n stream_type?: string;\n twitch_url?: string;\n updatedAt?: string;\n video_url?: string;\n youtube_url?: string;\n};\n\nexport type PartnerDefaultStreamCreate = {\n canva_url?: string;\n description?: string;\n /** Optional explicit duration for iframe-based streams */\n duration_seconds?: number;\n embed_url?: string;\n generic_iframe_url?: string;\n google_slides_url?: string;\n iframe_config?: {\n allow_flags?: string;\n auto_advance?: boolean;\n refresh_interval_seconds?: number;\n sandbox_flags?: string;\n slide_delay_ms?: number;\n };\n /** Seconds per image */\n image_duration?: number;\n images?: Array<string>;\n name?: string;\n social_wall_url?: string;\n stream_type?: \"local\" | \"youtube\" | \"uploaded\" | \"images\" | \"twitch\" | \"google_slides\" | \"canva\" | \"social_wall\" | \"generic_iframe\";\n twitch_url?: string;\n video_url?: string;\n youtube_url?: string;\n};\n\nexport type PartnerDefaultStreamUpdate = PartnerDefaultStreamCreate;\n\n/**\n * Batch device-registration body (`@trillboards/api-client`\n * `PartnerDeviceBatchRegistrationInput`) — up to 100 devices with optional\n * fleet-wide `defaults`. `defaults` applies to every device in the batch\n * except the per-device identifier fields (`device_id` / `device_name`).\n *\n */\nexport type PartnerDeviceBatchRegistrationInput = {\n /** Fleet-wide defaults applied to each device except its identifier fields. */\n defaults?: PartnerDeviceRegistrationInput;\n devices: Array<PartnerDeviceRegistrationInput>;\n};\n\n/**\n * Heartbeat payload from agent-core / agent-core-lite Android partner\n * SDKs. Only includes fields verified populated in production\n * `signal_observations` (last 30 days). Stub fields wired in Kotlin but\n * never observed in CH are intentionally excluded; re-add only after\n * telemetry confirms >1% population over 7 days.\n *\n */\nexport type PartnerDeviceHeartbeatBody = {\n advertisingId?: string | null;\n advertisingIdType?: \"gaid\" | \"idfa\" | null | null;\n advertising_identity?: AdvertisingIdentity;\n bleDeviceCount?: number;\n capabilities?: DeviceCapabilityPayload;\n discoveredNetworkDevices?: Array<MdnsNetworkDevice> | null;\n extended_identities?: Array<ExtendedIdentity>;\n fingerprint?: string;\n gatewayIpHash?: string | null;\n httpProbes?: Array<HttpProbeResult> | null;\n limitAdTracking?: boolean | null;\n metadata?: Record<string, unknown>;\n /** Capped at 50 devices (RSSI-sorted, strongest first). */\n nearbyBleDevices?: Array<BleScanResultData> | null;\n nearbyWifiNetworks?: Array<WifiScanResult> | null;\n networkDeviceCount?: number;\n /** Heartbeat schema version (1=baseline, 2=nativeSensorSnapshot) */\n schemaVersion?: number;\n screenId?: string | null;\n /** Per-source skip-reason counter map. Shape `{source: {reason: count}}`. */\n skipReasonCounts?: Record<string, Record<string, number>>;\n ssdpDevices?: Array<SsdpDeviceInfo> | null;\n status?: string;\n wifiBssidHash?: string | null;\n wifiEnvironment?: WifiEnvironmentSnapshot;\n wifiNetworkCount?: number;\n wifiSsidHash?: string | null;\n [key: string]: unknown;\n};\n\n/**\n * Request body accepted by the single-device registration endpoints\n * (`@trillboards/api-client` `PartnerDeviceRegistrationInput`). Additional\n * vendor-specific fields are accepted and forwarded to enrichment.\n *\n */\nexport type PartnerDeviceRegistrationInput = {\n /** Stable partner-owned device identifier. */\n device_id?: string;\n /** Legacy SDK alias for the device identifier, retained for backwards compatibility. */\n device_name?: string;\n device_type?: string;\n /** Display specification (pixel resolution and/or physical size). */\n display?: Record<string, unknown>;\n display_settings?: PartnerRegistrationDisplaySettings;\n /** Location hints (lat/lng, address, venue type). */\n location?: Record<string, unknown>;\n /** Friendly name for the device. */\n name?: string;\n /** Placement hints for the screen within the venue. */\n placement?: Record<string, unknown>;\n /** Venue taxonomy hints. */\n venue?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\nexport type PartnerHeartbeatCommand = {\n /** Command normalized for partner SDK compatibility. */\n command?: string;\n id?: string;\n payload?: Record<string, unknown>;\n queued_at?: string;\n};\n\nexport type PartnerHeartbeatData = {\n ad_delivery_profile?: PartnerAdDeliveryProfile;\n commands?: Array<PartnerHeartbeatCommand>;\n last_seen_at?: string;\n status?: \"online\" | \"offline\";\n};\n\nexport type PartnerHeartbeatMeasurementMetadata = {\n ageSeconds?: number | null;\n cachedAt?: string | null;\n receivedAt?: string | null;\n source?: \"redis_twin\" | \"pg_fallback\" | \"unknown\";\n [key: string]: unknown;\n};\n\nexport type PartnerHeartbeatQueryData = {\n adDeliveryProfile?: PartnerAdDeliveryProfile;\n deviceId: string;\n lastHeartbeatAt?: string | null;\n measurementMetadata?: PartnerHeartbeatMeasurementMetadata;\n stalenessSeconds?: number | null;\n telemetry?: PartnerSafeHeartbeatTelemetry;\n [key: string]: unknown;\n};\n\nexport type PartnerHeartbeatQueryResponse = {\n data?: PartnerHeartbeatQueryData;\n success?: boolean;\n};\n\n/**\n * Optional heartbeat payload. Nested telemetry objects are preferred; legacy flat keys\n * are still accepted for backward compatibility. The registered\n * `deviceId` is the binding boundary for both liveness and identity; no\n * separate partner API key is required.\n *\n */\nexport type PartnerHeartbeatRequest = {\n ad?: {\n last_vast_request_at?: string;\n last_vast_response_at?: string;\n proof_of_play_enabled?: boolean;\n };\n advertising_identity?: AdvertisingIdentity;\n agent_status?: string;\n agent_version?: string;\n android_api_level?: number;\n brightness?: number;\n desugaring_enabled?: boolean;\n device?: {\n android_api_level?: number;\n make?: string;\n model?: string;\n os?: string;\n osv?: string;\n webview_chromium_major?: number;\n };\n extended_identities?: Array<ExtendedIdentity>;\n ima_integration?: \"android_native\" | \"html5_webview\" | \"disabled\" | \"unknown\";\n ima_sdk_version?: string;\n ima_support_reason?: string;\n ima_supported?: boolean;\n input_source?: string;\n last_ima_error_code?: number;\n last_vast_error_code?: number;\n last_vast_request_at?: string;\n last_vast_response_at?: string;\n /** Current GPS fix for a moving screen. Processed only for screens whose `mobility_type` is `mobile` or `semi_mobile` (declare it at registration or via PATCH /device/{deviceId}), OR for any screen still missing coordinates (a one-time self-heal that also kicks off venue classification). Static screens with valid coordinates ignore it. Updates live geo-targeting, geofencing and analytics. Fully optional — omit it on stationary screens. */\n location?: {\n /** Horizontal accuracy radius in meters. Fixes above ~500m are clamped. */\n accuracy_m?: number;\n /** Up to 200 fixes recorded while the device was offline, replayed as a historical track. Timestamps MUST be in ascending order — a non-chronological batch is rejected with HTTP 400. Only the top-level `location` updates the live serving position. */\n buffered_locations?: Array<{\n accuracy_m?: number;\n heading?: number;\n lat: number;\n lng: number;\n speed_mps?: number;\n timestamp?: number;\n }>;\n /** Bearing in degrees (0–360, 0 = true north). Omit if unavailable. */\n heading?: number;\n /** Latitude in decimal degrees (WGS 84). */\n lat?: number;\n /** Longitude in decimal degrees (WGS 84). */\n lng?: number;\n /** `gps` — a live on-device fix. `gps_buffered` — a fix recorded while offline and replayed on reconnect. */\n source?: \"gps\" | \"gps_buffered\";\n /** Ground speed in meters per second. Omit if unavailable. */\n speed_mps?: number;\n /** Unix epoch milliseconds of the on-device fix. Send the device clock value; the server tolerates up to 10 minutes of skew. A position jump implying > 320 km/h between consecutive fixes is rejected. */\n timestamp?: number;\n };\n /** Alternate namespace for telemetry keys (legacy support). */\n metadata?: Record<string, unknown>;\n muted?: boolean;\n network?: {\n bandwidthMbps?: number;\n connectionType?: string;\n downlinkMbps?: number;\n effectiveType?: string;\n latencyRtt?: number;\n rtt?: number;\n saveData?: boolean;\n };\n network_strength_dbm?: number;\n power_state?: \"on\" | \"standby\" | \"off\" | \"unknown\";\n proof_of_play_enabled?: boolean;\n sdk?: {\n android_api_level?: number;\n desugaring_enabled?: boolean;\n ima_integration?: \"android_native\" | \"html5_webview\" | \"disabled\" | \"unknown\";\n ima_sdk_version?: string;\n ima_supported?: boolean;\n version?: string;\n webview_chromium_major?: number;\n };\n sdk_version?: string;\n telemetry?: PartnerHeartbeatTelemetry;\n temperature_c?: number;\n uptime_seconds?: number;\n volume?: number;\n webview_chromium_major?: number;\n};\n\nexport type PartnerHeartbeatResponse = {\n data?: PartnerHeartbeatData;\n success?: boolean;\n};\n\nexport type PartnerHeartbeatTelemetry = {\n agentStatus?: string;\n agentVersion?: string;\n android_api_level?: number;\n bandwidthMbps?: number;\n brightness?: number;\n connectionType?: string;\n desugaring_enabled?: boolean;\n downlinkMbps?: number;\n ima_integration?: \"android_native\" | \"html5_webview\" | \"disabled\" | \"unknown\";\n ima_sdk_version?: string;\n ima_support_reason?: string;\n ima_supported?: boolean;\n inputSource?: string;\n last_ima_error_code?: number;\n last_vast_error_code?: number;\n last_vast_request_at?: string;\n last_vast_response_at?: string;\n latencyRtt?: number;\n make?: string;\n model?: string;\n muted?: boolean;\n networkConnectionType?: string;\n networkEffectiveType?: string;\n networkStrengthDbm?: number;\n os?: string;\n osVersion?: string;\n osv?: string;\n powerState?: \"on\" | \"standby\" | \"off\" | \"unknown\";\n proof_of_play_enabled?: boolean;\n rtt?: number;\n saveData?: boolean;\n temperatureC?: number;\n uptimeSeconds?: number;\n volume?: number;\n webview_chromium_major?: number;\n [key: string]: unknown;\n};\n\nexport type PartnerLBarContent = {\n business_name?: string;\n contact_info?: Record<string, unknown>;\n current_promotion?: string;\n custom_messages?: Array<string>;\n display_settings?: Record<string, unknown>;\n enabled?: boolean;\n live_updates?: Record<string, unknown>;\n social_media?: Record<string, unknown>;\n store_hours?: Record<string, unknown>;\n};\n\nexport type PartnerLBarDisplayPreferences = {\n ad_surface_mode?: \"fullscreen\" | \"lbar\" | \"pip\" | \"all\";\n display_mode?: \"fullscreen\" | \"l-bar\";\n l_bar_ad_duration?: number;\n l_bar_ad_interval?: number;\n l_bar_ads_enabled?: boolean;\n l_bar_position?: \"bottom\" | \"right\";\n l_bar_size?: number;\n pip_settings?: {\n aspect_ratio?: number;\n enabled?: boolean;\n margin?: number;\n position?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\";\n size_ratio?: number;\n };\n};\n\nexport type PartnerLBarSettings = {\n ad_surfaces?: Record<string, unknown>;\n display_preferences?: PartnerLBarDisplayPreferences;\n l_bar_content?: PartnerLBarContent;\n playback_policy?: Record<string, unknown>;\n};\n\n/**\n * Stripe-style monetization requirements (account.requirements analogue).\n * Returned on device register / update / get / batch so bulk partners can\n * detect and self-remediate missing data instead of discovering silent\n * gaps later. `currently_due` blocks or limits monetization now;\n * `eventually_due` improves serving but isn't blocking.\n *\n */\nexport type PartnerMonetizationRequirements = {\n /** Requirements blocking or limiting monetization right now. */\n currently_due?: Array<PartnerRequirement>;\n /** Non-blocking improvements (e.g. display dimensions). */\n eventually_due?: Array<PartnerRequirement>;\n};\n\nexport type PartnerNetworkConfig = {\n ad_delivery?: {\n /** `/ads` response cache lifetime. Zero requires a fresh response for every request. */\n cache_max_age_seconds?: number;\n /** Delegates resettable advertising identity to the native Google IMA SDK; the API never fabricates one. Set null to restore the platform default identity path. */\n identity_mode?: \"ima_sdk\" | null;\n /** Fleet-wide hourly ad cap returned in `settings.max_ads_per_hour`. */\n max_ads_per_hour?: number;\n /** Requests non-personalized demand when true. Never provide an advertising identifier unless the OS legitimately exposes it. */\n non_personalized_ads?: boolean;\n /** Returned as both `settings.ad_interval` and `header_bidding_settings.min_interval_seconds`; the player should request each monetizable slot at this cadence. */\n request_interval_seconds?: number;\n /** Controls whether a scheduled self-promo/house slot may lead the VAST waterfall. `scheduled_primary` preserves the bounded house cadence; `fallback_only` keeps self-promo behind paid programmatic demand; `disabled` removes the self-promo/house creative from your screens entirely — it is served on neither `ads[]` nor the VAST waterfall, and no new house creative is generated for your screens. Paid-direct guarantees always retain priority and are never affected. Set null to restore `scheduled_primary`. */\n self_promo_priority_mode?: \"scheduled_primary\" | \"fallback_only\" | \"disabled\" | null;\n };\n /** White-label presentation for your buyer-facing advertiser portal. These values are read and written directly against the branding your portal renders — a GET returns what a buyer currently sees, and a write takes effect on their next page load. Omitted entirely if no white-label portal is linked to your partner account; writing branding in that state returns `409` `white_label_distributor_not_linked` rather than accepting values that would render nowhere. Contact Trillboards to have one linked. */\n branding?: {\n /** Shown as the portal name and the browser tab title. */\n display_name?: string;\n /** Absolute HTTPS URL. */\n favicon_url?: string;\n font_body?: string;\n font_heading?: string;\n /** Absolute HTTPS URL. Rendered in the portal header. */\n logo_url?: string;\n /** CSS color. HSL triplets (\"210 90% 40%\") and hex are both accepted. */\n primary_color?: string;\n secondary_color?: string;\n tagline?: string;\n };\n /** Default content preferences inherited by newly provisioned screens. */\n default_content_preferences?: Record<string, unknown>;\n default_waterfall?: {\n /** Preferred opaque source aliases from the `/ads` response. Sources not listed here remain enabled and are appended. Internal demand names and `sort_by: cpm` are rejected. */\n source_order?: Array<string>;\n /** Total deadline for one waterfall snapshot, in milliseconds. */\n total_timeout_ms?: number;\n };\n /** Limits your branded buyer portal to YOUR OWN screens. Off by default: a branded portal otherwise sells the whole Trillboards network, which is what most white-label partners want. The screen set is DERIVED from the media-owner identity your screens already carry — both the ones we host and the ones resold through partner exchanges — so it stays correct as you add inventory and there is no list to maintain. It cannot be set to another operator's inventory. */\n storefront?: {\n /** When true, every inventory surface in your buyers' portal — search, map, forecasts, quotes, bookings and proposals — is limited to your own screens. */\n enabled?: boolean;\n };\n};\n\n/**\n * Partner-safe partial update. Internal `partners`, `supply_chain`, seller\n * IDs, direct demand names, and CPM-sort controls are rejected.\n *\n */\nexport type PartnerNetworkConfigUpdate = PartnerNetworkConfig;\n\n/**\n * A log-level play for a partner-served ad.\n */\nexport type PartnerPlay = {\n /** Optional ad/line identifier; defaults to the sha-keyed creative. */\n ad_id?: string;\n /** ISO 8601 timestamp when the play completed. */\n completed_at: string;\n /** The classification reference from POST /creatives — `sha256:<hex>` or the bare 64-char content hash. */\n creative_ref: string;\n /** Play duration in seconds (default 30). */\n duration_seconds?: number;\n /** Your unique id for this play (idempotency key). */\n play_id: string;\n /** Optional partner request identifier. */\n request_id?: string;\n /** One of your registered earner-screen ids. */\n screen_id: string;\n};\n\n/**\n * Optional display behavior applied while registering or re-registering a device.\n */\nexport type PartnerRegistrationDisplaySettings = {\n content_fit?: ContentFitSettings;\n};\n\nexport type PartnerRequirement = {\n /** Stable machine code, e.g. location_unresolvable, location_awaiting_device_gps, enrichment_failed, display_size_missing. */\n code?: string;\n doc_url?: string;\n /** The request field this concerns (location, venue, display). */\n field?: string;\n /** Human-readable, actionable remediation. */\n message?: string;\n /** Specific reason variant, e.g. city_without_state, no_location_provided, geocode_failed, awaiting_device_gps. */\n reason?: string;\n};\n\n/**\n * Partner-safe subset of device telemetry. Strips MDM compliance,\n * Vertex embeddings, identity-correction internals, partner identifiers,\n * and Mongo `_id` so partners only see what they need to decide\n * whether a device is healthy enough to receive ads.\n *\n */\nexport type PartnerSafeHeartbeatTelemetry = {\n agentStatus?: string | null;\n agentVersion?: string | null;\n bandwidthMbps?: number | null;\n brightness?: number | null;\n connectionType?: string | null;\n consecutiveAdFailures?: number | null;\n effectiveType?: string | null;\n latencyRtt?: number | null;\n make?: string | null;\n model?: string | null;\n muted?: boolean | null;\n networkStrengthDbm?: number | null;\n onlineStatus?: \"online\" | \"offline\" | \"standby\" | \"unknown\" | null;\n os?: string | null;\n osv?: string | null;\n powerState?: string | null;\n temperatureC?: number | null;\n ua?: string | null;\n uptimeSeconds?: number | null;\n visibilityState?: string | null;\n volume?: number | null;\n [key: string]: unknown;\n};\n\nexport type PartnerSelfPromoAd = {\n _id?: string;\n campaign_link?: string;\n createdAt?: string;\n description?: string;\n name?: string;\n photos?: Array<string>;\n status?: string;\n video?: string;\n /** Measured length of the `video` creative in whole seconds, probed when the ad is created. This is the real media length and is what the served VAST declares as `<Duration>`. `null` means the media could not be measured, in which case the VAST declares the 30 second ad-slot default instead. */\n video_duration_seconds?: number | null;\n};\n\nexport type PartnerSelfPromoCreate = {\n campaign_link?: string;\n description?: string;\n end_date?: string;\n image_url?: string;\n name: string;\n screen_ids?: Array<string>;\n start_date?: string;\n video_url?: string;\n};\n\nexport type PartnerSelfPromoPlacement = {\n ads?: Array<{\n advertisement?: PartnerSelfPromoAd;\n allocation_id?: string;\n end_date?: string;\n start_date?: string;\n status?: string;\n }>;\n screen?: {\n _id?: string;\n name?: string;\n };\n};\n\nexport type PartnerStats = {\n active_devices?: number;\n last_impression_at?: string;\n pending_payout_cents?: number;\n total_devices?: number;\n total_impressions?: number;\n total_revenue_cents?: number;\n};\n\nexport type PayoutResponse = {\n amount_cents?: number;\n estimated_arrival?: string;\n payout_id?: string;\n status?: \"pending\" | \"processing\" | \"completed\" | \"failed\";\n stripe_transfer_id?: string | null;\n};\n\nexport type PlaygroundResult = {\n /** Whether the operation is safe for autonomous agents. */\n agent_safe: boolean;\n /** Billing tier: free, metered, or paid. */\n cost_tier: string;\n /** Whether the operation is idempotent. */\n idempotent: boolean;\n /** Object type identifier. */\n object: \"playground_result\";\n operation_id: string;\n /** Declared side effects of the operation. */\n side_effects: Array<string>;\n /** Whether the request body passed validation. */\n valid: boolean;\n /** The parsed/coerced body on success, null on failure. */\n validated_body?: unknown;\n /** Array of validation issues on failure, null on success. */\n validation_errors: Array<PlaygroundValidationError> | null;\n /** The HTTP method and path this operation maps to. */\n would_call: {\n method: string;\n path: string;\n };\n};\n\nexport type PlaygroundValidationError = {\n /** Zod issue code. */\n code: string;\n /** Human-readable validation message. */\n message: string;\n /** Dot-delimited path to the invalid field. */\n path: string;\n};\n\nexport type ProgrammaticSettingsInput = {\n /** Enable programmatic ads */\n enabled?: boolean;\n /** Minimum CPM in dollars */\n floor_price_cpm?: number;\n google_ima?: {\n ad_tag_url?: string;\n enabled?: boolean;\n max_duration?: number;\n };\n prebid?: {\n bidders?: Array<{\n name?: string;\n params?: Record<string, unknown>;\n }>;\n enabled?: boolean;\n };\n /** Ad source priority */\n priority?: \"direct_first\" | \"programmatic_first\" | \"highest_bid\";\n};\n\nexport type ProgrammaticSettingsResponse = {\n enabled?: boolean;\n floor_price_cpm?: number;\n google_ima?: {\n ad_tag_url?: string;\n enabled?: boolean;\n max_duration?: number;\n };\n object?: string;\n prebid?: {\n bidders?: Array<Record<string, unknown>>;\n enabled?: boolean;\n };\n priority?: string;\n request_id?: string;\n screen_id?: string;\n stats?: {\n avg_cpm?: number;\n fill_rate_percent?: number;\n impressions_today?: number;\n };\n updated_at?: string;\n};\n\nexport type RequestMetadataResponse = {\n duration_ms: number;\n /** Present only when the original request resulted in an error. */\n error?: {\n code: string;\n type: string;\n };\n method: string;\n /** Object type identifier. */\n object: \"request\";\n path: string;\n request_id: string;\n status_code: number;\n timestamp: string;\n};\n\n/**\n * The EFFECTIVE content policy for a screen + its provenance. Whole-layer\n * coalescing: the effective policy comes from exactly ONE layer.\n *\n */\nexport type ResolvedContentPolicy = {\n /** All content_preferences keys + blocked_iab_categories. */\n effective?: Record<string, unknown>;\n object?: string;\n provenance?: {\n /** Present only when source=group. */\n group_id?: string;\n source?: \"screen\" | \"group\" | \"network\" | \"default\";\n };\n screen_id?: string;\n};\n\n/**\n * The EFFECTIVE sensing view for a screen + its provenance (screen\n * deployment ?? group sensing config ?? default).\n *\n */\nexport type ResolvedSensingConfig = {\n effective?: {\n capture_interval_ms?: number | null;\n estimated_fps_impact?: number | null;\n min_confidence?: number | null;\n profile_name?: string | null;\n report_interval_ms?: number | null;\n };\n object?: string;\n provenance?: {\n /** Present only when source=group_default. */\n group_id?: string;\n source?: \"screen\" | \"group_default\" | \"default\";\n };\n screen_id?: string;\n};\n\n/**\n * Permission flags for each role. Owners have all permissions,\n * admins have operational permissions, viewers have read-only access.\n *\n */\nexport type RolePermissions = {\n /** Can configure webhooks */\n configure_webhooks?: boolean;\n /** Can edit screen settings */\n edit_screens?: boolean;\n /** Can invite/remove team members */\n manage_team?: boolean;\n /** Can request payouts */\n request_payouts?: boolean;\n /** Can rotate API keys */\n rotate_api_keys?: boolean;\n /** Can view impression analytics */\n view_analytics?: boolean;\n /** Can view earnings/revenue */\n view_earnings?: boolean;\n /** Can view impression data */\n view_impressions?: boolean;\n /** Can view payout history */\n view_payouts?: boolean;\n /** Can view online/offline status */\n view_screen_status?: boolean;\n /** Can view screen list */\n view_screens?: boolean;\n};\n\nexport type SDKConfig = {\n /** Seconds between ads */\n ad_interval?: number;\n allowed_ad_types?: Array<string>;\n cache_size?: number;\n /** Seconds to display image ads */\n image_duration?: number;\n max_ads_per_hour?: number;\n overlay_button_text?: string;\n sound_enabled?: boolean;\n};\n\n/**\n * A partner screen — the client-facing projection of a registered\n * device+screen pair (`@trillboards/api-client` `Screen`). The screens\n * resource reads the partner device endpoints.\n *\n */\nexport type Screen = {\n city?: string;\n country?: string;\n created_at: string;\n /** The paired device identifier. */\n device_id?: string;\n /** Player embed URL for the screen. */\n embed_url?: string;\n /** Friendly screen/venue name. */\n name: string;\n /** Display resolution label (e.g. \"1920x1080\") when known. */\n resolution?: string;\n /** Stable screen identifier. */\n screen_id: string;\n /** Screen lifecycle status (e.g. pending, active, offline, suspended). */\n status: string;\n timezone?: string;\n updated_at: string;\n /** Granular OpenOOH venue type of the screen's location. */\n venue_type?: string;\n};\n\nexport type ScreenAnalyticsResponse = {\n impressions?: {\n daily_average?: number;\n total?: number;\n /** Percentage change compared to previous period */\n trend_percent?: number;\n };\n period?: {\n days?: number;\n end?: string;\n start?: string;\n };\n screen?: {\n id?: string;\n location?: string;\n name?: string;\n online_status?: string;\n status?: string;\n };\n timeline?: Array<{\n avg_duration_ms?: number;\n date?: string;\n impressions?: number;\n }>;\n};\n\n/**\n * A reusable, named, partner-scoped set of screens that analytics,\n * moderation policy, sensing/model deployment, fleet commands, and\n * sensing routes can target. Members are always a subset of the\n * partner's own screens.\n *\n */\nexport type ScreenGroup = {\n created_at?: string;\n description?: string | null;\n /** Screen group id (sg_ prefix). */\n id?: string;\n name?: string;\n object?: string;\n /** Distinct member screens (COUNT and member list share one junction — they cannot diverge). */\n screen_count?: number;\n updated_at?: string;\n};\n\n/**\n * The typed content/moderation policy a screen group carries (Phase 4 live\n * policy). `null` when the group has no policy of its own. Member screens\n * inherit it at read/serve time when they have no explicit own policy\n * (screen ?? group ?? partner network default ?? system default). Mirrors\n * the per-screen content_preferences keys 1:1; blocked_iab_categories is\n * first-class here (the auction bcat).\n *\n */\nexport type ScreenGroupContentPolicy = {\n allow_adult_content?: boolean;\n allow_alcohol?: boolean;\n allow_gambling?: boolean;\n allow_political?: boolean;\n allow_profanity?: boolean;\n allow_religious?: boolean;\n allow_tobacco?: boolean;\n allow_violence?: boolean;\n allowed_categories?: Array<string>;\n allowed_keywords?: Array<string>;\n allowed_subjects?: Array<string>;\n auto_approve_known_brands?: boolean;\n blocked_categories?: Array<string>;\n blocked_iab_categories?: Array<string>;\n blocked_keywords?: Array<string>;\n blocked_subjects?: Array<string>;\n content_filtering_enabled?: boolean;\n group_id?: string;\n max_age_rating?: \"G\" | \"PG\" | \"PG-13\" | \"R\" | \"NC-17\";\n object?: string;\n preference_level?: \"strict\" | \"moderate\" | \"lenient\" | \"permissive\";\n updated_at?: string;\n} | null;\n\n/**\n * Partial, non-clobbering — only the fields present are written. Same keys\n * the per-screen content-preferences PUT accepts, plus blocked_iab_categories.\n *\n */\nexport type ScreenGroupContentPolicyInput = {\n allow_adult_content?: boolean;\n allow_alcohol?: boolean;\n allow_gambling?: boolean;\n allow_political?: boolean;\n allow_profanity?: boolean;\n allow_religious?: boolean;\n allow_tobacco?: boolean;\n allow_violence?: boolean;\n allowed_categories?: Array<string>;\n allowed_keywords?: Array<string>;\n allowed_subjects?: Array<string>;\n auto_approve_known_brands?: boolean;\n blocked_categories?: Array<string>;\n blocked_iab_categories?: Array<string>;\n blocked_keywords?: Array<string>;\n blocked_subjects?: Array<string>;\n content_filtering_enabled?: boolean;\n max_age_rating?: \"G\" | \"PG\" | \"PG-13\" | \"R\" | \"NC-17\";\n preference_level?: \"strict\" | \"moderate\" | \"lenient\" | \"permissive\";\n};\n\n/**\n * Webhook body for a Screen Group lifecycle event (`screen_group.created` | `updated` |\n * `deleted` | `member.added` | `member.removed` | `content_policy.updated` |\n * `sensing_config.updated`). Standard `{ id, event, timestamp, data }` envelope: `id` (`evt_…`)\n * is the idempotency key, and `data` is the Stripe-style `screen_group` /\n * `screen_group_content_policy` / `screen_group_sensing_config` object the REST API returns.\n * The event type is also in the `X-Trillboards-Event` header — verify the compound\n * `X-Trillboards-Signature` over the raw body first.\n *\n */\nexport type ScreenGroupEvent = {\n /** The screen_group / content-policy / sensing-config object. */\n data?: Record<string, unknown>;\n event?: \"screen_group.created\" | \"screen_group.updated\" | \"screen_group.deleted\" | \"screen_group.member.added\" | \"screen_group.member.removed\" | \"screen_group.content_policy.updated\" | \"screen_group.sensing_config.updated\";\n id?: string;\n timestamp?: string;\n};\n\n/**\n * A screen group's sensing profile binding (profile_name) + typed\n * performance overrides. `null` when the group has none. Member screens\n * inherit via the sensing resolver's group step when they have no\n * screen-specific deployment.\n *\n */\nexport type ScreenGroupSensingConfig = {\n /** Edge frame-capture cadence overrides pushed to member screens (SensingConfig.capture keys, milliseconds). Group wins over the profile default per-key when set. */\n capture?: {\n faceTriggeredIntervalMs?: number | null;\n minCaptureIntervalMs?: number | null;\n periodicIntervalMs?: number | null;\n vehicleTriggeredIntervalMs?: number | null;\n } | null;\n capture_interval_ms?: number | null;\n enabled?: boolean;\n estimated_fps_impact?: number | null;\n group_id?: string;\n min_confidence?: number | null;\n object?: string;\n profile_name?: string | null;\n report_interval_ms?: number | null;\n updated_at?: string;\n /** Per-screen cloud-vision budget for member screens. screen_hourly_pace wins when both are set; otherwise derived from screen_daily_calls. null = no group budget (fleet keeps platform-default caps). */\n vision_budget?: {\n screen_daily_calls?: number | null;\n screen_hourly_pace?: number | null;\n } | null;\n} | null;\n\n/**\n * Partial, non-clobbering. A null override means \"inherit that field from\n * the base profile\". profile_name must resolve to a builtin or an existing\n * custom profile (else 400).\n *\n */\nexport type ScreenGroupSensingConfigInput = {\n /** Edge frame-capture cadence block (milliseconds); null clears it. Unknown keys are rejected (400). */\n capture?: {\n faceTriggeredIntervalMs?: number | null;\n minCaptureIntervalMs?: number | null;\n periodicIntervalMs?: number | null;\n vehicleTriggeredIntervalMs?: number | null;\n } | null;\n capture_interval_ms?: number | null;\n enabled?: boolean;\n estimated_fps_impact?: number | null;\n min_confidence?: number | null;\n profile_name?: string | null;\n report_interval_ms?: number | null;\n /** Per-screen cloud-vision budget block; null clears it. Unknown keys are rejected (400). */\n vision_budget?: {\n screen_daily_calls?: number | null;\n screen_hourly_pace?: number | null;\n } | null;\n};\n\n/**\n * High-level sensing workload intent. Hardware tier and device telemetry are read-only server facts.\n */\nexport type SensingPerformanceMode = \"auto\" | \"presence_only\" | \"demographics\" | \"advanced\";\n\n/**\n * A Sense Anything Route — a (condition → channel actions) alert/automation rule.\n */\nexport type SensingRoute = {\n actions?: Array<SensingRouteAction>;\n /** One bit per weekday (127 = always). */\n activeDaysMask?: number;\n activeEndMinute?: number | null;\n activeStartMinute?: number | null;\n activeTz?: string | null;\n condition?: SensingRouteCondition | null;\n createdAt?: string;\n debounceSeconds?: number;\n digest?: {\n intervalMinutes?: number;\n metric?: \"count\" | \"avg\" | \"max\";\n nextRunAt?: string;\n windowMinutes?: number;\n } | null;\n enabled?: boolean;\n mode?: \"threshold\" | \"digest\";\n name?: string;\n ownerId?: string;\n ownerKind?: string;\n partnerId?: string;\n profileName?: string | null;\n routeId?: string;\n screenMongoIds?: Array<string>;\n sustainMinSamples?: number;\n sustainWindowSeconds?: number;\n /** The sg_ Screen Group this route targets. When set, the route fires on the group's LIVE members (screenMongoIds reflects the resolved members at read time) and no explicit screens are stored. */\n targetGroupId?: string | null;\n updatedAt?: string;\n};\n\n/**\n * One channel action fired when the route matches.\n */\nexport type SensingRouteAction = {\n /** Attach the evidence frame/clip (people-facing channels). */\n attachClip?: boolean;\n channel: \"webhook\" | \"whatsapp\" | \"sms\" | \"slack\" | \"email\" | \"clip\";\n /** E.164 phone number (channel=whatsapp|sms). */\n recipientE164?: string;\n /** Recipient email (channel=email). */\n recipientEmail?: string;\n /** Slack channel id (channel=slack). */\n slackChannelId?: string;\n /** Message template name (managed WhatsApp/SMS). */\n templateName?: string;\n /** Target webhook endpoint id (channel=webhook). */\n webhookId?: string;\n};\n\n/**\n * A threshold condition — the route fires when the sensed field crosses the value.\n */\nexport type SensingRouteCondition = {\n /** The sensed field key (snake_case) to evaluate. */\n field: string;\n op: \"gt\" | \"gte\" | \"lt\" | \"lte\" | \"eq\" | \"neq\";\n /** The threshold value (numeric, string, or boolean depending on the field). */\n value?: number | string | boolean;\n};\n\nexport type SensingSettingsResponse = {\n active_profile?: {\n capabilities?: Array<string>;\n capture_interval_ms?: number | null;\n profile_id?: string | null;\n profile_name?: string | null;\n report_interval_ms?: number | null;\n } | null;\n desired_mode?: SensingPerformanceMode;\n /** Read-only latest device telemetry used for safety checks. */\n device_capability?: {\n agent_version?: string | null;\n gpu_delegate_supported?: boolean | null;\n gpu_name?: string | null;\n model_tier?: string | null;\n recent_failure_count?: number;\n soc_name?: string | null;\n soc_vendor?: string | null;\n telemetry_fresh?: boolean;\n };\n effective_mode?: SensingPerformanceMode;\n last_apply_status?: Record<string, unknown> | null;\n modes?: Array<{\n label?: string;\n value?: SensingPerformanceMode;\n }>;\n safety?: {\n allowed?: boolean;\n blocks?: Array<{\n code?: string;\n message?: string;\n }>;\n warnings?: Array<{\n code?: string;\n message?: string;\n }>;\n };\n screen_id?: string;\n};\n\n/**\n * Webhook request BODY delivered when a Sense Anything Route fires. Unlike the\n * device/programmatic events, a Route fire delivers a FLAT, self-describing\n * payload (no `{event,timestamp,data}` wrapper) — the event type is in the\n * `X-Trillboards-Event` request header (`sensing.threshold_crossed` for a custom\n * sensed field, or the matching `audience.*` / `venue.*` event for a known\n * semantic; a scheduled-digest Route delivers `venue.traffic_summary`). All Route\n * events share this same body shape. Verify the `X-Trillboards-Signature` header\n * over the raw body before trusting it.\n *\n */\nexport type SensingThresholdCrossedEvent = {\n /** The sensed field key evaluated (null for count-only digests). */\n field?: string | null;\n fired_at?: string;\n /** The observed value that crossed the threshold. */\n observed?: unknown;\n op?: \"gt\" | \"gte\" | \"lt\" | \"lte\" | \"eq\" | \"neq\" | null;\n owner_kind?: \"earner_user\" | \"partner\";\n /** The Route that fired. */\n route_id?: string;\n route_name?: string;\n /** The screen (mongo id) whose observation crossed the threshold. */\n screen_id?: string;\n /** The configured threshold value (number, string, or boolean). */\n threshold?: unknown | null;\n};\n\nexport type SsdpDeviceInfo = {\n friendlyName?: string | null;\n location: string;\n manufacturer?: string | null;\n modelName?: string | null;\n server?: string | null;\n st: string;\n udn?: string | null;\n [key: string]: unknown;\n};\n\nexport type TeamInviteResponse = {\n email?: string;\n /** When the invitation expires (7 days from creation) */\n expires_at?: string;\n membership_id?: string;\n role?: \"admin\" | \"viewer\";\n status?: \"pending\" | \"active\";\n};\n\nexport type TeamMember = {\n accepted_at?: string | null;\n email?: string;\n invited_at?: string;\n invited_by?: {\n email?: string;\n name?: string;\n } | null;\n last_portal_access?: string | null;\n /** Unique membership record ID */\n membership_id?: string;\n name?: string;\n permissions?: RolePermissions;\n photo?: string | null;\n role?: \"owner\" | \"admin\" | \"viewer\";\n status?: \"active\" | \"pending\" | \"revoked\";\n /** User ID (null if pending invitation) */\n user_id?: string;\n};\n\nexport type Transaction = {\n amount_cents?: number;\n created_at?: string;\n date?: string;\n id?: string;\n /** Number of impressions (for earning transactions) */\n impressions?: number;\n /** Source of the transaction (e.g., impressions, payout) */\n source?: string;\n /** Stripe transfer ID (for payout transactions) */\n stripe_transfer_id?: string;\n type?: \"earning\" | \"payout\";\n};\n\n/**\n * Partial, non-clobbering update — include only the fields to change.\n */\nexport type UpdatePartnerSensingRouteRequest = {\n actions?: Array<SensingRouteAction>;\n activeDaysMask?: number;\n activeEndMinute?: number;\n activeStartMinute?: number;\n activeTz?: string;\n condition?: SensingRouteCondition;\n debounceSeconds?: number;\n digest?: {\n field?: string;\n intervalMinutes?: number;\n metric?: \"count\" | \"avg\" | \"max\";\n windowMinutes?: number;\n };\n enabled?: boolean;\n name?: string;\n profileName?: string | null;\n screenMongoIds?: Array<string>;\n sustainMinSamples?: number;\n sustainWindowSeconds?: number;\n /** Set to a sg_ group id to (re)target the group's live members, or null to switch back to an explicit screenMongoIds set. Mutually exclusive with screenMongoIds in one request. */\n targetGroupId?: string | null;\n};\n\n/**\n * The resolved programmatic VAST waterfall. `sources` is an ORDERED ARRAY and clients MUST iterate ALL of it — by `priority` ascending, skipping `enabled: false` — advancing to the next source on no-fill, empty VAST, timeout, IMA load error AND playback error (VAST 303 / 300 / 301 / 1009 all mean \"try the next source\", never \"stop\"). Reading `sources[0]` and stopping is the most common integration defect and reads as \"no demand\" when demand exists further down. Apply each source's own `timeout_ms`, and cap the whole loop at `total_timeout_ms`. Always handle player error and never leave the screen black; always fire the VAST `<Error>` beacon with `[ERRORCODE]` substituted. Full contract: docs/integrations/partner-native-ima-sdk.md §0 and §4.1. SQL/Admin-enabled sources remain visible; request-pressure decisions are enforced, when enabled, at first-party upstream fetch seams rather than by removing sources from this catalog.\n *\n */\nexport type VastWaterfall = {\n enabled?: boolean;\n /** Every source must be attempted, by `priority` ascending, until one actually plays. Not a preference list. */\n sources?: Array<VastWaterfallSource>;\n /** Budget in ms for the ENTIRE waterfall loop, across all sources. When it is spent, stop trying sources and return to your own content. */\n total_timeout_ms?: number;\n} | null;\n\n/**\n * One demand source in the VAST waterfall. Fetch `vast_url` (already a Trillboards vast-wrap URL — use as-is) and pass the response to your IMA SDK. A failure here means \"advance to the next source\", not \"the request had no demand\".\n */\nexport type VastWaterfallSource = {\n auction_request_id?: string;\n cpm?: number | null;\n /** High recent error rate measured server-side. Degraded sources are already pushed to the tail of the array for you — do NOT skip a source because of this flag. */\n degraded?: boolean;\n /** Whole seconds of the creative THIS source will serve, so you can schedule continuous loop playback without first fetching the VAST and probing the MP4. Present only on the first-party `trillboards_direct` source (a programmatic source's length is not known until its own VAST is fetched). It is the same number as the `<Duration>` in the VAST that `vast_url` returns, so use either — they cannot disagree. NOT a playback control: IMA still takes its real timing from the media, so treat this as scheduling metadata and keep honouring the actual quartile/complete events. A creative longer than your ad slot will still be cut off by the next poll; we warn the uploader at upload time when that is the case. */\n duration_seconds?: number;\n /** When false, skip this source entirely. Present-but-disabled sources may appear in the array. */\n enabled?: boolean;\n error_rate_pct?: number;\n fetch_mode?: string | null;\n /** Opaque public alias for the demand source. Echo it back as `variant_name` on `programmatic-event` reports. */\n name?: string;\n /** Opaque ascending sort key — lowest is tried first. Do NOT treat it as an index: it may start at 0 (a source we want to win outright — the `?test=1` source, an injected first-party bid, an auction winner — is stamped `priority: 0`), and values may be non-contiguous (some paths renumber survivors 1..N, others keep catalog values). Only the relative order is meaningful; sort ascending and do no arithmetic on it. */\n priority?: number;\n /** Per-source request identifier. Report against the source you actually used, not `sources[0]`. */\n request_id?: string;\n /** Per-source budget in ms for fetching and loading THIS source. Distinct from the waterfall-wide `total_timeout_ms`. */\n timeout_ms?: number;\n vast_url?: string;\n};\n\nexport type Webhook = {\n /** When webhook was created */\n created_at?: string;\n /** Subscribed event types */\n events?: Array<\"device.online\" | \"device.offline\" | \"impression.recorded\" | \"campaign.allocated\" | \"payout.processed\" | \"sensing.threshold_crossed\" | \"audience.spike\" | \"audience.venue_busy\" | \"audience.purchase_intent\" | \"audience.demographics_update\" | \"venue.traffic_summary\" | \"screen_group.created\" | \"screen_group.updated\" | \"screen_group.deleted\" | \"screen_group.member.added\" | \"screen_group.member.removed\" | \"screen_group.content_policy.updated\" | \"screen_group.sensing_config.updated\" | \"fleet_command.completed\" | \"fleet_command.failed\">;\n /** Total failed deliveries */\n failure_count?: number;\n /** Last time webhook was triggered */\n last_triggered_at?: string;\n /** Webhook signing secret (whsec_…). Returned when the webhook is created so partners can verify the compound `X-Trillboards-Signature` header over the raw payload (see the SDK's Webhooks.constructEvent). Treat as a credential — store it securely and never expose it client-side. */\n secret?: string;\n /** Webhook status */\n status?: \"active\" | \"inactive\";\n /** Total successful deliveries */\n success_count?: number;\n /** Webhook endpoint URL */\n url?: string;\n /** Unique webhook identifier */\n webhook_id?: string;\n};\n\nexport type WebhookDelivery = {\n /** When delivery was first attempted */\n attempted_at?: string;\n /** When delivery succeeded */\n delivered_at?: string;\n /** Error message if failed */\n error_message?: string;\n /** Event that triggered this delivery */\n event_type?: string;\n /** HTTP status code from endpoint */\n http_status?: number;\n /** Delivery record ID */\n id?: string;\n /** Response time in milliseconds */\n response_time_ms?: number;\n /** Number of retry attempts */\n retry_count?: number;\n /** Delivery status */\n status?: \"pending\" | \"success\" | \"failed\" | \"retrying\";\n};\n\n/**\n * Standard webhook event payload sent to your endpoint.\n * All events follow this structure.\n *\n */\nexport type WebhookEvent = {\n /** Event-specific data */\n data?: Record<string, unknown>;\n /** Event type */\n event?: string;\n /** When event occurred */\n timestamp?: string;\n};\n\nexport type WifiEnvironmentSnapshot = {\n channelCongestionRatio?: number | null;\n connectedChannelWidthMhz?: number | null;\n connectedFrequencyMhz?: number | null;\n connectedLinkSpeedMbps?: number | null;\n connectedSignalDbm?: number | null;\n frequencyBand?: string | null;\n medianSignalDbm?: number | null;\n networkCount?: number | null;\n rssiVariance?: number | null;\n scanTimestampMs?: number | null;\n signalSpreadDbm?: number | null;\n uniqueBssidCount?: number | null;\n [key: string]: unknown;\n} | null;\n\nexport type WifiScanResult = {\n channelWidthMhz?: number | null;\n frequencyMhz: number;\n rawBssid: string;\n signalStrengthDbm: number;\n [key: string]: unknown;\n};\n\n\n// ─── Operations ──────────────────────────────────────────────────────────\n\n/**\n * List self-promo ads\n * GET /ads/self-promo\n */\nexport interface listPartnerSelfPromoAdsOperation {\n readonly path: \"/ads/self-promo\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Array<PartnerSelfPromoAd>;\n success?: boolean;\n};\n}\n\n/**\n * Create self-promo ad (URL-based)\n * POST /ads/self-promo\n */\nexport interface createPartnerSelfPromoAdOperation {\n readonly path: \"/ads/self-promo\";\n readonly method: \"POST\";\n request: PartnerSelfPromoCreate;\n response: {\n data?: PartnerSelfPromoAd;\n success?: boolean;\n warnings?: PartnerCreativeWarnings;\n};\n}\n\n/**\n * List self-promo placements by screen\n * GET /ads/self-promo/placements\n */\nexport interface listPartnerSelfPromoPlacementsOperation {\n readonly path: \"/ads/self-promo/placements\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Array<PartnerSelfPromoPlacement>;\n success?: boolean;\n};\n}\n\n/**\n * Schedule existing self-promo ad to screens\n * POST /ads/self-promo/schedule\n */\nexport interface schedulePartnerSelfPromoOperation {\n readonly path: \"/ads/self-promo/schedule\";\n readonly method: \"POST\";\n request: {\n ad_id: string;\n end_date?: string;\n screen_ids: Array<string>;\n start_date?: string;\n};\n response: {\n success?: boolean;\n};\n}\n\n/**\n * Create self-promo ad (upload)\n * POST /ads/self-promo/upload\n */\nexport interface createPartnerSelfPromoUploadOperation {\n readonly path: \"/ads/self-promo/upload\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: PartnerSelfPromoAd;\n success?: boolean;\n warnings?: PartnerCreativeWarnings;\n};\n}\n\n/**\n * Disable a self-promo ad\n * POST /ads/self-promo/{ad_id}/disable\n */\nexport interface disableSelfPromoAdOperation {\n readonly path: \"/ads/self-promo/{ad_id}/disable\";\n readonly method: \"POST\";\n request: never;\n response: {\n ad_id?: string;\n status?: \"disabled\";\n};\n}\n\n/**\n * Register an AI agent\n * POST /agent/register\n */\nexport interface registerAgentOperation {\n readonly path: \"/agent/register\";\n readonly method: \"POST\";\n request: {\n /** Type of agent being registered */\n agent_type: \"dsp_agent\" | \"ssp_agent\" | \"trading_desk\" | \"analytics_platform\" | \"developer\";\n /** Company name (optional) */\n company?: string;\n /** Brief description of the agent's purpose */\n description?: string;\n /** Contact email */\n email: string;\n /** Agent or company name */\n name: string;\n /** Mint an AdCP **sandbox account** (`account.sandbox` in `get_adcp_capabilities`). Media buys made with the returned key validate end to end — screen resolution, published CPM/floor, flight parsing, derived impression goal, every error path — and return a well-formed response marked `sandbox: true`, but persist **no advertisements and no placements**. Nothing can serve, deliver, bill, or pay a venue. Use this for conformance and no-spend testing; register without it for a live account. */\n sandbox?: boolean;\n};\n response: {\n /** The AdCP **account** this key is bound to. Distinct from the `sandbox` block below, which describes auto-provisioned test SCREENS (supply); this is the account-level buying contract (demand) declared as `account.sandbox` in `get_adcp_capabilities`. */\n account?: {\n /** Seller-assigned account id. Same value as `partner_id`. */\n account_id?: string;\n note?: string;\n /** True when this is a sandbox account: its media buys write no advertisements and no placements, and every media-buy tool response is marked `sandbox: true`. */\n sandbox?: boolean;\n };\n agent_type?: string;\n /** API key for authentication (display once — save it!) */\n api_key?: string;\n /** MCP tools available to this agent */\n available_tools?: Array<string>;\n /** Exact same-key handoff for buyer/OpenRTB control-plane capabilities. */\n control_plane_onboarding?: {\n authorization?: string;\n endpoint?: string;\n method?: string;\n purpose?: string;\n reuses_api_key?: boolean;\n };\n docs_url?: string;\n /** Free tier limits per product */\n free_tiers?: Record<string, unknown>;\n mcp_endpoint?: string;\n mcp_transport?: string;\n /** Guidance for getting started */\n next_steps?: Array<string>;\n object?: string;\n /** Unique partner ID */\n partner_id?: string;\n pricing_url?: string;\n request_id?: string;\n /** Auto-provisioned test SCREENS (supply side). Unrelated to `account.sandbox`. */\n sandbox?: {\n note?: string;\n screens?: Array<{\n device_id?: string;\n name?: string;\n venue_type?: string;\n }>;\n };\n tools_url?: string;\n};\n}\n\n/**\n * Get partner analytics\n * GET /analytics\n */\nexport interface getAnalyticsOperation {\n readonly path: \"/analytics\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n devices_by_status?: Array<Record<string, unknown>>;\n impressions_by_day?: Array<{\n /** Date (YYYY-MM-DD) */\n _id?: string;\n impressions?: number;\n }>;\n partner?: {\n active_devices?: number;\n pending_payout_cents?: number;\n total_devices?: number;\n total_impressions?: number;\n total_revenue_cents?: number;\n };\n period?: {\n end?: string;\n start?: string;\n };\n };\n success?: boolean;\n};\n}\n\n/**\n * Visitor-flow continuity graph across the partner's screens\n * GET /analytics/audience-continuity\n */\nexport interface getAudienceContinuityOperation {\n readonly path: \"/analytics/audience-continuity\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n confidence?: string;\n sampleSize?: number;\n topPaths?: Array<Record<string, unknown>>;\n };\n status?: boolean;\n};\n}\n\n/**\n * Audience composition for the partner's screens\n * GET /analytics/audience-profile\n */\nexport interface getAudienceProfileOperation {\n readonly path: \"/analytics/audience-profile\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n sampleSize?: number;\n segments?: Array<Record<string, unknown>>;\n };\n status?: boolean;\n};\n}\n\n/**\n * BLE device discovery summary\n * GET /analytics/ble-summary\n */\nexport interface getBleSummaryOperation {\n readonly path: \"/analytics/ble-summary\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n totalObservations?: number;\n uniqueDevices?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Content performance — ad lineage and measured audience reactions\n * GET /analytics/content-performance\n */\nexport interface getContentPerformanceOperation {\n readonly path: \"/analytics/content-performance\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n byScreen?: Record<string, unknown>;\n creativeResponse?: Array<{\n adId?: string;\n advertiserName?: string;\n ageRating?: string;\n attentiveSeconds?: number;\n audioTerms?: Array<string>;\n avgAttention?: number;\n brandName?: string;\n confidence?: number;\n firstSeen?: string;\n iabCategories?: Array<string>;\n lastSeen?: string;\n moderationStatus?: string;\n plays?: number;\n viewers?: number;\n }>;\n /** Whether another page of creativeResponse exists after this one. */\n has_more?: boolean;\n nextOffset?: number | null;\n topAdvertisers?: Array<Record<string, unknown>>;\n /** Number of items the pagination cursor walks — the denominator `nextOffset`/`has_more` are computed against (the filtered set before per-page de-duplication). A page may render fewer rows when visually-identical creatives are merged for display, so page to completion via `has_more` rather than comparing `creativeResponse.length` to `total`. Null on the unfiltered legacy path. Describes the programmatic cursor; the offset-0 all-content block is additive. */\n total?: number | null;\n };\n status?: boolean;\n};\n}\n\n/**\n * Free-text search across the partner's creative catalogue\n * GET /analytics/creative-catalog\n */\nexport interface searchCreativeCatalogOperation {\n readonly path: \"/analytics/creative-catalog\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n creatives?: Array<{\n adId?: string;\n advertiserName?: string;\n assetUrl?: string | null;\n brandName?: string;\n iabCategories?: Array<string>;\n moderationStatus?: string;\n }>;\n /** Whether another page of results exists after this one. */\n has_more?: boolean;\n nextOffset?: number | null;\n /** Always null for catalogue search: the read over-fetches limit+1 for a free `has_more`, but an exact total would need a second COUNT round-trip the search path deliberately avoids. Page to completion via `has_more`. */\n total?: number | null;\n };\n status?: boolean;\n};\n}\n\n/**\n * Scene-level observations for a played creative\n * GET /analytics/creative-scenes\n */\nexport interface getCreativeScenesOperation {\n readonly path: \"/analytics/creative-scenes\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n adId?: string;\n nextCursor?: string | null;\n scenes?: Array<Record<string, unknown>>;\n screenId?: string;\n timeRange?: string;\n total?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Per-pair flow directionality + transition heatmap\n * GET /analytics/cross-screen-flow\n */\nexport interface getCrossScreenFlowOperation {\n readonly path: \"/analytics/cross-screen-flow\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n edges?: Array<Record<string, unknown>>;\n screens?: Array<Record<string, unknown>>;\n };\n status?: boolean;\n};\n}\n\n/**\n * Unified portfolio dashboard (earnings, ads, audience, screens, insights)\n * GET /analytics/dashboard\n */\nexport interface getPartnerAnalyticsDashboardOperation {\n readonly path: \"/analytics/dashboard\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n ads?: Record<string, unknown>;\n audience?: Record<string, unknown>;\n earnings?: {\n change?: Record<string, unknown>;\n current?: Record<string, unknown>;\n previous?: Record<string, unknown>;\n sparkline?: Array<Record<string, unknown>>;\n };\n insights?: Array<Record<string, unknown>>;\n period?: {\n endDate?: string | null;\n label?: string;\n startDate?: string | null;\n };\n screens?: Record<string, unknown>;\n topScreens?: Array<Record<string, unknown>>;\n };\n status?: boolean;\n};\n}\n\n/**\n * Device-type / OS / browser-class distribution among repeat visitors\n * GET /analytics/device-suite-signature\n */\nexport interface getDeviceSuiteSignatureOperation {\n readonly path: \"/analytics/device-suite-signature\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n deviceTypes?: Array<Record<string, unknown>>;\n totalDevices?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * CSV export of partner-scope analytics (summary / daily / per-screen)\n * GET /analytics/export\n */\nexport interface exportPartnerAnalyticsOperation {\n readonly path: \"/analytics/export\";\n readonly method: \"GET\";\n request: never;\n response: unknown;\n}\n\n/**\n * Per-ad daily breakdown for the partner fleet\n * GET /analytics/export/ads-by-day\n */\nexport interface exportPartnerAdsByDayOperation {\n readonly path: \"/analytics/export/ads-by-day\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Array<{\n ad_name?: string;\n advertiser_name?: string;\n campaign_type?: string;\n completion_rate?: number;\n date?: string;\n gross_revenue_cents?: number;\n plays_completed?: number;\n publisher_revenue_cents?: number;\n publisher_share_rate?: number;\n screen_name?: string;\n }>;\n status?: boolean;\n};\n}\n\n/**\n * 24-hour distribution across the partner's fleet\n * GET /analytics/fleet-hourly\n */\nexport interface getFleetHourlyOperation {\n readonly path: \"/analytics/fleet-hourly\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n hours?: Array<Record<string, unknown>>;\n timeRange?: string;\n };\n status?: boolean;\n};\n}\n\n/**\n * 4-stage discovery → awareness → engagement → conversion funnel\n * GET /analytics/halo-funnel\n */\nexport interface getHaloFunnelOperation {\n readonly path: \"/analytics/halo-funnel\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n stages?: Array<Record<string, unknown>>;\n };\n status?: boolean;\n};\n}\n\n/**\n * 24-hour returning-vs-first-timer audience clock\n * GET /analytics/loyalty-clock\n */\nexport interface getLoyaltyClockOperation {\n readonly path: \"/analytics/loyalty-clock\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n hours?: Array<{\n firstTimerShare?: number;\n hour?: number;\n returningShare?: number;\n sampleSize?: number;\n }>;\n sampleSize?: number;\n timeRange?: string;\n };\n status?: boolean;\n};\n}\n\n/**\n * Fleet-wide audience summary for the partner's screens\n * GET /analytics/network-summary\n */\nexport interface getNetworkSummaryOperation {\n readonly path: \"/analytics/network-summary\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n dataAvailable?: boolean;\n queriedAt?: string;\n timeRange?: string;\n totalScreens?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Daily/hourly fleet-wide audience timeseries\n * GET /analytics/network-trend\n */\nexport interface getNetworkTrendOperation {\n readonly path: \"/analytics/network-trend\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n interval?: string;\n series?: Array<Record<string, unknown>>;\n timeRange?: string;\n };\n status?: boolean;\n};\n}\n\n/**\n * Privacy-safe cross-screen proximity-graph summary\n * GET /analytics/proximity-summary\n */\nexport interface getProximitySummaryOperation {\n readonly path: \"/analytics/proximity-summary\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n continuityEdges?: Array<Record<string, unknown>>;\n crossScreenSignals?: number;\n gateDiagnostic?: Record<string, unknown>;\n repeatSignals?: number;\n sourceBreakdown?: Record<string, unknown>;\n topPaths?: Array<Record<string, unknown>>;\n uniqueSignals?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Per-creative scatter of avg-attention vs revenue-per-impression\n * GET /analytics/revenue-attention-correlation\n */\nexport interface getRevenueAttentionCorrelationOperation {\n readonly path: \"/analytics/revenue-attention-correlation\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n points?: Array<Record<string, unknown>>;\n trendLine?: Record<string, unknown> | null;\n };\n status?: boolean;\n};\n}\n\n/**\n * Paginated chronological feed of scene observations\n * GET /analytics/scene-feed\n */\nexport interface getSceneFeedOperation {\n readonly path: \"/analytics/scene-feed\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** Distinct calendar days with observations over the last 90 days. */\n activeDays?: number;\n /** Whether another page exists after this one. */\n has_more?: boolean;\n nextOffset?: number | null;\n scenes?: Array<Record<string, unknown>>;\n /** Distinct observations within the feed window — the exact set the feed pages over. */\n total?: number;\n /** Distinct (screen, scene-prefix) observations over the last 90 days (gamification stat; independent of the page window). */\n totalObservations?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Latest scene description per screen\n * GET /analytics/scene-intelligence\n */\nexport interface getSceneIntelligenceOperation {\n readonly path: \"/analytics/scene-intelligence\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** Present on EVERY response, success included. A field that appeared only on failure would make its absence the signal, and an absent field is indistinguishable from an old client or a version skew. */\n sceneDiagnostic: {\n /** True when the scene read completed and `scenes` reflects the fleet. False when it did not run to completion — `scenes` is then empty for want of an answer, not because the fleet is quiet. */\n measured: boolean;\n /** Null when `measured` is true. Otherwise names the operational failure. */\n reason: \"timeout\" | \"error\" | \"dependency_disabled\" | \"unknown\" | null;\n };\n scenes: Array<Record<string, unknown>>;\n };\n status?: boolean;\n};\n}\n\n/**\n * Rotate API key\n * POST /api-key/rotate\n */\nexport interface rotateApiKeyOperation {\n readonly path: \"/api-key/rotate\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: {\n /** New API key — shown only once! */\n api_key?: string;\n grace_period_hours?: number;\n message?: string;\n /** When the old key stops working */\n previous_key_expires_at?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get partner-wide audience analytics\n * GET /audience-analytics\n */\nexport interface getAudienceAnalyticsOperation {\n readonly path: \"/audience-analytics\";\n readonly method: \"GET\";\n request: never;\n response: AudienceAnalyticsResponse;\n}\n\n/**\n * Export audience data\n * GET /audience-export\n */\nexport interface exportAudienceDataOperation {\n readonly path: \"/audience-export\";\n readonly method: \"GET\";\n request: never;\n response: AudienceExportResponse;\n}\n\n/**\n * Get audience heatmap data\n * GET /audience/heatmap\n */\nexport interface getAudienceHeatmapOperation {\n readonly path: \"/audience/heatmap\";\n readonly method: \"GET\";\n request: never;\n response: {\n cells?: number;\n heatmap?: Array<Record<string, unknown>>;\n lookback_days?: number;\n object?: string;\n request_id?: string;\n screens_included?: number;\n};\n}\n\n/**\n * Get live audience data for a screen\n * GET /audience/live/{screenId}\n */\nexport interface getLiveAudienceOperation {\n readonly path: \"/audience/live/{screenId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n /** Null when screen is offline */\n audience?: {\n ad_receptivity?: number | null;\n attention_score?: number;\n crowd_density?: number;\n dominant_ambience?: string | null;\n dwell_time_ms?: number | null;\n emotional_engagement?: number | null;\n face_count?: number;\n income_level?: string | null;\n lifestyle_segment?: string | null;\n mood?: string | null;\n noise_level?: number | null;\n occupancy?: string | null;\n purchase_intent?: \"NONE\" | \"BROWSING\" | \"CONSIDERING\" | \"COMPARING\" | \"READY_TO_BUY\" | null;\n } | null;\n last_updated?: string | null;\n /** Present when screen is offline */\n message?: string;\n object?: string;\n request_id?: string;\n screen_id?: string;\n status?: \"live\" | \"offline\";\n};\n}\n\n/**\n * Find lookalike screens\n * GET /audience/lookalikes/{screenId}\n */\nexport interface getLookalikeScreensOperation {\n readonly path: \"/audience/lookalikes/{screenId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n filters?: {\n country?: string | null;\n min_similarity?: number;\n venue_type?: string | null;\n };\n matches?: Array<Record<string, unknown>>;\n matches_count?: number;\n object?: string;\n request_id?: string;\n source_screen_id?: string;\n};\n}\n\n/**\n * Predict screen audience\n * GET /audience/predict/{screenId}\n */\nexport interface predictScreenAudienceOperation {\n readonly path: \"/audience/predict/{screenId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n day_of_week?: number;\n hour_utc?: number;\n lookback_days?: number;\n /** Present when prediction is null */\n message?: string;\n object?: string;\n /** Null if insufficient historical data */\n prediction?: Record<string, unknown> | null;\n request_id?: string;\n screen_id?: string;\n};\n}\n\n/**\n * Resolved household reach for a campaign\n * GET /audience/resolved-household-reach/{campaignId}\n */\nexport interface getResolvedHouseholdReachOperation {\n readonly path: \"/audience/resolved-household-reach/{campaignId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n audience_composition?: Array<Record<string, unknown>>;\n campaign_id?: string;\n confidence_interval?: {\n lower?: number;\n upper?: number;\n };\n households_reached?: number;\n overlap_with_first_party?: number | null;\n};\n}\n\n/**\n * List audience segments\n * GET /audience/segments\n */\nexport interface listAudienceSegmentsOperation {\n readonly path: \"/audience/segments\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Array<AudienceSegment>;\n has_more?: boolean;\n object?: string;\n request_id?: string;\n total_count?: number;\n};\n}\n\n/**\n * Create audience segment\n * POST /audience/segments\n */\nexport interface createAudienceSegmentOperation {\n readonly path: \"/audience/segments\";\n readonly method: \"POST\";\n request: {\n description?: string;\n /** Segment name */\n name: string;\n rules: Array<{\n /** Rule field (e.g., venue_type, country, city, state) */\n field: string;\n /** Comparison operator (e.g., eq, neq, in, gt, lt) */\n operator: string;\n /** Rule value */\n value: unknown;\n }>;\n};\n response: AudienceSegment;\n}\n\n/**\n * Delete audience segment\n * DELETE /audience/segments/{segmentId}\n */\nexport interface deleteAudienceSegmentOperation {\n readonly path: \"/audience/segments/{segmentId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n deleted?: boolean;\n id?: string;\n object?: string;\n request_id?: string;\n};\n}\n\n/**\n * Get audience segment\n * GET /audience/segments/{segmentId}\n */\nexport interface getAudienceSegmentOperation {\n readonly path: \"/audience/segments/{segmentId}\";\n readonly method: \"GET\";\n request: never;\n response: AudienceSegment;\n}\n\n/**\n * Update audience segment\n * PATCH /audience/segments/{segmentId}\n */\nexport interface updateAudienceSegmentOperation {\n readonly path: \"/audience/segments/{segmentId}\";\n readonly method: \"PATCH\";\n request: {\n description?: string;\n is_active?: boolean;\n name?: string;\n rules?: Array<{\n field?: string;\n operator?: string;\n value?: unknown;\n }>;\n};\n response: AudienceSegment;\n}\n\n/**\n * Match screens to segment\n * POST /audience/segments/{segmentId}/match\n */\nexport interface matchAudienceSegmentOperation {\n readonly path: \"/audience/segments/{segmentId}/match\";\n readonly method: \"POST\";\n request: never;\n response: {\n matched_count?: number;\n matches?: Array<Record<string, unknown>>;\n object?: string;\n own_screens_only?: boolean;\n request_id?: string;\n segment_id?: string;\n segment_name?: string;\n};\n}\n\n/**\n * Estimate segment reach\n * POST /audience/segments/{segmentId}/reach\n */\nexport interface estimateSegmentReachOperation {\n readonly path: \"/audience/segments/{segmentId}/reach\";\n readonly method: \"POST\";\n request: never;\n response: {\n country_breakdown?: Record<string, number>;\n estimated_daily_cpm?: number;\n estimated_daily_impressions?: number;\n estimated_daily_revenue?: number;\n has_historical_data?: boolean;\n matched_screens?: number;\n object?: string;\n online_screens?: number;\n segment_id?: string;\n segment_name?: string;\n venue_breakdown?: Record<string, number>;\n};\n}\n\n/**\n * Generate VAST tag for segment\n * POST /audience/segments/{segmentId}/vast-tag\n */\nexport interface generateSegmentVastTagOperation {\n readonly path: \"/audience/segments/{segmentId}/vast-tag\";\n readonly method: \"POST\";\n request: {\n /** Click-through landing page URL */\n click_through?: string;\n /** Video creative URL */\n creative_url: string;\n /** Video duration in seconds */\n duration?: number;\n own_screens_only?: boolean;\n};\n response: {\n creative?: {\n click_through?: string | null;\n duration?: number;\n url?: string;\n };\n cust_params?: Array<string>;\n object?: string;\n screen_ids?: Array<string>;\n segment_id?: string;\n segment_name?: string;\n targeted_screens?: number;\n vast_tag_url?: string;\n};\n}\n\n/**\n * Get audience data statistics\n * GET /audience/stats\n */\nexport interface getAudienceStatsOperation {\n readonly path: \"/audience/stats\";\n readonly method: \"GET\";\n request: never;\n response: {\n data_access_tier?: \"basic\" | \"developer\" | \"enterprise\";\n newest_data?: string | null;\n object?: string;\n oldest_data?: string | null;\n request_id?: string;\n screens_with_data?: number;\n total_screens?: number;\n total_vectors?: number;\n};\n}\n\n/**\n * Cancel the partner's subscription at period end\n * POST /billing/cancel\n */\nexport interface cancelBillingSubscriptionOperation {\n readonly path: \"/billing/cancel\";\n readonly method: \"POST\";\n request: never;\n response: {\n effective_at?: string;\n status?: \"canceled\" | \"scheduled_for_cancellation\";\n};\n}\n\n/**\n * Purchase committed-use credits\n * POST /billing/credits\n */\nexport interface purchaseCreditsOperation {\n readonly path: \"/billing/credits\";\n readonly method: \"POST\";\n request: {\n /** Credit purchase tier */\n tier: \"tier_500\" | \"tier_2000\" | \"tier_5000\";\n};\n response: {\n /** Amount charged in cents */\n charged_cents?: number;\n /** Credits added to balance in cents */\n credits_added_cents?: number;\n /** Discount percentage applied */\n discount_pct?: number;\n object?: string;\n /** Stripe PaymentIntent ID */\n payment_intent_id?: string;\n request_id?: string;\n};\n}\n\n/**\n * Create Stripe Checkout session for credits\n * POST /billing/credits/checkout\n */\nexport interface createCreditCheckoutOperation {\n readonly path: \"/billing/credits/checkout\";\n readonly method: \"POST\";\n request: {\n /** URL to redirect if payment is cancelled */\n cancel_url?: string;\n /** URL to redirect after successful payment */\n success_url?: string;\n tier: \"tier_500\" | \"tier_2000\" | \"tier_5000\";\n};\n response: {\n /** Stripe Checkout URL — redirect user here */\n checkout_url?: string;\n message?: string;\n object?: string;\n request_id?: string;\n /** Stripe Checkout session ID */\n session_id?: string;\n};\n}\n\n/**\n * List available partner billing plans\n * GET /billing/plans\n */\nexport interface listBillingPlansOperation {\n readonly path: \"/billing/plans\";\n readonly method: \"GET\";\n request: never;\n response: {\n plans?: Array<{\n included_ads?: number;\n included_impressions?: number;\n overage_per_1k_impressions_cents?: number;\n price_cents_monthly?: number;\n tier?: string;\n }>;\n};\n}\n\n/**\n * Set up usage-based billing\n * POST /billing/setup\n */\nexport interface setupBillingOperation {\n readonly path: \"/billing/setup\";\n readonly method: \"POST\";\n request: {\n /** Stripe payment method token obtained from Stripe.js or Stripe Elements */\n payment_method_id: string;\n};\n response: {\n billing_status?: string;\n message?: string;\n object?: string;\n request_id?: string;\n stripe_customer_id?: string;\n};\n}\n\n/**\n * Subscribe the partner to a billing plan\n * POST /billing/subscribe\n */\nexport interface createBillingSubscriptionOperation {\n readonly path: \"/billing/subscribe\";\n readonly method: \"POST\";\n request: {\n tier: \"developer\" | \"enterprise\";\n};\n response: {\n checkout_url?: string | null;\n status?: \"active\" | \"requires_payment\";\n};\n}\n\n/**\n * Get the partner's current subscription\n * GET /billing/subscription\n */\nexport interface getBillingSubscriptionOperation {\n readonly path: \"/billing/subscription\";\n readonly method: \"GET\";\n request: never;\n response: {\n current_period_end?: string;\n status?: \"active\" | \"past_due\" | \"canceled\" | \"trialing\";\n stripe_customer_id?: string | null;\n tier?: string;\n};\n}\n\n/**\n * Get the partner's current-period usage\n * GET /billing/usage\n */\nexport interface getBillingUsageOperation {\n readonly path: \"/billing/usage\";\n readonly method: \"GET\";\n request: never;\n response: {\n ads_served?: number;\n audience_api_calls?: number;\n impressions?: number;\n overage_projection_cents?: number;\n period_end?: string;\n period_start?: string;\n};\n}\n\n/**\n * Get current billing period usage\n * GET /billing/usage-summary\n */\nexport interface getBillingUsageSummaryOperation {\n readonly path: \"/billing/usage-summary\";\n readonly method: \"GET\";\n request: never;\n response: {\n /** Current billing status */\n billing_status?: \"none\" | \"active\" | \"suspended\";\n /** Remaining prepaid credit balance in cents */\n credit_balance_cents?: number;\n object?: string;\n /** End of current billing period */\n period_end?: string;\n /** Start of current billing period */\n period_start?: string;\n /** Per-product usage breakdown */\n products?: Record<string, {\n meters?: Record<string, {\n billable?: number;\n cost_cents?: number;\n free_quota?: number;\n usage?: number;\n }>;\n }>;\n request_id?: string;\n /** Total cost in cents for current period */\n total_cost_cents?: number;\n};\n}\n\n/**\n * Stripe webhook callback\n * POST /billing/webhook\n */\nexport interface stripeWebhookCallbackOperation {\n readonly path: \"/billing/webhook\";\n readonly method: \"POST\";\n request: Record<string, unknown>;\n response: unknown;\n}\n\n/**\n * Get partner dashboard overview\n * GET /connect/dashboard\n */\nexport interface getConnectDashboardOperation {\n readonly path: \"/connect/dashboard\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n charts?: {\n daily_impressions?: Array<{\n date?: string;\n earnings_cents?: number;\n impressions?: number;\n }>;\n hourly_today?: Array<{\n hour?: number;\n impressions?: number;\n }>;\n };\n earnings?: {\n available_cents?: number;\n daily_average_cents?: number;\n lifetime_cents?: number;\n pending_payout_cents?: number;\n period_cents?: number;\n today_cents?: number;\n };\n impressions?: {\n all_time?: number;\n daily_average?: number;\n period?: number;\n today?: number;\n trend_percent?: number;\n };\n partner?: {\n cpm_cents?: number;\n name?: string;\n revenue_share_percent?: number;\n slug?: string;\n status?: string;\n stripe_status?: \"pending\" | \"active\" | \"restricted\" | \"not_connected\";\n };\n period?: {\n days?: number;\n end?: string;\n start?: string;\n };\n screens?: {\n offline?: number;\n online?: number;\n pending?: number;\n total?: number;\n };\n top_screens?: Array<{\n earnings_cents?: number;\n impressions?: number;\n location?: string | null;\n name?: string;\n screen_id?: string;\n status?: \"online\" | \"offline\" | \"unknown\";\n }>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get earnings chart data\n * GET /connect/earnings\n */\nexport interface getConnectEarningsChartOperation {\n readonly path: \"/connect/earnings\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n chart?: Array<{\n avg_view_duration_ms?: number;\n date?: string;\n earnings_cents?: number;\n impressions?: number;\n label?: string;\n unique_screens?: number;\n }>;\n period?: {\n days?: number;\n end?: string;\n start?: string;\n };\n summary?: {\n data_points?: number;\n group_by?: string;\n total_earnings_cents?: number;\n total_impressions?: number;\n };\n };\n success?: boolean;\n};\n}\n\n/**\n * Get screen health status\n * GET /connect/health\n */\nexport interface getConnectScreenHealthOperation {\n readonly path: \"/connect/health\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n checked_at?: string;\n filter?: string;\n screens?: Array<{\n device_id?: string;\n external_device_id?: string;\n fingerprint?: string;\n last_heartbeat?: string | null;\n last_seen?: string | null;\n location?: {\n city?: string | null;\n lat?: number | null;\n lng?: number | null;\n state?: string | null;\n };\n name?: string;\n registered_at?: string;\n screen_id?: string | null;\n screen_status?: \"pending\" | \"active\" | \"inactive\";\n status?: \"online\" | \"offline\" | \"never_connected\" | \"unknown\";\n time_since_last_seen_seconds?: number | null;\n uptime_24h_percent?: number | null;\n venue_type?: string | null;\n }>;\n summary?: {\n never_connected?: number;\n offline?: number;\n online?: number;\n total?: number;\n };\n };\n success?: boolean;\n};\n}\n\n/**\n * List content presets\n * GET /content-presets\n */\nexport interface listContentPresetsOperation {\n readonly path: \"/content-presets\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Array<ContentPreset>;\n has_more?: boolean;\n object?: string;\n total_count?: number;\n url?: string;\n};\n}\n\n/**\n * Get content preset\n * GET /content-presets/{presetId}\n */\nexport interface getContentPresetOperation {\n readonly path: \"/content-presets/{presetId}\";\n readonly method: \"GET\";\n request: never;\n response: ContentPreset;\n}\n\n/**\n * Submit a creative for classification\n * POST /creatives\n */\nexport interface submitPartnerCreativeOperation {\n readonly path: \"/creatives\";\n readonly method: \"POST\";\n request: {\n /** Optional advertiser/brand label to attach. */\n advertiser_name?: string;\n /** Public http(s) URL of the creative image or video. Must resolve to a public address — private/internal/cloud-metadata addresses are rejected. */\n media_url: string;\n};\n response: CreativeClassification;\n}\n\n/**\n * Get a creative classification\n * GET /creatives/{ref}\n */\nexport interface getPartnerCreativeOperation {\n readonly path: \"/creatives/{ref}\";\n readonly method: \"GET\";\n request: never;\n response: CreativeClassification;\n}\n\n/**\n * Get dashboard overview\n * GET /dashboard\n */\nexport interface getDashboardOperation {\n readonly path: \"/dashboard\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: DashboardResponse;\n success?: boolean;\n};\n}\n\n/**\n * Export the cross-screen proximity graph edge list\n * GET /data-export/proximity-graph-edges\n */\nexport interface exportProximityGraphEdgesOperation {\n readonly path: \"/data-export/proximity-graph-edges\";\n readonly method: \"GET\";\n request: never;\n response: unknown;\n}\n\n/**\n * List available datasets and per-dataset record counts\n * GET /data-export/summary\n */\nexport interface getDataExportSummaryOperation {\n readonly path: \"/data-export/summary\";\n readonly method: \"GET\";\n request: never;\n response: DataExportSummaryResponse;\n}\n\n/**\n * Export a partner-scoped dataset\n * GET /data-export/{dataset}\n */\nexport interface exportDatasetOperation {\n readonly path: \"/data-export/{dataset}\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n k_anonymity_threshold?: number;\n lookback_days?: number;\n /** Row shape depends on the requested `dataset`. For `audience_loyalty_features` see `AudienceLoyaltyFeaturesRow`. For other datasets the row shape is documented per-dataset in the Trillboards data dictionary. */\n rows?: Array<AudienceLoyaltyFeaturesRow | Record<string, unknown>>;\n total?: number;\n truncated?: boolean;\n };\n success?: boolean;\n};\n}\n\n/**\n * Geographic audience-density panel (data-licensing)\n * GET /data/geohash-audience-panel\n */\nexport interface getGeohashAudiencePanelOperation {\n readonly path: \"/data/geohash-audience-panel\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** True when the daily epsilon budget cannot accommodate this request. `rows` is empty in this case; no epsilon is deducted. */\n budget_exhausted?: boolean;\n /** Day exported (UTC). */\n date: string;\n /** Epsilon spent on this call (0 if `budget_exhausted` or CH unavailable). Deducted from `partner_dp_budget.epsilon_spent` on success. */\n epsilon_used: number;\n /** K-anonymity floor applied at SQL `HAVING`. Default 5; override via `partners.k_anon_floor`. */\n k_anonymity_threshold: number;\n partner_dp_budget: {\n /** Maximum epsilon allowed per day for this partner. */\n epsilon_max: number;\n /** Epsilon already spent today before this call. */\n epsilon_spent_before: number;\n };\n /** UUID partner_id (from `partners.partner_id`, migration 030). */\n partner_id: string;\n /** Noised per-row aggregates (k-anon-filtered + Laplace-perturbed). */\n rows: Array<{\n /** Noised average attention score (Laplace, sensitivity 0.1). */\n avg_attention: number;\n /** Noised average dwell seconds (Laplace, sensitivity 5). */\n avg_dwell_seconds: number;\n /** Noised average face count per observation (Laplace, sensitivity 1). */\n avg_face_count: number;\n /** 6-character geohash bucket. */\n geohash6: string;\n /** Hour bucket as the integer hour (0..23) cast to string. */\n hour: string;\n /** Income tier bucket (e.g. `low`, `mid`, `high`). */\n income_tier: string;\n /** Noised observation count (Laplace, sensitivity 1). */\n observation_count: number;\n /** Distinct screen count contributing to this bucket. */\n screen_count: number;\n /** Noised unique-device count (Laplace, sensitivity 1). */\n unique_devices: number;\n /** Venue category from `screens_live.venue_category`. */\n venue_category: string;\n }>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Outcome-attribution export (data-licensing)\n * GET /data/outcome-attribution\n */\nexport interface getOutcomeAttributionOperation {\n readonly path: \"/data/outcome-attribution\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** DP epsilon charged to the partner's daily budget for this call (0 if refunded). */\n epsilon_used: number;\n /** The reach grain applied (echoes the `grain` query param; defaults to `person`). */\n grain: \"person\" | \"device\";\n /** The per-partner k-anon floor applied at SQL HAVING. */\n k_anonymity_threshold: number;\n /** The validated lookback window used. */\n lookback_days: number;\n /** Daily DP budget snapshot at reservation time. */\n partner_dp_budget: {\n epsilon_max?: number;\n epsilon_spent_before?: number;\n };\n /** Noised per-(creative, screen) outcome aggregates (k-anon-filtered + Laplace-perturbed). */\n rows: Array<{\n /** Noised average exposures per reach-identity within the (creative, screen) cell (count of detail rows / distinct reach keys). A frequency over PEOPLE under person grain, over devices under device grain. */\n avg_frequency: number;\n /** Creative identifier from `completed_impressions.creative_id`. */\n creative_id: string;\n /** Noised count of exposed identities also seen on another screen. */\n cross_screen_devices: number;\n /** Noised count of distinct devices exposed to the creative on the screen. */\n exposed_devices: number;\n /** returned_devices / exposed_devices, recomputed from the noised counts. */\n return_rate: number;\n /** Noised count of exposed devices that returned (clamped ≤ exposed_devices). */\n returned_devices: number;\n /** The partner's own screen identifier. */\n screen_mongo_id: string;\n }>;\n /** Number of rows returned. */\n total: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Register a device\n * POST /device\n */\nexport interface registerDeviceOperation {\n readonly path: \"/device\";\n readonly method: \"POST\";\n request: {\n /** Any additional metadata for your records */\n custom_metadata?: Record<string, unknown>;\n /** Screen or venue description for enrichment */\n description?: string;\n /** Your internal device identifier */\n device_id: string;\n device_type?: \"vending_machine\" | \"kiosk\" | \"tablet\" | \"display\" | \"other\";\n /** Screen display specification. `width`/`height` are pixel resolution; `width_in`/`height_in` are physical inches. For accurate floor pricing we need physical inches — pass `width_in` + `height_in` if you've measured the screen, OR `ppi` so the server can derive inches from the pixel resolution. Pixel-only inputs (no `ppi`, no `*_in`) will NOT be recorded as physical size; they're still used for orientation detection and DSP slot dimensions. */\n display?: {\n /** Display resolution height in pixels (e.g. 1080) */\n height?: number;\n /** Physical screen height in INCHES. Pairs with `width_in`. */\n height_in?: number;\n orientation?: \"landscape\" | \"portrait\";\n /** Pixels per inch. Required if you want physical screen size derived from `width`/`height` (server computes widthInches = width / ppi). Typical: 40 (large TV), 96 (desktop monitor), 264 (tablet). */\n ppi?: number;\n /** Display resolution width in pixels (e.g. 1920) */\n width?: number;\n /** Physical screen width in INCHES. Overrides ppi-based derivation. Use this when you've measured the actual screen (most accurate for pricing). */\n width_in?: number;\n };\n display_settings?: PartnerRegistrationDisplaySettings;\n location?: {\n address?: string;\n city?: string;\n country?: string;\n lat?: number;\n lng?: number;\n state?: string;\n timezone?: string;\n venue_name?: string;\n venue_type?: \"mall\" | \"airport\" | \"retail\" | \"restaurant\" | \"office\" | \"gym\" | \"hospital\" | \"school\" | \"other\";\n zip?: string;\n };\n /** Reporting hints for moving screens (mobility_type mobile/semi_mobile). */\n mobile_settings?: {\n /** Minimum displacement before a fix is sent (device-side hint). */\n distance_threshold_meters?: number;\n /** Target GPS reporting interval (floor — the platform adapts to speed/battery). */\n update_interval_seconds?: number;\n vehicle_type?: \"taxi\" | \"rideshare\" | \"delivery\" | \"bus\" | \"food_truck\" | \"other\";\n };\n /** Declare a moving screen. `mobile` (taxi-top, transit) and `semi_mobile` (food truck, pop-up) screens report GPS via the heartbeat `location` field; `static` (default) screens ignore it. */\n mobility_type?: \"static\" | \"mobile\" | \"semi_mobile\";\n /** Friendly name for the device */\n name?: string;\n /** Photo URL for enrichment context */\n photo_url?: string;\n /** Optional additional photos for enrichment */\n photos?: Array<{\n /** photo type (context, close, angle, other) */\n type?: string;\n url?: string;\n }>;\n /** Physical placement details (optional) */\n placement?: {\n height_from_floor_ft?: number;\n mounting_type?: \"wall\" | \"ceiling\" | \"tabletop\" | \"window\" | \"stand\" | \"freestanding\" | \"floor_stand\" | \"counter\" | \"pole\" | \"vehicle\" | \"other\" | \"unknown\";\n orientation?: \"landscape\" | \"portrait\";\n viewing_distance_ft?: number;\n };\n /** Venue classification details (optional). Subcategory is free text and may be auto-enriched by AI. */\n venue?: {\n business_name?: string;\n category?: \"retail\" | \"restaurant\" | \"bar\" | \"cafe\" | \"hotel\" | \"office\" | \"gym\" | \"hospital\" | \"school\" | \"mall\" | \"airport\" | \"gas_station\" | \"convenience_store\" | \"laundromat\" | \"salon\" | \"auto_shop\" | \"other\";\n context_notes?: string;\n environment_type?: \"indoor\" | \"outdoor\" | \"semi_outdoor\" | \"transit\";\n placement_type?: \"digital_signage\" | \"point_of_sale\" | \"waiting_area\" | \"window_display\" | \"kiosk\" | \"other\";\n /** Free text subcategory (may be auto-enriched by AI) */\n subcategory?: string;\n };\n};\n response: {\n data?: {\n /** Our internal device ID */\n device_id?: string;\n /** Load this URL in your WebView */\n embed_url?: string;\n /** Enrichment completion state */\n enrichment_status?: string;\n /** Your device ID */\n external_device_id?: string;\n /** Device fingerprint for SDK */\n fingerprint?: string;\n /** Stripe-style readiness. `ready` — coordinates present and venue classified. `limited` — coordinates present, not yet classified (servable, missing venue/floor). `blocked` — no usable coordinates, or classification permanently failed. */\n monetization_status?: \"ready\" | \"limited\" | \"blocked\";\n requirements?: PartnerMonetizationRequirements;\n /** Linked screen ID */\n screen_id?: string;\n status?: string;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Delete a device\n * DELETE /device/{deviceId}\n */\nexport interface deleteDeviceOperation {\n readonly path: \"/device/{deviceId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get device info\n * GET /device/{deviceId}\n */\nexport interface getDeviceOperation {\n readonly path: \"/device/{deviceId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Device;\n success?: boolean;\n};\n}\n\n/**\n * Update device metadata\n * PATCH /device/{deviceId}\n */\nexport interface updateDeviceOperation {\n readonly path: \"/device/{deviceId}\";\n readonly method: \"PATCH\";\n request: {\n /** Any additional metadata for your records */\n custom_metadata?: Record<string, unknown>;\n /** Screen or venue description */\n description?: string;\n /** Screen display specification. `width`/`height` are pixels; pass `width_in`/`height_in` (inches) or `ppi` to record physical screen size for floor pricing. See POST /device for full unit semantics. */\n display?: {\n /** Display resolution height in pixels */\n height?: number;\n /** Physical screen height in inches (pairs with width_in) */\n height_in?: number;\n orientation?: \"landscape\" | \"portrait\";\n /** Pixels per inch (required to derive physical size from width/height) */\n ppi?: number;\n /** Display resolution width in pixels */\n width?: number;\n /** Physical screen width in inches (overrides ppi-based derivation) */\n width_in?: number;\n };\n /** Partner-owned device ID used for idempotent lookup and reconciliation */\n external_device_id?: string;\n location?: {\n address?: string;\n city?: string;\n country?: string;\n lat?: number;\n lng?: number;\n state?: string;\n timezone?: string;\n /** Alias for `venue.category` — a granular venue type. Accepted on PATCH (previously documented on register only). When both are sent, `venue.category` wins. On the response this field returns the OpenOOH CHILD slug (e.g. \"hotels\"/\"malls\"); `venue.category` returns the parent. */\n venue_type?: \"mall\" | \"airport\" | \"retail\" | \"restaurant\" | \"office\" | \"gym\" | \"hospital\" | \"school\" | \"other\";\n zip?: string;\n };\n /** Reporting hints for moving screens. Merges with existing settings. */\n mobile_settings?: {\n distance_threshold_meters?: number;\n update_interval_seconds?: number;\n vehicle_type?: \"taxi\" | \"rideshare\" | \"delivery\" | \"bus\" | \"food_truck\" | \"other\";\n };\n /** Update the screen's mobility. Set `mobile`/`semi_mobile` to have the heartbeat `location` field accepted for a moving screen. */\n mobility_type?: \"static\" | \"mobile\" | \"semi_mobile\";\n /** Friendly name for the device */\n name?: string;\n photo_url?: string;\n photos?: Array<{\n type?: string;\n url?: string;\n }>;\n placement?: {\n height_from_floor_ft?: number;\n mounting_type?: \"wall\" | \"ceiling\" | \"tabletop\" | \"window\" | \"stand\" | \"freestanding\" | \"floor_stand\" | \"counter\" | \"pole\" | \"vehicle\" | \"other\" | \"unknown\";\n orientation?: \"landscape\" | \"portrait\";\n viewing_distance_ft?: number;\n };\n venue?: {\n business_name?: string;\n /** Granular venue type on WRITE (child-level slug). On READ this returns the resolved OpenOOH PARENT (e.g. \"hotel\" write -> \"entertainment\" read); the child slug rides `venue.subcategory` and the numeric child id rides `venue.openooh_venue_type_id`. */\n category?: \"retail\" | \"restaurant\" | \"bar\" | \"cafe\" | \"hotel\" | \"office\" | \"gym\" | \"hospital\" | \"school\" | \"mall\" | \"airport\" | \"gas_station\" | \"convenience_store\" | \"laundromat\" | \"salon\" | \"auto_shop\" | \"other\";\n context_notes?: string;\n environment_type?: \"indoor\" | \"outdoor\" | \"semi_outdoor\" | \"transit\";\n /** Response-only. Canonical OpenOOH child id to reconcile the declared venue type against (e.g. 807 for hotels). */\n openooh_venue_type_id?: number;\n placement_type?: \"digital_signage\" | \"point_of_sale\" | \"waiting_area\" | \"window_display\" | \"kiosk\" | \"other\";\n /** OpenOOH child slug (e.g. \"hotels\"). Free text on write; resolved on read. */\n subcategory?: string;\n };\n};\n response: {\n data?: Device;\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get ads for device\n * GET /device/{deviceId}/ads\n */\nexport interface getAdsForDeviceOperation {\n readonly path: \"/device/{deviceId}/ads\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n ads?: Array<Ad>;\n cache_until?: string;\n /** Pending device commands to execute (remote management). */\n commands?: Array<{\n command?: string;\n id?: string;\n payload?: Record<string, unknown>;\n queued_at?: string;\n }>;\n /** Venue/content keywords for contextual targeting. Omitted from the response when empty. */\n content_keywords?: Array<string>;\n device?: {\n display?: {\n height?: number | null;\n width?: number | null;\n };\n fingerprint?: string;\n };\n /** DOOH context signals (venue type, geo, audience) forwarded to demand. */\n dooh_signals?: Record<string, unknown>;\n header_bidding_settings?: HeaderBiddingSettings;\n /** URL of the Trillboards-hosted IMA renderer for this screen, or null when the IMA player is not enabled for this deployment / there is no waterfall source. */\n ima_player_url?: string | null;\n screen_dimensions?: {\n height?: number;\n orientation?: \"portrait\" | \"landscape\";\n width?: number;\n };\n screen_id?: string;\n /** Serve locale derived from the venue country (e.g. \"en\", \"fr\"). */\n screen_locale?: string;\n screen_name?: string | null;\n screen_orientation?: \"portrait\" | \"landscape\";\n settings?: AdSettings;\n };\n success?: boolean;\n};\n}\n\n/**\n * Acknowledge a device command\n * POST /device/{deviceId}/commands/{commandId}/ack\n */\nexport interface ackDeviceCommandOperation {\n readonly path: \"/device/{deviceId}/commands/{commandId}/ack\";\n readonly method: \"POST\";\n request: {\n /** Command execution result */\n result?: Record<string, unknown>;\n /** Acknowledgment status */\n status?: string;\n};\n response: {\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Read live device heartbeat state\n * GET /device/{deviceId}/heartbeat\n */\nexport interface getDeviceHeartbeatOperation {\n readonly path: \"/device/{deviceId}/heartbeat\";\n readonly method: \"GET\";\n request: never;\n response: PartnerHeartbeatQueryResponse;\n}\n\n/**\n * Device heartbeat\n * POST /device/{deviceId}/heartbeat\n */\nexport interface heartbeatOperation {\n readonly path: \"/device/{deviceId}/heartbeat\";\n readonly method: \"POST\";\n request: PartnerHeartbeatRequest | PartnerDeviceHeartbeatBody;\n response: PartnerHeartbeatResponse;\n}\n\n/**\n * Record programmatic ad event (Server-side Analytics)\n * POST /device/{deviceId}/programmatic-event\n */\nexport interface recordProgrammaticEventOperation {\n readonly path: \"/device/{deviceId}/programmatic-event\";\n readonly method: \"POST\";\n request: {\n ad_id?: string;\n error_code?: string;\n error_message?: string;\n event: \"ad_started\" | \"ad_ended\" | \"no_fill\" | \"error\";\n reason?: string;\n request_id?: string;\n screen_orientation?: \"portrait\" | \"landscape\";\n slot_height?: number;\n slot_width?: number;\n variant_name?: string;\n};\n response: {\n success?: boolean;\n};\n}\n\n/**\n * List all devices\n * GET /devices\n */\nexport interface listDevicesOperation {\n readonly path: \"/devices\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n devices?: Array<DeviceSummary>;\n limit?: number;\n offset?: number;\n total?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Register a device (V2 single-call onboarding)\n * POST /devices\n */\nexport interface registerDeviceV2Operation {\n readonly path: \"/devices\";\n readonly method: \"POST\";\n request: {\n /** Optional display dimensions. One of three modes — the `mode` discriminator is required. */\n display?: {\n /** Physical screen height in INCHES. Pairs with `width_in`. */\n height_in: number;\n mode: \"inches\";\n /** Physical screen width in INCHES. No upper bound — large-format / billboard inventory is valid. */\n width_in: number;\n } | {\n height: number;\n mode: \"pixels_with_ppi\";\n ppi: number;\n width: number;\n } | {\n height: number;\n mode: \"pixels_only\";\n width: number;\n };\n /** Your stable per-device identifier (e.g. \"REC00005\"). */\n external_id: string;\n /** Optional hardware identity — improves DSP device matching. */\n hardware?: {\n make?: string;\n model?: string;\n os?: \"Android\" | \"iOS\" | \"Tizen\" | \"WebOS\" | \"Linux\" | \"FireOS\" | \"Other\";\n osv?: string;\n };\n /** Optional venue location — either lat/lng coordinates or a street address. */\n location?: {\n lat: number;\n lng: number;\n } | {\n address: string;\n };\n /** The device's real WebView User-Agent. Must include a Build fingerprint and be unique per device. */\n ua: string;\n};\n response: {\n data?: {\n device_id?: string;\n diagnostics_url?: string;\n /** Paste into an iframe to start serving. */\n embed_url?: string;\n /** Server-derived canonical device identity. */\n identity?: {\n derivation_confidence?: number | null;\n derivation_source?: string | null;\n device_class?: string | null;\n make?: string | null;\n model?: string | null;\n os?: string | null;\n osv?: string | null;\n };\n };\n success?: boolean;\n};\n}\n\n/**\n * Bulk register devices\n * POST /devices/batch\n */\nexport interface registerDevicesBatchOperation {\n readonly path: \"/devices/batch\";\n readonly method: \"POST\";\n request: {\n /** Default fields applied to each device */\n defaults?: {\n display_settings?: PartnerRegistrationDisplaySettings;\n };\n devices: Array<{\n device_id: string;\n device_type?: string;\n display?: Record<string, unknown>;\n display_settings?: PartnerRegistrationDisplaySettings;\n location?: Record<string, unknown>;\n name?: string;\n placement?: Record<string, unknown>;\n venue?: Record<string, unknown>;\n }>;\n};\n response: {\n devices?: Array<{\n device_id?: string;\n fingerprint?: string;\n screen_id?: string;\n status?: string;\n trillboard_id?: string;\n }>;\n errors?: Array<{\n device_id?: string;\n error?: string;\n status?: string;\n }>;\n success?: boolean;\n summary?: {\n created?: number;\n failed?: number;\n total?: number;\n updated?: number;\n };\n};\n}\n\n/**\n * Batch update screen orientation\n * POST /devices/batch/orientation\n */\nexport interface batchUpdateDeviceOrientationOperation {\n readonly path: \"/devices/batch/orientation\";\n readonly method: \"POST\";\n request: {\n device_ids: Array<string>;\n screen_orientation: \"portrait\" | \"landscape\" | \"mixed\" | \"unknown\";\n};\n response: {\n matched_devices?: number;\n missing_device_ids?: Array<string>;\n success?: boolean;\n total_devices?: number;\n updated_screens?: number;\n};\n}\n\n/**\n * Reconcile device fleet\n * POST /devices/reconcile\n */\nexport interface reconcileDevicesOperation {\n readonly path: \"/devices/reconcile\";\n readonly method: \"POST\";\n request: {\n /** Your device external IDs to reconcile. */\n external_ids: Array<string>;\n};\n response: {\n duplicate?: Array<Record<string, unknown>>;\n malformed?: Array<Record<string, unknown>>;\n matched?: Array<Record<string, unknown>>;\n missing?: Array<string>;\n orphan?: Array<Record<string, unknown>>;\n success?: boolean;\n summary?: {\n duplicate?: number;\n malformed?: number;\n matched?: number;\n missing?: number;\n orphan?: number;\n registered_active?: number;\n requested?: number;\n };\n truncated?: Record<string, unknown>;\n};\n}\n\n/**\n * Browsable HTML documentation index\n * GET /docs\n */\nexport interface partnerDocsBrowserOperation {\n readonly path: \"/docs\";\n readonly method: \"GET\";\n request: never;\n response: unknown;\n}\n\n/**\n * Get earnings summary\n * GET /earnings\n */\nexport interface getEarningsOperation {\n readonly path: \"/earnings\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: EarningsResponse;\n success?: boolean;\n};\n}\n\n/**\n * Get detailed earnings breakdown\n * GET /earnings/breakdown\n */\nexport interface getEarningsBreakdownOperation {\n readonly path: \"/earnings/breakdown\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: EarningsBreakdownResponse;\n success?: boolean;\n};\n}\n\n/**\n * Request a payout\n * POST /earnings/payout\n */\nexport interface requestPayoutOperation {\n readonly path: \"/earnings/payout\";\n readonly method: \"POST\";\n request: {\n /** Amount to payout in cents (optional, defaults to available balance) */\n amount_cents?: number;\n};\n response: {\n data?: PayoutResponse;\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get transaction history\n * GET /earnings/transactions\n */\nexport interface getTransactionsOperation {\n readonly path: \"/earnings/transactions\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n pagination?: Pagination;\n transactions?: Array<Transaction>;\n };\n success?: boolean;\n};\n}\n\n/**\n * List active SSE connections\n * GET /events/connections\n */\nexport interface getActiveSSEConnectionsOperation {\n readonly path: \"/events/connections\";\n readonly method: \"GET\";\n request: never;\n response: {\n connections?: Array<{\n connected_at?: string;\n connection_id?: string;\n ip?: string;\n subscribed_events?: Array<string>;\n }>;\n count?: number;\n max_connections?: number;\n object?: string;\n};\n}\n\n/**\n * Subscribe to real-time events (SSE)\n * GET /events/stream\n */\nexport interface subscribeToEventsOperation {\n readonly path: \"/events/stream\";\n readonly method: \"GET\";\n request: never;\n response: unknown;\n}\n\n/**\n * Poll a fleet-command job\n * GET /fleet-commands/{id}\n */\nexport interface getFleetCommandOperation {\n readonly path: \"/fleet-commands/{id}\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n fleet_command?: FleetCommand;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get fleet analytics\n * GET /fleet/analytics\n */\nexport interface getFleetAnalyticsOperation {\n readonly path: \"/fleet/analytics\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** Average attention score (0-1) */\n avg_attention?: number;\n /** Average CPM in dollars */\n avg_cpm?: number;\n /** Fill rate percentage (0-100) */\n fill_rate_pct?: number;\n impressions_24h?: number;\n screen_count?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Push command to fleet\n * POST /fleet/command\n */\nexport interface pushFleetCommandOperation {\n readonly path: \"/fleet/command\";\n readonly method: \"POST\";\n request: {\n command: {\n /** Command-specific data */\n payload?: Record<string, unknown>;\n type: \"reload\" | \"update_settings\" | \"restart\" | \"screenshot\" | \"clear_cache\" | \"update_content\" | \"refresh_ads\" | \"update_config\" | \"get_state\" | \"show_ad\" | \"play_ad\";\n };\n /** Optional filter to target specific devices */\n filter?: {\n country?: string;\n /** A screen group id (sg_) whose members are targeted (unioned with screenIds). */\n group?: string;\n screenIds?: Array<string>;\n venueType?: string;\n };\n};\n response: {\n data?: {\n errors?: Array<{\n error?: string;\n screenId?: string;\n }>;\n /** Devices successfully queued */\n queued?: number;\n /** Total devices matching filter */\n targeted?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get fleet overview\n * GET /fleet/overview\n */\nexport interface getFleetOverviewOperation {\n readonly path: \"/fleet/overview\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n countries?: Record<string, number>;\n offline?: number;\n online?: number;\n programmatic_enabled?: number;\n total_devices?: number;\n venue_types?: Record<string, number>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Update fleet-wide settings\n * POST /fleet/settings\n */\nexport interface updateFleetSettingsOperation {\n readonly path: \"/fleet/settings\";\n readonly method: \"POST\";\n request: {\n filter?: {\n country?: string;\n /** A screen group id (sg_) whose members are targeted (unioned with screenIds). */\n group?: string;\n screenIds?: Array<string>;\n venueType?: string;\n };\n /** Settings to update (merged with existing) */\n settings: {\n content_preferences?: Record<string, unknown>;\n display_settings?: Record<string, unknown>;\n header_bidding_settings?: {\n allocation?: number;\n enabled?: boolean;\n force_request?: boolean;\n min_interval_seconds?: number;\n };\n };\n};\n response: {\n data?: {\n errors?: Array<Record<string, unknown>>;\n targeted?: number;\n updated?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Record impression (pixel)\n * GET /impression\n */\nexport interface recordImpressionGetOperation {\n readonly path: \"/impression\";\n readonly method: \"GET\";\n request: never;\n response: {\n duplicate?: boolean;\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Record impression (POST)\n * POST /impression\n */\nexport interface recordImpressionPostOperation {\n readonly path: \"/impression\";\n readonly method: \"POST\";\n request: {\n adid: string;\n aid?: string;\n completed?: boolean;\n did?: string;\n display_area_ratio?: number;\n display_mode?: \"fullscreen\" | \"l-bar\" | \"pip\";\n duration?: number;\n impid: string;\n lbar_position?: \"bottom\" | \"right\";\n lbar_size?: number;\n lbar_slot_count?: number;\n lbar_slot_index?: number;\n sid?: string;\n sig?: string;\n sig_ts?: number;\n};\n response: {\n duplicate?: boolean;\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Batch record impressions\n * POST /impressions/batch\n */\nexport interface recordImpressionsBatchOperation {\n readonly path: \"/impressions/batch\";\n readonly method: \"POST\";\n request: {\n impressions: Array<{\n adid: string;\n aid?: string;\n completed?: boolean;\n device_fingerprint?: string;\n did?: string;\n display_area_ratio?: number;\n display_mode?: \"fullscreen\" | \"l-bar\" | \"pip\";\n duration?: number;\n impid: string;\n lbar_position?: \"bottom\" | \"right\";\n lbar_size?: number;\n lbar_slot_count?: number;\n lbar_slot_index?: number;\n sid?: string;\n sig?: string;\n sig_ts?: number;\n timestamp?: string;\n }>;\n};\n response: {\n data?: {\n errors?: Array<{\n error?: string;\n impid?: string;\n }>;\n failed?: number;\n recorded?: number;\n skipped?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get partner info\n * GET /info\n */\nexport interface getPartnerInfoOperation {\n readonly path: \"/info\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Partner;\n success?: boolean;\n};\n}\n\n/**\n * List intent categories\n * GET /intent/categories\n */\nexport interface listIntentCategoriesOperation {\n readonly path: \"/intent/categories\";\n readonly method: \"GET\";\n request: never;\n response: {\n count?: number;\n data?: Array<{\n description?: string;\n id?: string;\n /** Minimum intent score to match this category */\n min_intent_score?: number;\n name?: string;\n /** CPM multiplier applied when this intent is detected */\n premium_multiplier?: number;\n purchase_stages?: Array<\"READY_TO_BUY\" | \"COMPARING\" | \"CONSIDERING\" | \"BROWSING\">;\n }>;\n object?: string;\n};\n}\n\n/**\n * Get intent category details\n * GET /intent/categories/{categoryId}\n */\nexport interface getIntentCategoryOperation {\n readonly path: \"/intent/categories/{categoryId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n description?: string;\n iab_segments?: Array<Record<string, unknown>>;\n id?: string;\n min_intent_score?: number;\n name?: string;\n object?: string;\n premium_multiplier?: number;\n purchase_stages?: Array<string>;\n triggers?: Array<string>;\n};\n}\n\n/**\n * Get intent-based pricing for a screen\n * GET /intent/pricing/{screenId}\n */\nexport interface getIntentPricingOperation {\n readonly path: \"/intent/pricing/{screenId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n category_match?: {\n category_id?: string;\n category_name?: string;\n intent_score?: number;\n premium_multiplier?: number;\n purchase_stage?: string;\n } | null;\n current_intent?: {\n categories?: Array<string>;\n purchase_stage?: \"NONE\" | \"BROWSING\" | \"CONSIDERING\" | \"COMPARING\" | \"READY_TO_BUY\";\n /** Intent confidence score (0-1) */\n score?: number;\n /** Whether an ad swap should be triggered */\n should_trigger?: boolean;\n };\n object?: string;\n pricing?: {\n base_cpm?: number;\n category_id?: string;\n category_name?: string;\n /** Effective CPM after intent premium */\n intent_cpm?: number;\n /** Additional CPM from intent detection */\n intent_premium?: number;\n premium_multiplier?: number;\n };\n screen_id?: string;\n};\n}\n\n/**\n * Trillboards measurement methodology disclosure\n * GET /measurement-methodology\n */\nexport interface getMeasurementMethodologyOperation {\n readonly path: \"/measurement-methodology\";\n readonly method: \"GET\";\n request: never;\n response: MeasurementMethodology;\n}\n\n/**\n * Measurement methodology disclosure (JSON, no negotiation)\n * GET /measurement-methodology.json\n */\nexport interface getMeasurementMethodologyJsonOperation {\n readonly path: \"/measurement-methodology.json\";\n readonly method: \"GET\";\n request: never;\n response: MeasurementMethodology;\n}\n\n/**\n * Get network configuration\n * GET /network-config\n */\nexport interface getNetworkConfigOperation {\n readonly path: \"/network-config\";\n readonly method: \"GET\";\n request: never;\n response: {\n network_config?: PartnerNetworkConfig;\n object?: string;\n parent_partner_id?: string | null;\n};\n}\n\n/**\n * Partial update network configuration\n * PATCH /network-config\n */\nexport interface patchNetworkConfigOperation {\n readonly path: \"/network-config\";\n readonly method: \"PATCH\";\n request: PartnerNetworkConfigUpdate;\n response: {\n network_config?: PartnerNetworkConfig;\n object?: string;\n parent_partner_id?: string | null;\n};\n}\n\n/**\n * Update network configuration\n * PUT /network-config\n */\nexport interface updateNetworkConfigOperation {\n readonly path: \"/network-config\";\n readonly method: \"PUT\";\n request: PartnerNetworkConfigUpdate;\n response: {\n network_config?: PartnerNetworkConfig;\n object?: string;\n parent_partner_id?: string | null;\n};\n}\n\n/**\n * Network-wide audience and inventory trends\n * GET /network/trends\n */\nexport interface getNetworkTrendsOperation {\n readonly path: \"/network/trends\";\n readonly method: \"GET\";\n request: never;\n response: {\n audience_shift?: Array<Record<string, unknown>>;\n days?: number;\n venue_type_mix?: Array<Record<string, unknown>>;\n};\n}\n\n/**\n * Unauthenticated liveness probe\n * GET /ping\n */\nexport interface partnerPingOperation {\n readonly path: \"/ping\";\n readonly method: \"GET\";\n request: never;\n response: {\n ok?: boolean;\n service?: string;\n};\n}\n\n/**\n * Authenticated liveness probe\n * GET /ping/auth\n */\nexport interface partnerPingAuthOperation {\n readonly path: \"/ping/auth\";\n readonly method: \"GET\";\n request: never;\n response: {\n ok?: boolean;\n partner_id?: string;\n tier?: \"basic\" | \"developer\" | \"enterprise\";\n};\n}\n\n/**\n * Record a log-level play\n * POST /plays\n */\nexport interface recordPartnerPlayOperation {\n readonly path: \"/plays\";\n readonly method: \"POST\";\n request: PartnerPlay;\n response: {\n content_sha256?: string;\n object?: string;\n play_id?: string;\n status?: \"accepted\" | \"duplicate\";\n};\n}\n\n/**\n * Record a batch of log-level plays\n * POST /plays/batch\n */\nexport interface recordPartnerPlaysBatchOperation {\n readonly path: \"/plays/batch\";\n readonly method: \"POST\";\n request: {\n plays: Array<PartnerPlay>;\n};\n response: {\n accepted?: number;\n duplicate?: number;\n errors?: Array<{\n play_id?: string | null;\n reason?: string;\n }>;\n object?: string;\n rejected?: number;\n total?: number;\n};\n}\n\n/**\n * Get machine-readable pricing\n * GET /pricing\n */\nexport interface getPricingOperation {\n readonly path: \"/pricing\";\n readonly method: \"GET\";\n request: never;\n response: {\n agent_register_url?: string;\n billing_setup_url?: string;\n /** Volume discount tiers for prepaid credits */\n committed_use?: Record<string, {\n credits_usd?: number;\n discount_pct?: number;\n price_usd?: number;\n }>;\n currency?: string;\n description?: string;\n /** Free tier limits per product and meter */\n free_tiers?: Record<string, unknown>;\n model?: string;\n object?: string;\n /** Pricing details per product */\n products?: {\n attribution?: {\n description?: string;\n meters?: Record<string, {\n first_campaign_free?: boolean;\n per_unit?: string;\n unit_price_usd?: number;\n }>;\n name?: string;\n };\n data_api?: {\n description?: string;\n name?: string;\n notes?: string;\n tiers?: Array<{\n unit_price_usd?: number;\n /** null means unlimited (final tier) */\n up_to?: number | null;\n }>;\n unit?: string;\n };\n data_marketplace?: {\n description?: string;\n meters?: Record<string, {\n free_quota_per_month?: number;\n per_unit?: string;\n unit_price_usd?: number;\n }>;\n name?: string;\n notes?: string;\n revenue_share?: Record<string, unknown>;\n };\n fein_edge_ai?: {\n description?: string;\n name?: string;\n pricing?: string;\n };\n partner_platform?: {\n description?: string;\n name?: string;\n pricing?: string;\n revenue_share?: {\n distributor?: number;\n earner?: number;\n platform?: number;\n };\n };\n programmatic?: {\n description?: string;\n name?: string;\n pricing?: string;\n };\n proof_of_play?: {\n description?: string;\n name?: string;\n notes?: string;\n tiers?: Array<{\n unit_price_usd?: number;\n up_to?: number | null;\n }>;\n unit?: string;\n };\n };\n request_id?: string;\n};\n}\n\n/**\n * Record programmatic ad event (legacy SDK alias)\n * POST /programmatic-event\n */\nexport interface recordProgrammaticEventLegacyAliasOperation {\n readonly path: \"/programmatic-event\";\n readonly method: \"POST\";\n request: {\n ad_id?: string;\n /** Device fingerprint or external device ID */\n device_id?: string;\n /** Short legacy device identifier alias */\n did?: string;\n error_code?: string;\n error_message?: string;\n event: \"ad_started\" | \"ad_ended\" | \"no_fill\" | \"error\";\n reason?: string;\n request_id?: string;\n type?: \"ad_started\" | \"ad_ended\" | \"no_fill\" | \"error\";\n variant_name?: string;\n};\n response: {\n success?: boolean;\n};\n}\n\n/**\n * Quick start — register partner and first device in one call\n * POST /quick-start\n */\nexport interface quickStartOperation {\n readonly path: \"/quick-start\";\n readonly method: \"POST\";\n request: {\n /** Company or partner name */\n company_name: string;\n /** Display configuration for the first device */\n device_display?: Record<string, unknown>;\n /** Location for the first device */\n device_location?: Record<string, unknown>;\n /** Name for the first device */\n device_name?: string;\n email: string;\n /** Optional legacy classification. Omit for the default self-serve Partner API key. */\n partner_type?: string;\n};\n response: {\n data?: {\n credentials?: {\n /** Store securely — shown only once! */\n api_key?: string;\n api_key_prefix?: string;\n warning?: string;\n };\n device?: {\n device_id?: string;\n embed_url?: string;\n external_device_id?: string;\n fingerprint?: string;\n name?: string;\n screen_id?: string;\n status?: string;\n };\n integration?: {\n api_base?: string;\n docs_url?: string;\n embed_url?: string;\n iframe_snippet?: string;\n sdk_snippet?: string;\n sdk_url?: string;\n };\n next_steps?: Array<string>;\n partner?: {\n name?: string;\n partner_id?: string;\n revenue_share_percent?: number;\n slug?: string;\n status?: string;\n };\n sdk_config?: {\n ad_interval?: number;\n allowed_ad_types?: Array<string>;\n cache_size?: number;\n image_duration?: number;\n max_ads_per_hour?: number;\n sound_enabled?: boolean;\n };\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Register a new partner\n * POST /register\n */\nexport interface registerPartnerOperation {\n readonly path: \"/register\";\n readonly method: \"POST\";\n request: {\n /** Whitelist of allowed referrer domains */\n allowed_domains?: Array<string>;\n contact_email: string;\n contact_name?: string;\n /** Company or partner name */\n name: string;\n /** Optional legacy classification. Omit this field — it does not change which API key you receive. Existing integrations may continue sending historical values (including `ctv_publisher`) for backward compatibility; every partner_type mints the same self-serve Partner API key. */\n partner_type?: \"vending_machine\" | \"kiosk\" | \"digital_signage\" | \"retail_display\" | \"ctv_publisher\" | \"other\";\n /** Partner's revenue share percentage (negotiated per partner) */\n revenue_share_percent?: number;\n /** URL-safe identifier (lowercase, no spaces) */\n slug: string;\n};\n response: {\n data?: {\n /** Store this securely - only shown once. This ONE self-serve Partner API key authenticates the general Partner API surface in this spec AND the CTV Measurement SDK ingestion surface (`/v2/sdk/*`, `/v2/csi`) — it carries `sdk:*` and `mcp:tools` by default, so no separate CTV or MCP key is issued. Reuse it during OpenRTB onboarding to add buyer capabilities. */\n api_key?: string;\n partner_id?: string;\n /** Optional portal onboarding details for the partner owner account */\n portal_access?: {\n claim_complete_endpoint?: string;\n claim_request_endpoint?: string;\n claim_required?: boolean;\n claim_verify_endpoint?: string;\n email?: string;\n message?: string;\n new_account?: boolean;\n portal_auth_url?: string;\n portal_url?: string;\n user_id?: string;\n };\n revenue_share_percent?: number;\n slug?: string;\n status?: \"pending\" | \"active\";\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Generate a test event\n * POST /sandbox/event\n */\nexport interface generateSandboxEventOperation {\n readonly path: \"/sandbox/event\";\n readonly method: \"POST\";\n request: {\n /** Event type to generate */\n event_type: string;\n /** Target sandbox screen (auto-selects first if omitted) */\n screen_id?: string;\n};\n response: {\n /** Event payload (varies by event type) */\n data?: Record<string, unknown>;\n event?: string;\n event_id?: string;\n is_sandbox?: boolean;\n object?: string;\n screen_id?: string | null;\n /** Number of SSE connections that received this event */\n sse_delivered?: number;\n timestamp?: string;\n};\n}\n\n/**\n * Reset sandbox data\n * POST /sandbox/reset\n */\nexport interface resetSandboxOperation {\n readonly path: \"/sandbox/reset\";\n readonly method: \"POST\";\n request: never;\n response: {\n events_cleared?: number;\n object?: string;\n reset_at?: string;\n screens_cleared?: number;\n success?: boolean;\n};\n}\n\n/**\n * Create a sandbox screen\n * POST /sandbox/screen\n */\nexport interface createSandboxScreenOperation {\n readonly path: \"/sandbox/screen\";\n readonly method: \"POST\";\n request: {\n /** Custom screen name */\n name?: string;\n /** Override venue type */\n venue_type?: string;\n};\n response: {\n audience?: {\n avg_dwell_time_sec?: number;\n current_viewers?: number;\n demographics?: Record<string, unknown>;\n };\n created_at?: string;\n device_id?: string;\n display_settings?: Record<string, unknown>;\n fingerprint?: string;\n id?: string;\n is_sandbox?: boolean;\n last_heartbeat?: string;\n location?: {\n city?: string;\n latitude?: number;\n longitude?: number;\n name?: string;\n state?: string;\n venue_type?: string;\n };\n name?: string;\n object?: string;\n partner_id?: string;\n screen_id?: string;\n status?: string;\n};\n}\n\n/**\n * Get sandbox status\n * GET /sandbox/status\n */\nexport interface getSandboxStatusOperation {\n readonly path: \"/sandbox/status\";\n readonly method: \"GET\";\n request: never;\n response: {\n last_activity?: string | null;\n object?: string;\n recent_events?: Array<{\n event?: string;\n event_id?: string;\n timestamp?: string;\n }>;\n sandbox_screens?: Array<{\n created_at?: string;\n id?: string;\n last_heartbeat?: string;\n location?: Record<string, unknown>;\n name?: string;\n status?: string;\n }>;\n total_screens?: number;\n total_test_events?: number;\n};\n}\n\n/**\n * List screen groups\n * GET /screen-groups\n */\nexport interface listScreenGroupsOperation {\n readonly path: \"/screen-groups\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n has_more?: boolean;\n object?: string;\n screen_groups?: Array<ScreenGroup>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Create a screen group\n * POST /screen-groups\n */\nexport interface createScreenGroupOperation {\n readonly path: \"/screen-groups\";\n readonly method: \"POST\";\n request: {\n description?: string;\n name: string;\n screen_ids?: Array<string>;\n};\n response: {\n data?: {\n screen_group?: ScreenGroup;\n };\n success?: boolean;\n};\n}\n\n/**\n * Delete (archive) a screen group\n * DELETE /screen-groups/{groupId}\n */\nexport interface deleteScreenGroupOperation {\n readonly path: \"/screen-groups/{groupId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n data?: {\n deleted?: boolean;\n id?: string;\n object?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Retrieve a screen group\n * GET /screen-groups/{groupId}\n */\nexport interface getScreenGroupOperation {\n readonly path: \"/screen-groups/{groupId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n screen_group?: ScreenGroup;\n };\n success?: boolean;\n};\n}\n\n/**\n * Update a screen group\n * POST /screen-groups/{groupId}\n */\nexport interface updateScreenGroupOperation {\n readonly path: \"/screen-groups/{groupId}\";\n readonly method: \"POST\";\n request: {\n description?: string;\n name?: string;\n};\n response: {\n data?: {\n screen_group?: ScreenGroup;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get analytics for a screen group\n * GET /screen-groups/{groupId}/analytics\n */\nexport interface getScreenGroupAnalyticsOperation {\n readonly path: \"/screen-groups/{groupId}/analytics\";\n readonly method: \"GET\";\n request: never;\n response: {\n /** Fleet analytics scoped to the group's live member screens — the same payload as GET /fleet/analytics (which also returns an average attention score alongside the fields below). */\n data?: {\n avg_cpm?: number;\n fill_rate_pct?: number;\n group_id?: string;\n impressions_24h?: number;\n screen_count?: number;\n [key: string]: unknown;\n };\n success?: boolean;\n};\n}\n\n/**\n * Run a fleet command against a screen group\n * POST /screen-groups/{groupId}/commands\n */\nexport interface createScreenGroupCommandOperation {\n readonly path: \"/screen-groups/{groupId}/commands\";\n readonly method: \"POST\";\n request: {\n command: {\n payload?: Record<string, unknown>;\n type: \"reload\" | \"update_settings\" | \"restart\" | \"screenshot\" | \"clear_cache\" | \"update_content\" | \"refresh_ads\" | \"update_config\" | \"get_state\" | \"show_ad\" | \"play_ad\";\n };\n};\n response: {\n data?: {\n fleet_command?: FleetCommand;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get a screen group's content policy\n * GET /screen-groups/{groupId}/content-policy\n */\nexport interface getScreenGroupContentPolicyOperation {\n readonly path: \"/screen-groups/{groupId}/content-policy\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n content_policy?: ScreenGroupContentPolicy;\n };\n success?: boolean;\n};\n}\n\n/**\n * Set a screen group's content policy\n * PUT /screen-groups/{groupId}/content-policy\n */\nexport interface updateScreenGroupContentPolicyOperation {\n readonly path: \"/screen-groups/{groupId}/content-policy\";\n readonly method: \"PUT\";\n request: ScreenGroupContentPolicyInput;\n response: {\n data?: {\n content_policy?: ScreenGroupContentPolicy;\n };\n success?: boolean;\n};\n}\n\n/**\n * Remove members from a screen group\n * DELETE /screen-groups/{groupId}/members\n */\nexport interface removeScreenGroupMembersOperation {\n readonly path: \"/screen-groups/{groupId}/members\";\n readonly method: \"DELETE\";\n request: {\n screen_ids: Array<string>;\n};\n response: {\n data?: {\n removed?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * List a screen group's members\n * GET /screen-groups/{groupId}/members\n */\nexport interface listScreenGroupMembersOperation {\n readonly path: \"/screen-groups/{groupId}/members\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n data?: Array<{\n id?: string;\n object?: string;\n }>;\n has_more?: boolean;\n object?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Add members to a screen group\n * POST /screen-groups/{groupId}/members\n */\nexport interface addScreenGroupMembersOperation {\n readonly path: \"/screen-groups/{groupId}/members\";\n readonly method: \"POST\";\n request: {\n screen_ids: Array<string>;\n};\n response: {\n data?: {\n added?: number;\n rejected?: Array<{\n id?: string;\n reason?: string;\n }>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get a screen group's sensing config\n * GET /screen-groups/{groupId}/sensing-config\n */\nexport interface getScreenGroupSensingConfigOperation {\n readonly path: \"/screen-groups/{groupId}/sensing-config\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n sensing_config?: ScreenGroupSensingConfig;\n };\n success?: boolean;\n};\n}\n\n/**\n * Set a screen group's sensing config\n * PUT /screen-groups/{groupId}/sensing-config\n */\nexport interface updateScreenGroupSensingConfigOperation {\n readonly path: \"/screen-groups/{groupId}/sensing-config\";\n readonly method: \"PUT\";\n request: ScreenGroupSensingConfigInput;\n response: {\n data?: {\n sensing_config?: ScreenGroupSensingConfig;\n };\n success?: boolean;\n};\n}\n\n/**\n * OpenRTB SDA payload for a screen\n * GET /screen/{external_code}/audience-segments\n */\nexport interface getScreenAudienceSegmentsOperation {\n readonly path: \"/screen/{external_code}/audience-segments\";\n readonly method: \"GET\";\n request: never;\n response: {\n external_code?: string;\n segtax_4?: Array<{\n confidence?: number;\n id?: string;\n }>;\n segtax_600?: Array<{\n confidence?: number;\n id?: string;\n }>;\n};\n}\n\n/**\n * Batch update content preferences\n * POST /screens/batch/content-preferences\n */\nexport interface batchUpdateContentPreferencesOperation {\n readonly path: \"/screens/batch/content-preferences\";\n readonly method: \"POST\";\n request: {\n preferences?: ContentPreferencesInput;\n /** Preset ID to apply (alternative to preferences) */\n preset_id?: string;\n /** Array of screen IDs to update */\n screen_ids: Array<string>;\n};\n response: BatchResult;\n}\n\n/**\n * Batch update display settings\n * POST /screens/batch/display-settings\n */\nexport interface batchUpdateDisplaySettingsOperation {\n readonly path: \"/screens/batch/display-settings\";\n readonly method: \"POST\";\n request: {\n screen_ids: Array<string>;\n settings: DisplaySettingsInput;\n};\n response: BatchResult;\n}\n\n/**\n * Batch update programmatic settings\n * POST /screens/batch/programmatic-settings\n */\nexport interface batchUpdateProgrammaticSettingsOperation {\n readonly path: \"/screens/batch/programmatic-settings\";\n readonly method: \"POST\";\n request: {\n screen_ids: Array<string>;\n settings: ProgrammaticSettingsInput;\n};\n response: BatchResult;\n}\n\n/**\n * Resolve screen ID by device identifier\n * GET /screens/resolve\n */\nexport interface resolvePartnerScreenOperation {\n readonly path: \"/screens/resolve\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n device_id?: string;\n external_device_id?: string;\n fingerprint?: string;\n screen_id?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get per-screen analytics\n * GET /screens/{screenId}/analytics\n */\nexport interface getScreenAnalyticsOperation {\n readonly path: \"/screens/{screenId}/analytics\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: ScreenAnalyticsResponse;\n success?: boolean;\n};\n}\n\n/**\n * Current atmosphere (mood, noise, crowd density)\n * GET /screens/{screenId}/analytics/atmosphere\n */\nexport interface getPartnerScreenAtmosphereOperation {\n readonly path: \"/screens/{screenId}/analytics/atmosphere\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n crowdDensity?: string | null;\n currentViewers?: number | null;\n dataAge?: string;\n engagement?: number | null;\n lastUpdated?: string | null;\n mood?: string | null;\n noiseLevel?: string | null;\n };\n status?: boolean;\n};\n}\n\n/**\n * Time-bucketed venue intelligence with Lincoln-Petersen dedup\n * GET /screens/{screenId}/analytics/intelligence\n */\nexport interface getPartnerScreenIntelligenceOperation {\n readonly path: \"/screens/{screenId}/analytics/intelligence\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n dedup?: {\n camera_count?: number;\n method?: string;\n raw_total?: number;\n unique_total?: number;\n };\n from?: string;\n interval?: string;\n screen_id?: string;\n summary?: {\n avg_attention?: number;\n buckets?: number;\n total_unique_viewers?: number;\n };\n timeseries?: Array<Record<string, unknown>>;\n to?: string;\n };\n status?: boolean;\n};\n}\n\n/**\n * Per-screen taste profile + top-5 creative categories\n * GET /screens/{screenId}/analytics/taste-profile\n */\nexport interface getPartnerScreenTasteProfileOperation {\n readonly path: \"/screens/{screenId}/analytics/taste-profile\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n computedAt?: string | null;\n daypartDistribution?: Record<string, unknown> | null;\n ready?: boolean;\n sampleCount?: number;\n screenId?: string;\n tasteVersionHash?: string | null;\n topCategories?: Array<Record<string, unknown>>;\n updatedAt?: string | null;\n venueType?: string | null;\n windowEnd?: string | null;\n windowStart?: string | null;\n };\n status?: boolean;\n};\n}\n\n/**\n * Hourly foot-traffic patterns for a screen\n * GET /screens/{screenId}/analytics/traffic\n */\nexport interface getPartnerScreenTrafficOperation {\n readonly path: \"/screens/{screenId}/analytics/traffic\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n busyScore?: number;\n hourlyTraffic?: Array<Record<string, unknown>>;\n periodDays?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Verified Attention Seconds + CPM tier for a screen\n * GET /screens/{screenId}/analytics/vas\n */\nexport interface getPartnerScreenVASOperation {\n readonly path: \"/screens/{screenId}/analytics/vas\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n avgAttentionScore?: number;\n avgFaceCount?: number;\n avgVasWeighted?: number;\n lastMeasurement?: string | null;\n medianVas?: number;\n multiplier?: number;\n p90Vas?: number;\n tier?: string;\n totalMeasurements?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Apply content preset to screen\n * POST /screens/{screenId}/apply-preset\n */\nexport interface applyContentPresetOperation {\n readonly path: \"/screens/{screenId}/apply-preset\";\n readonly method: \"POST\";\n request: {\n /** ID of the preset to apply */\n preset_id: string;\n};\n response: ContentPreferencesResponse & {\n preset_applied?: string;\n };\n}\n\n/**\n * Get real-time audience metrics\n * GET /screens/{screenId}/audience-metrics\n */\nexport interface getAudienceMetricsOperation {\n readonly path: \"/screens/{screenId}/audience-metrics\";\n readonly method: \"GET\";\n request: never;\n response: AudienceMetricsResponse;\n}\n\n/**\n * Get screen content preferences\n * GET /screens/{screenId}/content-preferences\n */\nexport interface getContentPreferencesOperation {\n readonly path: \"/screens/{screenId}/content-preferences\";\n readonly method: \"GET\";\n request: never;\n response: ContentPreferencesResponse;\n}\n\n/**\n * Update content preferences (partial)\n * PATCH /screens/{screenId}/content-preferences\n */\nexport interface patchContentPreferencesOperation {\n readonly path: \"/screens/{screenId}/content-preferences\";\n readonly method: \"PATCH\";\n request: ContentPreferencesInput;\n response: ContentPreferencesResponse;\n}\n\n/**\n * Update content preferences (full)\n * PUT /screens/{screenId}/content-preferences\n */\nexport interface updateContentPreferencesOperation {\n readonly path: \"/screens/{screenId}/content-preferences\";\n readonly method: \"PUT\";\n request: ContentPreferencesInput;\n response: ContentPreferencesResponse;\n}\n\n/**\n * List default streams for a screen\n * GET /screens/{screenId}/default-streams\n */\nexport interface listPartnerDefaultStreamsOperation {\n readonly path: \"/screens/{screenId}/default-streams\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n current?: PartnerDefaultStream;\n streams?: Array<PartnerDefaultStream>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Create a default stream (URL-based)\n * POST /screens/{screenId}/default-streams\n */\nexport interface createPartnerDefaultStreamOperation {\n readonly path: \"/screens/{screenId}/default-streams\";\n readonly method: \"POST\";\n request: PartnerDefaultStreamCreate;\n response: {\n data?: PartnerDefaultStream;\n success?: boolean;\n};\n}\n\n/**\n * Upload image carousel default stream\n * POST /screens/{screenId}/default-streams/images\n */\nexport interface createPartnerDefaultStreamImagesOperation {\n readonly path: \"/screens/{screenId}/default-streams/images\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: PartnerDefaultStream;\n success?: boolean;\n};\n}\n\n/**\n * Reorder default streams\n * PUT /screens/{screenId}/default-streams/order\n */\nexport interface reorderPartnerDefaultStreamsOperation {\n readonly path: \"/screens/{screenId}/default-streams/order\";\n readonly method: \"PUT\";\n request: {\n order: Array<string>;\n};\n response: {\n success?: boolean;\n};\n}\n\n/**\n * Upload a video default stream\n * POST /screens/{screenId}/default-streams/upload\n */\nexport interface createPartnerDefaultStreamUploadOperation {\n readonly path: \"/screens/{screenId}/default-streams/upload\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: PartnerDefaultStream;\n success?: boolean;\n};\n}\n\n/**\n * Delete a default stream\n * DELETE /screens/{screenId}/default-streams/{streamId}\n */\nexport interface deletePartnerDefaultStreamOperation {\n readonly path: \"/screens/{screenId}/default-streams/{streamId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n success?: boolean;\n};\n}\n\n/**\n * Update a default stream\n * PUT /screens/{screenId}/default-streams/{streamId}\n */\nexport interface updatePartnerDefaultStreamOperation {\n readonly path: \"/screens/{screenId}/default-streams/{streamId}\";\n readonly method: \"PUT\";\n request: PartnerDefaultStreamUpdate;\n response: {\n data?: PartnerDefaultStream;\n success?: boolean;\n};\n}\n\n/**\n * Get screen demographics\n * GET /screens/{screenId}/demographics\n */\nexport interface getScreenDemographicsOperation {\n readonly path: \"/screens/{screenId}/demographics\";\n readonly method: \"GET\";\n request: never;\n response: DemographicsResponse;\n}\n\n/**\n * Get display settings\n * GET /screens/{screenId}/display-settings\n */\nexport interface getDisplaySettingsOperation {\n readonly path: \"/screens/{screenId}/display-settings\";\n readonly method: \"GET\";\n request: never;\n response: DisplaySettingsResponse;\n}\n\n/**\n * Update display settings (partial)\n * PATCH /screens/{screenId}/display-settings\n */\nexport interface patchDisplaySettingsOperation {\n readonly path: \"/screens/{screenId}/display-settings\";\n readonly method: \"PATCH\";\n request: DisplaySettingsInput;\n response: DisplaySettingsResponse;\n}\n\n/**\n * Update display settings (full)\n * PUT /screens/{screenId}/display-settings\n */\nexport interface updateDisplaySettingsOperation {\n readonly path: \"/screens/{screenId}/display-settings\";\n readonly method: \"PUT\";\n request: DisplaySettingsInput;\n response: DisplaySettingsResponse;\n}\n\n/**\n * Get L-Bar settings\n * GET /screens/{screenId}/l-bar\n */\nexport interface getPartnerLBarSettingsOperation {\n readonly path: \"/screens/{screenId}/l-bar\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: PartnerLBarSettings;\n success?: boolean;\n};\n}\n\n/**\n * Update L-Bar settings\n * PUT /screens/{screenId}/l-bar\n */\nexport interface updatePartnerLBarSettingsOperation {\n readonly path: \"/screens/{screenId}/l-bar\";\n readonly method: \"PUT\";\n request: {\n display_preferences?: PartnerLBarDisplayPreferences;\n l_bar_content?: PartnerLBarContent;\n};\n response: {\n data?: PartnerLBarSettings;\n success?: boolean;\n};\n}\n\n/**\n * Update L-Bar live updates\n * PUT /screens/{screenId}/l-bar/live-updates\n */\nexport interface updatePartnerLBarLiveUpdatesOperation {\n readonly path: \"/screens/{screenId}/l-bar/live-updates\";\n readonly method: \"PUT\";\n request: {\n custom_status?: string;\n promotion?: string;\n queue_number?: string;\n wait_time_minutes?: number;\n};\n response: {\n success?: boolean;\n};\n}\n\n/**\n * Get programmatic settings\n * GET /screens/{screenId}/programmatic-settings\n */\nexport interface getProgrammaticSettingsOperation {\n readonly path: \"/screens/{screenId}/programmatic-settings\";\n readonly method: \"GET\";\n request: never;\n response: ProgrammaticSettingsResponse;\n}\n\n/**\n * Update programmatic settings (partial)\n * PATCH /screens/{screenId}/programmatic-settings\n */\nexport interface patchProgrammaticSettingsOperation {\n readonly path: \"/screens/{screenId}/programmatic-settings\";\n readonly method: \"PATCH\";\n request: ProgrammaticSettingsInput;\n response: ProgrammaticSettingsResponse;\n}\n\n/**\n * Update programmatic settings (full)\n * PUT /screens/{screenId}/programmatic-settings\n */\nexport interface updateProgrammaticSettingsOperation {\n readonly path: \"/screens/{screenId}/programmatic-settings\";\n readonly method: \"PUT\";\n request: ProgrammaticSettingsInput;\n response: ProgrammaticSettingsResponse;\n}\n\n/**\n * Resolve the effective content policy for a screen\n * GET /screens/{screenId}/resolved-content-policy\n */\nexport interface getResolvedContentPolicyOperation {\n readonly path: \"/screens/{screenId}/resolved-content-policy\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: ResolvedContentPolicy;\n success?: boolean;\n};\n}\n\n/**\n * Resolve the effective sensing config for a screen\n * GET /screens/{screenId}/resolved-sensing-config\n */\nexport interface getResolvedSensingConfigOperation {\n readonly path: \"/screens/{screenId}/resolved-sensing-config\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: ResolvedSensingConfig;\n success?: boolean;\n};\n}\n\n/**\n * Read the custom sensing chips a screen is producing\n * GET /screens/{screenId}/sensing/chips\n */\nexport interface getScreenSensingChipsOperation {\n readonly path: \"/screens/{screenId}/sensing/chips\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** The custom field_keys this screen senses (from its active profile) */\n fields?: Array<{\n description?: string;\n field_key?: string;\n type?: string;\n }>;\n /** Recent chip observations (one row per field_key per observation) */\n rows?: Array<Record<string, unknown>>;\n screen_id?: string;\n total?: number;\n truncated?: boolean;\n };\n success?: boolean;\n};\n}\n\n/**\n * Generate a custom sensing profile from a natural-language intent\n * POST /screens/{screenId}/sensing/interpret-intent\n */\nexport interface interpretScreenSensingIntentOperation {\n readonly path: \"/screens/{screenId}/sensing/interpret-intent\";\n readonly method: \"POST\";\n request: {\n /** Optional device-capability hint for model selection */\n deviceTier?: string;\n /** Natural-language description of what to sense */\n intent: string;\n};\n response: {\n data?: {\n /** The generated profile — pass to /sensing/profile to deploy */\n profile?: Record<string, unknown>;\n screen_id?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Deploy a custom sensing profile to a screen\n * POST /screens/{screenId}/sensing/profile\n */\nexport interface deployScreenSensingProfileOperation {\n readonly path: \"/screens/{screenId}/sensing/profile\";\n readonly method: \"POST\";\n request: {\n /** The sensing profile object returned by interpret-intent */\n profile: Record<string, unknown>;\n};\n response: {\n data?: {\n command?: Record<string, unknown>;\n profile?: Record<string, unknown>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Read a screen's AI sensing performance settings\n * GET /screens/{screenId}/sensing/settings\n */\nexport interface getScreenSensingSettingsOperation {\n readonly path: \"/screens/{screenId}/sensing/settings\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: SensingSettingsResponse;\n success?: boolean;\n};\n}\n\n/**\n * Update a screen's AI sensing performance mode\n * PATCH /screens/{screenId}/sensing/settings\n */\nexport interface updateScreenSensingSettingsOperation {\n readonly path: \"/screens/{screenId}/sensing/settings\";\n readonly method: \"PATCH\";\n request: {\n performance_mode: SensingPerformanceMode;\n};\n response: {\n data?: {\n command?: Record<string, unknown>;\n profile?: Record<string, unknown>;\n settings?: SensingSettingsResponse;\n };\n success?: boolean;\n};\n}\n\n/**\n * List your Sense Anything Routes\n * GET /sensing/routes\n */\nexport interface listPartnerSensingRoutesOperation {\n readonly path: \"/sensing/routes\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n routes?: Array<SensingRoute>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Create a Sense Anything Route (threshold or scheduled-digest alert)\n * POST /sensing/routes\n */\nexport interface createPartnerSensingRouteOperation {\n readonly path: \"/sensing/routes\";\n readonly method: \"POST\";\n request: CreatePartnerSensingRouteRequest;\n response: {\n data?: {\n route?: SensingRoute;\n };\n success?: boolean;\n};\n}\n\n/**\n * Delete (soft) a Sense Anything Route\n * DELETE /sensing/routes/{routeId}\n */\nexport interface deletePartnerSensingRouteOperation {\n readonly path: \"/sensing/routes/{routeId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n data?: {\n routeId?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get one Sense Anything Route\n * GET /sensing/routes/{routeId}\n */\nexport interface getPartnerSensingRouteOperation {\n readonly path: \"/sensing/routes/{routeId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n route?: SensingRoute;\n };\n success?: boolean;\n};\n}\n\n/**\n * Update a Sense Anything Route (partial, non-clobbering)\n * PATCH /sensing/routes/{routeId}\n */\nexport interface updatePartnerSensingRouteOperation {\n readonly path: \"/sensing/routes/{routeId}\";\n readonly method: \"PATCH\";\n request: UpdatePartnerSensingRouteRequest;\n response: {\n data?: {\n route?: SensingRoute;\n };\n success?: boolean;\n};\n}\n\n/**\n * Create Stripe Connect account\n * POST /stripe/connect\n */\nexport interface createStripeConnectAccountOperation {\n readonly path: \"/stripe/connect\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: {\n account_id?: string;\n charges_enabled?: boolean;\n country?: string;\n default_currency?: string;\n details_submitted?: boolean;\n next_step?: string | null;\n payouts_enabled?: boolean;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get Stripe dashboard login link\n * GET /stripe/login-link\n */\nexport interface getStripeLoginLinkOperation {\n readonly path: \"/stripe/login-link\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n account_id?: string;\n instructions?: string;\n login_url?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get Stripe onboarding link\n * GET /stripe/onboarding-link\n */\nexport interface getStripeOnboardingLinkOperation {\n readonly path: \"/stripe/onboarding-link\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n account_id?: string;\n expires_at?: string;\n instructions?: string;\n onboarding_url?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Request a payout\n * POST /stripe/payout\n */\nexport interface requestStripePayoutOperation {\n readonly path: \"/stripe/payout\";\n readonly method: \"POST\";\n request: {\n /** Payout amount in cents (minimum $5.00) */\n amount_cents: number;\n /** Optional description for the payout */\n description?: string;\n /** Deduplication key to prevent duplicate payouts */\n idempotency_key?: string;\n};\n response: {\n data?: {\n amount_cents?: number;\n created?: string;\n currency?: string;\n description?: string;\n destination?: string;\n /** Estimated arrival (2-3 business days) */\n estimated_arrival?: string;\n status?: \"pending\" | \"reversed\";\n transfer_id?: string;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get payout history\n * GET /stripe/payouts\n */\nexport interface getStripePayoutHistoryOperation {\n readonly path: \"/stripe/payouts\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n has_more?: boolean;\n total?: number;\n transfers?: Array<{\n amount_cents?: number;\n created?: string;\n currency?: string;\n description?: string;\n status?: \"completed\" | \"reversed\";\n transfer_id?: string;\n }>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get Stripe account status\n * GET /stripe/status\n */\nexport interface getStripeAccountStatusOperation {\n readonly path: \"/stripe/status\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n account_id?: string | null;\n charges_enabled?: boolean;\n country?: string;\n default_currency?: string;\n details_submitted?: boolean;\n has_account?: boolean;\n payouts_enabled?: boolean;\n requirements?: {\n currently_due?: Array<string>;\n disabled_reason?: string | null;\n eventually_due?: Array<string>;\n past_due?: Array<string>;\n };\n status?: \"not_connected\" | \"pending\" | \"active\" | \"restricted\";\n };\n success?: boolean;\n};\n}\n\n/**\n * Stripe webhook receiver\n * POST /stripe/webhook\n */\nexport interface handleStripeWebhookOperation {\n readonly path: \"/stripe/webhook\";\n readonly method: \"POST\";\n request: Record<string, unknown>;\n response: {\n event_type?: string;\n received?: boolean;\n};\n}\n\n/**\n * List team members\n * GET /team\n */\nexport interface listTeamMembersOperation {\n readonly path: \"/team\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n members?: Array<TeamMember>;\n partner?: {\n name?: string;\n slug?: string;\n };\n total?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Accept team invitation\n * POST /team/accept\n */\nexport interface acceptInvitationOperation {\n readonly path: \"/team/accept\";\n readonly method: \"POST\";\n request: {\n /** Invitation token from email link */\n token: string;\n};\n response: {\n data?: {\n partner?: {\n id?: string;\n name?: string;\n slug?: string;\n };\n permissions?: RolePermissions;\n portal_url?: string;\n role?: string;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Invite a team member\n * POST /team/invite\n */\nexport interface inviteTeamMemberOperation {\n readonly path: \"/team/invite\";\n readonly method: \"POST\";\n request: {\n /** Email address of the invitee */\n email: string;\n /** Optional name of the invitee */\n name?: string;\n /** Role to assign to the team member */\n role?: \"admin\" | \"viewer\";\n};\n response: {\n data?: TeamInviteResponse;\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get invitation details\n * GET /team/invite/{token}\n */\nexport interface getInvitationByTokenOperation {\n readonly path: \"/team/invite/{token}\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n email?: string;\n expires_at?: string;\n invited_at?: string;\n partner?: {\n name?: string;\n slug?: string;\n };\n role?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Resend invitation\n * POST /team/{membershipId}/resend\n */\nexport interface resendInvitationOperation {\n readonly path: \"/team/{membershipId}/resend\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: {\n email?: string;\n expires_at?: string;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Remove a team member\n * DELETE /team/{userId}\n */\nexport interface removeTeamMemberOperation {\n readonly path: \"/team/{userId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Change team member role\n * PATCH /team/{userId}/role\n */\nexport interface changeTeamMemberRoleOperation {\n readonly path: \"/team/{userId}/role\";\n readonly method: \"PATCH\";\n request: {\n role: \"admin\" | \"viewer\";\n};\n response: {\n data?: {\n new_role?: string;\n old_role?: string;\n permissions?: RolePermissions;\n user_id?: string;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get public key for proof verification\n * GET /tracking/.well-known/public-key\n */\nexport interface getTrackingPublicKeyOperation {\n readonly path: \"/tracking/.well-known/public-key\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** Signature algorithm (ed25519 for public key, sha256 for HMAC fallback) */\n algorithm?: \"ed25519\" | \"sha256\";\n documentation?: string;\n /** Key identifier for rotation support */\n keyId?: string;\n /** Hex-encoded Ed25519 public key (null if using HMAC fallback) */\n publicKey?: string | null;\n verificationUrl?: string;\n version?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Record batch impressions with proof generation\n * POST /tracking/batch\n */\nexport interface recordTrackingBatchOperation {\n readonly path: \"/tracking/batch\";\n readonly method: \"POST\";\n request: {\n impressions: Array<{\n /** Ad identifier from VAST response */\n ad_id: string;\n /** Optional audience metrics */\n audience?: {\n /** Attention score (0-1) */\n attention?: number;\n /** How long viewers were present */\n dwell_time_ms?: number;\n /** Number of viewers detected */\n face_count?: number;\n };\n /** Partner's device identifier */\n device_id: string;\n /** Video duration played in milliseconds */\n duration_ms?: number;\n /** VAST event type */\n event?: \"start\" | \"complete\" | \"error\" | \"firstQuartile\" | \"midpoint\" | \"thirdQuartile\";\n /** Optional client-generated ID (auto-generated if not provided) */\n impression_id?: string;\n /** When the event occurred (defaults to now) */\n timestamp?: string;\n }>;\n};\n response: {\n data?: {\n /** Number of duplicate impressions skipped */\n duplicates?: number;\n /** Details of failed impressions (max 10 shown) */\n errors?: Array<{\n error?: string;\n impression_id?: string;\n }>;\n /** Number of impressions that failed validation */\n failed?: number;\n /** Number of impressions successfully recorded */\n processed?: number;\n /** Time to process the batch */\n processing_time_ms?: number;\n /** Cryptographic proofs for each processed impression */\n proofs?: Array<{\n impression_id?: string;\n public_key_id?: string;\n /** Ed25519 signature (or SHA256 fallback) */\n signature?: string;\n }>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get API usage summary\n * GET /usage\n */\nexport interface getUsageSummaryOperation {\n readonly path: \"/usage\";\n readonly method: \"GET\";\n request: never;\n response: {\n /** Average response time in milliseconds */\n avgResponseTime?: number;\n dailyBreakdown?: Array<{\n avg_response_ms?: number;\n date?: string;\n total_calls?: number;\n total_errors?: number;\n }>;\n /** Error rate percentage (0-100) */\n errorRate?: number;\n object?: string;\n period?: {\n end_date?: string;\n start_date?: string;\n };\n topEndpoints?: Array<{\n endpoint?: string;\n method?: string;\n total_calls?: number;\n total_errors?: number;\n }>;\n totalCalls?: number;\n totalErrors?: number;\n};\n}\n\n/**\n * Get real-time usage dashboard\n * GET /usage/dashboard\n */\nexport interface getUsageDashboardOperation {\n readonly path: \"/usage/dashboard\";\n readonly method: \"GET\";\n request: never;\n response: {\n last_7_days?: {\n avg_response_ms?: number;\n daily_breakdown?: Array<{\n avg_response_ms?: number;\n date?: string;\n total_calls?: number;\n total_errors?: number;\n }>;\n error_rate?: number;\n total_calls?: number;\n total_errors?: number;\n };\n object?: string;\n rate_limit?: {\n current_rate?: number;\n max_rate?: number;\n percent_used?: number;\n window_reset?: string;\n window_seconds?: number;\n };\n today?: {\n avg_response_ms?: number;\n error_rate?: number;\n top_endpoints?: Array<{\n avg_response_ms?: number;\n endpoint?: string;\n method?: string;\n total_calls?: number;\n total_errors?: number;\n }>;\n total_calls?: number;\n total_errors?: number;\n };\n};\n}\n\n/**\n * Get rate limit status\n * GET /usage/rate-limit\n */\nexport interface getRateLimitStatusOperation {\n readonly path: \"/usage/rate-limit\";\n readonly method: \"GET\";\n request: never;\n response: {\n current_rate?: number;\n max_rate?: number;\n object?: string;\n percent_used?: number;\n tier?: \"basic\" | \"developer\" | \"enterprise\";\n window_reset?: string;\n window_seconds?: number;\n};\n}\n\n/**\n * Query API changelog\n * GET /v1/changelog\n */\nexport interface queryChangelogOperation {\n readonly path: \"/v1/changelog\";\n readonly method: \"GET\";\n request: never;\n response: ChangelogResponse;\n}\n\n/**\n * Dry-run validate a request body against an operation schema\n * POST /v1/playground/{operation_id}\n */\nexport interface playgroundDryRunOperation {\n readonly path: \"/v1/playground/{operation_id}\";\n readonly method: \"POST\";\n request: never;\n response: PlaygroundResult;\n}\n\n/**\n * Look up metadata for a recent API request\n * GET /v1/requests/{request_id}\n */\nexport interface getRequestMetadataOperation {\n readonly path: \"/v1/requests/{request_id}\";\n readonly method: \"GET\";\n request: never;\n response: RequestMetadataResponse;\n}\n\n/**\n * Get VAST configuration for direct Google integration\n * GET /vast/config\n */\nexport interface getVastConfigOperation {\n readonly path: \"/vast/config\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** Google Ad Manager ad unit path */\n ad_unit?: string;\n /** IAB content categories to block */\n blocked_categories?: Array<string>;\n /** How long to cache this config */\n cache_ttl_seconds?: number;\n /** Floor price in cents (CPM) */\n floor_price_cpm?: number;\n integration_guide?: string;\n parameters?: {\n height?: number;\n /** Maximum ad duration in seconds */\n max_duration?: number;\n /** Minimum ad duration in seconds */\n min_duration?: number;\n /** Venue type code for targeting */\n venuetype?: number;\n width?: number;\n };\n /** Recommended VAST fetch timeout */\n timeout_ms?: number;\n tracking?: {\n batch_endpoint?: string;\n max_batch_size?: number;\n single_endpoint?: string;\n };\n /** Configuration variant name for debugging */\n variant?: string;\n /** VAST URL template with placeholders for {width} and {height}. Partner replaces placeholders and appends correlator. */\n vast_tag_template?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * List nearby Trillboards venues\n * GET /venues/nearby\n */\nexport interface getVenuesNearbyOperation {\n readonly path: \"/venues/nearby\";\n readonly method: \"GET\";\n request: never;\n response: {\n count?: number;\n venues?: Array<{\n distance_m?: number;\n screen_id?: string;\n venue_type?: string;\n }>;\n};\n}\n\n/**\n * Real-world atmosphere signals for a venue\n * GET /venues/{screenId}/atmosphere\n */\nexport interface getVenueAtmosphereOperation {\n readonly path: \"/venues/{screenId}/atmosphere\";\n readonly method: \"GET\";\n request: never;\n response: {\n days?: number;\n dominant_ambience?: string;\n lighting_band?: \"dark\" | \"dim\" | \"lit\" | \"bright\";\n motion_intensity?: number;\n noise_level_db?: number;\n screen_id?: string;\n};\n}\n\n/**\n * Foot-traffic profile for a venue\n * GET /venues/{screenId}/traffic\n */\nexport interface getVenueTrafficOperation {\n readonly path: \"/venues/{screenId}/traffic\";\n readonly method: \"GET\";\n request: never;\n response: {\n daily?: Array<Record<string, unknown>>;\n hourly?: Array<{\n face_count_avg?: number;\n hour?: number;\n }>;\n screen_id?: string;\n};\n}\n\n/**\n * Get venue intelligence report\n * GET /venues/{venueId}/intelligence\n */\nexport interface getVenueIntelligenceOperation {\n readonly path: \"/venues/{venueId}/intelligence\";\n readonly method: \"GET\";\n request: never;\n response: {\n dedup?: {\n camera_count?: number;\n method?: \"lincoln_petersen\" | \"single_camera\";\n raw_total?: number;\n unique_total?: number;\n };\n from?: string;\n interval?: string;\n summary?: {\n avg_attention?: number;\n buckets?: number;\n total_unique_viewers?: number;\n };\n timeseries?: Array<{\n age_distribution?: Record<string, number>;\n avg_attention?: number;\n avg_engagement?: number;\n avg_noise_level?: number | null;\n brand_mention_windows?: number;\n bucket?: string;\n gender_distribution?: {\n female?: number;\n male?: number;\n };\n income_level?: string | null;\n measurements?: number;\n mood?: string | null;\n peak_viewers?: number;\n raw_viewers?: number;\n screen_count?: number;\n /** Deduplicated viewer count */\n viewers?: number;\n weather?: {\n condition?: string | null;\n is_raining?: boolean;\n temperature_f?: number | null;\n };\n }>;\n to?: string;\n venue_id?: string;\n};\n}\n\n/**\n * List webhooks\n * GET /webhooks\n */\nexport interface listWebhooksOperation {\n readonly path: \"/webhooks\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n webhooks?: Array<Webhook>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Create webhook subscription\n * POST /webhooks\n */\nexport interface createWebhookOperation {\n readonly path: \"/webhooks\";\n readonly method: \"POST\";\n request: {\n /** Events to subscribe to */\n events: Array<\"device.online\" | \"device.offline\" | \"device.requirements_updated\" | \"impression.recorded\" | \"campaign.allocated\" | \"payout.processed\" | \"sensing.threshold_crossed\" | \"audience.spike\" | \"audience.venue_busy\" | \"audience.purchase_intent\" | \"audience.demographics_update\" | \"venue.traffic_summary\" | \"programmatic.ad_started\" | \"programmatic.ad_ended\" | \"programmatic.no_fill\" | \"programmatic.error\" | \"screen_group.created\" | \"screen_group.updated\" | \"screen_group.deleted\" | \"screen_group.member.added\" | \"screen_group.member.removed\" | \"screen_group.content_policy.updated\" | \"screen_group.sensing_config.updated\" | \"fleet_command.completed\" | \"fleet_command.failed\">;\n /** Webhook endpoint URL (HTTPS required in production) */\n url: string;\n};\n response: {\n data?: {\n events?: Array<string>;\n /** Webhook signing secret (shown only once!) */\n secret?: string;\n status?: \"active\" | \"inactive\";\n url?: string;\n webhook_id?: string;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Delete webhook\n * DELETE /webhooks/{webhookId}\n */\nexport interface deleteWebhookOperation {\n readonly path: \"/webhooks/{webhookId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Update webhook\n * PATCH /webhooks/{webhookId}\n */\nexport interface updateWebhookOperation {\n readonly path: \"/webhooks/{webhookId}\";\n readonly method: \"PATCH\";\n request: {\n events?: Array<\"device.online\" | \"device.offline\" | \"device.requirements_updated\" | \"impression.recorded\" | \"campaign.allocated\" | \"payout.processed\" | \"sensing.threshold_crossed\" | \"audience.spike\" | \"audience.venue_busy\" | \"audience.purchase_intent\" | \"audience.demographics_update\" | \"venue.traffic_summary\" | \"programmatic.ad_started\" | \"programmatic.ad_ended\" | \"programmatic.no_fill\" | \"programmatic.error\" | \"screen_group.created\" | \"screen_group.updated\" | \"screen_group.deleted\" | \"screen_group.member.added\" | \"screen_group.member.removed\" | \"screen_group.content_policy.updated\" | \"screen_group.sensing_config.updated\" | \"fleet_command.completed\" | \"fleet_command.failed\">;\n status?: \"active\" | \"inactive\";\n url?: string;\n};\n response: {\n data?: Webhook;\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get delivery history\n * GET /webhooks/{webhookId}/deliveries\n */\nexport interface getWebhookDeliveriesOperation {\n readonly path: \"/webhooks/{webhookId}/deliveries\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n deliveries?: Array<WebhookDelivery>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Test webhook\n * POST /webhooks/{webhookId}/test\n */\nexport interface testWebhookOperation {\n readonly path: \"/webhooks/{webhookId}/test\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: {\n error?: string;\n response_time_ms?: number;\n status?: number;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n\n// ─── Type registry ───────────────────────────────────────────────────────\n\nexport const generatedTypes = {\n schemaCount: 112,\n operationCount: 211,\n schemas: [\"Ad\",\"AdSettings\",\"AdvertisingIdentity\",\"AnalyticsData\",\"AudienceAnalyticsResponse\",\"AudienceAttentionPrediction\",\"AudienceData\",\"AudienceExportResponse\",\"AudienceLoyaltyFeaturesRow\",\"AudienceMetricsResponse\",\"AudienceSegment\",\"AudienceSocialAttention\",\"BatchResult\",\"BillingInfo\",\"BleScanResultData\",\"ChangelogEntry\",\"ChangelogResponse\",\"ContentFitSettings\",\"ContentPreferencesInput\",\"ContentPreferencesResponse\",\"ContentPreset\",\"CreatePartnerSensingRouteRequest\",\"CreativeClassification\",\"DashboardResponse\",\"DataExportSummaryResponse\",\"DemographicsResponse\",\"Device\",\"DeviceCapabilityPayload\",\"DeviceSummary\",\"DisplaySettingsInput\",\"DisplaySettingsResponse\",\"EarningsBreakdownResponse\",\"EarningsData\",\"EarningsResponse\",\"Error\",\"ErrorEntry\",\"ExtendedIdentity\",\"FleetCommand\",\"FleetCommandEvent\",\"HeaderBiddingSettings\",\"HttpProbeResult\",\"Impression\",\"MdnsNetworkDevice\",\"MeasurementMethodology\",\"Pagination\",\"Partner\",\"PartnerAdDeliveryProfile\",\"PartnerCreativeWarnings\",\"PartnerDefaultStream\",\"PartnerDefaultStreamCreate\",\"PartnerDefaultStreamUpdate\",\"PartnerDeviceBatchRegistrationInput\",\"PartnerDeviceHeartbeatBody\",\"PartnerDeviceRegistrationInput\",\"PartnerHeartbeatCommand\",\"PartnerHeartbeatData\",\"PartnerHeartbeatMeasurementMetadata\",\"PartnerHeartbeatQueryData\",\"PartnerHeartbeatQueryResponse\",\"PartnerHeartbeatRequest\",\"PartnerHeartbeatResponse\",\"PartnerHeartbeatTelemetry\",\"PartnerLBarContent\",\"PartnerLBarDisplayPreferences\",\"PartnerLBarSettings\",\"PartnerMonetizationRequirements\",\"PartnerNetworkConfig\",\"PartnerNetworkConfigUpdate\",\"PartnerPlay\",\"PartnerRegistrationDisplaySettings\",\"PartnerRequirement\",\"PartnerSafeHeartbeatTelemetry\",\"PartnerSelfPromoAd\",\"PartnerSelfPromoCreate\",\"PartnerSelfPromoPlacement\",\"PartnerStats\",\"PayoutResponse\",\"PlaygroundResult\",\"PlaygroundValidationError\",\"ProgrammaticSettingsInput\",\"ProgrammaticSettingsResponse\",\"RequestMetadataResponse\",\"ResolvedContentPolicy\",\"ResolvedSensingConfig\",\"RolePermissions\",\"SDKConfig\",\"Screen\",\"ScreenAnalyticsResponse\",\"ScreenGroup\",\"ScreenGroupContentPolicy\",\"ScreenGroupContentPolicyInput\",\"ScreenGroupEvent\",\"ScreenGroupSensingConfig\",\"ScreenGroupSensingConfigInput\",\"SensingPerformanceMode\",\"SensingRoute\",\"SensingRouteAction\",\"SensingRouteCondition\",\"SensingSettingsResponse\",\"SensingThresholdCrossedEvent\",\"SsdpDeviceInfo\",\"TeamInviteResponse\",\"TeamMember\",\"Transaction\",\"UpdatePartnerSensingRouteRequest\",\"VastWaterfall\",\"VastWaterfallSource\",\"Webhook\",\"WebhookDelivery\",\"WebhookEvent\",\"WifiEnvironmentSnapshot\",\"WifiScanResult\"] as const,\n operations: [\"listPartnerSelfPromoAds\",\"createPartnerSelfPromoAd\",\"listPartnerSelfPromoPlacements\",\"schedulePartnerSelfPromo\",\"createPartnerSelfPromoUpload\",\"disableSelfPromoAd\",\"registerAgent\",\"getAnalytics\",\"getAudienceContinuity\",\"getAudienceProfile\",\"getBleSummary\",\"getContentPerformance\",\"searchCreativeCatalog\",\"getCreativeScenes\",\"getCrossScreenFlow\",\"getPartnerAnalyticsDashboard\",\"getDeviceSuiteSignature\",\"exportPartnerAnalytics\",\"exportPartnerAdsByDay\",\"getFleetHourly\",\"getHaloFunnel\",\"getLoyaltyClock\",\"getNetworkSummary\",\"getNetworkTrend\",\"getProximitySummary\",\"getRevenueAttentionCorrelation\",\"getSceneFeed\",\"getSceneIntelligence\",\"rotateApiKey\",\"getAudienceAnalytics\",\"exportAudienceData\",\"getAudienceHeatmap\",\"getLiveAudience\",\"getLookalikeScreens\",\"predictScreenAudience\",\"getResolvedHouseholdReach\",\"listAudienceSegments\",\"createAudienceSegment\",\"deleteAudienceSegment\",\"getAudienceSegment\",\"updateAudienceSegment\",\"matchAudienceSegment\",\"estimateSegmentReach\",\"generateSegmentVastTag\",\"getAudienceStats\",\"cancelBillingSubscription\",\"purchaseCredits\",\"createCreditCheckout\",\"listBillingPlans\",\"setupBilling\",\"createBillingSubscription\",\"getBillingSubscription\",\"getBillingUsage\",\"getBillingUsageSummary\",\"stripeWebhookCallback\",\"getConnectDashboard\",\"getConnectEarningsChart\",\"getConnectScreenHealth\",\"listContentPresets\",\"getContentPreset\",\"submitPartnerCreative\",\"getPartnerCreative\",\"getDashboard\",\"exportProximityGraphEdges\",\"getDataExportSummary\",\"exportDataset\",\"getGeohashAudiencePanel\",\"getOutcomeAttribution\",\"registerDevice\",\"deleteDevice\",\"getDevice\",\"updateDevice\",\"getAdsForDevice\",\"ackDeviceCommand\",\"getDeviceHeartbeat\",\"heartbeat\",\"recordProgrammaticEvent\",\"listDevices\",\"registerDeviceV2\",\"registerDevicesBatch\",\"batchUpdateDeviceOrientation\",\"reconcileDevices\",\"partnerDocsBrowser\",\"getEarnings\",\"getEarningsBreakdown\",\"requestPayout\",\"getTransactions\",\"getActiveSSEConnections\",\"subscribeToEvents\",\"getFleetCommand\",\"getFleetAnalytics\",\"pushFleetCommand\",\"getFleetOverview\",\"updateFleetSettings\",\"recordImpressionGet\",\"recordImpressionPost\",\"recordImpressionsBatch\",\"getPartnerInfo\",\"listIntentCategories\",\"getIntentCategory\",\"getIntentPricing\",\"getMeasurementMethodology\",\"getMeasurementMethodologyJson\",\"getNetworkConfig\",\"patchNetworkConfig\",\"updateNetworkConfig\",\"getNetworkTrends\",\"partnerPing\",\"partnerPingAuth\",\"recordPartnerPlay\",\"recordPartnerPlaysBatch\",\"getPricing\",\"recordProgrammaticEventLegacyAlias\",\"quickStart\",\"registerPartner\",\"generateSandboxEvent\",\"resetSandbox\",\"createSandboxScreen\",\"getSandboxStatus\",\"listScreenGroups\",\"createScreenGroup\",\"deleteScreenGroup\",\"getScreenGroup\",\"updateScreenGroup\",\"getScreenGroupAnalytics\",\"createScreenGroupCommand\",\"getScreenGroupContentPolicy\",\"updateScreenGroupContentPolicy\",\"removeScreenGroupMembers\",\"listScreenGroupMembers\",\"addScreenGroupMembers\",\"getScreenGroupSensingConfig\",\"updateScreenGroupSensingConfig\",\"getScreenAudienceSegments\",\"batchUpdateContentPreferences\",\"batchUpdateDisplaySettings\",\"batchUpdateProgrammaticSettings\",\"resolvePartnerScreen\",\"getScreenAnalytics\",\"getPartnerScreenAtmosphere\",\"getPartnerScreenIntelligence\",\"getPartnerScreenTasteProfile\",\"getPartnerScreenTraffic\",\"getPartnerScreenVAS\",\"applyContentPreset\",\"getAudienceMetrics\",\"getContentPreferences\",\"patchContentPreferences\",\"updateContentPreferences\",\"listPartnerDefaultStreams\",\"createPartnerDefaultStream\",\"createPartnerDefaultStreamImages\",\"reorderPartnerDefaultStreams\",\"createPartnerDefaultStreamUpload\",\"deletePartnerDefaultStream\",\"updatePartnerDefaultStream\",\"getScreenDemographics\",\"getDisplaySettings\",\"patchDisplaySettings\",\"updateDisplaySettings\",\"getPartnerLBarSettings\",\"updatePartnerLBarSettings\",\"updatePartnerLBarLiveUpdates\",\"getProgrammaticSettings\",\"patchProgrammaticSettings\",\"updateProgrammaticSettings\",\"getResolvedContentPolicy\",\"getResolvedSensingConfig\",\"getScreenSensingChips\",\"interpretScreenSensingIntent\",\"deployScreenSensingProfile\",\"getScreenSensingSettings\",\"updateScreenSensingSettings\",\"listPartnerSensingRoutes\",\"createPartnerSensingRoute\",\"deletePartnerSensingRoute\",\"getPartnerSensingRoute\",\"updatePartnerSensingRoute\",\"createStripeConnectAccount\",\"getStripeLoginLink\",\"getStripeOnboardingLink\",\"requestStripePayout\",\"getStripePayoutHistory\",\"getStripeAccountStatus\",\"handleStripeWebhook\",\"listTeamMembers\",\"acceptInvitation\",\"inviteTeamMember\",\"getInvitationByToken\",\"resendInvitation\",\"removeTeamMember\",\"changeTeamMemberRole\",\"getTrackingPublicKey\",\"recordTrackingBatch\",\"getUsageSummary\",\"getUsageDashboard\",\"getRateLimitStatus\",\"queryChangelog\",\"playgroundDryRun\",\"getRequestMetadata\",\"getVastConfig\",\"getVenuesNearby\",\"getVenueAtmosphere\",\"getVenueTraffic\",\"getVenueIntelligence\",\"listWebhooks\",\"createWebhook\",\"deleteWebhook\",\"updateWebhook\",\"getWebhookDeliveries\",\"testWebhook\"] as const,\n} as const;\n\nexport type GeneratedSchemaName = (typeof generatedTypes.schemas)[number];\nexport type GeneratedOperationName = (typeof generatedTypes.operations)[number];\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/generated/index.ts"],"names":[],"mappings":";;;AAw7NO,IAAM,cAAA,GAAiB;AAAA,EAC5B,WAAA,EAAa,GAAA;AAAA,EACb,cAAA,EAAgB,GAAA;AAAA,EAChB,OAAA,EAAS,CAAC,IAAA,EAAK,YAAA,EAAa,qBAAA,EAAsB,iBAAgB,2BAAA,EAA4B,6BAAA,EAA8B,cAAA,EAAe,wBAAA,EAAyB,4BAAA,EAA6B,yBAAA,EAA0B,mBAAkB,yBAAA,EAA0B,aAAA,EAAc,aAAA,EAAc,mBAAA,EAAoB,gBAAA,EAAiB,mBAAA,EAAoB,oBAAA,EAAqB,yBAAA,EAA0B,4BAAA,EAA6B,eAAA,EAAgB,kCAAA,EAAmC,wBAAA,EAAyB,mBAAA,EAAoB,2BAAA,EAA4B,wBAAuB,QAAA,EAAS,yBAAA,EAA0B,eAAA,EAAgB,sBAAA,EAAuB,yBAAA,EAA0B,2BAAA,EAA4B,gBAAe,kBAAA,EAAmB,OAAA,EAAQ,YAAA,EAAa,kBAAA,EAAmB,cAAA,EAAe,mBAAA,EAAoB,yBAAwB,iBAAA,EAAkB,YAAA,EAAa,mBAAA,EAAoB,wBAAA,EAAyB,YAAA,EAAa,SAAA,EAAU,0BAAA,EAA2B,yBAAA,EAA0B,sBAAA,EAAuB,4BAAA,EAA6B,4BAAA,EAA6B,qCAAA,EAAsC,4BAAA,EAA6B,gCAAA,EAAiC,2BAA0B,sBAAA,EAAuB,qCAAA,EAAsC,2BAAA,EAA4B,+BAAA,EAAgC,yBAAA,EAA0B,0BAAA,EAA2B,6BAA4B,oBAAA,EAAqB,+BAAA,EAAgC,qBAAA,EAAsB,iCAAA,EAAkC,sBAAA,EAAuB,4BAAA,EAA6B,eAAc,oCAAA,EAAqC,oBAAA,EAAqB,+BAAA,EAAgC,oBAAA,EAAqB,wBAAA,EAAyB,2BAAA,EAA4B,cAAA,EAAe,gBAAA,EAAiB,kBAAA,EAAmB,2BAAA,EAA4B,2BAAA,EAA4B,8BAAA,EAA+B,yBAAA,EAA0B,uBAAA,EAAwB,yBAAwB,iBAAA,EAAkB,WAAA,EAAY,QAAA,EAAS,yBAAA,EAA0B,aAAA,EAAc,0BAAA,EAA2B,+BAAA,EAAgC,kBAAA,EAAmB,0BAAA,EAA2B,+BAAA,EAAgC,wBAAA,EAAyB,cAAA,EAAe,oBAAA,EAAqB,uBAAA,EAAwB,2BAA0B,8BAAA,EAA+B,gBAAA,EAAiB,oBAAA,EAAqB,YAAA,EAAa,aAAA,EAAc,kCAAA,EAAmC,eAAA,EAAgB,qBAAA,EAAsB,SAAA,EAAU,iBAAA,EAAkB,cAAA,EAAe,yBAAA,EAA0B,gBAAgB,CAAA;AAAA,EAC79E,UAAA,EAAY,CAAC,yBAAA,EAA0B,0BAAA,EAA2B,kCAAiC,0BAAA,EAA2B,8BAAA,EAA+B,oBAAA,EAAqB,eAAA,EAAgB,cAAA,EAAe,uBAAA,EAAwB,sBAAqB,eAAA,EAAgB,uBAAA,EAAwB,uBAAA,EAAwB,mBAAA,EAAoB,oBAAA,EAAqB,8BAAA,EAA+B,2BAA0B,wBAAA,EAAyB,uBAAA,EAAwB,gBAAA,EAAiB,eAAA,EAAgB,iBAAA,EAAkB,mBAAA,EAAoB,mBAAkB,qBAAA,EAAsB,gCAAA,EAAiC,gBAAe,sBAAA,EAAuB,cAAA,EAAe,wBAAuB,oBAAA,EAAqB,oBAAA,EAAqB,iBAAA,EAAkB,qBAAA,EAAsB,uBAAA,EAAwB,2BAAA,EAA4B,wBAAuB,uBAAA,EAAwB,uBAAA,EAAwB,oBAAA,EAAqB,uBAAA,EAAwB,sBAAA,EAAuB,sBAAA,EAAuB,0BAAyB,kBAAA,EAAmB,2BAAA,EAA4B,iBAAA,EAAkB,sBAAA,EAAuB,kBAAA,EAAmB,cAAA,EAAe,6BAA4B,wBAAA,EAAyB,iBAAA,EAAkB,0BAAyB,uBAAA,EAAwB,qBAAA,EAAsB,2BAA0B,wBAAA,EAAyB,oBAAA,EAAqB,kBAAA,EAAmB,uBAAA,EAAwB,oBAAA,EAAqB,cAAA,EAAe,6BAA4B,sBAAA,EAAuB,eAAA,EAAgB,yBAAA,EAA0B,uBAAA,EAAwB,gBAAA,EAAiB,cAAA,EAAe,aAAY,cAAA,EAAe,iBAAA,EAAkB,kBAAA,EAAmB,oBAAA,EAAqB,WAAA,EAAY,yBAAA,EAA0B,eAAc,kBAAA,EAAmB,sBAAA,EAAuB,gCAA+B,kBAAA,EAAmB,oBAAA,EAAqB,eAAc,sBAAA,EAAuB,eAAA,EAAgB,iBAAA,EAAkB,yBAAA,EAA0B,mBAAA,EAAoB,iBAAA,EAAkB,qBAAoB,kBAAA,EAAmB,kBAAA,EAAmB,qBAAA,EAAsB,qBAAA,EAAsB,sBAAA,EAAuB,wBAAA,EAAyB,kBAAiB,sBAAA,EAAuB,mBAAA,EAAoB,kBAAA,EAAmB,2BAAA,EAA4B,+BAAA,EAAgC,kBAAA,EAAmB,sBAAqB,qBAAA,EAAsB,kBAAA,EAAmB,eAAc,iBAAA,EAAkB,mBAAA,EAAoB,2BAA0B,YAAA,EAAa,oCAAA,EAAqC,YAAA,EAAa,iBAAA,EAAkB,sBAAA,EAAuB,cAAA,EAAe,uBAAsB,kBAAA,EAAmB,kBAAA,EAAmB,mBAAA,EAAoB,mBAAA,EAAoB,gBAAA,EAAiB,mBAAA,EAAoB,2BAA0B,0BAAA,EAA2B,6BAAA,EAA8B,gCAAA,EAAiC,0BAAA,EAA2B,wBAAA,EAAyB,uBAAA,EAAwB,+BAA8B,gCAAA,EAAiC,2BAAA,EAA4B,iCAAgC,4BAAA,EAA6B,iCAAA,EAAkC,wBAAuB,oBAAA,EAAqB,4BAAA,EAA6B,8BAAA,EAA+B,8BAAA,EAA+B,yBAAA,EAA0B,qBAAA,EAAsB,sBAAqB,oBAAA,EAAqB,uBAAA,EAAwB,yBAAA,EAA0B,0BAAA,EAA2B,2BAAA,EAA4B,4BAAA,EAA6B,oCAAmC,8BAAA,EAA+B,kCAAA,EAAmC,4BAAA,EAA6B,4BAAA,EAA6B,uBAAA,EAAwB,oBAAA,EAAqB,wBAAuB,uBAAA,EAAwB,wBAAA,EAAyB,6BAA4B,8BAAA,EAA+B,yBAAA,EAA0B,6BAA4B,4BAAA,EAA6B,0BAAA,EAA2B,0BAAA,EAA2B,uBAAA,EAAwB,8BAAA,EAA+B,4BAAA,EAA6B,4BAA2B,6BAAA,EAA8B,0BAAA,EAA2B,2BAAA,EAA4B,2BAAA,EAA4B,wBAAA,EAAyB,2BAAA,EAA4B,8BAA6B,oBAAA,EAAqB,yBAAA,EAA0B,qBAAA,EAAsB,wBAAA,EAAyB,wBAAA,EAAyB,qBAAA,EAAsB,mBAAkB,kBAAA,EAAmB,kBAAA,EAAmB,wBAAuB,kBAAA,EAAmB,kBAAA,EAAmB,wBAAuB,sBAAA,EAAuB,qBAAA,EAAsB,iBAAA,EAAkB,mBAAA,EAAoB,oBAAA,EAAqB,gBAAA,EAAiB,oBAAmB,oBAAA,EAAqB,eAAA,EAAgB,iBAAA,EAAkB,oBAAA,EAAqB,iBAAA,EAAkB,sBAAA,EAAuB,gBAAe,eAAA,EAAgB,eAAA,EAAgB,eAAA,EAAgB,sBAAA,EAAuB,aAAa;AAC7sJ","file":"generated.js","sourcesContent":["/* eslint-disable */\n/**\n * AUTO-GENERATED. DO NOT EDIT.\n *\n * Generated from: trillboard-api/docs/openapi/merged/partner-api.json\n * Generator: trillboards-api-client/scripts/generate.js\n *\n * Re-emit via `npm run generate`.\n */\n\n// OpenAPI version: 3.0.3\n// API title: Trillboards Partner API\n// API version: 1.2.0\n// Schema count: 112\n// Operation count: 211\n\n// ─── Component schemas ───────────────────────────────────────────────────\n\nexport type Ad = {\n /** Placement/allocation ID used for delivery accounting, make-goods, and pacing. */\n allocation_id?: string;\n /** Duration in seconds */\n duration?: number;\n /** Advertisement ID */\n id?: string;\n /** Server-generated impression ID that must be echoed when reporting proof-of-play. */\n impression_id?: string;\n /** **Deprecated alias of `tracking.impression_url`.** These two fields are the same string, byte for byte, produced from one value server-side — they are not two different hooks and firing both records the same call twice. Read `tracking.impression_url`; this flat field is retained only for clients that predate the `tracking` object and will be removed once they are off it. */\n impression_url?: string;\n title?: string;\n /** Structured proof-of-play URLs for clients that prefer named tracking hooks over legacy flat fields. **Fire exactly one of `impression_url` / `complete_url` per play.** They resolve to the same endpoint and differ only by the `completed` query parameter, which that endpoint does not act on (see `GET /impression`) — calling both records the play twice. */\n tracking?: {\n /** Call when the ad completes playback/display dwell. This is `impression_url` plus `&completed=true`; the flag is inert server-side, so this is a delivery-accounting call, not proof of play. */\n complete_url?: string;\n /** Call when the ad is presented. Identical to the top-level `impression_url`. */\n impression_url?: string;\n /** **Server-signed proof of play. Present only on owner-billable direct bookings; absent on self-promo, house/QR, demo and fully-delivered placements.** When present, fire it VERBATIM — including the `sig`, `request_id` and `impid` parameters — once the ad has finished playing. Do not rewrite, re-sign, re-order, or drop any query parameter: the signature covers the values and any edit invalidates it. This is the only completion signal on the `data.ads` rail that settles; `complete_url` above is delivery accounting and is not billing-grade. Replays of the same play are collapsed on the SIGNED `request_id`, which carries this serve's `impression_id`. Because it is covered by `sig`, a replay that alters it to claim a fresh dedup key fails verification and records nothing — one served play can settle at most once. Firing it in addition to `complete_url` is correct and does not double-count — they land in different stores. */\n owned_direct_complete_url?: string;\n };\n type?: \"video\" | \"image\";\n /** Media URL (CDN) */\n url?: string;\n};\n\nexport type AdSettings = {\n /** Partner-configured ad rotation cadence in seconds, served from the screen display setting `ad_interval_seconds` when present and legacy display preferences only as fallback. */\n ad_interval?: number;\n content_fit?: ContentFitSettings;\n /** Seconds to display image ads; independent from ad rotation cadence. */\n image_duration?: number;\n max_ads_per_hour?: number;\n overlay_button_text?: string;\n sound_enabled?: boolean;\n};\n\n/**\n * Stateful resettable operating-system advertising identity. Send\n * `available` only with the current OS ID; send `limited`,\n * `consent_denied`, `unavailable`, `unsupported`, or `error` to clear a\n * previously observed identifier. UID2 and hashed email are audience\n * tokens, not OS advertising IDs, and do not belong in this envelope.\n *\n */\nexport type AdvertisingIdentity = {\n expires_at?: string | null;\n /** Present only when status is `available`. */\n id?: string | null;\n /** Resettable OS identifier type. GAID maps to OpenRTB `aaid`. */\n id_type?: \"gaid\" | \"aaid\" | \"afai\" | \"rida\" | \"tifa\" | \"idfa\" | null;\n /** Must be false for `available` and true for `limited`. */\n limit_ad_tracking: boolean | null;\n observed_at: string;\n source: \"google_play_services\" | \"amazon_fire_os\" | \"roku_os\" | \"samsung_tizen\" | \"lg_webos\" | \"apple_platform\" | \"host_supplied\";\n source_version?: string | null;\n status: \"available\" | \"limited\" | \"consent_denied\" | \"unavailable\" | \"unsupported\" | \"error\";\n};\n\n/**\n * Partner analytics summary (`@trillboards/api-client` `AnalyticsData`).\n *\n */\nexport type AnalyticsData = {\n average_cpm: number;\n /** Optional per-screen breakdown. */\n by_screen?: Array<{\n earnings: number;\n impressions: number;\n name: string;\n screen_id: string;\n }>;\n /** Fraction of ad opportunities filled, 0..1. */\n fill_rate: number;\n /** The window this summary covers (e.g. day, week, month). */\n period: string;\n screens_active: number;\n screens_total: number;\n total_earnings: number;\n total_impressions: number;\n};\n\nexport type AudienceAnalyticsResponse = {\n data?: {\n audience?: {\n avg_attention?: number;\n avg_face_count?: number;\n screens_with_data?: number;\n };\n overview?: {\n active_screens?: number;\n avg_impressions_per_screen?: number;\n total_impressions?: number;\n total_screens?: number;\n };\n period?: string;\n timestamp?: string;\n trends?: {\n audience_trend?: \"increasing\" | \"stable\" | \"decreasing\";\n impressions_trend?: \"increasing\" | \"stable\" | \"decreasing\";\n };\n };\n request_id?: string;\n success?: boolean;\n};\n\n/**\n * Backend-derived predictive attention signal + buyer-grade attentive-seconds. 1:1 with audience_metrics. Never null by contract; placeholder on row 1.\n */\nexport type AudienceAttentionPrediction = {\n /** attentive_face_count SMALLINT: distinct viewers meeting the >=1s threshold; the buyer-side CPMA denominator. NEVER NULL. */\n attentive_face_count: number;\n /** attentive_seconds_observed = SUM(per_face[].gaze_seconds >= 1.0), OpenOOH 2024 4.2. NEVER NULL by DDL, so 0.000 means 'no viewer met threshold' ONLY when per_face_observations[] was present. NUMERIC(6,3). */\n attentive_seconds_observed: number;\n /** attentive_seconds_predicted_15s: expected next-15s attentive seconds from per-screen history x attention-weight; bootstrap = linear extrapolation. No global tau. NUMERIC(6,3). */\n attentive_seconds_predicted_15s: number;\n next_state_abs_error?: number | null;\n next_state_attention_forecast?: number | null;\n next_state_attention_realized?: number | null;\n next_state_confidence?: number | null;\n next_state_forecast_at?: string | null;\n next_state_graded_at?: string | null;\n next_state_horizon_minutes?: number | null;\n next_state_method?: string | null;\n next_state_persist_abs_error?: number | null;\n next_state_sample_size?: number | null;\n next_state_xscreen_abs_error?: number | null;\n next_state_xscreen_method?: string | null;\n next_state_xscreen_sample_size?: number | null;\n next_state_xsv_abs_error?: number | null;\n next_state_xsv_sample_size?: number | null;\n /** predicted_attention_next_30s enum {high,medium,low,none}. 'none' is below 'low'; fires when rolling history converges to zero or on a trend down from 'low'. */\n predicted_attention_next_30s: \"high\" | \"medium\" | \"low\" | \"none\";\n /** predicted_disengagement_imminent needs elevated dwell AND a falling trend, so it is unreachable whenever the history vector is empty. A 0% fire rate is a HISTORY-PLUMBING alarm, not a quiet fleet. */\n predicted_disengagement_imminent: boolean;\n prediction_evidence: string;\n};\n\n/**\n * Live/aggregate audience data for a screen\n * (`@trillboards/api-client` `AudienceData`).\n *\n */\nexport type AudienceData = {\n /** Count of attentive viewers in the sample. */\n attention_count: number;\n /** Optional demographic breakdown. */\n demographics?: Record<string, unknown>;\n /** Average dwell time for the sample. */\n dwell_time_avg: number;\n screen_id: string;\n timestamp: string;\n};\n\nexport type AudienceExportResponse = {\n data?: Array<{\n audience?: {\n avg_attention?: number;\n avg_face_count?: number;\n demographics?: Record<string, unknown>;\n income_profile?: Record<string, unknown>;\n lifestyle_segments?: Array<string>;\n };\n country?: string;\n impressions?: number;\n location?: string;\n period?: {\n end?: string;\n start?: string;\n };\n screen_id?: string;\n screen_name?: string;\n }>;\n request_id?: string;\n success?: boolean;\n summary?: {\n aggregation?: string;\n period?: Record<string, unknown>;\n total_impressions?: number;\n total_screens?: number;\n };\n};\n\n/**\n * Per-device cross-day loyalty feature row emitted by the\n * `audience_loyalty_features` dataset. Keyed by a partner-scoped\n * pseudonymous ID — the same physical device yields a different ID\n * for each partner because the HMAC salt is partner-specific\n * (`partner_salt` on `platform_api_keys`).\n *\n */\nexport type AudienceLoyaltyFeaturesRow = {\n _match_disclosure?: {\n match_confidence?: \"high\" | \"medium\" | \"low\";\n primary_signal_source?: \"ble_continuity\" | \"ble_mac_stable\" | \"mdns_vendor_model\" | \"fixed_mac\";\n };\n demographic_inference?: {\n age_bracket?: string;\n attention_score_avg?: number;\n audience_attire_archetype?: string;\n audience_group_composition?: string;\n audience_intent_stage?: string;\n gender_distribution?: Record<string, unknown>;\n };\n /** Partner-scoped HMAC of cross-day device key (16 hex chars + tb_ prefix). Different partners get different IDs for the same physical device — preventing collusion. */\n device_id_pseudonymous: string;\n distinct_days_in_window: number;\n distinct_venues_in_window?: number;\n /** Days since this device was first observed at any of the partner-scoped screens. */\n first_seen_relative_days: number;\n last_seen_relative_days: number;\n manufacturer_class: \"premium\" | \"mainstream\" | \"audio_iot\" | \"other\";\n manufacturer_label?: string;\n /** Raw cross-day-stable identifiers when available (NULL for randomized phone MACs without Continuity). */\n raw_identifiers?: {\n ble_mac?: string | null;\n /** First 3 bytes of BLE MAC (IEEE OUI vendor lookup). */\n ble_mac_oui?: string | null;\n ble_mac_oui_vendor?: string | null;\n manufacturer_company_id?: number | null;\n mdns_hostname?: string | null;\n wifi_bssid?: string | null;\n };\n top_day_of_week?: number;\n top_hour_of_day?: number;\n /** List of venue_category labels (Bar, Restaurant, etc.) the device was observed at. */\n venue_archetypes?: Array<string>;\n visit_count_in_window: number;\n};\n\nexport type AudienceMetricsResponse = {\n data?: {\n aggregated?: {\n avgAttention?: number;\n avgDwellMs?: number;\n avgFaceCount?: number;\n groupComposition?: Record<string, unknown>;\n incomeProfile?: {\n high?: number;\n low?: number;\n medium?: number;\n premium?: number;\n };\n };\n history?: Array<Record<string, unknown>>;\n live?: {\n /** Average attention score (0-1) */\n avgAttention?: number;\n /** Average faces detected */\n avgFaceCount?: number;\n incomeLevel?: \"unknown\" | \"low\" | \"medium\" | \"high\" | \"premium\";\n /** Maximum faces detected in period */\n maxFaces?: number;\n mood?: string;\n screenEngagement?: string;\n };\n period?: string;\n screen_id?: string;\n screen_name?: string;\n timestamp?: string;\n };\n request_id?: string;\n success?: boolean;\n};\n\nexport type AudienceSegment = {\n created_at?: string;\n description?: string;\n id?: string;\n is_active?: boolean;\n last_matched_at?: string;\n last_matched_count?: number;\n name?: string;\n object?: string;\n request_id?: string;\n rules?: Array<{\n field?: string;\n operator?: string;\n value?: unknown;\n }>;\n updated_at?: string;\n};\n\n/**\n * Buyer-grade social amplification signal (5 typed columns). Cloud Vertex Gemini producer. 1 row per audience observation when cascade is observable.\n */\nexport type AudienceSocialAttention = {\n amplification_evidence: string;\n cascade_depth: number;\n /** All 5 columns NOT NULL except primary_attention_anchor_face_index (only legit NULL: no anchor or solo scene). */\n primary_attention_anchor_face_index?: number | null;\n /** NUMERIC(4,3). */\n social_amplification_factor: number;\n /** viral_attention_score is the headline number Viant/T-Vision license. Composite of social_amplification_factor × cascade_depth × emotional engagement. NUMERIC(4,3). */\n viral_attention_score: number;\n};\n\nexport type BatchResult = {\n /** Number that failed */\n failed_count?: number;\n failed_screens?: Array<{\n error?: string;\n screen_id?: string;\n }>;\n object?: string;\n request_id?: string;\n /** Number of screens requested to update */\n total_requested?: number;\n /** Number successfully updated */\n updated_count?: number;\n /** IDs of successfully updated screens */\n updated_screens?: Array<string>;\n};\n\n/**\n * Partner billing snapshot — plan, credits, and month-to-date usage\n * (`@trillboards/api-client` `BillingInfo`).\n *\n */\nexport type BillingInfo = {\n credits_remaining: number;\n credits_used: number;\n plan: string;\n /** Whether the partner has a connected Stripe account. */\n stripe_connected: boolean;\n /** Usage counters for the current billing month, keyed by metric. */\n usage_this_month: Record<string, number>;\n};\n\nexport type BleScanResultData = {\n appleContinuitySubtype?: number | null;\n deviceType?: number | null;\n ibeaconMajor?: number | null;\n ibeaconMinor?: number | null;\n ibeaconUuid?: string | null;\n manufacturerCompanyId?: number | null;\n rawAddress: string;\n rssi: number;\n serviceUuids?: Array<string> | null;\n stableManufacturerPayloadHex?: string | null;\n txPowerDbm?: number | null;\n [key: string]: unknown;\n};\n\nexport type ChangelogEntry = {\n /** ISO date string or null for unreleased */\n date: string | null;\n /** Human-readable change description */\n description: string;\n /** API surface: data, sdk, device, sensing, openrtb, partner, all */\n surface: string;\n /** Keepachangelog type: added, changed, deprecated, removed, fixed, security */\n type: string;\n /** \"unreleased\" or a date like \"2026-04-16\" */\n version: string;\n};\n\nexport type ChangelogResponse = {\n /** Matching changelog entries */\n data: Array<ChangelogEntry>;\n /** Always \"list\" */\n object: \"list\";\n /** Number of entries returned */\n total: number;\n};\n\n/**\n * Per-content-type sizing returned and accepted by the Partner API.\n * `fit` preserves the entire creative and may letterbox; `fill` covers\n * the screen and may crop edges. Omitting this object from a write leaves\n * the screen's current behavior unchanged.\n *\n */\nexport type ContentFitSettings = {\n /** Sizing for direct and programmatic advertisements. */\n advertisements?: \"fit\" | \"fill\";\n /** Sizing for default/background streams. */\n default_streams?: \"fit\" | \"fill\";\n /** Sizing for self-promotion and QR-code house ads. */\n self_promo?: \"fit\" | \"fill\";\n};\n\nexport type ContentPreferencesInput = {\n /** Specific advertiser IDs to block */\n blocked_advertisers?: Array<string>;\n /** Ad categories to block (e.g., \"alcohol\", \"gambling\", \"adult\") */\n blocked_categories?: Array<string>;\n /** Max times same ad can show per hour */\n max_ad_frequency?: number;\n /** Minimum ad content rating */\n min_ad_rating?: \"G\" | \"PG\" | \"PG-13\" | \"R\";\n /** Preferred ad categories (prioritized in auctions) */\n preferred_categories?: Array<string>;\n};\n\nexport type ContentPreferencesResponse = {\n blocked_advertisers?: Array<string>;\n blocked_categories?: Array<string>;\n max_ad_frequency?: number;\n min_ad_rating?: string;\n object?: string;\n preferred_categories?: Array<string>;\n request_id?: string;\n screen_id?: string;\n updated_at?: string;\n};\n\nexport type ContentPreset = {\n /** Advertiser IDs blocked */\n blocked_advertisers?: Array<string>;\n /** Categories blocked by this preset */\n blocked_categories?: Array<string>;\n /** Preset description */\n description?: string;\n /** Unique preset identifier */\n id?: string;\n /** Minimum ad rating allowed */\n min_ad_rating?: \"G\" | \"PG\" | \"PG-13\" | \"R\";\n /** Human-readable preset name */\n name?: string;\n /** Full preference object applied by this preset */\n preferences?: Record<string, unknown>;\n};\n\nexport type CreatePartnerSensingRouteRequest = {\n actions: Array<SensingRouteAction>;\n activeDaysMask?: number;\n activeEndMinute?: number;\n activeStartMinute?: number;\n activeTz?: string;\n condition?: SensingRouteCondition;\n debounceSeconds?: number;\n /** Required when mode=digest. `field` is required for avg/max. */\n digest?: {\n field?: string;\n intervalMinutes?: number;\n metric?: \"count\" | \"avg\" | \"max\";\n windowMinutes?: number;\n };\n enabled?: boolean;\n mode?: \"threshold\" | \"digest\";\n name: string;\n /** Bind to a named Sense Anything profile (stable across redeploys). */\n profileName?: string;\n /** Screens to watch — all owned by this partner (foreign → 403). Provide EITHER screenMongoIds OR targetGroupId, not both. */\n screenMongoIds?: Array<string>;\n /** DEPRECATED and rejected on write with 400. A duration expressed as N readings inside a fixed window can only be satisfied by a screen reporting faster than window/(N-1) seconds, and nothing knows that rate when the route is saved - so the route saves cleanly and then never fires at all. Send sustainSeconds instead. Still honoured for rows that already carry it. */\n sustainMinSamples?: number;\n /** How long the condition must hold before the FIRST alert, in seconds (600 = ten minutes). Omit to alert on the first true reading. Cadence-independent, because the evaluator compares timestamps - correct however often the screen reports, including when that rate changes while the condition holds. */\n sustainSeconds?: number;\n /** DEPRECATED and rejected on write with 400. A duration expressed as N readings inside a fixed window can only be satisfied by a screen reporting faster than window/(N-1) seconds, and nothing knows that rate when the route is saved - so the route saves cleanly and then never fires at all. Send sustainSeconds instead. Still honoured for rows that already carry it. */\n sustainWindowSeconds?: number;\n /** A sg_ Screen Group id (owned by this partner) to target instead of an explicit screen set. The route fires on the group's live members. Requires SENSING_ROUTES_GROUP_TARGET_ENABLED. */\n targetGroupId?: string;\n};\n\n/**\n * Structured creative classification — the same shape the Trillboards venue portal renders for a served ad.\n */\nexport type CreativeClassification = {\n advertiser_name?: string | null;\n /** One of G, PG, PG-13, R, NC-17 (null until classified). */\n age_rating?: string | null;\n analysis?: {\n keywords?: Array<string>;\n mood?: string | null;\n quality?: string | null;\n setting?: string | null;\n subjects?: Array<string>;\n /** On-screen text (OCR). */\n text_content?: string | null;\n };\n categorization?: {\n brand?: string | null;\n category?: string | null;\n iab_categories?: Array<string>;\n };\n /** Classification confidence, 0..1. */\n confidence?: number | null;\n content_sha256?: string;\n /** Canonical reference — `sha256:<hex>` of the creative bytes. Use as `creative_ref` when posting plays. */\n id?: string;\n moderation?: {\n approved?: boolean;\n flags?: Array<string>;\n };\n object?: string;\n status?: \"pending\" | \"approved\" | \"flagged\" | \"blocked\";\n thumbnail_url?: string | null;\n};\n\nexport type DashboardResponse = {\n earnings?: {\n available_payout_cents?: number;\n next_payout_date?: string;\n pending_payout_cents?: number;\n revenue_share_percent?: number;\n total_earned_cents?: number;\n };\n partner?: {\n created_at?: string;\n name?: string;\n slug?: string;\n status?: \"pending\" | \"active\" | \"suspended\" | \"terminated\";\n };\n recent_activity?: Array<{\n ad_id?: string;\n screen_id?: string;\n timestamp?: string;\n type?: string;\n }>;\n stats?: {\n active_screens?: number;\n offline_screens?: number;\n pending_screens?: number;\n total_impressions_month?: number;\n total_impressions_today?: number;\n total_impressions_week?: number;\n total_screens?: number;\n };\n stripe_status?: {\n account_status?: string;\n connect_account_id?: string;\n };\n top_screens?: Array<{\n impressions_today?: number;\n location?: string;\n name?: string;\n screen_id?: string;\n }>;\n};\n\n/**\n * Per-dataset record counts + date ranges for the partner's screens.\n * Returned by `GET /data-export/summary`.\n *\n */\nexport type DataExportSummaryResponse = {\n data?: {\n /** Map of dataset name to record summary */\n datasets?: Record<string, {\n earliest?: string | null;\n latest?: string | null;\n total_records?: number;\n }>;\n k_anonymity_threshold?: number;\n lookback_days?: number;\n screen_count?: number;\n };\n success?: boolean;\n};\n\nexport type DemographicsResponse = {\n data?: {\n data_quality?: {\n confidence?: number;\n sample_size?: number;\n };\n demographics?: {\n age_distribution?: {\n \"18-25\"?: number;\n \"26-35\"?: number;\n \"36-50\"?: number;\n \"50+\"?: number;\n };\n gender_split?: {\n female?: number;\n male?: number;\n };\n group_composition?: {\n couples?: number;\n families?: number;\n friends?: number;\n solo?: number;\n work_groups?: number;\n };\n income_profile?: {\n high?: number;\n low?: number;\n medium?: number;\n premium?: number;\n };\n lifestyle_segments?: Array<string>;\n };\n period?: string;\n screen_id?: string;\n screen_name?: string;\n timestamp?: string;\n };\n request_id?: string;\n success?: boolean;\n};\n\nexport type Device = {\n created_at?: string;\n device_id?: string;\n device_type?: string;\n /** Screen display specification. `width`/`height` are pixel resolution; `width_in`/`height_in` are physical inches. Pixel-only inputs are NOT recorded as physical size — pass `width_in`/`height_in` (most accurate) or `ppi` so the server can derive inches from pixels. */\n display?: {\n /** Display resolution height in pixels */\n height?: number;\n /** Physical screen height in inches */\n height_in?: number;\n orientation?: string;\n /** Pixels per inch (required to derive physical size from width/height) */\n ppi?: number;\n /** Display resolution width in pixels */\n width?: number;\n /** Physical screen width in inches */\n width_in?: number;\n };\n embed_url?: string;\n enrichment?: Record<string, unknown>;\n external_device_id?: string;\n fingerprint?: string;\n location?: Record<string, unknown>;\n name?: string;\n screen_id?: string;\n status?: \"pending\" | \"active\" | \"offline\" | \"suspended\";\n updated_at?: string;\n venue?: Record<string, unknown>;\n};\n\nexport type DeviceCapabilityPayload = {\n agentType?: string | null;\n agentVersion?: string | null;\n audienceSensing?: {\n cameraAvailable?: boolean | null;\n cameraCount?: number | null;\n cameraHealth?: {\n lastFailureClass?: string | null;\n lastFailureMessage?: string | null;\n lastFrameAtMs?: number | null;\n retryCount?: number | null;\n state?: string | null;\n [key: string]: unknown;\n } | null;\n cameraType?: string | null;\n microphoneAvailable?: boolean | null;\n sensingMode?: string | null;\n [key: string]: unknown;\n } | null;\n audioControl?: {\n mute?: boolean | null;\n volume?: boolean | null;\n [key: string]: unknown;\n } | null;\n capabilitiesVersion?: number | null;\n environmentSensors?: {\n ambientLight?: boolean | null;\n temperature?: boolean | null;\n [key: string]: unknown;\n } | null;\n inputControl?: {\n appSwitch?: boolean | null;\n hdmi?: boolean | null;\n [key: string]: unknown;\n } | null;\n isDeviceOwner?: boolean | null;\n managementCapabilities?: {\n clearCache?: boolean | null;\n installApk?: boolean | null;\n kioskMode?: boolean | null;\n reboot?: boolean | null;\n restart?: boolean | null;\n screenshot?: boolean | null;\n wipe?: boolean | null;\n [key: string]: unknown;\n } | null;\n mlCapabilities?: {\n availableRamMb?: number | null;\n chipsetName?: string | null;\n chipsetVendor?: string | null;\n cpuAbi?: string | null;\n densityDpi?: number | null;\n gpuDelegateSupported?: boolean | null;\n gpuName?: string | null;\n hasNpu?: boolean | null;\n maxVlmSizeMb?: number | null;\n nnapiSupported?: boolean | null;\n npuName?: string | null;\n osApiLevel?: number | null;\n recommendedModelTier?: string | null;\n screenHeightPx?: number | null;\n screenWidthPx?: number | null;\n totalRamMb?: number | null;\n [key: string]: unknown;\n } | null;\n powerControl?: {\n cec?: boolean | null;\n softBlackout?: boolean | null;\n wol?: boolean | null;\n [key: string]: unknown;\n } | null;\n wifiCsiSensing?: {\n csiAvailable?: boolean | null;\n csiHardwareType?: string | null;\n csiNodeCount?: number | null;\n [key: string]: unknown;\n } | null;\n [key: string]: unknown;\n};\n\nexport type DeviceSummary = {\n created_at?: string;\n device_id?: string;\n device_type?: string;\n display?: Record<string, unknown>;\n embed_url?: string;\n enrichment?: Record<string, unknown>;\n external_device_id?: string;\n fingerprint?: string;\n location?: Record<string, unknown>;\n name?: string;\n screen_id?: string;\n status?: string;\n updated_at?: string;\n venue?: Record<string, unknown>;\n};\n\nexport type DisplaySettingsInput = {\n /** Default ad duration in seconds */\n ad_duration_default?: number;\n /** Screen brightness percentage */\n brightness?: number;\n content_fit?: ContentFitSettings;\n /** Ad display mode */\n display_mode?: \"fullscreen\" | \"l-bar\" | \"split\";\n /** What to show when no ads */\n idle_content?: \"default_stream\" | \"black\" | \"logo\";\n /** Mute audio */\n mute?: boolean;\n /** Screen orientation */\n orientation?: \"landscape\" | \"portrait\" | \"auto\";\n /** QR code position on screen */\n qr_code_position?: \"bottom-left\" | \"bottom-right\" | \"top-left\" | \"top-right\" | \"none\";\n /** Transition effect between ads */\n transition_effect?: \"fade\" | \"slide\" | \"none\";\n /** Audio volume percentage */\n volume?: number;\n};\n\nexport type DisplaySettingsResponse = {\n ad_duration_default?: number;\n ad_surfaces?: Array<{\n height_percent?: number;\n id?: string;\n position?: string;\n width_percent?: number;\n }>;\n brightness?: number;\n content_fit?: ContentFitSettings;\n display_mode?: string;\n idle_content?: string;\n mute?: boolean;\n object?: string;\n orientation?: string;\n playback_policy?: {\n allow_skip?: boolean;\n max_duration_seconds?: number;\n min_break_between_ads?: number;\n };\n qr_code_position?: string;\n request_id?: string;\n screen_id?: string;\n transition_effect?: string;\n updated_at?: string;\n volume?: number;\n};\n\nexport type EarningsBreakdownResponse = {\n breakdown?: Array<{\n /** Date or screen_id depending on group_by */\n date?: string;\n earnings_cents?: number;\n impressions?: number;\n /** Screen ID (when grouped by screen) */\n screen_id?: string;\n }>;\n pending_programmatic?: {\n confirmation_date?: string;\n estimated_cents?: number;\n };\n period?: {\n end?: string;\n group_by?: \"day\" | \"week\" | \"screen\";\n start?: string;\n };\n summary?: {\n direct_cents?: number;\n programmatic_cents?: number;\n total_cents?: number;\n total_impressions?: number;\n };\n};\n\n/**\n * Partner earnings summary with optional daily series\n * (`@trillboards/api-client` `EarningsData`).\n *\n */\nexport type EarningsData = {\n average_cpm: number;\n /** Optional per-day earnings/impressions series. */\n daily?: Array<{\n /** Day label (YYYY-MM-DD). */\n date: string;\n earnings: number;\n impressions: number;\n }>;\n last_payout_amount?: number;\n last_payout_date?: string;\n /** Balance not yet paid out. */\n pending_payout: number;\n period: string;\n total_earnings: number;\n total_impressions: number;\n};\n\nexport type EarningsResponse = {\n /** Amount available for immediate payout */\n available_for_payout_cents?: number;\n breakdown?: {\n direct_campaigns?: number;\n programmatic_floodgates?: number;\n programmatic_google?: number;\n };\n next_payout_estimate?: {\n amount_cents?: number;\n date?: string;\n stripe_status?: string;\n };\n /** Minimum amount required for payout */\n payout_threshold_cents?: number;\n /** Programmatic earnings pending Net-60 confirmation */\n pending_confirmation_cents?: number;\n /** Partner's revenue share percentage */\n revenue_share_percent?: number;\n /** Estimated earnings for current month */\n this_month_cents?: number;\n /** Total earnings since partner started */\n total_lifetime_cents?: number;\n};\n\nexport type Error = {\n error?: string;\n message?: string;\n success?: boolean;\n};\n\n/**\n * A single partner API error-log record\n * (`@trillboards/api-client` `ErrorEntry`) — one logged error occurrence\n * scoped to the partner. Distinct from the public error *catalog* entries\n * (`ErrorListItem` / `ErrorCodeResponse`), which describe error codes in\n * the abstract.\n *\n */\nexport type ErrorEntry = {\n /** Stable machine error code (e.g. not_found). */\n code: string;\n doc_url: string;\n /** The API path that produced the error. */\n endpoint: string;\n id: string;\n message: string;\n /** The HTTP method of the failing request. */\n method: string;\n /** The request parameter the error concerns, if any. */\n param?: string;\n request_id: string;\n timestamp: string;\n /** Stripe-style error taxonomy (matches the SDK's ApiErrorType). */\n type: \"invalid_request_error\" | \"authentication_error\" | \"permission_error\" | \"rate_limit_error\" | \"idempotency_error\" | \"api_error\";\n};\n\n/**\n * Exact DSP-matchable audience identity kept separate from the resettable\n * OS advertising ID. `hem_sha256` is an existing SHA-256 digest: send it\n * directly (the server lowercases hexadecimal once and never hashes it\n * again). `uid2_token` is an opaque, case-sensitive UID2 advertising\n * token: send it exactly as issued and include `expires_at` so it can be\n * refreshed; tokens contain no whitespace. Use `unavailable` with no\n * `id` to clear a prior value.\n *\n */\nexport type ExtendedIdentity = {\n /** OpenRTB person-based identifier type. */\n atype: 3;\n expires_at?: string | null;\n id?: string | null;\n id_type: \"hem_sha256\" | \"uid2_token\";\n observed_at: string;\n /** Canonical top-level domain for this identity system. */\n source: string;\n source_version?: string | null;\n status: \"available\" | \"unavailable\";\n};\n\n/**\n * A fleet-command job: one batch that fanned a device command across a screen group's\n * members. Poll via GET /fleet-commands/{id}.\n *\n */\nexport type FleetCommand = {\n command_type?: string;\n completed_at?: string | null;\n created_at?: string;\n error?: string | null;\n /** Screens that could not be enqueued */\n failed?: number;\n group_id?: string | null;\n /** Job id (fc_ prefix). */\n id?: string;\n object?: string;\n /** Screens the command was enqueued to */\n queued?: number;\n results?: Array<{\n device_command_id?: string | null;\n error?: string | null;\n screen_id?: string;\n status?: \"queued\" | \"failed\";\n }>;\n status?: \"queued\" | \"running\" | \"completed\" | \"failed\";\n /** Member screens resolved for this command */\n targeted?: number;\n updated_at?: string;\n};\n\n/**\n * Webhook body for a group fleet-command terminal state (`fleet_command.completed` |\n * `fleet_command.failed`). Standard `{ id, event, timestamp, data }` envelope; `data` is the\n * `fleet_command` job object (status, targeted/queued/failed counts, per-screen results; on\n * failure, an `error` message). The event type is also in the `X-Trillboards-Event` header —\n * verify the compound `X-Trillboards-Signature` over the raw body first.\n *\n */\nexport type FleetCommandEvent = {\n /** The fleet_command job object. */\n data?: Record<string, unknown>;\n event?: \"fleet_command.completed\" | \"fleet_command.failed\";\n id?: string;\n timestamp?: string;\n};\n\n/**\n * Programmatic header-bidding configuration and the resolved VAST waterfall for the screen. The `vast_waterfall.sources[]` array is the programmatic demand path — fetch each source's `vast_url` in priority order and hand the returned VAST to your IMA SDK. Source names are opaque public aliases. Source-health request-pressure governance does not remove SQL/Admin-enabled sources from this catalog.\n *\n */\nexport type HeaderBiddingSettings = {\n ad_buffering?: {\n enabled?: boolean;\n max_buffer?: number;\n max_cache_age_seconds?: number;\n min_buffer?: number;\n warmup_count?: number;\n } | null;\n ad_pod?: Record<string, unknown> | null;\n allocation?: number;\n auction_request_id?: string;\n enabled?: boolean;\n experiment_variant?: string | null;\n fast_loop?: Record<string, unknown> | null;\n fetch_mode?: string | null;\n force_request?: boolean;\n ima_profile?: Record<string, unknown> | null;\n min_interval_seconds?: number;\n prebid?: Record<string, unknown> | null;\n provider?: string;\n regional_config?: {\n ad_buffer_percentage?: number;\n enable_network_adaptation?: boolean;\n fallback_timeout_ms?: number;\n preferred_resolution?: string;\n timeout_ms?: number;\n vquality?: string;\n } | null;\n /** Per-request waterfall identifier; echo it back on programmatic-event reports. */\n request_id?: string;\n request_mode?: string;\n source_name?: string | null;\n source_priority?: number | null;\n variant_name?: string;\n vast_cache?: {\n enabled?: boolean;\n priority?: string;\n ttl_seconds?: number;\n } | null;\n vast_tag_url?: string;\n vast_waterfall?: VastWaterfall;\n} | null;\n\nexport type HttpProbeResult = {\n host: string;\n port?: number | null;\n server?: string | null;\n [key: string]: unknown;\n};\n\n/**\n * A recorded ad impression / play for a partner screen\n * (`@trillboards/api-client` `Impression`).\n *\n */\nexport type Impression = {\n /** Kind of ad served (e.g. direct, programmatic, self_promo). */\n ad_type?: string;\n advertiser_name?: string;\n /** Effective CPM for the impression, in the partner's currency. */\n cpm?: number;\n device_id: string;\n /** Play duration in seconds. */\n duration_seconds?: number;\n /** Earner revenue accrued for the impression. */\n earnings?: number;\n impression_id: string;\n played_at: string;\n screen_id: string;\n};\n\nexport type MdnsNetworkDevice = {\n host?: string | null;\n instanceName: string;\n mdnsModel?: string | null;\n mdnsSoftwareVersion?: string | null;\n mdnsVendor?: string | null;\n port?: number | null;\n serviceType: string;\n [key: string]: unknown;\n};\n\n/**\n * Versioned public disclosure of how audience measurement is produced.\n * Describes WHAT is measured and HOW IT IS QUALIFIED — deliberately never\n * names infrastructure or source locations.\n *\n */\nexport type MeasurementMethodology = {\n canonical_path?: string;\n /** What each screen observes and what is dropped at the edge. */\n capture_stack?: Record<string, unknown>;\n /** Cross-day identity, including measured coverage (1.6% of identifiable BLE rows). An earlier revision said ~31%; that graded the presence of stable_payload_hash and ignored the sanitizer the identity expression applies, and it is withdrawn. */\n cross_day_matching?: Record<string, unknown>;\n display_exposure_zone?: Record<string, unknown>;\n dwell_qualification_thresholds?: Record<string, unknown>;\n edge_confidence_model?: Record<string, unknown>;\n /** Evidence grades, which are decisionable, and person-grain resolution. */\n evidence_grade_ladder: Record<string, unknown>;\n fallback_path?: string;\n /** How identifiers are keyed, and what erasure means. */\n hashing?: Record<string, unknown>;\n /** The counting UNIT. Reach and unique-device counts are counts of BLE identifiers, not devices and not people; one device contributes several identifiers per window and the number grows with the window. Carries the measured identifiers-per-device per fleet type and the controlled comparison it was derived from. */\n identifier_inflation?: Record<string, unknown>;\n mrc_ooh_phase2_alignment: Record<string, unknown>;\n parser_versions?: Record<string, unknown>;\n /** k-anonymity floor and differential-privacy budget. */\n privacy_gates: Record<string, unknown>;\n /** Per-store retention in days. */\n retention: Record<string, unknown>;\n /** Tables a reviewer re-derives every published count from. */\n source_tables: Array<string>;\n /** Bumped on any disclosure change; drives the ETag. */\n version: string;\n};\n\nexport type Pagination = {\n /** Whether more items exist */\n has_more?: boolean;\n /** Items per page */\n limit?: number;\n /** Current offset */\n offset?: number;\n /** Total number of items */\n total?: number;\n};\n\nexport type Partner = {\n integration_tier?: string;\n name?: string;\n partner_id?: string;\n /** Legacy classification retained for existing integrations. New integrations should not branch on this field. */\n partner_type?: string;\n revenue_share_percent?: number;\n sdk_config?: SDKConfig;\n slug?: string;\n stats?: PartnerStats;\n status?: \"pending\" | \"active\" | \"suspended\" | \"terminated\";\n stripe_account_status?: string;\n};\n\nexport type PartnerAdDeliveryProfile = {\n android_api_level?: number | null;\n auto_recovery_enabled?: boolean;\n ima_integration?: \"android_native\" | \"html5_webview\" | \"disabled\" | \"unknown\";\n mode?: \"ima_sdk\" | \"vast_fallback\";\n notes?: Array<string>;\n reason?: string;\n webview_chromium_major?: number | null;\n};\n\n/**\n * Non-fatal advisories about the creative that was just accepted. The ad IS created and will serve — these describe problems only the uploader can fix. Empty when there is nothing to report. The most important one is an over-length video: a spot longer than the 30 second ad slot is cut off when the next ad starts, so it never reaches its completion event and its final seconds are never seen.\n */\nexport type PartnerCreativeWarnings = Array<string>;\n\nexport type PartnerDefaultStream = {\n _id?: string;\n canva_url?: string;\n createdAt?: string;\n description?: string;\n duration_seconds?: number;\n embed_url?: string;\n generic_iframe_url?: string;\n google_slides_url?: string;\n iframe_config?: Record<string, unknown>;\n image_duration?: number;\n images?: Array<string>;\n is_active?: boolean;\n is_currently_playing?: boolean;\n name?: string;\n partner_id?: string;\n playback_order?: number;\n screenId?: string;\n social_wall_url?: string;\n stream_type?: string;\n twitch_url?: string;\n updatedAt?: string;\n video_url?: string;\n youtube_url?: string;\n};\n\nexport type PartnerDefaultStreamCreate = {\n canva_url?: string;\n description?: string;\n /** Optional explicit duration for iframe-based streams */\n duration_seconds?: number;\n embed_url?: string;\n generic_iframe_url?: string;\n google_slides_url?: string;\n iframe_config?: {\n allow_flags?: string;\n auto_advance?: boolean;\n refresh_interval_seconds?: number;\n sandbox_flags?: string;\n slide_delay_ms?: number;\n };\n /** Seconds per image */\n image_duration?: number;\n images?: Array<string>;\n name?: string;\n social_wall_url?: string;\n stream_type?: \"local\" | \"youtube\" | \"uploaded\" | \"images\" | \"twitch\" | \"google_slides\" | \"canva\" | \"social_wall\" | \"generic_iframe\";\n twitch_url?: string;\n video_url?: string;\n youtube_url?: string;\n};\n\nexport type PartnerDefaultStreamUpdate = PartnerDefaultStreamCreate;\n\n/**\n * Batch device-registration body (`@trillboards/api-client`\n * `PartnerDeviceBatchRegistrationInput`) — up to 100 devices with optional\n * fleet-wide `defaults`. `defaults` applies to every device in the batch\n * except the per-device identifier fields (`device_id` / `device_name`).\n *\n */\nexport type PartnerDeviceBatchRegistrationInput = {\n /** Fleet-wide defaults applied to each device except its identifier fields. */\n defaults?: PartnerDeviceRegistrationInput;\n devices: Array<PartnerDeviceRegistrationInput>;\n};\n\n/**\n * Heartbeat payload from agent-core / agent-core-lite Android partner\n * SDKs. Only includes fields verified populated in production\n * `signal_observations` (last 30 days). Stub fields wired in Kotlin but\n * never observed in CH are intentionally excluded; re-add only after\n * telemetry confirms >1% population over 7 days.\n *\n */\nexport type PartnerDeviceHeartbeatBody = {\n advertisingId?: string | null;\n advertisingIdType?: \"gaid\" | \"idfa\" | null | null;\n advertising_identity?: AdvertisingIdentity;\n bleDeviceCount?: number;\n capabilities?: DeviceCapabilityPayload;\n discoveredNetworkDevices?: Array<MdnsNetworkDevice> | null;\n extended_identities?: Array<ExtendedIdentity>;\n fingerprint?: string;\n gatewayIpHash?: string | null;\n httpProbes?: Array<HttpProbeResult> | null;\n limitAdTracking?: boolean | null;\n metadata?: Record<string, unknown>;\n /** Capped at 50 devices (RSSI-sorted, strongest first). */\n nearbyBleDevices?: Array<BleScanResultData> | null;\n nearbyWifiNetworks?: Array<WifiScanResult> | null;\n networkDeviceCount?: number;\n /** Heartbeat schema version (1=baseline, 2=nativeSensorSnapshot) */\n schemaVersion?: number;\n screenId?: string | null;\n /** Per-source skip-reason counter map. Shape `{source: {reason: count}}`. */\n skipReasonCounts?: Record<string, Record<string, number>>;\n ssdpDevices?: Array<SsdpDeviceInfo> | null;\n status?: string;\n wifiBssidHash?: string | null;\n wifiEnvironment?: WifiEnvironmentSnapshot;\n wifiNetworkCount?: number;\n wifiSsidHash?: string | null;\n [key: string]: unknown;\n};\n\n/**\n * Request body accepted by the single-device registration endpoints\n * (`@trillboards/api-client` `PartnerDeviceRegistrationInput`). Additional\n * vendor-specific fields are accepted and forwarded to enrichment.\n *\n */\nexport type PartnerDeviceRegistrationInput = {\n /** Stable partner-owned device identifier. */\n device_id?: string;\n /** Legacy SDK alias for the device identifier, retained for backwards compatibility. */\n device_name?: string;\n device_type?: string;\n /** Display specification (pixel resolution and/or physical size). */\n display?: Record<string, unknown>;\n display_settings?: PartnerRegistrationDisplaySettings;\n /** Location hints (lat/lng, address, venue type). */\n location?: Record<string, unknown>;\n /** Friendly name for the device. */\n name?: string;\n /** Placement hints for the screen within the venue. */\n placement?: Record<string, unknown>;\n /** Venue taxonomy hints. */\n venue?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\nexport type PartnerHeartbeatCommand = {\n /** Command normalized for partner SDK compatibility. */\n command?: string;\n id?: string;\n payload?: Record<string, unknown>;\n queued_at?: string;\n};\n\nexport type PartnerHeartbeatData = {\n ad_delivery_profile?: PartnerAdDeliveryProfile;\n commands?: Array<PartnerHeartbeatCommand>;\n last_seen_at?: string;\n status?: \"online\" | \"offline\";\n};\n\nexport type PartnerHeartbeatMeasurementMetadata = {\n ageSeconds?: number | null;\n cachedAt?: string | null;\n receivedAt?: string | null;\n source?: \"redis_twin\" | \"pg_fallback\" | \"unknown\";\n [key: string]: unknown;\n};\n\nexport type PartnerHeartbeatQueryData = {\n adDeliveryProfile?: PartnerAdDeliveryProfile;\n deviceId: string;\n lastHeartbeatAt?: string | null;\n measurementMetadata?: PartnerHeartbeatMeasurementMetadata;\n stalenessSeconds?: number | null;\n telemetry?: PartnerSafeHeartbeatTelemetry;\n [key: string]: unknown;\n};\n\nexport type PartnerHeartbeatQueryResponse = {\n data?: PartnerHeartbeatQueryData;\n success?: boolean;\n};\n\n/**\n * Optional heartbeat payload. Nested telemetry objects are preferred; legacy flat keys\n * are still accepted for backward compatibility. The registered\n * `deviceId` is the binding boundary for both liveness and identity; no\n * separate partner API key is required.\n *\n */\nexport type PartnerHeartbeatRequest = {\n ad?: {\n last_vast_request_at?: string;\n last_vast_response_at?: string;\n proof_of_play_enabled?: boolean;\n };\n advertising_identity?: AdvertisingIdentity;\n agent_status?: string;\n agent_version?: string;\n android_api_level?: number;\n brightness?: number;\n desugaring_enabled?: boolean;\n device?: {\n android_api_level?: number;\n make?: string;\n model?: string;\n os?: string;\n osv?: string;\n webview_chromium_major?: number;\n };\n extended_identities?: Array<ExtendedIdentity>;\n ima_integration?: \"android_native\" | \"html5_webview\" | \"disabled\" | \"unknown\";\n ima_sdk_version?: string;\n ima_support_reason?: string;\n ima_supported?: boolean;\n input_source?: string;\n last_ima_error_code?: number;\n last_vast_error_code?: number;\n last_vast_request_at?: string;\n last_vast_response_at?: string;\n /** Current GPS fix for a moving screen. Processed only for screens whose `mobility_type` is `mobile` or `semi_mobile` (declare it at registration or via PATCH /device/{deviceId}), OR for any screen still missing coordinates (a one-time self-heal that also kicks off venue classification). Static screens with valid coordinates ignore it. Updates live geo-targeting, geofencing and analytics. Fully optional — omit it on stationary screens. */\n location?: {\n /** Horizontal accuracy radius in meters. Fixes above ~500m are clamped. */\n accuracy_m?: number;\n /** Up to 200 fixes recorded while the device was offline, replayed as a historical track. Timestamps MUST be in ascending order — a non-chronological batch is rejected with HTTP 400. Only the top-level `location` updates the live serving position. */\n buffered_locations?: Array<{\n accuracy_m?: number;\n heading?: number;\n lat: number;\n lng: number;\n speed_mps?: number;\n timestamp?: number;\n }>;\n /** Bearing in degrees (0–360, 0 = true north). Omit if unavailable. */\n heading?: number;\n /** Latitude in decimal degrees (WGS 84). */\n lat?: number;\n /** Longitude in decimal degrees (WGS 84). */\n lng?: number;\n /** `gps` — a live on-device fix. `gps_buffered` — a fix recorded while offline and replayed on reconnect. */\n source?: \"gps\" | \"gps_buffered\";\n /** Ground speed in meters per second. Omit if unavailable. */\n speed_mps?: number;\n /** Unix epoch milliseconds of the on-device fix. Send the device clock value; the server tolerates up to 10 minutes of skew. A position jump implying > 320 km/h between consecutive fixes is rejected. */\n timestamp?: number;\n };\n /** Alternate namespace for telemetry keys (legacy support). */\n metadata?: Record<string, unknown>;\n muted?: boolean;\n network?: {\n bandwidthMbps?: number;\n connectionType?: string;\n downlinkMbps?: number;\n effectiveType?: string;\n latencyRtt?: number;\n rtt?: number;\n saveData?: boolean;\n };\n network_strength_dbm?: number;\n power_state?: \"on\" | \"standby\" | \"off\" | \"unknown\";\n proof_of_play_enabled?: boolean;\n sdk?: {\n android_api_level?: number;\n desugaring_enabled?: boolean;\n ima_integration?: \"android_native\" | \"html5_webview\" | \"disabled\" | \"unknown\";\n ima_sdk_version?: string;\n ima_supported?: boolean;\n version?: string;\n webview_chromium_major?: number;\n };\n sdk_version?: string;\n telemetry?: PartnerHeartbeatTelemetry;\n temperature_c?: number;\n uptime_seconds?: number;\n volume?: number;\n webview_chromium_major?: number;\n};\n\nexport type PartnerHeartbeatResponse = {\n data?: PartnerHeartbeatData;\n success?: boolean;\n};\n\nexport type PartnerHeartbeatTelemetry = {\n agentStatus?: string;\n agentVersion?: string;\n android_api_level?: number;\n bandwidthMbps?: number;\n brightness?: number;\n connectionType?: string;\n desugaring_enabled?: boolean;\n downlinkMbps?: number;\n ima_integration?: \"android_native\" | \"html5_webview\" | \"disabled\" | \"unknown\";\n ima_sdk_version?: string;\n ima_support_reason?: string;\n ima_supported?: boolean;\n inputSource?: string;\n last_ima_error_code?: number;\n last_vast_error_code?: number;\n last_vast_request_at?: string;\n last_vast_response_at?: string;\n latencyRtt?: number;\n make?: string;\n model?: string;\n muted?: boolean;\n networkConnectionType?: string;\n networkEffectiveType?: string;\n networkStrengthDbm?: number;\n os?: string;\n osVersion?: string;\n osv?: string;\n powerState?: \"on\" | \"standby\" | \"off\" | \"unknown\";\n proof_of_play_enabled?: boolean;\n rtt?: number;\n saveData?: boolean;\n temperatureC?: number;\n uptimeSeconds?: number;\n volume?: number;\n webview_chromium_major?: number;\n [key: string]: unknown;\n};\n\nexport type PartnerLBarContent = {\n business_name?: string;\n contact_info?: Record<string, unknown>;\n current_promotion?: string;\n custom_messages?: Array<string>;\n display_settings?: Record<string, unknown>;\n enabled?: boolean;\n live_updates?: Record<string, unknown>;\n social_media?: Record<string, unknown>;\n store_hours?: Record<string, unknown>;\n};\n\nexport type PartnerLBarDisplayPreferences = {\n ad_surface_mode?: \"fullscreen\" | \"lbar\" | \"pip\" | \"all\";\n display_mode?: \"fullscreen\" | \"l-bar\";\n l_bar_ad_duration?: number;\n l_bar_ad_interval?: number;\n l_bar_ads_enabled?: boolean;\n l_bar_position?: \"bottom\" | \"right\";\n l_bar_size?: number;\n pip_settings?: {\n aspect_ratio?: number;\n enabled?: boolean;\n margin?: number;\n position?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\";\n size_ratio?: number;\n };\n};\n\nexport type PartnerLBarSettings = {\n ad_surfaces?: Record<string, unknown>;\n display_preferences?: PartnerLBarDisplayPreferences;\n l_bar_content?: PartnerLBarContent;\n playback_policy?: Record<string, unknown>;\n};\n\n/**\n * Stripe-style monetization requirements (account.requirements analogue).\n * Returned on device register / update / get / batch so bulk partners can\n * detect and self-remediate missing data instead of discovering silent\n * gaps later. `currently_due` blocks or limits monetization now;\n * `eventually_due` improves serving but isn't blocking.\n *\n */\nexport type PartnerMonetizationRequirements = {\n /** Requirements blocking or limiting monetization right now. */\n currently_due?: Array<PartnerRequirement>;\n /** Non-blocking improvements (e.g. display dimensions). */\n eventually_due?: Array<PartnerRequirement>;\n};\n\nexport type PartnerNetworkConfig = {\n ad_delivery?: {\n /** `/ads` response cache lifetime. Zero requires a fresh response for every request. */\n cache_max_age_seconds?: number;\n /** Delegates resettable advertising identity to the native Google IMA SDK; the API never fabricates one. Set null to restore the platform default identity path. */\n identity_mode?: \"ima_sdk\" | null;\n /** Fleet-wide hourly ad cap returned in `settings.max_ads_per_hour`. */\n max_ads_per_hour?: number;\n /** Requests non-personalized demand when true. Never provide an advertising identifier unless the OS legitimately exposes it. */\n non_personalized_ads?: boolean;\n /** Returned as both `settings.ad_interval` and `header_bidding_settings.min_interval_seconds`; the player should request each monetizable slot at this cadence. */\n request_interval_seconds?: number;\n /** Controls whether a scheduled self-promo/house slot may lead the VAST waterfall. `scheduled_primary` preserves the bounded house cadence; `fallback_only` keeps self-promo behind paid programmatic demand; `disabled` removes the self-promo/house creative from your screens entirely — it is served on neither `ads[]` nor the VAST waterfall, and no new house creative is generated for your screens. Paid-direct guarantees always retain priority and are never affected. Set null to restore `scheduled_primary`. */\n self_promo_priority_mode?: \"scheduled_primary\" | \"fallback_only\" | \"disabled\" | null;\n };\n /** White-label presentation for your buyer-facing advertiser portal. These values are read and written directly against the branding your portal renders — a GET returns what a buyer currently sees, and a write takes effect on their next page load. Omitted entirely if no white-label portal is linked to your partner account; writing branding in that state returns `409` `white_label_distributor_not_linked` rather than accepting values that would render nowhere. Contact Trillboards to have one linked. */\n branding?: {\n /** Shown as the portal name and the browser tab title. */\n display_name?: string;\n /** Absolute HTTPS URL. */\n favicon_url?: string;\n font_body?: string;\n font_heading?: string;\n /** Absolute HTTPS URL. Rendered in the portal header. */\n logo_url?: string;\n /** CSS color. HSL triplets (\"210 90% 40%\") and hex are both accepted. */\n primary_color?: string;\n secondary_color?: string;\n tagline?: string;\n };\n /** Default content preferences inherited by newly provisioned screens. */\n default_content_preferences?: Record<string, unknown>;\n default_waterfall?: {\n /** Preferred opaque source aliases from the `/ads` response. Sources not listed here remain enabled and are appended. Internal demand names and `sort_by: cpm` are rejected. */\n source_order?: Array<string>;\n /** Total deadline for one waterfall snapshot, in milliseconds. */\n total_timeout_ms?: number;\n };\n /** Limits your branded buyer portal to YOUR OWN screens. Off by default: a branded portal otherwise sells the whole Trillboards network, which is what most white-label partners want. The screen set is DERIVED from the media-owner identity your screens already carry — both the ones we host and the ones resold through partner exchanges — so it stays correct as you add inventory and there is no list to maintain. It cannot be set to another operator's inventory. */\n storefront?: {\n /** When true, every inventory surface in your buyers' portal — search, map, forecasts, quotes, bookings and proposals — is limited to your own screens. */\n enabled?: boolean;\n };\n};\n\n/**\n * Partner-safe partial update. Internal `partners`, `supply_chain`, seller\n * IDs, direct demand names, and CPM-sort controls are rejected.\n *\n */\nexport type PartnerNetworkConfigUpdate = PartnerNetworkConfig;\n\n/**\n * A log-level play for a partner-served ad.\n */\nexport type PartnerPlay = {\n /** Optional ad/line identifier; defaults to the sha-keyed creative. */\n ad_id?: string;\n /** ISO 8601 timestamp when the play completed. */\n completed_at: string;\n /** The classification reference from POST /creatives — `sha256:<hex>` or the bare 64-char content hash. */\n creative_ref: string;\n /** Play duration in seconds (default 30). */\n duration_seconds?: number;\n /** Your unique id for this play (idempotency key). */\n play_id: string;\n /** Optional partner request identifier. */\n request_id?: string;\n /** One of your registered earner-screen ids. */\n screen_id: string;\n};\n\n/**\n * Optional display behavior applied while registering or re-registering a device.\n */\nexport type PartnerRegistrationDisplaySettings = {\n content_fit?: ContentFitSettings;\n};\n\nexport type PartnerRequirement = {\n /** Stable machine code, e.g. location_unresolvable, location_awaiting_device_gps, enrichment_failed, display_size_missing. */\n code?: string;\n doc_url?: string;\n /** The request field this concerns (location, venue, display). */\n field?: string;\n /** Human-readable, actionable remediation. */\n message?: string;\n /** Specific reason variant, e.g. city_without_state, no_location_provided, geocode_failed, awaiting_device_gps. */\n reason?: string;\n};\n\n/**\n * Partner-safe subset of device telemetry. Strips MDM compliance,\n * Vertex embeddings, identity-correction internals, partner identifiers,\n * and Mongo `_id` so partners only see what they need to decide\n * whether a device is healthy enough to receive ads.\n *\n */\nexport type PartnerSafeHeartbeatTelemetry = {\n agentStatus?: string | null;\n agentVersion?: string | null;\n bandwidthMbps?: number | null;\n brightness?: number | null;\n connectionType?: string | null;\n consecutiveAdFailures?: number | null;\n effectiveType?: string | null;\n latencyRtt?: number | null;\n make?: string | null;\n model?: string | null;\n muted?: boolean | null;\n networkStrengthDbm?: number | null;\n onlineStatus?: \"online\" | \"offline\" | \"standby\" | \"unknown\" | null;\n os?: string | null;\n osv?: string | null;\n powerState?: string | null;\n temperatureC?: number | null;\n ua?: string | null;\n uptimeSeconds?: number | null;\n visibilityState?: string | null;\n volume?: number | null;\n [key: string]: unknown;\n};\n\nexport type PartnerSelfPromoAd = {\n _id?: string;\n campaign_link?: string;\n createdAt?: string;\n description?: string;\n name?: string;\n photos?: Array<string>;\n status?: string;\n video?: string;\n /** Measured length of the `video` creative in whole seconds, probed when the ad is created. This is the real media length and is what the served VAST declares as `<Duration>`. `null` means the media could not be measured, in which case the VAST declares the 30 second ad-slot default instead. */\n video_duration_seconds?: number | null;\n};\n\nexport type PartnerSelfPromoCreate = {\n campaign_link?: string;\n description?: string;\n end_date?: string;\n image_url?: string;\n name: string;\n screen_ids?: Array<string>;\n start_date?: string;\n video_url?: string;\n};\n\nexport type PartnerSelfPromoPlacement = {\n ads?: Array<{\n advertisement?: PartnerSelfPromoAd;\n allocation_id?: string;\n end_date?: string;\n start_date?: string;\n status?: string;\n }>;\n screen?: {\n _id?: string;\n name?: string;\n };\n};\n\nexport type PartnerStats = {\n active_devices?: number;\n last_impression_at?: string;\n pending_payout_cents?: number;\n total_devices?: number;\n total_impressions?: number;\n total_revenue_cents?: number;\n};\n\nexport type PayoutResponse = {\n amount_cents?: number;\n estimated_arrival?: string;\n payout_id?: string;\n status?: \"pending\" | \"processing\" | \"completed\" | \"failed\";\n stripe_transfer_id?: string | null;\n};\n\nexport type PlaygroundResult = {\n /** Whether the operation is safe for autonomous agents. */\n agent_safe: boolean;\n /** Billing tier: free, metered, or paid. */\n cost_tier: string;\n /** Whether the operation is idempotent. */\n idempotent: boolean;\n /** Object type identifier. */\n object: \"playground_result\";\n operation_id: string;\n /** Declared side effects of the operation. */\n side_effects: Array<string>;\n /** Whether the request body passed validation. */\n valid: boolean;\n /** The parsed/coerced body on success, null on failure. */\n validated_body?: unknown;\n /** Array of validation issues on failure, null on success. */\n validation_errors: Array<PlaygroundValidationError> | null;\n /** The HTTP method and path this operation maps to. */\n would_call: {\n method: string;\n path: string;\n };\n};\n\nexport type PlaygroundValidationError = {\n /** Zod issue code. */\n code: string;\n /** Human-readable validation message. */\n message: string;\n /** Dot-delimited path to the invalid field. */\n path: string;\n};\n\nexport type ProgrammaticSettingsInput = {\n /** Enable programmatic ads */\n enabled?: boolean;\n /** Minimum CPM in dollars */\n floor_price_cpm?: number;\n google_ima?: {\n ad_tag_url?: string;\n enabled?: boolean;\n max_duration?: number;\n };\n prebid?: {\n bidders?: Array<{\n name?: string;\n params?: Record<string, unknown>;\n }>;\n enabled?: boolean;\n };\n /** Ad source priority */\n priority?: \"direct_first\" | \"programmatic_first\" | \"highest_bid\";\n};\n\nexport type ProgrammaticSettingsResponse = {\n enabled?: boolean;\n floor_price_cpm?: number;\n google_ima?: {\n ad_tag_url?: string;\n enabled?: boolean;\n max_duration?: number;\n };\n object?: string;\n prebid?: {\n bidders?: Array<Record<string, unknown>>;\n enabled?: boolean;\n };\n priority?: string;\n request_id?: string;\n screen_id?: string;\n stats?: {\n avg_cpm?: number;\n fill_rate_percent?: number;\n impressions_today?: number;\n };\n updated_at?: string;\n};\n\nexport type RequestMetadataResponse = {\n duration_ms: number;\n /** Present only when the original request resulted in an error. */\n error?: {\n code: string;\n type: string;\n };\n method: string;\n /** Object type identifier. */\n object: \"request\";\n path: string;\n request_id: string;\n status_code: number;\n timestamp: string;\n};\n\n/**\n * The EFFECTIVE content policy for a screen + its provenance. Whole-layer\n * coalescing: the effective policy comes from exactly ONE layer.\n *\n */\nexport type ResolvedContentPolicy = {\n /** All content_preferences keys + blocked_iab_categories. */\n effective?: Record<string, unknown>;\n object?: string;\n provenance?: {\n /** Present only when source=group. */\n group_id?: string;\n source?: \"screen\" | \"group\" | \"network\" | \"default\";\n };\n screen_id?: string;\n};\n\n/**\n * The EFFECTIVE sensing view for a screen + its provenance (screen\n * deployment ?? group sensing config ?? default).\n *\n */\nexport type ResolvedSensingConfig = {\n effective?: {\n capture_interval_ms?: number | null;\n estimated_fps_impact?: number | null;\n min_confidence?: number | null;\n profile_name?: string | null;\n report_interval_ms?: number | null;\n };\n object?: string;\n provenance?: {\n /** Present only when source=group_default. */\n group_id?: string;\n source?: \"screen\" | \"group_default\" | \"default\";\n };\n screen_id?: string;\n};\n\n/**\n * Permission flags for each role. Owners have all permissions,\n * admins have operational permissions, viewers have read-only access.\n *\n */\nexport type RolePermissions = {\n /** Can configure webhooks */\n configure_webhooks?: boolean;\n /** Can edit screen settings */\n edit_screens?: boolean;\n /** Can invite/remove team members */\n manage_team?: boolean;\n /** Can request payouts */\n request_payouts?: boolean;\n /** Can rotate API keys */\n rotate_api_keys?: boolean;\n /** Can view impression analytics */\n view_analytics?: boolean;\n /** Can view earnings/revenue */\n view_earnings?: boolean;\n /** Can view impression data */\n view_impressions?: boolean;\n /** Can view payout history */\n view_payouts?: boolean;\n /** Can view online/offline status */\n view_screen_status?: boolean;\n /** Can view screen list */\n view_screens?: boolean;\n};\n\nexport type SDKConfig = {\n /** Seconds between ads */\n ad_interval?: number;\n allowed_ad_types?: Array<string>;\n cache_size?: number;\n /** Seconds to display image ads */\n image_duration?: number;\n max_ads_per_hour?: number;\n overlay_button_text?: string;\n sound_enabled?: boolean;\n};\n\n/**\n * A partner screen — the client-facing projection of a registered\n * device+screen pair (`@trillboards/api-client` `Screen`). The screens\n * resource reads the partner device endpoints.\n *\n */\nexport type Screen = {\n city?: string;\n country?: string;\n created_at: string;\n /** The paired device identifier. */\n device_id?: string;\n /** Player embed URL for the screen. */\n embed_url?: string;\n /** Friendly screen/venue name. */\n name: string;\n /** Display resolution label (e.g. \"1920x1080\") when known. */\n resolution?: string;\n /** Stable screen identifier. */\n screen_id: string;\n /** Screen lifecycle status (e.g. pending, active, offline, suspended). */\n status: string;\n timezone?: string;\n updated_at: string;\n /** Granular OpenOOH venue type of the screen's location. */\n venue_type?: string;\n};\n\nexport type ScreenAnalyticsResponse = {\n impressions?: {\n daily_average?: number;\n total?: number;\n /** Percentage change compared to previous period */\n trend_percent?: number;\n };\n period?: {\n days?: number;\n end?: string;\n start?: string;\n };\n screen?: {\n id?: string;\n location?: string;\n name?: string;\n online_status?: string;\n status?: string;\n };\n timeline?: Array<{\n avg_duration_ms?: number;\n date?: string;\n impressions?: number;\n }>;\n};\n\n/**\n * A reusable, named, partner-scoped set of screens that analytics,\n * moderation policy, sensing/model deployment, fleet commands, and\n * sensing routes can target. Members are always a subset of the\n * partner's own screens.\n *\n */\nexport type ScreenGroup = {\n created_at?: string;\n description?: string | null;\n /** Screen group id (sg_ prefix). */\n id?: string;\n name?: string;\n object?: string;\n /** Distinct member screens (COUNT and member list share one junction — they cannot diverge). */\n screen_count?: number;\n updated_at?: string;\n};\n\n/**\n * The typed content/moderation policy a screen group carries (Phase 4 live\n * policy). `null` when the group has no policy of its own. Member screens\n * inherit it at read/serve time when they have no explicit own policy\n * (screen ?? group ?? partner network default ?? system default). Mirrors\n * the per-screen content_preferences keys 1:1; blocked_iab_categories is\n * first-class here (the auction bcat).\n *\n */\nexport type ScreenGroupContentPolicy = {\n allow_adult_content?: boolean;\n allow_alcohol?: boolean;\n allow_gambling?: boolean;\n allow_political?: boolean;\n allow_profanity?: boolean;\n allow_religious?: boolean;\n allow_tobacco?: boolean;\n allow_violence?: boolean;\n allowed_categories?: Array<string>;\n allowed_keywords?: Array<string>;\n allowed_subjects?: Array<string>;\n auto_approve_known_brands?: boolean;\n blocked_categories?: Array<string>;\n blocked_iab_categories?: Array<string>;\n blocked_keywords?: Array<string>;\n blocked_subjects?: Array<string>;\n content_filtering_enabled?: boolean;\n group_id?: string;\n max_age_rating?: \"G\" | \"PG\" | \"PG-13\" | \"R\" | \"NC-17\";\n object?: string;\n preference_level?: \"strict\" | \"moderate\" | \"lenient\" | \"permissive\";\n updated_at?: string;\n} | null;\n\n/**\n * Partial, non-clobbering — only the fields present are written. Same keys\n * the per-screen content-preferences PUT accepts, plus blocked_iab_categories.\n *\n */\nexport type ScreenGroupContentPolicyInput = {\n allow_adult_content?: boolean;\n allow_alcohol?: boolean;\n allow_gambling?: boolean;\n allow_political?: boolean;\n allow_profanity?: boolean;\n allow_religious?: boolean;\n allow_tobacco?: boolean;\n allow_violence?: boolean;\n allowed_categories?: Array<string>;\n allowed_keywords?: Array<string>;\n allowed_subjects?: Array<string>;\n auto_approve_known_brands?: boolean;\n blocked_categories?: Array<string>;\n blocked_iab_categories?: Array<string>;\n blocked_keywords?: Array<string>;\n blocked_subjects?: Array<string>;\n content_filtering_enabled?: boolean;\n max_age_rating?: \"G\" | \"PG\" | \"PG-13\" | \"R\" | \"NC-17\";\n preference_level?: \"strict\" | \"moderate\" | \"lenient\" | \"permissive\";\n};\n\n/**\n * Webhook body for a Screen Group lifecycle event (`screen_group.created` | `updated` |\n * `deleted` | `member.added` | `member.removed` | `content_policy.updated` |\n * `sensing_config.updated`). Standard `{ id, event, timestamp, data }` envelope: `id` (`evt_…`)\n * is the idempotency key, and `data` is the Stripe-style `screen_group` /\n * `screen_group_content_policy` / `screen_group_sensing_config` object the REST API returns.\n * The event type is also in the `X-Trillboards-Event` header — verify the compound\n * `X-Trillboards-Signature` over the raw body first.\n *\n */\nexport type ScreenGroupEvent = {\n /** The screen_group / content-policy / sensing-config object. */\n data?: Record<string, unknown>;\n event?: \"screen_group.created\" | \"screen_group.updated\" | \"screen_group.deleted\" | \"screen_group.member.added\" | \"screen_group.member.removed\" | \"screen_group.content_policy.updated\" | \"screen_group.sensing_config.updated\";\n id?: string;\n timestamp?: string;\n};\n\n/**\n * A screen group's sensing profile binding (profile_name) + typed\n * performance overrides. `null` when the group has none. Member screens\n * inherit via the sensing resolver's group step when they have no\n * screen-specific deployment.\n *\n */\nexport type ScreenGroupSensingConfig = {\n /** Edge frame-capture cadence overrides pushed to member screens (SensingConfig.capture keys, milliseconds). Group wins over the profile default per-key when set. */\n capture?: {\n faceTriggeredIntervalMs?: number | null;\n minCaptureIntervalMs?: number | null;\n periodicIntervalMs?: number | null;\n vehicleTriggeredIntervalMs?: number | null;\n } | null;\n capture_interval_ms?: number | null;\n enabled?: boolean;\n estimated_fps_impact?: number | null;\n group_id?: string;\n min_confidence?: number | null;\n object?: string;\n profile_name?: string | null;\n report_interval_ms?: number | null;\n updated_at?: string;\n /** Per-screen cloud-vision budget for member screens. screen_hourly_pace wins when both are set; otherwise derived from screen_daily_calls. null = no group budget (fleet keeps platform-default caps). */\n vision_budget?: {\n screen_daily_calls?: number | null;\n screen_hourly_pace?: number | null;\n } | null;\n} | null;\n\n/**\n * Partial, non-clobbering. A null override means \"inherit that field from\n * the base profile\". profile_name must resolve to a builtin or an existing\n * custom profile (else 400).\n *\n */\nexport type ScreenGroupSensingConfigInput = {\n /** Edge frame-capture cadence block (milliseconds); null clears it. Unknown keys are rejected (400). */\n capture?: {\n faceTriggeredIntervalMs?: number | null;\n minCaptureIntervalMs?: number | null;\n periodicIntervalMs?: number | null;\n vehicleTriggeredIntervalMs?: number | null;\n } | null;\n capture_interval_ms?: number | null;\n enabled?: boolean;\n estimated_fps_impact?: number | null;\n min_confidence?: number | null;\n profile_name?: string | null;\n report_interval_ms?: number | null;\n /** Per-screen cloud-vision budget block; null clears it. Unknown keys are rejected (400). */\n vision_budget?: {\n screen_daily_calls?: number | null;\n screen_hourly_pace?: number | null;\n } | null;\n};\n\n/**\n * High-level sensing workload intent. Hardware tier and device telemetry are read-only server facts.\n */\nexport type SensingPerformanceMode = \"auto\" | \"presence_only\" | \"demographics\" | \"advanced\";\n\n/**\n * A Sense Anything Route — a (condition → channel actions) alert/automation rule.\n */\nexport type SensingRoute = {\n actions?: Array<SensingRouteAction>;\n /** One bit per weekday (127 = always). */\n activeDaysMask?: number;\n activeEndMinute?: number | null;\n activeStartMinute?: number | null;\n activeTz?: string | null;\n condition?: SensingRouteCondition | null;\n createdAt?: string;\n debounceSeconds?: number;\n digest?: {\n intervalMinutes?: number;\n metric?: \"count\" | \"avg\" | \"max\";\n nextRunAt?: string;\n windowMinutes?: number;\n } | null;\n enabled?: boolean;\n mode?: \"threshold\" | \"digest\";\n name?: string;\n ownerId?: string;\n ownerKind?: string;\n partnerId?: string;\n profileName?: string | null;\n routeId?: string;\n screenMongoIds?: Array<string>;\n /** DEPRECATED and rejected on write with 400. A duration expressed as N readings inside a fixed window can only be satisfied by a screen reporting faster than window/(N-1) seconds, and nothing knows that rate when the route is saved - so the route saves cleanly and then never fires at all. Send sustainSeconds instead. Still honoured for rows that already carry it. */\n sustainMinSamples?: number;\n /** How long the condition must hold before the FIRST alert, in seconds (600 = ten minutes). Omit to alert on the first true reading. Cadence-independent, because the evaluator compares timestamps - correct however often the screen reports, including when that rate changes while the condition holds. */\n sustainSeconds?: number | null;\n /** DEPRECATED and rejected on write with 400. A duration expressed as N readings inside a fixed window can only be satisfied by a screen reporting faster than window/(N-1) seconds, and nothing knows that rate when the route is saved - so the route saves cleanly and then never fires at all. Send sustainSeconds instead. Still honoured for rows that already carry it. */\n sustainWindowSeconds?: number;\n /** The sg_ Screen Group this route targets. When set, the route fires on the group's LIVE members (screenMongoIds reflects the resolved members at read time) and no explicit screens are stored. */\n targetGroupId?: string | null;\n updatedAt?: string;\n};\n\n/**\n * One channel action fired when the route matches.\n */\nexport type SensingRouteAction = {\n /** Attach the evidence frame/clip (people-facing channels). */\n attachClip?: boolean;\n channel: \"webhook\" | \"whatsapp\" | \"sms\" | \"slack\" | \"email\" | \"clip\";\n /** E.164 phone number (channel=whatsapp|sms). */\n recipientE164?: string;\n /** Recipient email (channel=email). */\n recipientEmail?: string;\n /** Slack channel id (channel=slack). */\n slackChannelId?: string;\n /** Message template name (managed WhatsApp/SMS). */\n templateName?: string;\n /** Target webhook endpoint id (channel=webhook). */\n webhookId?: string;\n};\n\n/**\n * A threshold condition — the route fires when the sensed field crosses the value.\n */\nexport type SensingRouteCondition = {\n /** The sensed field key (snake_case) to evaluate. */\n field: string;\n op: \"gt\" | \"gte\" | \"lt\" | \"lte\" | \"eq\" | \"neq\";\n /** The threshold value (numeric, string, or boolean depending on the field). */\n value?: number | string | boolean;\n};\n\nexport type SensingSettingsResponse = {\n active_profile?: {\n capabilities?: Array<string>;\n capture_interval_ms?: number | null;\n profile_id?: string | null;\n profile_name?: string | null;\n report_interval_ms?: number | null;\n } | null;\n desired_mode?: SensingPerformanceMode;\n /** Read-only latest device telemetry used for safety checks. */\n device_capability?: {\n agent_version?: string | null;\n gpu_delegate_supported?: boolean | null;\n gpu_name?: string | null;\n model_tier?: string | null;\n recent_failure_count?: number;\n soc_name?: string | null;\n soc_vendor?: string | null;\n telemetry_fresh?: boolean;\n };\n effective_mode?: SensingPerformanceMode;\n last_apply_status?: Record<string, unknown> | null;\n modes?: Array<{\n label?: string;\n value?: SensingPerformanceMode;\n }>;\n safety?: {\n allowed?: boolean;\n blocks?: Array<{\n code?: string;\n message?: string;\n }>;\n warnings?: Array<{\n code?: string;\n message?: string;\n }>;\n };\n screen_id?: string;\n};\n\n/**\n * Webhook request BODY delivered when a Sense Anything Route fires. Unlike the\n * device/programmatic events, a Route fire delivers a FLAT, self-describing\n * payload (no `{event,timestamp,data}` wrapper) — the event type is in the\n * `X-Trillboards-Event` request header (`sensing.threshold_crossed` for a custom\n * sensed field, or the matching `audience.*` / `venue.*` event for a known\n * semantic; a scheduled-digest Route delivers `venue.traffic_summary`). All Route\n * events share this same body shape. Verify the `X-Trillboards-Signature` header\n * over the raw body before trusting it.\n *\n */\nexport type SensingThresholdCrossedEvent = {\n /** The sensed field key evaluated (null for count-only digests). */\n field?: string | null;\n fired_at?: string;\n /** The observed value that crossed the threshold. */\n observed?: unknown;\n op?: \"gt\" | \"gte\" | \"lt\" | \"lte\" | \"eq\" | \"neq\" | null;\n owner_kind?: \"earner_user\" | \"partner\";\n /** The Route that fired. */\n route_id?: string;\n route_name?: string;\n /** The screen (mongo id) whose observation crossed the threshold. */\n screen_id?: string;\n /** The configured threshold value (number, string, or boolean). */\n threshold?: unknown | null;\n};\n\nexport type SsdpDeviceInfo = {\n friendlyName?: string | null;\n location: string;\n manufacturer?: string | null;\n modelName?: string | null;\n server?: string | null;\n st: string;\n udn?: string | null;\n [key: string]: unknown;\n};\n\nexport type TeamInviteResponse = {\n email?: string;\n /** When the invitation expires (7 days from creation) */\n expires_at?: string;\n membership_id?: string;\n role?: \"admin\" | \"viewer\";\n status?: \"pending\" | \"active\";\n};\n\nexport type TeamMember = {\n accepted_at?: string | null;\n email?: string;\n invited_at?: string;\n invited_by?: {\n email?: string;\n name?: string;\n } | null;\n last_portal_access?: string | null;\n /** Unique membership record ID */\n membership_id?: string;\n name?: string;\n permissions?: RolePermissions;\n photo?: string | null;\n role?: \"owner\" | \"admin\" | \"viewer\";\n status?: \"active\" | \"pending\" | \"revoked\";\n /** User ID (null if pending invitation) */\n user_id?: string;\n};\n\nexport type Transaction = {\n amount_cents?: number;\n created_at?: string;\n date?: string;\n id?: string;\n /** Number of impressions (for earning transactions) */\n impressions?: number;\n /** Source of the transaction (e.g., impressions, payout) */\n source?: string;\n /** Stripe transfer ID (for payout transactions) */\n stripe_transfer_id?: string;\n type?: \"earning\" | \"payout\";\n};\n\n/**\n * Partial, non-clobbering update — include only the fields to change.\n */\nexport type UpdatePartnerSensingRouteRequest = {\n actions?: Array<SensingRouteAction>;\n activeDaysMask?: number;\n activeEndMinute?: number;\n activeStartMinute?: number;\n activeTz?: string;\n condition?: SensingRouteCondition;\n debounceSeconds?: number;\n digest?: {\n field?: string;\n intervalMinutes?: number;\n metric?: \"count\" | \"avg\" | \"max\";\n windowMinutes?: number;\n };\n enabled?: boolean;\n name?: string;\n profileName?: string | null;\n screenMongoIds?: Array<string>;\n /** DEPRECATED and rejected on write with 400. A duration expressed as N readings inside a fixed window can only be satisfied by a screen reporting faster than window/(N-1) seconds, and nothing knows that rate when the route is saved - so the route saves cleanly and then never fires at all. Send sustainSeconds instead. Still honoured for rows that already carry it. */\n sustainMinSamples?: number;\n /** How long the condition must hold before the FIRST alert, in seconds (600 = ten minutes). Omit to alert on the first true reading. Cadence-independent, because the evaluator compares timestamps - correct however often the screen reports, including when that rate changes while the condition holds. */\n sustainSeconds?: number;\n /** DEPRECATED and rejected on write with 400. A duration expressed as N readings inside a fixed window can only be satisfied by a screen reporting faster than window/(N-1) seconds, and nothing knows that rate when the route is saved - so the route saves cleanly and then never fires at all. Send sustainSeconds instead. Still honoured for rows that already carry it. */\n sustainWindowSeconds?: number;\n /** Set to a sg_ group id to (re)target the group's live members, or null to switch back to an explicit screenMongoIds set. Mutually exclusive with screenMongoIds in one request. */\n targetGroupId?: string | null;\n};\n\n/**\n * The resolved programmatic VAST waterfall. `sources` is an ORDERED ARRAY and clients MUST iterate ALL of it — by `priority` ascending, skipping `enabled: false` — advancing to the next source on no-fill, empty VAST, timeout, IMA load error AND playback error (VAST 303 / 300 / 301 / 1009 all mean \"try the next source\", never \"stop\"). Reading `sources[0]` and stopping is the most common integration defect and reads as \"no demand\" when demand exists further down. Apply each source's own `timeout_ms`, and cap the whole loop at `total_timeout_ms`. Always handle player error and never leave the screen black; always fire the VAST `<Error>` beacon with `[ERRORCODE]` substituted. Full contract: docs/integrations/partner-native-ima-sdk.md §0 and §4.1. SQL/Admin-enabled sources remain visible; request-pressure decisions are enforced, when enabled, at first-party upstream fetch seams rather than by removing sources from this catalog.\n *\n */\nexport type VastWaterfall = {\n enabled?: boolean;\n /** Every source must be attempted, by `priority` ascending, until one actually plays. Not a preference list. */\n sources?: Array<VastWaterfallSource>;\n /** Budget in ms for the ENTIRE waterfall loop, across all sources. When it is spent, stop trying sources and return to your own content. */\n total_timeout_ms?: number;\n} | null;\n\n/**\n * One demand source in the VAST waterfall. Fetch `vast_url` (already a Trillboards vast-wrap URL — use as-is) and pass the response to your IMA SDK. A failure here means \"advance to the next source\", not \"the request had no demand\".\n */\nexport type VastWaterfallSource = {\n auction_request_id?: string;\n cpm?: number | null;\n /** High recent error rate measured server-side. Degraded sources are already pushed to the tail of the array for you — do NOT skip a source because of this flag. */\n degraded?: boolean;\n /** Whole seconds of the creative THIS source will serve, so you can schedule continuous loop playback without first fetching the VAST and probing the MP4. Present only on the first-party `trillboards_direct` source (a programmatic source's length is not known until its own VAST is fetched). It is the same number as the `<Duration>` in the VAST that `vast_url` returns, so use either — they cannot disagree. NOT a playback control: IMA still takes its real timing from the media, so treat this as scheduling metadata and keep honouring the actual quartile/complete events. A creative longer than your ad slot will still be cut off by the next poll; we warn the uploader at upload time when that is the case. */\n duration_seconds?: number;\n /** When false, skip this source entirely. Present-but-disabled sources may appear in the array. */\n enabled?: boolean;\n error_rate_pct?: number;\n fetch_mode?: string | null;\n /** Opaque public alias for the demand source. Echo it back as `variant_name` on `programmatic-event` reports. */\n name?: string;\n /** Opaque ascending sort key — lowest is tried first. Do NOT treat it as an index: it may start at 0 (a source we want to win outright — the `?test=1` source, an injected first-party bid, an auction winner — is stamped `priority: 0`), and values may be non-contiguous (some paths renumber survivors 1..N, others keep catalog values). Only the relative order is meaningful; sort ascending and do no arithmetic on it. */\n priority?: number;\n /** Per-source request identifier. Report against the source you actually used, not `sources[0]`. */\n request_id?: string;\n /** Per-source budget in ms for fetching and loading THIS source. Distinct from the waterfall-wide `total_timeout_ms`. */\n timeout_ms?: number;\n vast_url?: string;\n};\n\nexport type Webhook = {\n /** When webhook was created */\n created_at?: string;\n /** Subscribed event types */\n events?: Array<\"device.online\" | \"device.offline\" | \"impression.recorded\" | \"campaign.allocated\" | \"payout.processed\" | \"sensing.threshold_crossed\" | \"audience.spike\" | \"audience.venue_busy\" | \"audience.purchase_intent\" | \"audience.demographics_update\" | \"venue.traffic_summary\" | \"screen_group.created\" | \"screen_group.updated\" | \"screen_group.deleted\" | \"screen_group.member.added\" | \"screen_group.member.removed\" | \"screen_group.content_policy.updated\" | \"screen_group.sensing_config.updated\" | \"fleet_command.completed\" | \"fleet_command.failed\">;\n /** Total failed deliveries */\n failure_count?: number;\n /** Last time webhook was triggered */\n last_triggered_at?: string;\n /** Webhook signing secret (whsec_…). Returned when the webhook is created so partners can verify the compound `X-Trillboards-Signature` header over the raw payload (see the SDK's Webhooks.constructEvent). Treat as a credential — store it securely and never expose it client-side. */\n secret?: string;\n /** Webhook status */\n status?: \"active\" | \"inactive\";\n /** Total successful deliveries */\n success_count?: number;\n /** Webhook endpoint URL */\n url?: string;\n /** Unique webhook identifier */\n webhook_id?: string;\n};\n\nexport type WebhookDelivery = {\n /** When delivery was first attempted */\n attempted_at?: string;\n /** When delivery succeeded */\n delivered_at?: string;\n /** Error message if failed */\n error_message?: string;\n /** Event that triggered this delivery */\n event_type?: string;\n /** HTTP status code from endpoint */\n http_status?: number;\n /** Delivery record ID */\n id?: string;\n /** Response time in milliseconds */\n response_time_ms?: number;\n /** Number of retry attempts */\n retry_count?: number;\n /** Delivery status */\n status?: \"pending\" | \"success\" | \"failed\" | \"retrying\";\n};\n\n/**\n * Standard webhook event payload sent to your endpoint.\n * All events follow this structure.\n *\n */\nexport type WebhookEvent = {\n /** Event-specific data */\n data?: Record<string, unknown>;\n /** Event type */\n event?: string;\n /** When event occurred */\n timestamp?: string;\n};\n\nexport type WifiEnvironmentSnapshot = {\n channelCongestionRatio?: number | null;\n connectedChannelWidthMhz?: number | null;\n connectedFrequencyMhz?: number | null;\n connectedLinkSpeedMbps?: number | null;\n connectedSignalDbm?: number | null;\n frequencyBand?: string | null;\n medianSignalDbm?: number | null;\n networkCount?: number | null;\n rssiVariance?: number | null;\n scanTimestampMs?: number | null;\n signalSpreadDbm?: number | null;\n uniqueBssidCount?: number | null;\n [key: string]: unknown;\n} | null;\n\nexport type WifiScanResult = {\n channelWidthMhz?: number | null;\n frequencyMhz: number;\n rawBssid: string;\n signalStrengthDbm: number;\n [key: string]: unknown;\n};\n\n\n// ─── Operations ──────────────────────────────────────────────────────────\n\n/**\n * List self-promo ads\n * GET /ads/self-promo\n */\nexport interface listPartnerSelfPromoAdsOperation {\n readonly path: \"/ads/self-promo\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Array<PartnerSelfPromoAd>;\n success?: boolean;\n};\n}\n\n/**\n * Create self-promo ad (URL-based)\n * POST /ads/self-promo\n */\nexport interface createPartnerSelfPromoAdOperation {\n readonly path: \"/ads/self-promo\";\n readonly method: \"POST\";\n request: PartnerSelfPromoCreate;\n response: {\n data?: PartnerSelfPromoAd;\n success?: boolean;\n warnings?: PartnerCreativeWarnings;\n};\n}\n\n/**\n * List self-promo placements by screen\n * GET /ads/self-promo/placements\n */\nexport interface listPartnerSelfPromoPlacementsOperation {\n readonly path: \"/ads/self-promo/placements\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Array<PartnerSelfPromoPlacement>;\n success?: boolean;\n};\n}\n\n/**\n * Schedule existing self-promo ad to screens\n * POST /ads/self-promo/schedule\n */\nexport interface schedulePartnerSelfPromoOperation {\n readonly path: \"/ads/self-promo/schedule\";\n readonly method: \"POST\";\n request: {\n ad_id: string;\n end_date?: string;\n screen_ids: Array<string>;\n start_date?: string;\n};\n response: {\n success?: boolean;\n};\n}\n\n/**\n * Create self-promo ad (upload)\n * POST /ads/self-promo/upload\n */\nexport interface createPartnerSelfPromoUploadOperation {\n readonly path: \"/ads/self-promo/upload\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: PartnerSelfPromoAd;\n success?: boolean;\n warnings?: PartnerCreativeWarnings;\n};\n}\n\n/**\n * Disable a self-promo ad\n * POST /ads/self-promo/{ad_id}/disable\n */\nexport interface disableSelfPromoAdOperation {\n readonly path: \"/ads/self-promo/{ad_id}/disable\";\n readonly method: \"POST\";\n request: never;\n response: {\n ad_id?: string;\n status?: \"disabled\";\n};\n}\n\n/**\n * Register an AI agent\n * POST /agent/register\n */\nexport interface registerAgentOperation {\n readonly path: \"/agent/register\";\n readonly method: \"POST\";\n request: {\n /** Type of agent being registered */\n agent_type: \"dsp_agent\" | \"ssp_agent\" | \"trading_desk\" | \"analytics_platform\" | \"developer\";\n /** Company name (optional) */\n company?: string;\n /** Brief description of the agent's purpose */\n description?: string;\n /** Contact email */\n email: string;\n /** Agent or company name */\n name: string;\n /** Mint an AdCP **sandbox account** (`account.sandbox` in `get_adcp_capabilities`). Media buys made with the returned key validate end to end — screen resolution, published CPM/floor, flight parsing, derived impression goal, every error path — and return a well-formed response marked `sandbox: true`, but persist **no advertisements and no placements**. Nothing can serve, deliver, bill, or pay a venue. Use this for conformance and no-spend testing; register without it for a live account. */\n sandbox?: boolean;\n};\n response: {\n /** The AdCP **account** this key is bound to. Distinct from the `sandbox` block below, which describes auto-provisioned test SCREENS (supply); this is the account-level buying contract (demand) declared as `account.sandbox` in `get_adcp_capabilities`. */\n account?: {\n /** Seller-assigned account id. Same value as `partner_id`. */\n account_id?: string;\n note?: string;\n /** True when this is a sandbox account: its media buys write no advertisements and no placements, and every media-buy tool response is marked `sandbox: true`. */\n sandbox?: boolean;\n };\n agent_type?: string;\n /** API key for authentication (display once — save it!) */\n api_key?: string;\n /** MCP tools available to this agent */\n available_tools?: Array<string>;\n /** Exact same-key handoff for buyer/OpenRTB control-plane capabilities. */\n control_plane_onboarding?: {\n authorization?: string;\n endpoint?: string;\n method?: string;\n purpose?: string;\n reuses_api_key?: boolean;\n };\n docs_url?: string;\n /** Free tier limits per product */\n free_tiers?: Record<string, unknown>;\n mcp_endpoint?: string;\n mcp_transport?: string;\n /** Guidance for getting started */\n next_steps?: Array<string>;\n object?: string;\n /** Unique partner ID */\n partner_id?: string;\n pricing_url?: string;\n request_id?: string;\n /** Auto-provisioned test SCREENS (supply side). Unrelated to `account.sandbox`. */\n sandbox?: {\n note?: string;\n screens?: Array<{\n device_id?: string;\n name?: string;\n venue_type?: string;\n }>;\n };\n tools_url?: string;\n};\n}\n\n/**\n * Get partner analytics\n * GET /analytics\n */\nexport interface getAnalyticsOperation {\n readonly path: \"/analytics\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n devices_by_status?: Array<Record<string, unknown>>;\n impressions_by_day?: Array<{\n /** Date (YYYY-MM-DD) */\n _id?: string;\n impressions?: number;\n }>;\n partner?: {\n active_devices?: number;\n pending_payout_cents?: number;\n total_devices?: number;\n total_impressions?: number;\n total_revenue_cents?: number;\n };\n period?: {\n end?: string;\n start?: string;\n };\n };\n success?: boolean;\n};\n}\n\n/**\n * Visitor-flow continuity graph across the partner's screens\n * GET /analytics/audience-continuity\n */\nexport interface getAudienceContinuityOperation {\n readonly path: \"/analytics/audience-continuity\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n confidence?: string;\n sampleSize?: number;\n topPaths?: Array<Record<string, unknown>>;\n };\n status?: boolean;\n};\n}\n\n/**\n * Audience composition for the partner's screens\n * GET /analytics/audience-profile\n */\nexport interface getAudienceProfileOperation {\n readonly path: \"/analytics/audience-profile\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n sampleSize?: number;\n segments?: Array<Record<string, unknown>>;\n };\n status?: boolean;\n};\n}\n\n/**\n * BLE device discovery summary\n * GET /analytics/ble-summary\n */\nexport interface getBleSummaryOperation {\n readonly path: \"/analytics/ble-summary\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n totalObservations?: number;\n uniqueDevices?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Content performance — ad lineage and measured audience reactions\n * GET /analytics/content-performance\n */\nexport interface getContentPerformanceOperation {\n readonly path: \"/analytics/content-performance\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n byScreen?: Record<string, unknown>;\n creativeResponse?: Array<{\n adId?: string;\n advertiserName?: string;\n ageRating?: string;\n attentiveSeconds?: number;\n audioTerms?: Array<string>;\n avgAttention?: number;\n brandName?: string;\n confidence?: number;\n firstSeen?: string;\n iabCategories?: Array<string>;\n lastSeen?: string;\n moderationStatus?: string;\n plays?: number;\n viewers?: number;\n }>;\n /** Whether another page of creativeResponse exists after this one. */\n has_more?: boolean;\n nextOffset?: number | null;\n topAdvertisers?: Array<Record<string, unknown>>;\n /** Number of items the pagination cursor walks — the denominator `nextOffset`/`has_more` are computed against (the filtered set before per-page de-duplication). A page may render fewer rows when visually-identical creatives are merged for display, so page to completion via `has_more` rather than comparing `creativeResponse.length` to `total`. Null on the unfiltered legacy path. Describes the programmatic cursor; the offset-0 all-content block is additive. */\n total?: number | null;\n };\n status?: boolean;\n};\n}\n\n/**\n * Free-text search across the partner's creative catalogue\n * GET /analytics/creative-catalog\n */\nexport interface searchCreativeCatalogOperation {\n readonly path: \"/analytics/creative-catalog\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n creatives?: Array<{\n adId?: string;\n advertiserName?: string;\n assetUrl?: string | null;\n brandName?: string;\n iabCategories?: Array<string>;\n moderationStatus?: string;\n }>;\n /** Whether another page of results exists after this one. */\n has_more?: boolean;\n nextOffset?: number | null;\n /** Always null for catalogue search: the read over-fetches limit+1 for a free `has_more`, but an exact total would need a second COUNT round-trip the search path deliberately avoids. Page to completion via `has_more`. */\n total?: number | null;\n };\n status?: boolean;\n};\n}\n\n/**\n * Scene-level observations for a played creative\n * GET /analytics/creative-scenes\n */\nexport interface getCreativeScenesOperation {\n readonly path: \"/analytics/creative-scenes\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n adId?: string;\n nextCursor?: string | null;\n scenes?: Array<Record<string, unknown>>;\n screenId?: string;\n timeRange?: string;\n total?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Per-pair flow directionality + transition heatmap\n * GET /analytics/cross-screen-flow\n */\nexport interface getCrossScreenFlowOperation {\n readonly path: \"/analytics/cross-screen-flow\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n edges?: Array<Record<string, unknown>>;\n screens?: Array<Record<string, unknown>>;\n };\n status?: boolean;\n};\n}\n\n/**\n * Unified portfolio dashboard (earnings, ads, audience, screens, insights)\n * GET /analytics/dashboard\n */\nexport interface getPartnerAnalyticsDashboardOperation {\n readonly path: \"/analytics/dashboard\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n ads?: Record<string, unknown>;\n audience?: Record<string, unknown>;\n earnings?: {\n change?: Record<string, unknown>;\n current?: Record<string, unknown>;\n previous?: Record<string, unknown>;\n sparkline?: Array<Record<string, unknown>>;\n };\n insights?: Array<Record<string, unknown>>;\n period?: {\n endDate?: string | null;\n label?: string;\n startDate?: string | null;\n };\n screens?: Record<string, unknown>;\n topScreens?: Array<Record<string, unknown>>;\n };\n status?: boolean;\n};\n}\n\n/**\n * Device-type / OS / browser-class distribution among repeat visitors\n * GET /analytics/device-suite-signature\n */\nexport interface getDeviceSuiteSignatureOperation {\n readonly path: \"/analytics/device-suite-signature\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n deviceTypes?: Array<Record<string, unknown>>;\n totalDevices?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * CSV export of partner-scope analytics (summary / daily / per-screen)\n * GET /analytics/export\n */\nexport interface exportPartnerAnalyticsOperation {\n readonly path: \"/analytics/export\";\n readonly method: \"GET\";\n request: never;\n response: unknown;\n}\n\n/**\n * Per-ad daily breakdown for the partner fleet\n * GET /analytics/export/ads-by-day\n */\nexport interface exportPartnerAdsByDayOperation {\n readonly path: \"/analytics/export/ads-by-day\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Array<{\n ad_name?: string;\n advertiser_name?: string;\n campaign_type?: string;\n completion_rate?: number;\n date?: string;\n gross_revenue_cents?: number;\n plays_completed?: number;\n publisher_revenue_cents?: number;\n publisher_share_rate?: number;\n screen_name?: string;\n }>;\n status?: boolean;\n};\n}\n\n/**\n * 24-hour distribution across the partner's fleet\n * GET /analytics/fleet-hourly\n */\nexport interface getFleetHourlyOperation {\n readonly path: \"/analytics/fleet-hourly\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n hours?: Array<Record<string, unknown>>;\n timeRange?: string;\n };\n status?: boolean;\n};\n}\n\n/**\n * 4-stage discovery → awareness → engagement → conversion funnel\n * GET /analytics/halo-funnel\n */\nexport interface getHaloFunnelOperation {\n readonly path: \"/analytics/halo-funnel\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n stages?: Array<Record<string, unknown>>;\n };\n status?: boolean;\n};\n}\n\n/**\n * 24-hour returning-vs-first-timer audience clock\n * GET /analytics/loyalty-clock\n */\nexport interface getLoyaltyClockOperation {\n readonly path: \"/analytics/loyalty-clock\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n hours?: Array<{\n firstTimerShare?: number;\n hour?: number;\n returningShare?: number;\n sampleSize?: number;\n }>;\n sampleSize?: number;\n timeRange?: string;\n };\n status?: boolean;\n};\n}\n\n/**\n * Fleet-wide audience summary for the partner's screens\n * GET /analytics/network-summary\n */\nexport interface getNetworkSummaryOperation {\n readonly path: \"/analytics/network-summary\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n dataAvailable?: boolean;\n queriedAt?: string;\n timeRange?: string;\n totalScreens?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Daily/hourly fleet-wide audience timeseries\n * GET /analytics/network-trend\n */\nexport interface getNetworkTrendOperation {\n readonly path: \"/analytics/network-trend\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n interval?: string;\n series?: Array<Record<string, unknown>>;\n timeRange?: string;\n };\n status?: boolean;\n};\n}\n\n/**\n * Privacy-safe cross-screen proximity-graph summary\n * GET /analytics/proximity-summary\n */\nexport interface getProximitySummaryOperation {\n readonly path: \"/analytics/proximity-summary\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n continuityEdges?: Array<Record<string, unknown>>;\n crossScreenSignals?: number;\n gateDiagnostic?: Record<string, unknown>;\n repeatSignals?: number;\n sourceBreakdown?: Record<string, unknown>;\n topPaths?: Array<Record<string, unknown>>;\n uniqueSignals?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Per-creative scatter of avg-attention vs revenue-per-impression\n * GET /analytics/revenue-attention-correlation\n */\nexport interface getRevenueAttentionCorrelationOperation {\n readonly path: \"/analytics/revenue-attention-correlation\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n points?: Array<Record<string, unknown>>;\n trendLine?: Record<string, unknown> | null;\n };\n status?: boolean;\n};\n}\n\n/**\n * Paginated chronological feed of scene observations\n * GET /analytics/scene-feed\n */\nexport interface getSceneFeedOperation {\n readonly path: \"/analytics/scene-feed\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** Distinct calendar days with observations over the last 90 days. */\n activeDays?: number;\n /** Whether another page exists after this one. */\n has_more?: boolean;\n nextOffset?: number | null;\n scenes?: Array<Record<string, unknown>>;\n /** Distinct observations within the feed window — the exact set the feed pages over. */\n total?: number;\n /** Distinct (screen, scene-prefix) observations over the last 90 days (gamification stat; independent of the page window). */\n totalObservations?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Latest scene description per screen\n * GET /analytics/scene-intelligence\n */\nexport interface getSceneIntelligenceOperation {\n readonly path: \"/analytics/scene-intelligence\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** Present on EVERY response, success included. A field that appeared only on failure would make its absence the signal, and an absent field is indistinguishable from an old client or a version skew. */\n sceneDiagnostic: {\n /** True when the scene read completed and `scenes` reflects the fleet. False when it did not run to completion — `scenes` is then empty for want of an answer, not because the fleet is quiet. */\n measured: boolean;\n /** Null when `measured` is true. Otherwise names the operational failure. */\n reason: \"timeout\" | \"error\" | \"dependency_disabled\" | \"unknown\" | null;\n };\n scenes: Array<Record<string, unknown>>;\n };\n status?: boolean;\n};\n}\n\n/**\n * Rotate API key\n * POST /api-key/rotate\n */\nexport interface rotateApiKeyOperation {\n readonly path: \"/api-key/rotate\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: {\n /** New API key — shown only once! */\n api_key?: string;\n grace_period_hours?: number;\n message?: string;\n /** When the old key stops working */\n previous_key_expires_at?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get partner-wide audience analytics\n * GET /audience-analytics\n */\nexport interface getAudienceAnalyticsOperation {\n readonly path: \"/audience-analytics\";\n readonly method: \"GET\";\n request: never;\n response: AudienceAnalyticsResponse;\n}\n\n/**\n * Export audience data\n * GET /audience-export\n */\nexport interface exportAudienceDataOperation {\n readonly path: \"/audience-export\";\n readonly method: \"GET\";\n request: never;\n response: AudienceExportResponse;\n}\n\n/**\n * Get audience heatmap data\n * GET /audience/heatmap\n */\nexport interface getAudienceHeatmapOperation {\n readonly path: \"/audience/heatmap\";\n readonly method: \"GET\";\n request: never;\n response: {\n cells?: number;\n heatmap?: Array<Record<string, unknown>>;\n lookback_days?: number;\n object?: string;\n request_id?: string;\n screens_included?: number;\n};\n}\n\n/**\n * Get live audience data for a screen\n * GET /audience/live/{screenId}\n */\nexport interface getLiveAudienceOperation {\n readonly path: \"/audience/live/{screenId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n /** Null when screen is offline */\n audience?: {\n ad_receptivity?: number | null;\n attention_score?: number;\n crowd_density?: number;\n dominant_ambience?: string | null;\n dwell_time_ms?: number | null;\n emotional_engagement?: number | null;\n face_count?: number;\n income_level?: string | null;\n lifestyle_segment?: string | null;\n mood?: string | null;\n noise_level?: number | null;\n occupancy?: string | null;\n purchase_intent?: \"NONE\" | \"BROWSING\" | \"CONSIDERING\" | \"COMPARING\" | \"READY_TO_BUY\" | null;\n } | null;\n last_updated?: string | null;\n /** Present when screen is offline */\n message?: string;\n object?: string;\n request_id?: string;\n screen_id?: string;\n status?: \"live\" | \"offline\";\n};\n}\n\n/**\n * Find lookalike screens\n * GET /audience/lookalikes/{screenId}\n */\nexport interface getLookalikeScreensOperation {\n readonly path: \"/audience/lookalikes/{screenId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n filters?: {\n country?: string | null;\n min_similarity?: number;\n venue_type?: string | null;\n };\n matches?: Array<Record<string, unknown>>;\n matches_count?: number;\n object?: string;\n request_id?: string;\n source_screen_id?: string;\n};\n}\n\n/**\n * Predict screen audience\n * GET /audience/predict/{screenId}\n */\nexport interface predictScreenAudienceOperation {\n readonly path: \"/audience/predict/{screenId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n day_of_week?: number;\n hour_utc?: number;\n lookback_days?: number;\n /** Present when prediction is null */\n message?: string;\n object?: string;\n /** Null if insufficient historical data */\n prediction?: Record<string, unknown> | null;\n request_id?: string;\n screen_id?: string;\n};\n}\n\n/**\n * Resolved household reach for a campaign\n * GET /audience/resolved-household-reach/{campaignId}\n */\nexport interface getResolvedHouseholdReachOperation {\n readonly path: \"/audience/resolved-household-reach/{campaignId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n audience_composition?: Array<Record<string, unknown>>;\n campaign_id?: string;\n confidence_interval?: {\n lower?: number;\n upper?: number;\n };\n households_reached?: number;\n overlap_with_first_party?: number | null;\n};\n}\n\n/**\n * List audience segments\n * GET /audience/segments\n */\nexport interface listAudienceSegmentsOperation {\n readonly path: \"/audience/segments\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Array<AudienceSegment>;\n has_more?: boolean;\n object?: string;\n request_id?: string;\n total_count?: number;\n};\n}\n\n/**\n * Create audience segment\n * POST /audience/segments\n */\nexport interface createAudienceSegmentOperation {\n readonly path: \"/audience/segments\";\n readonly method: \"POST\";\n request: {\n description?: string;\n /** Segment name */\n name: string;\n rules: Array<{\n /** Rule field (e.g., venue_type, country, city, state) */\n field: string;\n /** Comparison operator (e.g., eq, neq, in, gt, lt) */\n operator: string;\n /** Rule value */\n value: unknown;\n }>;\n};\n response: AudienceSegment;\n}\n\n/**\n * Delete audience segment\n * DELETE /audience/segments/{segmentId}\n */\nexport interface deleteAudienceSegmentOperation {\n readonly path: \"/audience/segments/{segmentId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n deleted?: boolean;\n id?: string;\n object?: string;\n request_id?: string;\n};\n}\n\n/**\n * Get audience segment\n * GET /audience/segments/{segmentId}\n */\nexport interface getAudienceSegmentOperation {\n readonly path: \"/audience/segments/{segmentId}\";\n readonly method: \"GET\";\n request: never;\n response: AudienceSegment;\n}\n\n/**\n * Update audience segment\n * PATCH /audience/segments/{segmentId}\n */\nexport interface updateAudienceSegmentOperation {\n readonly path: \"/audience/segments/{segmentId}\";\n readonly method: \"PATCH\";\n request: {\n description?: string;\n is_active?: boolean;\n name?: string;\n rules?: Array<{\n field?: string;\n operator?: string;\n value?: unknown;\n }>;\n};\n response: AudienceSegment;\n}\n\n/**\n * Match screens to segment\n * POST /audience/segments/{segmentId}/match\n */\nexport interface matchAudienceSegmentOperation {\n readonly path: \"/audience/segments/{segmentId}/match\";\n readonly method: \"POST\";\n request: never;\n response: {\n matched_count?: number;\n matches?: Array<Record<string, unknown>>;\n object?: string;\n own_screens_only?: boolean;\n request_id?: string;\n segment_id?: string;\n segment_name?: string;\n};\n}\n\n/**\n * Estimate segment reach\n * POST /audience/segments/{segmentId}/reach\n */\nexport interface estimateSegmentReachOperation {\n readonly path: \"/audience/segments/{segmentId}/reach\";\n readonly method: \"POST\";\n request: never;\n response: {\n country_breakdown?: Record<string, number>;\n estimated_daily_cpm?: number;\n estimated_daily_impressions?: number;\n estimated_daily_revenue?: number;\n has_historical_data?: boolean;\n matched_screens?: number;\n object?: string;\n online_screens?: number;\n segment_id?: string;\n segment_name?: string;\n venue_breakdown?: Record<string, number>;\n};\n}\n\n/**\n * Generate VAST tag for segment\n * POST /audience/segments/{segmentId}/vast-tag\n */\nexport interface generateSegmentVastTagOperation {\n readonly path: \"/audience/segments/{segmentId}/vast-tag\";\n readonly method: \"POST\";\n request: {\n /** Click-through landing page URL */\n click_through?: string;\n /** Video creative URL */\n creative_url: string;\n /** Video duration in seconds */\n duration?: number;\n own_screens_only?: boolean;\n};\n response: {\n creative?: {\n click_through?: string | null;\n duration?: number;\n url?: string;\n };\n cust_params?: Array<string>;\n object?: string;\n screen_ids?: Array<string>;\n segment_id?: string;\n segment_name?: string;\n targeted_screens?: number;\n vast_tag_url?: string;\n};\n}\n\n/**\n * Get audience data statistics\n * GET /audience/stats\n */\nexport interface getAudienceStatsOperation {\n readonly path: \"/audience/stats\";\n readonly method: \"GET\";\n request: never;\n response: {\n data_access_tier?: \"basic\" | \"developer\" | \"enterprise\";\n newest_data?: string | null;\n object?: string;\n oldest_data?: string | null;\n request_id?: string;\n screens_with_data?: number;\n total_screens?: number;\n total_vectors?: number;\n};\n}\n\n/**\n * Cancel the partner's subscription at period end\n * POST /billing/cancel\n */\nexport interface cancelBillingSubscriptionOperation {\n readonly path: \"/billing/cancel\";\n readonly method: \"POST\";\n request: never;\n response: {\n effective_at?: string;\n status?: \"canceled\" | \"scheduled_for_cancellation\";\n};\n}\n\n/**\n * Purchase committed-use credits\n * POST /billing/credits\n */\nexport interface purchaseCreditsOperation {\n readonly path: \"/billing/credits\";\n readonly method: \"POST\";\n request: {\n /** Credit purchase tier */\n tier: \"tier_500\" | \"tier_2000\" | \"tier_5000\";\n};\n response: {\n /** Amount charged in cents */\n charged_cents?: number;\n /** Credits added to balance in cents */\n credits_added_cents?: number;\n /** Discount percentage applied */\n discount_pct?: number;\n object?: string;\n /** Stripe PaymentIntent ID */\n payment_intent_id?: string;\n request_id?: string;\n};\n}\n\n/**\n * Create Stripe Checkout session for credits\n * POST /billing/credits/checkout\n */\nexport interface createCreditCheckoutOperation {\n readonly path: \"/billing/credits/checkout\";\n readonly method: \"POST\";\n request: {\n /** URL to redirect if payment is cancelled */\n cancel_url?: string;\n /** URL to redirect after successful payment */\n success_url?: string;\n tier: \"tier_500\" | \"tier_2000\" | \"tier_5000\";\n};\n response: {\n /** Stripe Checkout URL — redirect user here */\n checkout_url?: string;\n message?: string;\n object?: string;\n request_id?: string;\n /** Stripe Checkout session ID */\n session_id?: string;\n};\n}\n\n/**\n * List available partner billing plans\n * GET /billing/plans\n */\nexport interface listBillingPlansOperation {\n readonly path: \"/billing/plans\";\n readonly method: \"GET\";\n request: never;\n response: {\n plans?: Array<{\n included_ads?: number;\n included_impressions?: number;\n overage_per_1k_impressions_cents?: number;\n price_cents_monthly?: number;\n tier?: string;\n }>;\n};\n}\n\n/**\n * Set up usage-based billing\n * POST /billing/setup\n */\nexport interface setupBillingOperation {\n readonly path: \"/billing/setup\";\n readonly method: \"POST\";\n request: {\n /** Stripe payment method token obtained from Stripe.js or Stripe Elements */\n payment_method_id: string;\n};\n response: {\n billing_status?: string;\n message?: string;\n object?: string;\n request_id?: string;\n stripe_customer_id?: string;\n};\n}\n\n/**\n * Subscribe the partner to a billing plan\n * POST /billing/subscribe\n */\nexport interface createBillingSubscriptionOperation {\n readonly path: \"/billing/subscribe\";\n readonly method: \"POST\";\n request: {\n tier: \"developer\" | \"enterprise\";\n};\n response: {\n checkout_url?: string | null;\n status?: \"active\" | \"requires_payment\";\n};\n}\n\n/**\n * Get the partner's current subscription\n * GET /billing/subscription\n */\nexport interface getBillingSubscriptionOperation {\n readonly path: \"/billing/subscription\";\n readonly method: \"GET\";\n request: never;\n response: {\n current_period_end?: string;\n status?: \"active\" | \"past_due\" | \"canceled\" | \"trialing\";\n stripe_customer_id?: string | null;\n tier?: string;\n};\n}\n\n/**\n * Get the partner's current-period usage\n * GET /billing/usage\n */\nexport interface getBillingUsageOperation {\n readonly path: \"/billing/usage\";\n readonly method: \"GET\";\n request: never;\n response: {\n ads_served?: number;\n audience_api_calls?: number;\n impressions?: number;\n overage_projection_cents?: number;\n period_end?: string;\n period_start?: string;\n};\n}\n\n/**\n * Get current billing period usage\n * GET /billing/usage-summary\n */\nexport interface getBillingUsageSummaryOperation {\n readonly path: \"/billing/usage-summary\";\n readonly method: \"GET\";\n request: never;\n response: {\n /** Current billing status */\n billing_status?: \"none\" | \"active\" | \"suspended\";\n /** Remaining prepaid credit balance in cents */\n credit_balance_cents?: number;\n object?: string;\n /** End of current billing period */\n period_end?: string;\n /** Start of current billing period */\n period_start?: string;\n /** Per-product usage breakdown */\n products?: Record<string, {\n meters?: Record<string, {\n billable?: number;\n cost_cents?: number;\n free_quota?: number;\n usage?: number;\n }>;\n }>;\n request_id?: string;\n /** Total cost in cents for current period */\n total_cost_cents?: number;\n};\n}\n\n/**\n * Stripe webhook callback\n * POST /billing/webhook\n */\nexport interface stripeWebhookCallbackOperation {\n readonly path: \"/billing/webhook\";\n readonly method: \"POST\";\n request: Record<string, unknown>;\n response: unknown;\n}\n\n/**\n * Get partner dashboard overview\n * GET /connect/dashboard\n */\nexport interface getConnectDashboardOperation {\n readonly path: \"/connect/dashboard\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n charts?: {\n daily_impressions?: Array<{\n date?: string;\n earnings_cents?: number;\n impressions?: number;\n }>;\n hourly_today?: Array<{\n hour?: number;\n impressions?: number;\n }>;\n };\n earnings?: {\n available_cents?: number;\n daily_average_cents?: number;\n lifetime_cents?: number;\n pending_payout_cents?: number;\n period_cents?: number;\n today_cents?: number;\n };\n impressions?: {\n all_time?: number;\n daily_average?: number;\n period?: number;\n today?: number;\n trend_percent?: number;\n };\n partner?: {\n cpm_cents?: number;\n name?: string;\n revenue_share_percent?: number;\n slug?: string;\n status?: string;\n stripe_status?: \"pending\" | \"active\" | \"restricted\" | \"not_connected\";\n };\n period?: {\n days?: number;\n end?: string;\n start?: string;\n };\n screens?: {\n offline?: number;\n online?: number;\n pending?: number;\n total?: number;\n };\n top_screens?: Array<{\n earnings_cents?: number;\n impressions?: number;\n location?: string | null;\n name?: string;\n screen_id?: string;\n status?: \"online\" | \"offline\" | \"unknown\";\n }>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get earnings chart data\n * GET /connect/earnings\n */\nexport interface getConnectEarningsChartOperation {\n readonly path: \"/connect/earnings\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n chart?: Array<{\n avg_view_duration_ms?: number;\n date?: string;\n earnings_cents?: number;\n impressions?: number;\n label?: string;\n unique_screens?: number;\n }>;\n period?: {\n days?: number;\n end?: string;\n start?: string;\n };\n summary?: {\n data_points?: number;\n group_by?: string;\n total_earnings_cents?: number;\n total_impressions?: number;\n };\n };\n success?: boolean;\n};\n}\n\n/**\n * Get screen health status\n * GET /connect/health\n */\nexport interface getConnectScreenHealthOperation {\n readonly path: \"/connect/health\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n checked_at?: string;\n filter?: string;\n screens?: Array<{\n device_id?: string;\n external_device_id?: string;\n fingerprint?: string;\n last_heartbeat?: string | null;\n last_seen?: string | null;\n location?: {\n city?: string | null;\n lat?: number | null;\n lng?: number | null;\n state?: string | null;\n };\n name?: string;\n registered_at?: string;\n screen_id?: string | null;\n screen_status?: \"pending\" | \"active\" | \"inactive\";\n status?: \"online\" | \"offline\" | \"never_connected\" | \"unknown\";\n time_since_last_seen_seconds?: number | null;\n uptime_24h_percent?: number | null;\n venue_type?: string | null;\n }>;\n summary?: {\n never_connected?: number;\n offline?: number;\n online?: number;\n total?: number;\n };\n };\n success?: boolean;\n};\n}\n\n/**\n * List content presets\n * GET /content-presets\n */\nexport interface listContentPresetsOperation {\n readonly path: \"/content-presets\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Array<ContentPreset>;\n has_more?: boolean;\n object?: string;\n total_count?: number;\n url?: string;\n};\n}\n\n/**\n * Get content preset\n * GET /content-presets/{presetId}\n */\nexport interface getContentPresetOperation {\n readonly path: \"/content-presets/{presetId}\";\n readonly method: \"GET\";\n request: never;\n response: ContentPreset;\n}\n\n/**\n * Submit a creative for classification\n * POST /creatives\n */\nexport interface submitPartnerCreativeOperation {\n readonly path: \"/creatives\";\n readonly method: \"POST\";\n request: {\n /** Optional advertiser/brand label to attach. */\n advertiser_name?: string;\n /** Public http(s) URL of the creative image or video. Must resolve to a public address — private/internal/cloud-metadata addresses are rejected. */\n media_url: string;\n};\n response: CreativeClassification;\n}\n\n/**\n * Get a creative classification\n * GET /creatives/{ref}\n */\nexport interface getPartnerCreativeOperation {\n readonly path: \"/creatives/{ref}\";\n readonly method: \"GET\";\n request: never;\n response: CreativeClassification;\n}\n\n/**\n * Get dashboard overview\n * GET /dashboard\n */\nexport interface getDashboardOperation {\n readonly path: \"/dashboard\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: DashboardResponse;\n success?: boolean;\n};\n}\n\n/**\n * Export the cross-screen proximity graph edge list\n * GET /data-export/proximity-graph-edges\n */\nexport interface exportProximityGraphEdgesOperation {\n readonly path: \"/data-export/proximity-graph-edges\";\n readonly method: \"GET\";\n request: never;\n response: unknown;\n}\n\n/**\n * List available datasets and per-dataset record counts\n * GET /data-export/summary\n */\nexport interface getDataExportSummaryOperation {\n readonly path: \"/data-export/summary\";\n readonly method: \"GET\";\n request: never;\n response: DataExportSummaryResponse;\n}\n\n/**\n * Export a partner-scoped dataset\n * GET /data-export/{dataset}\n */\nexport interface exportDatasetOperation {\n readonly path: \"/data-export/{dataset}\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n k_anonymity_threshold?: number;\n lookback_days?: number;\n /** Row shape depends on the requested `dataset`. For `audience_loyalty_features` see `AudienceLoyaltyFeaturesRow`. For other datasets the row shape is documented per-dataset in the Trillboards data dictionary. */\n rows?: Array<AudienceLoyaltyFeaturesRow | Record<string, unknown>>;\n total?: number;\n truncated?: boolean;\n };\n success?: boolean;\n};\n}\n\n/**\n * Geographic audience-density panel (data-licensing)\n * GET /data/geohash-audience-panel\n */\nexport interface getGeohashAudiencePanelOperation {\n readonly path: \"/data/geohash-audience-panel\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** True when the daily epsilon budget cannot accommodate this request. `rows` is empty in this case; no epsilon is deducted. */\n budget_exhausted?: boolean;\n /** Day exported (UTC). */\n date: string;\n /** Epsilon spent on this call (0 if `budget_exhausted` or CH unavailable). Deducted from `partner_dp_budget.epsilon_spent` on success. */\n epsilon_used: number;\n /** K-anonymity floor applied at SQL `HAVING`. Default 5; override via `partners.k_anon_floor`. */\n k_anonymity_threshold: number;\n partner_dp_budget: {\n /** Maximum epsilon allowed per day for this partner. */\n epsilon_max: number;\n /** Epsilon already spent today before this call. */\n epsilon_spent_before: number;\n };\n /** UUID partner_id (from `partners.partner_id`, migration 030). */\n partner_id: string;\n /** Noised per-row aggregates (k-anon-filtered + Laplace-perturbed). */\n rows: Array<{\n /** Noised average attention score (Laplace, sensitivity 0.1). */\n avg_attention: number;\n /** Noised average dwell seconds (Laplace, sensitivity 5). */\n avg_dwell_seconds: number;\n /** Noised average face count per observation (Laplace, sensitivity 1). */\n avg_face_count: number;\n /** 6-character geohash bucket. */\n geohash6: string;\n /** Hour bucket as the integer hour (0..23) cast to string. */\n hour: string;\n /** Income tier bucket (e.g. `low`, `mid`, `high`). */\n income_tier: string;\n /** Noised observation count (Laplace, sensitivity 1). */\n observation_count: number;\n /** Distinct screen count contributing to this bucket. */\n screen_count: number;\n /** Noised unique-device count (Laplace, sensitivity 1). */\n unique_devices: number;\n /** Venue category from `screens_live.venue_category`. */\n venue_category: string;\n }>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Outcome-attribution export (data-licensing)\n * GET /data/outcome-attribution\n */\nexport interface getOutcomeAttributionOperation {\n readonly path: \"/data/outcome-attribution\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** DP epsilon charged to the partner's daily budget for this call (0 if refunded). */\n epsilon_used: number;\n /** The reach grain applied (echoes the `grain` query param; defaults to `person`). */\n grain: \"person\" | \"device\";\n /** The per-partner k-anon floor applied at SQL HAVING. */\n k_anonymity_threshold: number;\n /** The validated lookback window used. */\n lookback_days: number;\n /** Daily DP budget snapshot at reservation time. */\n partner_dp_budget: {\n epsilon_max?: number;\n epsilon_spent_before?: number;\n };\n /** Noised per-(creative, screen) outcome aggregates (k-anon-filtered + Laplace-perturbed). */\n rows: Array<{\n /** Noised average exposures per reach-identity within the (creative, screen) cell (count of detail rows / distinct reach keys). A frequency over PEOPLE under person grain, over devices under device grain. */\n avg_frequency: number;\n /** Creative identifier from `completed_impressions.creative_id`. */\n creative_id: string;\n /** Noised count of exposed identities also seen on another screen. */\n cross_screen_devices: number;\n /** Noised count of distinct devices exposed to the creative on the screen. */\n exposed_devices: number;\n /** returned_devices / exposed_devices, recomputed from the noised counts. */\n return_rate: number;\n /** Noised count of exposed devices that returned (clamped ≤ exposed_devices). */\n returned_devices: number;\n /** The partner's own screen identifier. */\n screen_mongo_id: string;\n }>;\n /** Number of rows returned. */\n total: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Register a device\n * POST /device\n */\nexport interface registerDeviceOperation {\n readonly path: \"/device\";\n readonly method: \"POST\";\n request: {\n /** Any additional metadata for your records */\n custom_metadata?: Record<string, unknown>;\n /** Screen or venue description for enrichment */\n description?: string;\n /** Your internal device identifier */\n device_id: string;\n device_type?: \"vending_machine\" | \"kiosk\" | \"tablet\" | \"display\" | \"other\";\n /** Screen display specification. `width`/`height` are pixel resolution; `width_in`/`height_in` are physical inches. For accurate floor pricing we need physical inches — pass `width_in` + `height_in` if you've measured the screen, OR `ppi` so the server can derive inches from the pixel resolution. Pixel-only inputs (no `ppi`, no `*_in`) will NOT be recorded as physical size; they're still used for orientation detection and DSP slot dimensions. */\n display?: {\n /** Display resolution height in pixels (e.g. 1080) */\n height?: number;\n /** Physical screen height in INCHES. Pairs with `width_in`. */\n height_in?: number;\n orientation?: \"landscape\" | \"portrait\";\n /** Pixels per inch. Required if you want physical screen size derived from `width`/`height` (server computes widthInches = width / ppi). Typical: 40 (large TV), 96 (desktop monitor), 264 (tablet). */\n ppi?: number;\n /** Display resolution width in pixels (e.g. 1920) */\n width?: number;\n /** Physical screen width in INCHES. Overrides ppi-based derivation. Use this when you've measured the actual screen (most accurate for pricing). */\n width_in?: number;\n };\n display_settings?: PartnerRegistrationDisplaySettings;\n location?: {\n address?: string;\n city?: string;\n country?: string;\n lat?: number;\n lng?: number;\n state?: string;\n timezone?: string;\n venue_name?: string;\n venue_type?: \"mall\" | \"airport\" | \"retail\" | \"restaurant\" | \"office\" | \"gym\" | \"hospital\" | \"school\" | \"other\";\n zip?: string;\n };\n /** Reporting hints for moving screens (mobility_type mobile/semi_mobile). */\n mobile_settings?: {\n /** Minimum displacement before a fix is sent (device-side hint). */\n distance_threshold_meters?: number;\n /** Target GPS reporting interval (floor — the platform adapts to speed/battery). */\n update_interval_seconds?: number;\n vehicle_type?: \"taxi\" | \"rideshare\" | \"delivery\" | \"bus\" | \"food_truck\" | \"other\";\n };\n /** Declare a moving screen. `mobile` (taxi-top, transit) and `semi_mobile` (food truck, pop-up) screens report GPS via the heartbeat `location` field; `static` (default) screens ignore it. */\n mobility_type?: \"static\" | \"mobile\" | \"semi_mobile\";\n /** Friendly name for the device */\n name?: string;\n /** Photo URL for enrichment context */\n photo_url?: string;\n /** Optional additional photos for enrichment */\n photos?: Array<{\n /** photo type (context, close, angle, other) */\n type?: string;\n url?: string;\n }>;\n /** Physical placement details (optional) */\n placement?: {\n height_from_floor_ft?: number;\n mounting_type?: \"wall\" | \"ceiling\" | \"tabletop\" | \"window\" | \"stand\" | \"freestanding\" | \"floor_stand\" | \"counter\" | \"pole\" | \"vehicle\" | \"other\" | \"unknown\";\n orientation?: \"landscape\" | \"portrait\";\n viewing_distance_ft?: number;\n };\n /** Venue classification details (optional). Subcategory is free text and may be auto-enriched by AI. */\n venue?: {\n business_name?: string;\n category?: \"retail\" | \"restaurant\" | \"bar\" | \"cafe\" | \"hotel\" | \"office\" | \"gym\" | \"hospital\" | \"school\" | \"mall\" | \"airport\" | \"gas_station\" | \"convenience_store\" | \"laundromat\" | \"salon\" | \"auto_shop\" | \"other\";\n context_notes?: string;\n environment_type?: \"indoor\" | \"outdoor\" | \"semi_outdoor\" | \"transit\";\n placement_type?: \"digital_signage\" | \"point_of_sale\" | \"waiting_area\" | \"window_display\" | \"kiosk\" | \"other\";\n /** Free text subcategory (may be auto-enriched by AI) */\n subcategory?: string;\n };\n};\n response: {\n data?: {\n /** Our internal device ID */\n device_id?: string;\n /** Load this URL in your WebView */\n embed_url?: string;\n /** Enrichment completion state */\n enrichment_status?: string;\n /** Your device ID */\n external_device_id?: string;\n /** Device fingerprint for SDK */\n fingerprint?: string;\n /** Stripe-style readiness. `ready` — coordinates present and venue classified. `limited` — coordinates present, not yet classified (servable, missing venue/floor). `blocked` — no usable coordinates, or classification permanently failed. */\n monetization_status?: \"ready\" | \"limited\" | \"blocked\";\n requirements?: PartnerMonetizationRequirements;\n /** Linked screen ID */\n screen_id?: string;\n status?: string;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Delete a device\n * DELETE /device/{deviceId}\n */\nexport interface deleteDeviceOperation {\n readonly path: \"/device/{deviceId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get device info\n * GET /device/{deviceId}\n */\nexport interface getDeviceOperation {\n readonly path: \"/device/{deviceId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Device;\n success?: boolean;\n};\n}\n\n/**\n * Update device metadata\n * PATCH /device/{deviceId}\n */\nexport interface updateDeviceOperation {\n readonly path: \"/device/{deviceId}\";\n readonly method: \"PATCH\";\n request: {\n /** Any additional metadata for your records */\n custom_metadata?: Record<string, unknown>;\n /** Screen or venue description */\n description?: string;\n /** Screen display specification. `width`/`height` are pixels; pass `width_in`/`height_in` (inches) or `ppi` to record physical screen size for floor pricing. See POST /device for full unit semantics. */\n display?: {\n /** Display resolution height in pixels */\n height?: number;\n /** Physical screen height in inches (pairs with width_in) */\n height_in?: number;\n orientation?: \"landscape\" | \"portrait\";\n /** Pixels per inch (required to derive physical size from width/height) */\n ppi?: number;\n /** Display resolution width in pixels */\n width?: number;\n /** Physical screen width in inches (overrides ppi-based derivation) */\n width_in?: number;\n };\n /** Partner-owned device ID used for idempotent lookup and reconciliation */\n external_device_id?: string;\n location?: {\n address?: string;\n city?: string;\n country?: string;\n lat?: number;\n lng?: number;\n state?: string;\n timezone?: string;\n /** Alias for `venue.category` — a granular venue type. Accepted on PATCH (previously documented on register only). When both are sent, `venue.category` wins. On the response this field returns the OpenOOH CHILD slug (e.g. \"hotels\"/\"malls\"); `venue.category` returns the parent. */\n venue_type?: \"mall\" | \"airport\" | \"retail\" | \"restaurant\" | \"office\" | \"gym\" | \"hospital\" | \"school\" | \"other\";\n zip?: string;\n };\n /** Reporting hints for moving screens. Merges with existing settings. */\n mobile_settings?: {\n distance_threshold_meters?: number;\n update_interval_seconds?: number;\n vehicle_type?: \"taxi\" | \"rideshare\" | \"delivery\" | \"bus\" | \"food_truck\" | \"other\";\n };\n /** Update the screen's mobility. Set `mobile`/`semi_mobile` to have the heartbeat `location` field accepted for a moving screen. */\n mobility_type?: \"static\" | \"mobile\" | \"semi_mobile\";\n /** Friendly name for the device */\n name?: string;\n photo_url?: string;\n photos?: Array<{\n type?: string;\n url?: string;\n }>;\n placement?: {\n height_from_floor_ft?: number;\n mounting_type?: \"wall\" | \"ceiling\" | \"tabletop\" | \"window\" | \"stand\" | \"freestanding\" | \"floor_stand\" | \"counter\" | \"pole\" | \"vehicle\" | \"other\" | \"unknown\";\n orientation?: \"landscape\" | \"portrait\";\n viewing_distance_ft?: number;\n };\n venue?: {\n business_name?: string;\n /** Granular venue type on WRITE (child-level slug). On READ this returns the resolved OpenOOH PARENT (e.g. \"hotel\" write -> \"entertainment\" read); the child slug rides `venue.subcategory` and the numeric child id rides `venue.openooh_venue_type_id`. */\n category?: \"retail\" | \"restaurant\" | \"bar\" | \"cafe\" | \"hotel\" | \"office\" | \"gym\" | \"hospital\" | \"school\" | \"mall\" | \"airport\" | \"gas_station\" | \"convenience_store\" | \"laundromat\" | \"salon\" | \"auto_shop\" | \"other\";\n context_notes?: string;\n environment_type?: \"indoor\" | \"outdoor\" | \"semi_outdoor\" | \"transit\";\n /** Response-only. Canonical OpenOOH child id to reconcile the declared venue type against (e.g. 807 for hotels). */\n openooh_venue_type_id?: number;\n placement_type?: \"digital_signage\" | \"point_of_sale\" | \"waiting_area\" | \"window_display\" | \"kiosk\" | \"other\";\n /** OpenOOH child slug (e.g. \"hotels\"). Free text on write; resolved on read. */\n subcategory?: string;\n };\n};\n response: {\n data?: Device;\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get ads for device\n * GET /device/{deviceId}/ads\n */\nexport interface getAdsForDeviceOperation {\n readonly path: \"/device/{deviceId}/ads\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n ads?: Array<Ad>;\n cache_until?: string;\n /** Pending device commands to execute (remote management). */\n commands?: Array<{\n command?: string;\n id?: string;\n payload?: Record<string, unknown>;\n queued_at?: string;\n }>;\n /** Venue/content keywords for contextual targeting. Omitted from the response when empty. */\n content_keywords?: Array<string>;\n device?: {\n display?: {\n height?: number | null;\n width?: number | null;\n };\n fingerprint?: string;\n };\n /** DOOH context signals (venue type, geo, audience) forwarded to demand. */\n dooh_signals?: Record<string, unknown>;\n header_bidding_settings?: HeaderBiddingSettings;\n /** URL of the Trillboards-hosted IMA renderer for this screen, or null when the IMA player is not enabled for this deployment / there is no waterfall source. */\n ima_player_url?: string | null;\n screen_dimensions?: {\n height?: number;\n orientation?: \"portrait\" | \"landscape\";\n width?: number;\n };\n screen_id?: string;\n /** Serve locale derived from the venue country (e.g. \"en\", \"fr\"). */\n screen_locale?: string;\n screen_name?: string | null;\n screen_orientation?: \"portrait\" | \"landscape\";\n settings?: AdSettings;\n };\n success?: boolean;\n};\n}\n\n/**\n * Acknowledge a device command\n * POST /device/{deviceId}/commands/{commandId}/ack\n */\nexport interface ackDeviceCommandOperation {\n readonly path: \"/device/{deviceId}/commands/{commandId}/ack\";\n readonly method: \"POST\";\n request: {\n /** Command execution result */\n result?: Record<string, unknown>;\n /** Acknowledgment status */\n status?: string;\n};\n response: {\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Read live device heartbeat state\n * GET /device/{deviceId}/heartbeat\n */\nexport interface getDeviceHeartbeatOperation {\n readonly path: \"/device/{deviceId}/heartbeat\";\n readonly method: \"GET\";\n request: never;\n response: PartnerHeartbeatQueryResponse;\n}\n\n/**\n * Device heartbeat\n * POST /device/{deviceId}/heartbeat\n */\nexport interface heartbeatOperation {\n readonly path: \"/device/{deviceId}/heartbeat\";\n readonly method: \"POST\";\n request: PartnerHeartbeatRequest | PartnerDeviceHeartbeatBody;\n response: PartnerHeartbeatResponse;\n}\n\n/**\n * Record programmatic ad event (Server-side Analytics)\n * POST /device/{deviceId}/programmatic-event\n */\nexport interface recordProgrammaticEventOperation {\n readonly path: \"/device/{deviceId}/programmatic-event\";\n readonly method: \"POST\";\n request: {\n ad_id?: string;\n error_code?: string;\n error_message?: string;\n event: \"ad_started\" | \"ad_ended\" | \"no_fill\" | \"error\";\n reason?: string;\n request_id?: string;\n screen_orientation?: \"portrait\" | \"landscape\";\n slot_height?: number;\n slot_width?: number;\n variant_name?: string;\n};\n response: {\n success?: boolean;\n};\n}\n\n/**\n * List all devices\n * GET /devices\n */\nexport interface listDevicesOperation {\n readonly path: \"/devices\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n devices?: Array<DeviceSummary>;\n limit?: number;\n offset?: number;\n total?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Register a device (V2 single-call onboarding)\n * POST /devices\n */\nexport interface registerDeviceV2Operation {\n readonly path: \"/devices\";\n readonly method: \"POST\";\n request: {\n /** Optional display dimensions. One of three modes — the `mode` discriminator is required. */\n display?: {\n /** Physical screen height in INCHES. Pairs with `width_in`. */\n height_in: number;\n mode: \"inches\";\n /** Physical screen width in INCHES. No upper bound — large-format / billboard inventory is valid. */\n width_in: number;\n } | {\n height: number;\n mode: \"pixels_with_ppi\";\n ppi: number;\n width: number;\n } | {\n height: number;\n mode: \"pixels_only\";\n width: number;\n };\n /** Your stable per-device identifier (e.g. \"REC00005\"). */\n external_id: string;\n /** Optional hardware identity — improves DSP device matching. */\n hardware?: {\n make?: string;\n model?: string;\n os?: \"Android\" | \"iOS\" | \"Tizen\" | \"WebOS\" | \"Linux\" | \"FireOS\" | \"Other\";\n osv?: string;\n };\n /** Optional venue location — either lat/lng coordinates or a street address. */\n location?: {\n lat: number;\n lng: number;\n } | {\n address: string;\n };\n /** The device's real WebView User-Agent. Must include a Build fingerprint and be unique per device. */\n ua: string;\n};\n response: {\n data?: {\n device_id?: string;\n diagnostics_url?: string;\n /** Paste into an iframe to start serving. */\n embed_url?: string;\n /** Server-derived canonical device identity. */\n identity?: {\n derivation_confidence?: number | null;\n derivation_source?: string | null;\n device_class?: string | null;\n make?: string | null;\n model?: string | null;\n os?: string | null;\n osv?: string | null;\n };\n };\n success?: boolean;\n};\n}\n\n/**\n * Bulk register devices\n * POST /devices/batch\n */\nexport interface registerDevicesBatchOperation {\n readonly path: \"/devices/batch\";\n readonly method: \"POST\";\n request: {\n /** Default fields applied to each device */\n defaults?: {\n display_settings?: PartnerRegistrationDisplaySettings;\n };\n devices: Array<{\n device_id: string;\n device_type?: string;\n display?: Record<string, unknown>;\n display_settings?: PartnerRegistrationDisplaySettings;\n location?: Record<string, unknown>;\n name?: string;\n placement?: Record<string, unknown>;\n venue?: Record<string, unknown>;\n }>;\n};\n response: {\n devices?: Array<{\n device_id?: string;\n fingerprint?: string;\n screen_id?: string;\n status?: string;\n trillboard_id?: string;\n }>;\n errors?: Array<{\n device_id?: string;\n error?: string;\n status?: string;\n }>;\n success?: boolean;\n summary?: {\n created?: number;\n failed?: number;\n total?: number;\n updated?: number;\n };\n};\n}\n\n/**\n * Batch update screen orientation\n * POST /devices/batch/orientation\n */\nexport interface batchUpdateDeviceOrientationOperation {\n readonly path: \"/devices/batch/orientation\";\n readonly method: \"POST\";\n request: {\n device_ids: Array<string>;\n screen_orientation: \"portrait\" | \"landscape\" | \"mixed\" | \"unknown\";\n};\n response: {\n matched_devices?: number;\n missing_device_ids?: Array<string>;\n success?: boolean;\n total_devices?: number;\n updated_screens?: number;\n};\n}\n\n/**\n * Reconcile device fleet\n * POST /devices/reconcile\n */\nexport interface reconcileDevicesOperation {\n readonly path: \"/devices/reconcile\";\n readonly method: \"POST\";\n request: {\n /** Your device external IDs to reconcile. */\n external_ids: Array<string>;\n};\n response: {\n duplicate?: Array<Record<string, unknown>>;\n malformed?: Array<Record<string, unknown>>;\n matched?: Array<Record<string, unknown>>;\n missing?: Array<string>;\n orphan?: Array<Record<string, unknown>>;\n success?: boolean;\n summary?: {\n duplicate?: number;\n malformed?: number;\n matched?: number;\n missing?: number;\n orphan?: number;\n registered_active?: number;\n requested?: number;\n };\n truncated?: Record<string, unknown>;\n};\n}\n\n/**\n * Browsable HTML documentation index\n * GET /docs\n */\nexport interface partnerDocsBrowserOperation {\n readonly path: \"/docs\";\n readonly method: \"GET\";\n request: never;\n response: unknown;\n}\n\n/**\n * Get earnings summary\n * GET /earnings\n */\nexport interface getEarningsOperation {\n readonly path: \"/earnings\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: EarningsResponse;\n success?: boolean;\n};\n}\n\n/**\n * Get detailed earnings breakdown\n * GET /earnings/breakdown\n */\nexport interface getEarningsBreakdownOperation {\n readonly path: \"/earnings/breakdown\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: EarningsBreakdownResponse;\n success?: boolean;\n};\n}\n\n/**\n * Request a payout\n * POST /earnings/payout\n */\nexport interface requestPayoutOperation {\n readonly path: \"/earnings/payout\";\n readonly method: \"POST\";\n request: {\n /** Amount to payout in cents (optional, defaults to available balance) */\n amount_cents?: number;\n};\n response: {\n data?: PayoutResponse;\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get transaction history\n * GET /earnings/transactions\n */\nexport interface getTransactionsOperation {\n readonly path: \"/earnings/transactions\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n pagination?: Pagination;\n transactions?: Array<Transaction>;\n };\n success?: boolean;\n};\n}\n\n/**\n * List active SSE connections\n * GET /events/connections\n */\nexport interface getActiveSSEConnectionsOperation {\n readonly path: \"/events/connections\";\n readonly method: \"GET\";\n request: never;\n response: {\n connections?: Array<{\n connected_at?: string;\n connection_id?: string;\n ip?: string;\n subscribed_events?: Array<string>;\n }>;\n count?: number;\n max_connections?: number;\n object?: string;\n};\n}\n\n/**\n * Subscribe to real-time events (SSE)\n * GET /events/stream\n */\nexport interface subscribeToEventsOperation {\n readonly path: \"/events/stream\";\n readonly method: \"GET\";\n request: never;\n response: unknown;\n}\n\n/**\n * Poll a fleet-command job\n * GET /fleet-commands/{id}\n */\nexport interface getFleetCommandOperation {\n readonly path: \"/fleet-commands/{id}\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n fleet_command?: FleetCommand;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get fleet analytics\n * GET /fleet/analytics\n */\nexport interface getFleetAnalyticsOperation {\n readonly path: \"/fleet/analytics\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** Average attention score (0-1) */\n avg_attention?: number;\n /** Average CPM in dollars */\n avg_cpm?: number;\n /** Fill rate percentage (0-100) */\n fill_rate_pct?: number;\n impressions_24h?: number;\n screen_count?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Push command to fleet\n * POST /fleet/command\n */\nexport interface pushFleetCommandOperation {\n readonly path: \"/fleet/command\";\n readonly method: \"POST\";\n request: {\n command: {\n /** Command-specific data */\n payload?: Record<string, unknown>;\n type: \"reload\" | \"update_settings\" | \"restart\" | \"screenshot\" | \"clear_cache\" | \"update_content\" | \"refresh_ads\" | \"update_config\" | \"get_state\" | \"show_ad\" | \"play_ad\";\n };\n /** Optional filter to target specific devices */\n filter?: {\n country?: string;\n /** A screen group id (sg_) whose members are targeted (unioned with screenIds). */\n group?: string;\n screenIds?: Array<string>;\n venueType?: string;\n };\n};\n response: {\n data?: {\n errors?: Array<{\n error?: string;\n screenId?: string;\n }>;\n /** Devices successfully queued */\n queued?: number;\n /** Total devices matching filter */\n targeted?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get fleet overview\n * GET /fleet/overview\n */\nexport interface getFleetOverviewOperation {\n readonly path: \"/fleet/overview\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n countries?: Record<string, number>;\n offline?: number;\n online?: number;\n programmatic_enabled?: number;\n total_devices?: number;\n venue_types?: Record<string, number>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Update fleet-wide settings\n * POST /fleet/settings\n */\nexport interface updateFleetSettingsOperation {\n readonly path: \"/fleet/settings\";\n readonly method: \"POST\";\n request: {\n filter?: {\n country?: string;\n /** A screen group id (sg_) whose members are targeted (unioned with screenIds). */\n group?: string;\n screenIds?: Array<string>;\n venueType?: string;\n };\n /** Settings to update (merged with existing) */\n settings: {\n content_preferences?: Record<string, unknown>;\n display_settings?: Record<string, unknown>;\n header_bidding_settings?: {\n allocation?: number;\n enabled?: boolean;\n force_request?: boolean;\n min_interval_seconds?: number;\n };\n };\n};\n response: {\n data?: {\n errors?: Array<Record<string, unknown>>;\n targeted?: number;\n updated?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Record impression (pixel)\n * GET /impression\n */\nexport interface recordImpressionGetOperation {\n readonly path: \"/impression\";\n readonly method: \"GET\";\n request: never;\n response: {\n duplicate?: boolean;\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Record impression (POST)\n * POST /impression\n */\nexport interface recordImpressionPostOperation {\n readonly path: \"/impression\";\n readonly method: \"POST\";\n request: {\n adid: string;\n aid?: string;\n completed?: boolean;\n did?: string;\n display_area_ratio?: number;\n display_mode?: \"fullscreen\" | \"l-bar\" | \"pip\";\n duration?: number;\n impid: string;\n lbar_position?: \"bottom\" | \"right\";\n lbar_size?: number;\n lbar_slot_count?: number;\n lbar_slot_index?: number;\n sid?: string;\n sig?: string;\n sig_ts?: number;\n};\n response: {\n duplicate?: boolean;\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Batch record impressions\n * POST /impressions/batch\n */\nexport interface recordImpressionsBatchOperation {\n readonly path: \"/impressions/batch\";\n readonly method: \"POST\";\n request: {\n impressions: Array<{\n adid: string;\n aid?: string;\n completed?: boolean;\n device_fingerprint?: string;\n did?: string;\n display_area_ratio?: number;\n display_mode?: \"fullscreen\" | \"l-bar\" | \"pip\";\n duration?: number;\n impid: string;\n lbar_position?: \"bottom\" | \"right\";\n lbar_size?: number;\n lbar_slot_count?: number;\n lbar_slot_index?: number;\n sid?: string;\n sig?: string;\n sig_ts?: number;\n timestamp?: string;\n }>;\n};\n response: {\n data?: {\n errors?: Array<{\n error?: string;\n impid?: string;\n }>;\n failed?: number;\n recorded?: number;\n skipped?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get partner info\n * GET /info\n */\nexport interface getPartnerInfoOperation {\n readonly path: \"/info\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: Partner;\n success?: boolean;\n};\n}\n\n/**\n * List intent categories\n * GET /intent/categories\n */\nexport interface listIntentCategoriesOperation {\n readonly path: \"/intent/categories\";\n readonly method: \"GET\";\n request: never;\n response: {\n count?: number;\n data?: Array<{\n description?: string;\n id?: string;\n /** Minimum intent score to match this category */\n min_intent_score?: number;\n name?: string;\n /** CPM multiplier applied when this intent is detected */\n premium_multiplier?: number;\n purchase_stages?: Array<\"READY_TO_BUY\" | \"COMPARING\" | \"CONSIDERING\" | \"BROWSING\">;\n }>;\n object?: string;\n};\n}\n\n/**\n * Get intent category details\n * GET /intent/categories/{categoryId}\n */\nexport interface getIntentCategoryOperation {\n readonly path: \"/intent/categories/{categoryId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n description?: string;\n iab_segments?: Array<Record<string, unknown>>;\n id?: string;\n min_intent_score?: number;\n name?: string;\n object?: string;\n premium_multiplier?: number;\n purchase_stages?: Array<string>;\n triggers?: Array<string>;\n};\n}\n\n/**\n * Get intent-based pricing for a screen\n * GET /intent/pricing/{screenId}\n */\nexport interface getIntentPricingOperation {\n readonly path: \"/intent/pricing/{screenId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n category_match?: {\n category_id?: string;\n category_name?: string;\n intent_score?: number;\n premium_multiplier?: number;\n purchase_stage?: string;\n } | null;\n current_intent?: {\n categories?: Array<string>;\n purchase_stage?: \"NONE\" | \"BROWSING\" | \"CONSIDERING\" | \"COMPARING\" | \"READY_TO_BUY\";\n /** Intent confidence score (0-1) */\n score?: number;\n /** Whether an ad swap should be triggered */\n should_trigger?: boolean;\n };\n object?: string;\n pricing?: {\n base_cpm?: number;\n category_id?: string;\n category_name?: string;\n /** Effective CPM after intent premium */\n intent_cpm?: number;\n /** Additional CPM from intent detection */\n intent_premium?: number;\n premium_multiplier?: number;\n };\n screen_id?: string;\n};\n}\n\n/**\n * Trillboards measurement methodology disclosure\n * GET /measurement-methodology\n */\nexport interface getMeasurementMethodologyOperation {\n readonly path: \"/measurement-methodology\";\n readonly method: \"GET\";\n request: never;\n response: MeasurementMethodology;\n}\n\n/**\n * Measurement methodology disclosure (JSON, no negotiation)\n * GET /measurement-methodology.json\n */\nexport interface getMeasurementMethodologyJsonOperation {\n readonly path: \"/measurement-methodology.json\";\n readonly method: \"GET\";\n request: never;\n response: MeasurementMethodology;\n}\n\n/**\n * Get network configuration\n * GET /network-config\n */\nexport interface getNetworkConfigOperation {\n readonly path: \"/network-config\";\n readonly method: \"GET\";\n request: never;\n response: {\n network_config?: PartnerNetworkConfig;\n object?: string;\n parent_partner_id?: string | null;\n};\n}\n\n/**\n * Partial update network configuration\n * PATCH /network-config\n */\nexport interface patchNetworkConfigOperation {\n readonly path: \"/network-config\";\n readonly method: \"PATCH\";\n request: PartnerNetworkConfigUpdate;\n response: {\n network_config?: PartnerNetworkConfig;\n object?: string;\n parent_partner_id?: string | null;\n};\n}\n\n/**\n * Update network configuration\n * PUT /network-config\n */\nexport interface updateNetworkConfigOperation {\n readonly path: \"/network-config\";\n readonly method: \"PUT\";\n request: PartnerNetworkConfigUpdate;\n response: {\n network_config?: PartnerNetworkConfig;\n object?: string;\n parent_partner_id?: string | null;\n};\n}\n\n/**\n * Network-wide audience and inventory trends\n * GET /network/trends\n */\nexport interface getNetworkTrendsOperation {\n readonly path: \"/network/trends\";\n readonly method: \"GET\";\n request: never;\n response: {\n audience_shift?: Array<Record<string, unknown>>;\n days?: number;\n venue_type_mix?: Array<Record<string, unknown>>;\n};\n}\n\n/**\n * Unauthenticated liveness probe\n * GET /ping\n */\nexport interface partnerPingOperation {\n readonly path: \"/ping\";\n readonly method: \"GET\";\n request: never;\n response: {\n ok?: boolean;\n service?: string;\n};\n}\n\n/**\n * Authenticated liveness probe\n * GET /ping/auth\n */\nexport interface partnerPingAuthOperation {\n readonly path: \"/ping/auth\";\n readonly method: \"GET\";\n request: never;\n response: {\n ok?: boolean;\n partner_id?: string;\n tier?: \"basic\" | \"developer\" | \"enterprise\";\n};\n}\n\n/**\n * Record a log-level play\n * POST /plays\n */\nexport interface recordPartnerPlayOperation {\n readonly path: \"/plays\";\n readonly method: \"POST\";\n request: PartnerPlay;\n response: {\n content_sha256?: string;\n object?: string;\n play_id?: string;\n status?: \"accepted\" | \"duplicate\";\n};\n}\n\n/**\n * Record a batch of log-level plays\n * POST /plays/batch\n */\nexport interface recordPartnerPlaysBatchOperation {\n readonly path: \"/plays/batch\";\n readonly method: \"POST\";\n request: {\n plays: Array<PartnerPlay>;\n};\n response: {\n accepted?: number;\n duplicate?: number;\n errors?: Array<{\n play_id?: string | null;\n reason?: string;\n }>;\n object?: string;\n rejected?: number;\n total?: number;\n};\n}\n\n/**\n * Get machine-readable pricing\n * GET /pricing\n */\nexport interface getPricingOperation {\n readonly path: \"/pricing\";\n readonly method: \"GET\";\n request: never;\n response: {\n agent_register_url?: string;\n billing_setup_url?: string;\n /** Volume discount tiers for prepaid credits */\n committed_use?: Record<string, {\n credits_usd?: number;\n discount_pct?: number;\n price_usd?: number;\n }>;\n currency?: string;\n description?: string;\n /** Free tier limits per product and meter */\n free_tiers?: Record<string, unknown>;\n model?: string;\n object?: string;\n /** Pricing details per product */\n products?: {\n attribution?: {\n description?: string;\n meters?: Record<string, {\n first_campaign_free?: boolean;\n per_unit?: string;\n unit_price_usd?: number;\n }>;\n name?: string;\n };\n data_api?: {\n description?: string;\n name?: string;\n notes?: string;\n tiers?: Array<{\n unit_price_usd?: number;\n /** null means unlimited (final tier) */\n up_to?: number | null;\n }>;\n unit?: string;\n };\n data_marketplace?: {\n description?: string;\n meters?: Record<string, {\n free_quota_per_month?: number;\n per_unit?: string;\n unit_price_usd?: number;\n }>;\n name?: string;\n notes?: string;\n revenue_share?: Record<string, unknown>;\n };\n fein_edge_ai?: {\n description?: string;\n name?: string;\n pricing?: string;\n };\n partner_platform?: {\n description?: string;\n name?: string;\n pricing?: string;\n revenue_share?: {\n distributor?: number;\n earner?: number;\n platform?: number;\n };\n };\n programmatic?: {\n description?: string;\n name?: string;\n pricing?: string;\n };\n proof_of_play?: {\n description?: string;\n name?: string;\n notes?: string;\n tiers?: Array<{\n unit_price_usd?: number;\n up_to?: number | null;\n }>;\n unit?: string;\n };\n };\n request_id?: string;\n};\n}\n\n/**\n * Record programmatic ad event (legacy SDK alias)\n * POST /programmatic-event\n */\nexport interface recordProgrammaticEventLegacyAliasOperation {\n readonly path: \"/programmatic-event\";\n readonly method: \"POST\";\n request: {\n ad_id?: string;\n /** Device fingerprint or external device ID */\n device_id?: string;\n /** Short legacy device identifier alias */\n did?: string;\n error_code?: string;\n error_message?: string;\n event: \"ad_started\" | \"ad_ended\" | \"no_fill\" | \"error\";\n reason?: string;\n request_id?: string;\n type?: \"ad_started\" | \"ad_ended\" | \"no_fill\" | \"error\";\n variant_name?: string;\n};\n response: {\n success?: boolean;\n};\n}\n\n/**\n * Quick start — register partner and first device in one call\n * POST /quick-start\n */\nexport interface quickStartOperation {\n readonly path: \"/quick-start\";\n readonly method: \"POST\";\n request: {\n /** Company or partner name */\n company_name: string;\n /** Display configuration for the first device */\n device_display?: Record<string, unknown>;\n /** Location for the first device */\n device_location?: Record<string, unknown>;\n /** Name for the first device */\n device_name?: string;\n email: string;\n /** Optional legacy classification. Omit for the default self-serve Partner API key. */\n partner_type?: string;\n};\n response: {\n data?: {\n credentials?: {\n /** Store securely — shown only once! */\n api_key?: string;\n api_key_prefix?: string;\n warning?: string;\n };\n device?: {\n device_id?: string;\n embed_url?: string;\n external_device_id?: string;\n fingerprint?: string;\n name?: string;\n screen_id?: string;\n status?: string;\n };\n integration?: {\n api_base?: string;\n docs_url?: string;\n embed_url?: string;\n iframe_snippet?: string;\n sdk_snippet?: string;\n sdk_url?: string;\n };\n next_steps?: Array<string>;\n partner?: {\n name?: string;\n partner_id?: string;\n revenue_share_percent?: number;\n slug?: string;\n status?: string;\n };\n sdk_config?: {\n ad_interval?: number;\n allowed_ad_types?: Array<string>;\n cache_size?: number;\n image_duration?: number;\n max_ads_per_hour?: number;\n sound_enabled?: boolean;\n };\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Register a new partner\n * POST /register\n */\nexport interface registerPartnerOperation {\n readonly path: \"/register\";\n readonly method: \"POST\";\n request: {\n /** Whitelist of allowed referrer domains */\n allowed_domains?: Array<string>;\n contact_email: string;\n contact_name?: string;\n /** Company or partner name */\n name: string;\n /** Optional legacy classification. Omit this field — it does not change which API key you receive. Existing integrations may continue sending historical values (including `ctv_publisher`) for backward compatibility; every partner_type mints the same self-serve Partner API key. */\n partner_type?: \"vending_machine\" | \"kiosk\" | \"digital_signage\" | \"retail_display\" | \"ctv_publisher\" | \"other\";\n /** Partner's revenue share percentage (negotiated per partner) */\n revenue_share_percent?: number;\n /** URL-safe identifier (lowercase, no spaces) */\n slug: string;\n};\n response: {\n data?: {\n /** Store this securely - only shown once. This ONE self-serve Partner API key authenticates the general Partner API surface in this spec AND the CTV Measurement SDK ingestion surface (`/v2/sdk/*`, `/v2/csi`) — it carries `sdk:*` and `mcp:tools` by default, so no separate CTV or MCP key is issued. Reuse it during OpenRTB onboarding to add buyer capabilities. */\n api_key?: string;\n partner_id?: string;\n /** Optional portal onboarding details for the partner owner account */\n portal_access?: {\n claim_complete_endpoint?: string;\n claim_request_endpoint?: string;\n claim_required?: boolean;\n claim_verify_endpoint?: string;\n email?: string;\n message?: string;\n new_account?: boolean;\n portal_auth_url?: string;\n portal_url?: string;\n user_id?: string;\n };\n revenue_share_percent?: number;\n slug?: string;\n status?: \"pending\" | \"active\";\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Generate a test event\n * POST /sandbox/event\n */\nexport interface generateSandboxEventOperation {\n readonly path: \"/sandbox/event\";\n readonly method: \"POST\";\n request: {\n /** Event type to generate */\n event_type: string;\n /** Target sandbox screen (auto-selects first if omitted) */\n screen_id?: string;\n};\n response: {\n /** Event payload (varies by event type) */\n data?: Record<string, unknown>;\n event?: string;\n event_id?: string;\n is_sandbox?: boolean;\n object?: string;\n screen_id?: string | null;\n /** Number of SSE connections that received this event */\n sse_delivered?: number;\n timestamp?: string;\n};\n}\n\n/**\n * Reset sandbox data\n * POST /sandbox/reset\n */\nexport interface resetSandboxOperation {\n readonly path: \"/sandbox/reset\";\n readonly method: \"POST\";\n request: never;\n response: {\n events_cleared?: number;\n object?: string;\n reset_at?: string;\n screens_cleared?: number;\n success?: boolean;\n};\n}\n\n/**\n * Create a sandbox screen\n * POST /sandbox/screen\n */\nexport interface createSandboxScreenOperation {\n readonly path: \"/sandbox/screen\";\n readonly method: \"POST\";\n request: {\n /** Custom screen name */\n name?: string;\n /** Override venue type */\n venue_type?: string;\n};\n response: {\n audience?: {\n avg_dwell_time_sec?: number;\n current_viewers?: number;\n demographics?: Record<string, unknown>;\n };\n created_at?: string;\n device_id?: string;\n display_settings?: Record<string, unknown>;\n fingerprint?: string;\n id?: string;\n is_sandbox?: boolean;\n last_heartbeat?: string;\n location?: {\n city?: string;\n latitude?: number;\n longitude?: number;\n name?: string;\n state?: string;\n venue_type?: string;\n };\n name?: string;\n object?: string;\n partner_id?: string;\n screen_id?: string;\n status?: string;\n};\n}\n\n/**\n * Get sandbox status\n * GET /sandbox/status\n */\nexport interface getSandboxStatusOperation {\n readonly path: \"/sandbox/status\";\n readonly method: \"GET\";\n request: never;\n response: {\n last_activity?: string | null;\n object?: string;\n recent_events?: Array<{\n event?: string;\n event_id?: string;\n timestamp?: string;\n }>;\n sandbox_screens?: Array<{\n created_at?: string;\n id?: string;\n last_heartbeat?: string;\n location?: Record<string, unknown>;\n name?: string;\n status?: string;\n }>;\n total_screens?: number;\n total_test_events?: number;\n};\n}\n\n/**\n * List screen groups\n * GET /screen-groups\n */\nexport interface listScreenGroupsOperation {\n readonly path: \"/screen-groups\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n has_more?: boolean;\n object?: string;\n screen_groups?: Array<ScreenGroup>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Create a screen group\n * POST /screen-groups\n */\nexport interface createScreenGroupOperation {\n readonly path: \"/screen-groups\";\n readonly method: \"POST\";\n request: {\n description?: string;\n name: string;\n screen_ids?: Array<string>;\n};\n response: {\n data?: {\n screen_group?: ScreenGroup;\n };\n success?: boolean;\n};\n}\n\n/**\n * Delete (archive) a screen group\n * DELETE /screen-groups/{groupId}\n */\nexport interface deleteScreenGroupOperation {\n readonly path: \"/screen-groups/{groupId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n data?: {\n deleted?: boolean;\n id?: string;\n object?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Retrieve a screen group\n * GET /screen-groups/{groupId}\n */\nexport interface getScreenGroupOperation {\n readonly path: \"/screen-groups/{groupId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n screen_group?: ScreenGroup;\n };\n success?: boolean;\n};\n}\n\n/**\n * Update a screen group\n * POST /screen-groups/{groupId}\n */\nexport interface updateScreenGroupOperation {\n readonly path: \"/screen-groups/{groupId}\";\n readonly method: \"POST\";\n request: {\n description?: string;\n name?: string;\n};\n response: {\n data?: {\n screen_group?: ScreenGroup;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get analytics for a screen group\n * GET /screen-groups/{groupId}/analytics\n */\nexport interface getScreenGroupAnalyticsOperation {\n readonly path: \"/screen-groups/{groupId}/analytics\";\n readonly method: \"GET\";\n request: never;\n response: {\n /** Fleet analytics scoped to the group's live member screens — the same payload as GET /fleet/analytics (which also returns an average attention score alongside the fields below). */\n data?: {\n avg_cpm?: number;\n fill_rate_pct?: number;\n group_id?: string;\n impressions_24h?: number;\n screen_count?: number;\n [key: string]: unknown;\n };\n success?: boolean;\n};\n}\n\n/**\n * Run a fleet command against a screen group\n * POST /screen-groups/{groupId}/commands\n */\nexport interface createScreenGroupCommandOperation {\n readonly path: \"/screen-groups/{groupId}/commands\";\n readonly method: \"POST\";\n request: {\n command: {\n payload?: Record<string, unknown>;\n type: \"reload\" | \"update_settings\" | \"restart\" | \"screenshot\" | \"clear_cache\" | \"update_content\" | \"refresh_ads\" | \"update_config\" | \"get_state\" | \"show_ad\" | \"play_ad\";\n };\n};\n response: {\n data?: {\n fleet_command?: FleetCommand;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get a screen group's content policy\n * GET /screen-groups/{groupId}/content-policy\n */\nexport interface getScreenGroupContentPolicyOperation {\n readonly path: \"/screen-groups/{groupId}/content-policy\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n content_policy?: ScreenGroupContentPolicy;\n };\n success?: boolean;\n};\n}\n\n/**\n * Set a screen group's content policy\n * PUT /screen-groups/{groupId}/content-policy\n */\nexport interface updateScreenGroupContentPolicyOperation {\n readonly path: \"/screen-groups/{groupId}/content-policy\";\n readonly method: \"PUT\";\n request: ScreenGroupContentPolicyInput;\n response: {\n data?: {\n content_policy?: ScreenGroupContentPolicy;\n };\n success?: boolean;\n};\n}\n\n/**\n * Remove members from a screen group\n * DELETE /screen-groups/{groupId}/members\n */\nexport interface removeScreenGroupMembersOperation {\n readonly path: \"/screen-groups/{groupId}/members\";\n readonly method: \"DELETE\";\n request: {\n screen_ids: Array<string>;\n};\n response: {\n data?: {\n removed?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * List a screen group's members\n * GET /screen-groups/{groupId}/members\n */\nexport interface listScreenGroupMembersOperation {\n readonly path: \"/screen-groups/{groupId}/members\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n data?: Array<{\n id?: string;\n object?: string;\n }>;\n has_more?: boolean;\n object?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Add members to a screen group\n * POST /screen-groups/{groupId}/members\n */\nexport interface addScreenGroupMembersOperation {\n readonly path: \"/screen-groups/{groupId}/members\";\n readonly method: \"POST\";\n request: {\n screen_ids: Array<string>;\n};\n response: {\n data?: {\n added?: number;\n rejected?: Array<{\n id?: string;\n reason?: string;\n }>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get a screen group's sensing config\n * GET /screen-groups/{groupId}/sensing-config\n */\nexport interface getScreenGroupSensingConfigOperation {\n readonly path: \"/screen-groups/{groupId}/sensing-config\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n sensing_config?: ScreenGroupSensingConfig;\n };\n success?: boolean;\n};\n}\n\n/**\n * Set a screen group's sensing config\n * PUT /screen-groups/{groupId}/sensing-config\n */\nexport interface updateScreenGroupSensingConfigOperation {\n readonly path: \"/screen-groups/{groupId}/sensing-config\";\n readonly method: \"PUT\";\n request: ScreenGroupSensingConfigInput;\n response: {\n data?: {\n sensing_config?: ScreenGroupSensingConfig;\n };\n success?: boolean;\n};\n}\n\n/**\n * OpenRTB SDA payload for a screen\n * GET /screen/{external_code}/audience-segments\n */\nexport interface getScreenAudienceSegmentsOperation {\n readonly path: \"/screen/{external_code}/audience-segments\";\n readonly method: \"GET\";\n request: never;\n response: {\n external_code?: string;\n segtax_4?: Array<{\n confidence?: number;\n id?: string;\n }>;\n segtax_600?: Array<{\n confidence?: number;\n id?: string;\n }>;\n};\n}\n\n/**\n * Batch update content preferences\n * POST /screens/batch/content-preferences\n */\nexport interface batchUpdateContentPreferencesOperation {\n readonly path: \"/screens/batch/content-preferences\";\n readonly method: \"POST\";\n request: {\n preferences?: ContentPreferencesInput;\n /** Preset ID to apply (alternative to preferences) */\n preset_id?: string;\n /** Array of screen IDs to update */\n screen_ids: Array<string>;\n};\n response: BatchResult;\n}\n\n/**\n * Batch update display settings\n * POST /screens/batch/display-settings\n */\nexport interface batchUpdateDisplaySettingsOperation {\n readonly path: \"/screens/batch/display-settings\";\n readonly method: \"POST\";\n request: {\n screen_ids: Array<string>;\n settings: DisplaySettingsInput;\n};\n response: BatchResult;\n}\n\n/**\n * Batch update programmatic settings\n * POST /screens/batch/programmatic-settings\n */\nexport interface batchUpdateProgrammaticSettingsOperation {\n readonly path: \"/screens/batch/programmatic-settings\";\n readonly method: \"POST\";\n request: {\n screen_ids: Array<string>;\n settings: ProgrammaticSettingsInput;\n};\n response: BatchResult;\n}\n\n/**\n * Resolve screen ID by device identifier\n * GET /screens/resolve\n */\nexport interface resolvePartnerScreenOperation {\n readonly path: \"/screens/resolve\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n device_id?: string;\n external_device_id?: string;\n fingerprint?: string;\n screen_id?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get per-screen analytics\n * GET /screens/{screenId}/analytics\n */\nexport interface getScreenAnalyticsOperation {\n readonly path: \"/screens/{screenId}/analytics\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: ScreenAnalyticsResponse;\n success?: boolean;\n};\n}\n\n/**\n * Current atmosphere (mood, noise, crowd density)\n * GET /screens/{screenId}/analytics/atmosphere\n */\nexport interface getPartnerScreenAtmosphereOperation {\n readonly path: \"/screens/{screenId}/analytics/atmosphere\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n crowdDensity?: string | null;\n currentViewers?: number | null;\n dataAge?: string;\n engagement?: number | null;\n lastUpdated?: string | null;\n mood?: string | null;\n noiseLevel?: string | null;\n };\n status?: boolean;\n};\n}\n\n/**\n * Time-bucketed venue intelligence with Lincoln-Petersen dedup\n * GET /screens/{screenId}/analytics/intelligence\n */\nexport interface getPartnerScreenIntelligenceOperation {\n readonly path: \"/screens/{screenId}/analytics/intelligence\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n dedup?: {\n camera_count?: number;\n method?: string;\n raw_total?: number;\n unique_total?: number;\n };\n from?: string;\n interval?: string;\n screen_id?: string;\n summary?: {\n avg_attention?: number;\n buckets?: number;\n total_unique_viewers?: number;\n };\n timeseries?: Array<Record<string, unknown>>;\n to?: string;\n };\n status?: boolean;\n};\n}\n\n/**\n * Per-screen taste profile + top-5 creative categories\n * GET /screens/{screenId}/analytics/taste-profile\n */\nexport interface getPartnerScreenTasteProfileOperation {\n readonly path: \"/screens/{screenId}/analytics/taste-profile\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n computedAt?: string | null;\n daypartDistribution?: Record<string, unknown> | null;\n ready?: boolean;\n sampleCount?: number;\n screenId?: string;\n tasteVersionHash?: string | null;\n topCategories?: Array<Record<string, unknown>>;\n updatedAt?: string | null;\n venueType?: string | null;\n windowEnd?: string | null;\n windowStart?: string | null;\n };\n status?: boolean;\n};\n}\n\n/**\n * Hourly foot-traffic patterns for a screen\n * GET /screens/{screenId}/analytics/traffic\n */\nexport interface getPartnerScreenTrafficOperation {\n readonly path: \"/screens/{screenId}/analytics/traffic\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n busyScore?: number;\n hourlyTraffic?: Array<Record<string, unknown>>;\n periodDays?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Verified Attention Seconds + CPM tier for a screen\n * GET /screens/{screenId}/analytics/vas\n */\nexport interface getPartnerScreenVASOperation {\n readonly path: \"/screens/{screenId}/analytics/vas\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n avgAttentionScore?: number;\n avgFaceCount?: number;\n avgVasWeighted?: number;\n lastMeasurement?: string | null;\n medianVas?: number;\n multiplier?: number;\n p90Vas?: number;\n tier?: string;\n totalMeasurements?: number;\n };\n status?: boolean;\n};\n}\n\n/**\n * Apply content preset to screen\n * POST /screens/{screenId}/apply-preset\n */\nexport interface applyContentPresetOperation {\n readonly path: \"/screens/{screenId}/apply-preset\";\n readonly method: \"POST\";\n request: {\n /** ID of the preset to apply */\n preset_id: string;\n};\n response: ContentPreferencesResponse & {\n preset_applied?: string;\n };\n}\n\n/**\n * Get real-time audience metrics\n * GET /screens/{screenId}/audience-metrics\n */\nexport interface getAudienceMetricsOperation {\n readonly path: \"/screens/{screenId}/audience-metrics\";\n readonly method: \"GET\";\n request: never;\n response: AudienceMetricsResponse;\n}\n\n/**\n * Get screen content preferences\n * GET /screens/{screenId}/content-preferences\n */\nexport interface getContentPreferencesOperation {\n readonly path: \"/screens/{screenId}/content-preferences\";\n readonly method: \"GET\";\n request: never;\n response: ContentPreferencesResponse;\n}\n\n/**\n * Update content preferences (partial)\n * PATCH /screens/{screenId}/content-preferences\n */\nexport interface patchContentPreferencesOperation {\n readonly path: \"/screens/{screenId}/content-preferences\";\n readonly method: \"PATCH\";\n request: ContentPreferencesInput;\n response: ContentPreferencesResponse;\n}\n\n/**\n * Update content preferences (full)\n * PUT /screens/{screenId}/content-preferences\n */\nexport interface updateContentPreferencesOperation {\n readonly path: \"/screens/{screenId}/content-preferences\";\n readonly method: \"PUT\";\n request: ContentPreferencesInput;\n response: ContentPreferencesResponse;\n}\n\n/**\n * List default streams for a screen\n * GET /screens/{screenId}/default-streams\n */\nexport interface listPartnerDefaultStreamsOperation {\n readonly path: \"/screens/{screenId}/default-streams\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n current?: PartnerDefaultStream;\n streams?: Array<PartnerDefaultStream>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Create a default stream (URL-based)\n * POST /screens/{screenId}/default-streams\n */\nexport interface createPartnerDefaultStreamOperation {\n readonly path: \"/screens/{screenId}/default-streams\";\n readonly method: \"POST\";\n request: PartnerDefaultStreamCreate;\n response: {\n data?: PartnerDefaultStream;\n success?: boolean;\n};\n}\n\n/**\n * Upload image carousel default stream\n * POST /screens/{screenId}/default-streams/images\n */\nexport interface createPartnerDefaultStreamImagesOperation {\n readonly path: \"/screens/{screenId}/default-streams/images\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: PartnerDefaultStream;\n success?: boolean;\n};\n}\n\n/**\n * Reorder default streams\n * PUT /screens/{screenId}/default-streams/order\n */\nexport interface reorderPartnerDefaultStreamsOperation {\n readonly path: \"/screens/{screenId}/default-streams/order\";\n readonly method: \"PUT\";\n request: {\n order: Array<string>;\n};\n response: {\n success?: boolean;\n};\n}\n\n/**\n * Upload a video default stream\n * POST /screens/{screenId}/default-streams/upload\n */\nexport interface createPartnerDefaultStreamUploadOperation {\n readonly path: \"/screens/{screenId}/default-streams/upload\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: PartnerDefaultStream;\n success?: boolean;\n};\n}\n\n/**\n * Delete a default stream\n * DELETE /screens/{screenId}/default-streams/{streamId}\n */\nexport interface deletePartnerDefaultStreamOperation {\n readonly path: \"/screens/{screenId}/default-streams/{streamId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n success?: boolean;\n};\n}\n\n/**\n * Update a default stream\n * PUT /screens/{screenId}/default-streams/{streamId}\n */\nexport interface updatePartnerDefaultStreamOperation {\n readonly path: \"/screens/{screenId}/default-streams/{streamId}\";\n readonly method: \"PUT\";\n request: PartnerDefaultStreamUpdate;\n response: {\n data?: PartnerDefaultStream;\n success?: boolean;\n};\n}\n\n/**\n * Get screen demographics\n * GET /screens/{screenId}/demographics\n */\nexport interface getScreenDemographicsOperation {\n readonly path: \"/screens/{screenId}/demographics\";\n readonly method: \"GET\";\n request: never;\n response: DemographicsResponse;\n}\n\n/**\n * Get display settings\n * GET /screens/{screenId}/display-settings\n */\nexport interface getDisplaySettingsOperation {\n readonly path: \"/screens/{screenId}/display-settings\";\n readonly method: \"GET\";\n request: never;\n response: DisplaySettingsResponse;\n}\n\n/**\n * Update display settings (partial)\n * PATCH /screens/{screenId}/display-settings\n */\nexport interface patchDisplaySettingsOperation {\n readonly path: \"/screens/{screenId}/display-settings\";\n readonly method: \"PATCH\";\n request: DisplaySettingsInput;\n response: DisplaySettingsResponse;\n}\n\n/**\n * Update display settings (full)\n * PUT /screens/{screenId}/display-settings\n */\nexport interface updateDisplaySettingsOperation {\n readonly path: \"/screens/{screenId}/display-settings\";\n readonly method: \"PUT\";\n request: DisplaySettingsInput;\n response: DisplaySettingsResponse;\n}\n\n/**\n * Get L-Bar settings\n * GET /screens/{screenId}/l-bar\n */\nexport interface getPartnerLBarSettingsOperation {\n readonly path: \"/screens/{screenId}/l-bar\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: PartnerLBarSettings;\n success?: boolean;\n};\n}\n\n/**\n * Update L-Bar settings\n * PUT /screens/{screenId}/l-bar\n */\nexport interface updatePartnerLBarSettingsOperation {\n readonly path: \"/screens/{screenId}/l-bar\";\n readonly method: \"PUT\";\n request: {\n display_preferences?: PartnerLBarDisplayPreferences;\n l_bar_content?: PartnerLBarContent;\n};\n response: {\n data?: PartnerLBarSettings;\n success?: boolean;\n};\n}\n\n/**\n * Update L-Bar live updates\n * PUT /screens/{screenId}/l-bar/live-updates\n */\nexport interface updatePartnerLBarLiveUpdatesOperation {\n readonly path: \"/screens/{screenId}/l-bar/live-updates\";\n readonly method: \"PUT\";\n request: {\n custom_status?: string;\n promotion?: string;\n queue_number?: string;\n wait_time_minutes?: number;\n};\n response: {\n success?: boolean;\n};\n}\n\n/**\n * Get programmatic settings\n * GET /screens/{screenId}/programmatic-settings\n */\nexport interface getProgrammaticSettingsOperation {\n readonly path: \"/screens/{screenId}/programmatic-settings\";\n readonly method: \"GET\";\n request: never;\n response: ProgrammaticSettingsResponse;\n}\n\n/**\n * Update programmatic settings (partial)\n * PATCH /screens/{screenId}/programmatic-settings\n */\nexport interface patchProgrammaticSettingsOperation {\n readonly path: \"/screens/{screenId}/programmatic-settings\";\n readonly method: \"PATCH\";\n request: ProgrammaticSettingsInput;\n response: ProgrammaticSettingsResponse;\n}\n\n/**\n * Update programmatic settings (full)\n * PUT /screens/{screenId}/programmatic-settings\n */\nexport interface updateProgrammaticSettingsOperation {\n readonly path: \"/screens/{screenId}/programmatic-settings\";\n readonly method: \"PUT\";\n request: ProgrammaticSettingsInput;\n response: ProgrammaticSettingsResponse;\n}\n\n/**\n * Resolve the effective content policy for a screen\n * GET /screens/{screenId}/resolved-content-policy\n */\nexport interface getResolvedContentPolicyOperation {\n readonly path: \"/screens/{screenId}/resolved-content-policy\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: ResolvedContentPolicy;\n success?: boolean;\n};\n}\n\n/**\n * Resolve the effective sensing config for a screen\n * GET /screens/{screenId}/resolved-sensing-config\n */\nexport interface getResolvedSensingConfigOperation {\n readonly path: \"/screens/{screenId}/resolved-sensing-config\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: ResolvedSensingConfig;\n success?: boolean;\n};\n}\n\n/**\n * Read the custom sensing chips a screen is producing\n * GET /screens/{screenId}/sensing/chips\n */\nexport interface getScreenSensingChipsOperation {\n readonly path: \"/screens/{screenId}/sensing/chips\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** The custom field_keys this screen senses (from its active profile) */\n fields?: Array<{\n description?: string;\n field_key?: string;\n type?: string;\n }>;\n /** Recent chip observations (one row per field_key per observation) */\n rows?: Array<Record<string, unknown>>;\n screen_id?: string;\n total?: number;\n truncated?: boolean;\n };\n success?: boolean;\n};\n}\n\n/**\n * Generate a custom sensing profile from a natural-language intent\n * POST /screens/{screenId}/sensing/interpret-intent\n */\nexport interface interpretScreenSensingIntentOperation {\n readonly path: \"/screens/{screenId}/sensing/interpret-intent\";\n readonly method: \"POST\";\n request: {\n /** Optional device-capability hint for model selection */\n deviceTier?: string;\n /** Natural-language description of what to sense */\n intent: string;\n};\n response: {\n data?: {\n /** The generated profile — pass to /sensing/profile to deploy */\n profile?: Record<string, unknown>;\n screen_id?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Deploy a custom sensing profile to a screen\n * POST /screens/{screenId}/sensing/profile\n */\nexport interface deployScreenSensingProfileOperation {\n readonly path: \"/screens/{screenId}/sensing/profile\";\n readonly method: \"POST\";\n request: {\n /** The sensing profile object returned by interpret-intent */\n profile: Record<string, unknown>;\n};\n response: {\n data?: {\n command?: Record<string, unknown>;\n profile?: Record<string, unknown>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Read a screen's AI sensing performance settings\n * GET /screens/{screenId}/sensing/settings\n */\nexport interface getScreenSensingSettingsOperation {\n readonly path: \"/screens/{screenId}/sensing/settings\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: SensingSettingsResponse;\n success?: boolean;\n};\n}\n\n/**\n * Update a screen's AI sensing performance mode\n * PATCH /screens/{screenId}/sensing/settings\n */\nexport interface updateScreenSensingSettingsOperation {\n readonly path: \"/screens/{screenId}/sensing/settings\";\n readonly method: \"PATCH\";\n request: {\n performance_mode: SensingPerformanceMode;\n};\n response: {\n data?: {\n command?: Record<string, unknown>;\n profile?: Record<string, unknown>;\n settings?: SensingSettingsResponse;\n };\n success?: boolean;\n};\n}\n\n/**\n * List your Sense Anything Routes\n * GET /sensing/routes\n */\nexport interface listPartnerSensingRoutesOperation {\n readonly path: \"/sensing/routes\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n routes?: Array<SensingRoute>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Create a Sense Anything Route (threshold or scheduled-digest alert)\n * POST /sensing/routes\n */\nexport interface createPartnerSensingRouteOperation {\n readonly path: \"/sensing/routes\";\n readonly method: \"POST\";\n request: CreatePartnerSensingRouteRequest;\n response: {\n data?: {\n route?: SensingRoute;\n };\n success?: boolean;\n};\n}\n\n/**\n * Delete (soft) a Sense Anything Route\n * DELETE /sensing/routes/{routeId}\n */\nexport interface deletePartnerSensingRouteOperation {\n readonly path: \"/sensing/routes/{routeId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n data?: {\n routeId?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get one Sense Anything Route\n * GET /sensing/routes/{routeId}\n */\nexport interface getPartnerSensingRouteOperation {\n readonly path: \"/sensing/routes/{routeId}\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n route?: SensingRoute;\n };\n success?: boolean;\n};\n}\n\n/**\n * Update a Sense Anything Route (partial, non-clobbering)\n * PATCH /sensing/routes/{routeId}\n */\nexport interface updatePartnerSensingRouteOperation {\n readonly path: \"/sensing/routes/{routeId}\";\n readonly method: \"PATCH\";\n request: UpdatePartnerSensingRouteRequest;\n response: {\n data?: {\n route?: SensingRoute;\n };\n success?: boolean;\n};\n}\n\n/**\n * Create Stripe Connect account\n * POST /stripe/connect\n */\nexport interface createStripeConnectAccountOperation {\n readonly path: \"/stripe/connect\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: {\n account_id?: string;\n charges_enabled?: boolean;\n country?: string;\n default_currency?: string;\n details_submitted?: boolean;\n next_step?: string | null;\n payouts_enabled?: boolean;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get Stripe dashboard login link\n * GET /stripe/login-link\n */\nexport interface getStripeLoginLinkOperation {\n readonly path: \"/stripe/login-link\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n account_id?: string;\n instructions?: string;\n login_url?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get Stripe onboarding link\n * GET /stripe/onboarding-link\n */\nexport interface getStripeOnboardingLinkOperation {\n readonly path: \"/stripe/onboarding-link\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n account_id?: string;\n expires_at?: string;\n instructions?: string;\n onboarding_url?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Request a payout\n * POST /stripe/payout\n */\nexport interface requestStripePayoutOperation {\n readonly path: \"/stripe/payout\";\n readonly method: \"POST\";\n request: {\n /** Payout amount in cents (minimum $5.00) */\n amount_cents: number;\n /** Optional description for the payout */\n description?: string;\n /** Deduplication key to prevent duplicate payouts */\n idempotency_key?: string;\n};\n response: {\n data?: {\n amount_cents?: number;\n created?: string;\n currency?: string;\n description?: string;\n destination?: string;\n /** Estimated arrival (2-3 business days) */\n estimated_arrival?: string;\n status?: \"pending\" | \"reversed\";\n transfer_id?: string;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get payout history\n * GET /stripe/payouts\n */\nexport interface getStripePayoutHistoryOperation {\n readonly path: \"/stripe/payouts\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n has_more?: boolean;\n total?: number;\n transfers?: Array<{\n amount_cents?: number;\n created?: string;\n currency?: string;\n description?: string;\n status?: \"completed\" | \"reversed\";\n transfer_id?: string;\n }>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get Stripe account status\n * GET /stripe/status\n */\nexport interface getStripeAccountStatusOperation {\n readonly path: \"/stripe/status\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n account_id?: string | null;\n charges_enabled?: boolean;\n country?: string;\n default_currency?: string;\n details_submitted?: boolean;\n has_account?: boolean;\n payouts_enabled?: boolean;\n requirements?: {\n currently_due?: Array<string>;\n disabled_reason?: string | null;\n eventually_due?: Array<string>;\n past_due?: Array<string>;\n };\n status?: \"not_connected\" | \"pending\" | \"active\" | \"restricted\";\n };\n success?: boolean;\n};\n}\n\n/**\n * Stripe webhook receiver\n * POST /stripe/webhook\n */\nexport interface handleStripeWebhookOperation {\n readonly path: \"/stripe/webhook\";\n readonly method: \"POST\";\n request: Record<string, unknown>;\n response: {\n event_type?: string;\n received?: boolean;\n};\n}\n\n/**\n * List team members\n * GET /team\n */\nexport interface listTeamMembersOperation {\n readonly path: \"/team\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n members?: Array<TeamMember>;\n partner?: {\n name?: string;\n slug?: string;\n };\n total?: number;\n };\n success?: boolean;\n};\n}\n\n/**\n * Accept team invitation\n * POST /team/accept\n */\nexport interface acceptInvitationOperation {\n readonly path: \"/team/accept\";\n readonly method: \"POST\";\n request: {\n /** Invitation token from email link */\n token: string;\n};\n response: {\n data?: {\n partner?: {\n id?: string;\n name?: string;\n slug?: string;\n };\n permissions?: RolePermissions;\n portal_url?: string;\n role?: string;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Invite a team member\n * POST /team/invite\n */\nexport interface inviteTeamMemberOperation {\n readonly path: \"/team/invite\";\n readonly method: \"POST\";\n request: {\n /** Email address of the invitee */\n email: string;\n /** Optional name of the invitee */\n name?: string;\n /** Role to assign to the team member */\n role?: \"admin\" | \"viewer\";\n};\n response: {\n data?: TeamInviteResponse;\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get invitation details\n * GET /team/invite/{token}\n */\nexport interface getInvitationByTokenOperation {\n readonly path: \"/team/invite/{token}\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n email?: string;\n expires_at?: string;\n invited_at?: string;\n partner?: {\n name?: string;\n slug?: string;\n };\n role?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Resend invitation\n * POST /team/{membershipId}/resend\n */\nexport interface resendInvitationOperation {\n readonly path: \"/team/{membershipId}/resend\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: {\n email?: string;\n expires_at?: string;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Remove a team member\n * DELETE /team/{userId}\n */\nexport interface removeTeamMemberOperation {\n readonly path: \"/team/{userId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Change team member role\n * PATCH /team/{userId}/role\n */\nexport interface changeTeamMemberRoleOperation {\n readonly path: \"/team/{userId}/role\";\n readonly method: \"PATCH\";\n request: {\n role: \"admin\" | \"viewer\";\n};\n response: {\n data?: {\n new_role?: string;\n old_role?: string;\n permissions?: RolePermissions;\n user_id?: string;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get public key for proof verification\n * GET /tracking/.well-known/public-key\n */\nexport interface getTrackingPublicKeyOperation {\n readonly path: \"/tracking/.well-known/public-key\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** Signature algorithm (ed25519 for public key, sha256 for HMAC fallback) */\n algorithm?: \"ed25519\" | \"sha256\";\n documentation?: string;\n /** Key identifier for rotation support */\n keyId?: string;\n /** Hex-encoded Ed25519 public key (null if using HMAC fallback) */\n publicKey?: string | null;\n verificationUrl?: string;\n version?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * Record batch impressions with proof generation\n * POST /tracking/batch\n */\nexport interface recordTrackingBatchOperation {\n readonly path: \"/tracking/batch\";\n readonly method: \"POST\";\n request: {\n impressions: Array<{\n /** Ad identifier from VAST response */\n ad_id: string;\n /** Optional audience metrics */\n audience?: {\n /** Attention score (0-1) */\n attention?: number;\n /** How long viewers were present */\n dwell_time_ms?: number;\n /** Number of viewers detected */\n face_count?: number;\n };\n /** Partner's device identifier */\n device_id: string;\n /** Video duration played in milliseconds */\n duration_ms?: number;\n /** VAST event type */\n event?: \"start\" | \"complete\" | \"error\" | \"firstQuartile\" | \"midpoint\" | \"thirdQuartile\";\n /** Optional client-generated ID (auto-generated if not provided) */\n impression_id?: string;\n /** When the event occurred (defaults to now) */\n timestamp?: string;\n }>;\n};\n response: {\n data?: {\n /** Number of duplicate impressions skipped */\n duplicates?: number;\n /** Details of failed impressions (max 10 shown) */\n errors?: Array<{\n error?: string;\n impression_id?: string;\n }>;\n /** Number of impressions that failed validation */\n failed?: number;\n /** Number of impressions successfully recorded */\n processed?: number;\n /** Time to process the batch */\n processing_time_ms?: number;\n /** Cryptographic proofs for each processed impression */\n proofs?: Array<{\n impression_id?: string;\n public_key_id?: string;\n /** Ed25519 signature (or SHA256 fallback) */\n signature?: string;\n }>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Get API usage summary\n * GET /usage\n */\nexport interface getUsageSummaryOperation {\n readonly path: \"/usage\";\n readonly method: \"GET\";\n request: never;\n response: {\n /** Average response time in milliseconds */\n avgResponseTime?: number;\n dailyBreakdown?: Array<{\n avg_response_ms?: number;\n date?: string;\n total_calls?: number;\n total_errors?: number;\n }>;\n /** Error rate percentage (0-100) */\n errorRate?: number;\n object?: string;\n period?: {\n end_date?: string;\n start_date?: string;\n };\n topEndpoints?: Array<{\n endpoint?: string;\n method?: string;\n total_calls?: number;\n total_errors?: number;\n }>;\n totalCalls?: number;\n totalErrors?: number;\n};\n}\n\n/**\n * Get real-time usage dashboard\n * GET /usage/dashboard\n */\nexport interface getUsageDashboardOperation {\n readonly path: \"/usage/dashboard\";\n readonly method: \"GET\";\n request: never;\n response: {\n last_7_days?: {\n avg_response_ms?: number;\n daily_breakdown?: Array<{\n avg_response_ms?: number;\n date?: string;\n total_calls?: number;\n total_errors?: number;\n }>;\n error_rate?: number;\n total_calls?: number;\n total_errors?: number;\n };\n object?: string;\n rate_limit?: {\n current_rate?: number;\n max_rate?: number;\n percent_used?: number;\n window_reset?: string;\n window_seconds?: number;\n };\n today?: {\n avg_response_ms?: number;\n error_rate?: number;\n top_endpoints?: Array<{\n avg_response_ms?: number;\n endpoint?: string;\n method?: string;\n total_calls?: number;\n total_errors?: number;\n }>;\n total_calls?: number;\n total_errors?: number;\n };\n};\n}\n\n/**\n * Get rate limit status\n * GET /usage/rate-limit\n */\nexport interface getRateLimitStatusOperation {\n readonly path: \"/usage/rate-limit\";\n readonly method: \"GET\";\n request: never;\n response: {\n current_rate?: number;\n max_rate?: number;\n object?: string;\n percent_used?: number;\n tier?: \"basic\" | \"developer\" | \"enterprise\";\n window_reset?: string;\n window_seconds?: number;\n};\n}\n\n/**\n * Query API changelog\n * GET /v1/changelog\n */\nexport interface queryChangelogOperation {\n readonly path: \"/v1/changelog\";\n readonly method: \"GET\";\n request: never;\n response: ChangelogResponse;\n}\n\n/**\n * Dry-run validate a request body against an operation schema\n * POST /v1/playground/{operation_id}\n */\nexport interface playgroundDryRunOperation {\n readonly path: \"/v1/playground/{operation_id}\";\n readonly method: \"POST\";\n request: never;\n response: PlaygroundResult;\n}\n\n/**\n * Look up metadata for a recent API request\n * GET /v1/requests/{request_id}\n */\nexport interface getRequestMetadataOperation {\n readonly path: \"/v1/requests/{request_id}\";\n readonly method: \"GET\";\n request: never;\n response: RequestMetadataResponse;\n}\n\n/**\n * Get VAST configuration for direct Google integration\n * GET /vast/config\n */\nexport interface getVastConfigOperation {\n readonly path: \"/vast/config\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n /** Google Ad Manager ad unit path */\n ad_unit?: string;\n /** IAB content categories to block */\n blocked_categories?: Array<string>;\n /** How long to cache this config */\n cache_ttl_seconds?: number;\n /** Floor price in cents (CPM) */\n floor_price_cpm?: number;\n integration_guide?: string;\n parameters?: {\n height?: number;\n /** Maximum ad duration in seconds */\n max_duration?: number;\n /** Minimum ad duration in seconds */\n min_duration?: number;\n /** Venue type code for targeting */\n venuetype?: number;\n width?: number;\n };\n /** Recommended VAST fetch timeout */\n timeout_ms?: number;\n tracking?: {\n batch_endpoint?: string;\n max_batch_size?: number;\n single_endpoint?: string;\n };\n /** Configuration variant name for debugging */\n variant?: string;\n /** VAST URL template with placeholders for {width} and {height}. Partner replaces placeholders and appends correlator. */\n vast_tag_template?: string;\n };\n success?: boolean;\n};\n}\n\n/**\n * List nearby Trillboards venues\n * GET /venues/nearby\n */\nexport interface getVenuesNearbyOperation {\n readonly path: \"/venues/nearby\";\n readonly method: \"GET\";\n request: never;\n response: {\n count?: number;\n venues?: Array<{\n distance_m?: number;\n screen_id?: string;\n venue_type?: string;\n }>;\n};\n}\n\n/**\n * Real-world atmosphere signals for a venue\n * GET /venues/{screenId}/atmosphere\n */\nexport interface getVenueAtmosphereOperation {\n readonly path: \"/venues/{screenId}/atmosphere\";\n readonly method: \"GET\";\n request: never;\n response: {\n days?: number;\n dominant_ambience?: string;\n lighting_band?: \"dark\" | \"dim\" | \"lit\" | \"bright\";\n motion_intensity?: number;\n noise_level_db?: number;\n screen_id?: string;\n};\n}\n\n/**\n * Foot-traffic profile for a venue\n * GET /venues/{screenId}/traffic\n */\nexport interface getVenueTrafficOperation {\n readonly path: \"/venues/{screenId}/traffic\";\n readonly method: \"GET\";\n request: never;\n response: {\n daily?: Array<Record<string, unknown>>;\n hourly?: Array<{\n face_count_avg?: number;\n hour?: number;\n }>;\n screen_id?: string;\n};\n}\n\n/**\n * Get venue intelligence report\n * GET /venues/{venueId}/intelligence\n */\nexport interface getVenueIntelligenceOperation {\n readonly path: \"/venues/{venueId}/intelligence\";\n readonly method: \"GET\";\n request: never;\n response: {\n dedup?: {\n camera_count?: number;\n method?: \"lincoln_petersen\" | \"single_camera\";\n raw_total?: number;\n unique_total?: number;\n };\n from?: string;\n interval?: string;\n summary?: {\n avg_attention?: number;\n buckets?: number;\n total_unique_viewers?: number;\n };\n timeseries?: Array<{\n age_distribution?: Record<string, number>;\n avg_attention?: number;\n avg_engagement?: number;\n avg_noise_level?: number | null;\n brand_mention_windows?: number;\n bucket?: string;\n gender_distribution?: {\n female?: number;\n male?: number;\n };\n income_level?: string | null;\n measurements?: number;\n mood?: string | null;\n peak_viewers?: number;\n raw_viewers?: number;\n screen_count?: number;\n /** Deduplicated viewer count */\n viewers?: number;\n weather?: {\n condition?: string | null;\n is_raining?: boolean;\n temperature_f?: number | null;\n };\n }>;\n to?: string;\n venue_id?: string;\n};\n}\n\n/**\n * List webhooks\n * GET /webhooks\n */\nexport interface listWebhooksOperation {\n readonly path: \"/webhooks\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n webhooks?: Array<Webhook>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Create webhook subscription\n * POST /webhooks\n */\nexport interface createWebhookOperation {\n readonly path: \"/webhooks\";\n readonly method: \"POST\";\n request: {\n /** Events to subscribe to */\n events: Array<\"device.online\" | \"device.offline\" | \"device.requirements_updated\" | \"impression.recorded\" | \"campaign.allocated\" | \"payout.processed\" | \"sensing.threshold_crossed\" | \"audience.spike\" | \"audience.venue_busy\" | \"audience.purchase_intent\" | \"audience.demographics_update\" | \"venue.traffic_summary\" | \"programmatic.ad_started\" | \"programmatic.ad_ended\" | \"programmatic.no_fill\" | \"programmatic.error\" | \"screen_group.created\" | \"screen_group.updated\" | \"screen_group.deleted\" | \"screen_group.member.added\" | \"screen_group.member.removed\" | \"screen_group.content_policy.updated\" | \"screen_group.sensing_config.updated\" | \"fleet_command.completed\" | \"fleet_command.failed\">;\n /** Webhook endpoint URL (HTTPS required in production) */\n url: string;\n};\n response: {\n data?: {\n events?: Array<string>;\n /** Webhook signing secret (shown only once!) */\n secret?: string;\n status?: \"active\" | \"inactive\";\n url?: string;\n webhook_id?: string;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Delete webhook\n * DELETE /webhooks/{webhookId}\n */\nexport interface deleteWebhookOperation {\n readonly path: \"/webhooks/{webhookId}\";\n readonly method: \"DELETE\";\n request: never;\n response: {\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Update webhook\n * PATCH /webhooks/{webhookId}\n */\nexport interface updateWebhookOperation {\n readonly path: \"/webhooks/{webhookId}\";\n readonly method: \"PATCH\";\n request: {\n events?: Array<\"device.online\" | \"device.offline\" | \"device.requirements_updated\" | \"impression.recorded\" | \"campaign.allocated\" | \"payout.processed\" | \"sensing.threshold_crossed\" | \"audience.spike\" | \"audience.venue_busy\" | \"audience.purchase_intent\" | \"audience.demographics_update\" | \"venue.traffic_summary\" | \"programmatic.ad_started\" | \"programmatic.ad_ended\" | \"programmatic.no_fill\" | \"programmatic.error\" | \"screen_group.created\" | \"screen_group.updated\" | \"screen_group.deleted\" | \"screen_group.member.added\" | \"screen_group.member.removed\" | \"screen_group.content_policy.updated\" | \"screen_group.sensing_config.updated\" | \"fleet_command.completed\" | \"fleet_command.failed\">;\n status?: \"active\" | \"inactive\";\n url?: string;\n};\n response: {\n data?: Webhook;\n message?: string;\n success?: boolean;\n};\n}\n\n/**\n * Get delivery history\n * GET /webhooks/{webhookId}/deliveries\n */\nexport interface getWebhookDeliveriesOperation {\n readonly path: \"/webhooks/{webhookId}/deliveries\";\n readonly method: \"GET\";\n request: never;\n response: {\n data?: {\n deliveries?: Array<WebhookDelivery>;\n };\n success?: boolean;\n};\n}\n\n/**\n * Test webhook\n * POST /webhooks/{webhookId}/test\n */\nexport interface testWebhookOperation {\n readonly path: \"/webhooks/{webhookId}/test\";\n readonly method: \"POST\";\n request: never;\n response: {\n data?: {\n error?: string;\n response_time_ms?: number;\n status?: number;\n };\n message?: string;\n success?: boolean;\n};\n}\n\n\n// ─── Type registry ───────────────────────────────────────────────────────\n\nexport const generatedTypes = {\n schemaCount: 112,\n operationCount: 211,\n schemas: [\"Ad\",\"AdSettings\",\"AdvertisingIdentity\",\"AnalyticsData\",\"AudienceAnalyticsResponse\",\"AudienceAttentionPrediction\",\"AudienceData\",\"AudienceExportResponse\",\"AudienceLoyaltyFeaturesRow\",\"AudienceMetricsResponse\",\"AudienceSegment\",\"AudienceSocialAttention\",\"BatchResult\",\"BillingInfo\",\"BleScanResultData\",\"ChangelogEntry\",\"ChangelogResponse\",\"ContentFitSettings\",\"ContentPreferencesInput\",\"ContentPreferencesResponse\",\"ContentPreset\",\"CreatePartnerSensingRouteRequest\",\"CreativeClassification\",\"DashboardResponse\",\"DataExportSummaryResponse\",\"DemographicsResponse\",\"Device\",\"DeviceCapabilityPayload\",\"DeviceSummary\",\"DisplaySettingsInput\",\"DisplaySettingsResponse\",\"EarningsBreakdownResponse\",\"EarningsData\",\"EarningsResponse\",\"Error\",\"ErrorEntry\",\"ExtendedIdentity\",\"FleetCommand\",\"FleetCommandEvent\",\"HeaderBiddingSettings\",\"HttpProbeResult\",\"Impression\",\"MdnsNetworkDevice\",\"MeasurementMethodology\",\"Pagination\",\"Partner\",\"PartnerAdDeliveryProfile\",\"PartnerCreativeWarnings\",\"PartnerDefaultStream\",\"PartnerDefaultStreamCreate\",\"PartnerDefaultStreamUpdate\",\"PartnerDeviceBatchRegistrationInput\",\"PartnerDeviceHeartbeatBody\",\"PartnerDeviceRegistrationInput\",\"PartnerHeartbeatCommand\",\"PartnerHeartbeatData\",\"PartnerHeartbeatMeasurementMetadata\",\"PartnerHeartbeatQueryData\",\"PartnerHeartbeatQueryResponse\",\"PartnerHeartbeatRequest\",\"PartnerHeartbeatResponse\",\"PartnerHeartbeatTelemetry\",\"PartnerLBarContent\",\"PartnerLBarDisplayPreferences\",\"PartnerLBarSettings\",\"PartnerMonetizationRequirements\",\"PartnerNetworkConfig\",\"PartnerNetworkConfigUpdate\",\"PartnerPlay\",\"PartnerRegistrationDisplaySettings\",\"PartnerRequirement\",\"PartnerSafeHeartbeatTelemetry\",\"PartnerSelfPromoAd\",\"PartnerSelfPromoCreate\",\"PartnerSelfPromoPlacement\",\"PartnerStats\",\"PayoutResponse\",\"PlaygroundResult\",\"PlaygroundValidationError\",\"ProgrammaticSettingsInput\",\"ProgrammaticSettingsResponse\",\"RequestMetadataResponse\",\"ResolvedContentPolicy\",\"ResolvedSensingConfig\",\"RolePermissions\",\"SDKConfig\",\"Screen\",\"ScreenAnalyticsResponse\",\"ScreenGroup\",\"ScreenGroupContentPolicy\",\"ScreenGroupContentPolicyInput\",\"ScreenGroupEvent\",\"ScreenGroupSensingConfig\",\"ScreenGroupSensingConfigInput\",\"SensingPerformanceMode\",\"SensingRoute\",\"SensingRouteAction\",\"SensingRouteCondition\",\"SensingSettingsResponse\",\"SensingThresholdCrossedEvent\",\"SsdpDeviceInfo\",\"TeamInviteResponse\",\"TeamMember\",\"Transaction\",\"UpdatePartnerSensingRouteRequest\",\"VastWaterfall\",\"VastWaterfallSource\",\"Webhook\",\"WebhookDelivery\",\"WebhookEvent\",\"WifiEnvironmentSnapshot\",\"WifiScanResult\"] as const,\n operations: [\"listPartnerSelfPromoAds\",\"createPartnerSelfPromoAd\",\"listPartnerSelfPromoPlacements\",\"schedulePartnerSelfPromo\",\"createPartnerSelfPromoUpload\",\"disableSelfPromoAd\",\"registerAgent\",\"getAnalytics\",\"getAudienceContinuity\",\"getAudienceProfile\",\"getBleSummary\",\"getContentPerformance\",\"searchCreativeCatalog\",\"getCreativeScenes\",\"getCrossScreenFlow\",\"getPartnerAnalyticsDashboard\",\"getDeviceSuiteSignature\",\"exportPartnerAnalytics\",\"exportPartnerAdsByDay\",\"getFleetHourly\",\"getHaloFunnel\",\"getLoyaltyClock\",\"getNetworkSummary\",\"getNetworkTrend\",\"getProximitySummary\",\"getRevenueAttentionCorrelation\",\"getSceneFeed\",\"getSceneIntelligence\",\"rotateApiKey\",\"getAudienceAnalytics\",\"exportAudienceData\",\"getAudienceHeatmap\",\"getLiveAudience\",\"getLookalikeScreens\",\"predictScreenAudience\",\"getResolvedHouseholdReach\",\"listAudienceSegments\",\"createAudienceSegment\",\"deleteAudienceSegment\",\"getAudienceSegment\",\"updateAudienceSegment\",\"matchAudienceSegment\",\"estimateSegmentReach\",\"generateSegmentVastTag\",\"getAudienceStats\",\"cancelBillingSubscription\",\"purchaseCredits\",\"createCreditCheckout\",\"listBillingPlans\",\"setupBilling\",\"createBillingSubscription\",\"getBillingSubscription\",\"getBillingUsage\",\"getBillingUsageSummary\",\"stripeWebhookCallback\",\"getConnectDashboard\",\"getConnectEarningsChart\",\"getConnectScreenHealth\",\"listContentPresets\",\"getContentPreset\",\"submitPartnerCreative\",\"getPartnerCreative\",\"getDashboard\",\"exportProximityGraphEdges\",\"getDataExportSummary\",\"exportDataset\",\"getGeohashAudiencePanel\",\"getOutcomeAttribution\",\"registerDevice\",\"deleteDevice\",\"getDevice\",\"updateDevice\",\"getAdsForDevice\",\"ackDeviceCommand\",\"getDeviceHeartbeat\",\"heartbeat\",\"recordProgrammaticEvent\",\"listDevices\",\"registerDeviceV2\",\"registerDevicesBatch\",\"batchUpdateDeviceOrientation\",\"reconcileDevices\",\"partnerDocsBrowser\",\"getEarnings\",\"getEarningsBreakdown\",\"requestPayout\",\"getTransactions\",\"getActiveSSEConnections\",\"subscribeToEvents\",\"getFleetCommand\",\"getFleetAnalytics\",\"pushFleetCommand\",\"getFleetOverview\",\"updateFleetSettings\",\"recordImpressionGet\",\"recordImpressionPost\",\"recordImpressionsBatch\",\"getPartnerInfo\",\"listIntentCategories\",\"getIntentCategory\",\"getIntentPricing\",\"getMeasurementMethodology\",\"getMeasurementMethodologyJson\",\"getNetworkConfig\",\"patchNetworkConfig\",\"updateNetworkConfig\",\"getNetworkTrends\",\"partnerPing\",\"partnerPingAuth\",\"recordPartnerPlay\",\"recordPartnerPlaysBatch\",\"getPricing\",\"recordProgrammaticEventLegacyAlias\",\"quickStart\",\"registerPartner\",\"generateSandboxEvent\",\"resetSandbox\",\"createSandboxScreen\",\"getSandboxStatus\",\"listScreenGroups\",\"createScreenGroup\",\"deleteScreenGroup\",\"getScreenGroup\",\"updateScreenGroup\",\"getScreenGroupAnalytics\",\"createScreenGroupCommand\",\"getScreenGroupContentPolicy\",\"updateScreenGroupContentPolicy\",\"removeScreenGroupMembers\",\"listScreenGroupMembers\",\"addScreenGroupMembers\",\"getScreenGroupSensingConfig\",\"updateScreenGroupSensingConfig\",\"getScreenAudienceSegments\",\"batchUpdateContentPreferences\",\"batchUpdateDisplaySettings\",\"batchUpdateProgrammaticSettings\",\"resolvePartnerScreen\",\"getScreenAnalytics\",\"getPartnerScreenAtmosphere\",\"getPartnerScreenIntelligence\",\"getPartnerScreenTasteProfile\",\"getPartnerScreenTraffic\",\"getPartnerScreenVAS\",\"applyContentPreset\",\"getAudienceMetrics\",\"getContentPreferences\",\"patchContentPreferences\",\"updateContentPreferences\",\"listPartnerDefaultStreams\",\"createPartnerDefaultStream\",\"createPartnerDefaultStreamImages\",\"reorderPartnerDefaultStreams\",\"createPartnerDefaultStreamUpload\",\"deletePartnerDefaultStream\",\"updatePartnerDefaultStream\",\"getScreenDemographics\",\"getDisplaySettings\",\"patchDisplaySettings\",\"updateDisplaySettings\",\"getPartnerLBarSettings\",\"updatePartnerLBarSettings\",\"updatePartnerLBarLiveUpdates\",\"getProgrammaticSettings\",\"patchProgrammaticSettings\",\"updateProgrammaticSettings\",\"getResolvedContentPolicy\",\"getResolvedSensingConfig\",\"getScreenSensingChips\",\"interpretScreenSensingIntent\",\"deployScreenSensingProfile\",\"getScreenSensingSettings\",\"updateScreenSensingSettings\",\"listPartnerSensingRoutes\",\"createPartnerSensingRoute\",\"deletePartnerSensingRoute\",\"getPartnerSensingRoute\",\"updatePartnerSensingRoute\",\"createStripeConnectAccount\",\"getStripeLoginLink\",\"getStripeOnboardingLink\",\"requestStripePayout\",\"getStripePayoutHistory\",\"getStripeAccountStatus\",\"handleStripeWebhook\",\"listTeamMembers\",\"acceptInvitation\",\"inviteTeamMember\",\"getInvitationByToken\",\"resendInvitation\",\"removeTeamMember\",\"changeTeamMemberRole\",\"getTrackingPublicKey\",\"recordTrackingBatch\",\"getUsageSummary\",\"getUsageDashboard\",\"getRateLimitStatus\",\"queryChangelog\",\"playgroundDryRun\",\"getRequestMetadata\",\"getVastConfig\",\"getVenuesNearby\",\"getVenueAtmosphere\",\"getVenueTraffic\",\"getVenueIntelligence\",\"listWebhooks\",\"createWebhook\",\"deleteWebhook\",\"updateWebhook\",\"getWebhookDeliveries\",\"testWebhook\"] as const,\n} as const;\n\nexport type GeneratedSchemaName = (typeof generatedTypes.schemas)[number];\nexport type GeneratedOperationName = (typeof generatedTypes.operations)[number];\n"]}
|