Endpoints: 28,729MCP servers: 18,413Payout addresses: 2,071Paid calls: 1,552Letters: 14Defects: 1,331counted 1 min ago
teppi

Server definition

Hash
sha256:abf5669d261278ac7fe6d755b1014c2317aa9fc317f0e6cc571804b2b45d46cf
What it is
What a remote MCP server returned when asked what it offers: 83 tools

The blob, as servednamed by its sha256

{ "instructions": "DOOH Exchange Seller Agent — AdCP + MCP Server (Protocol 2025-11-25)\n\nThe first DOOH (Digital Out-of-Home) seller agent in the AdCP ecosystem.\nProvides programmatic access to 24,000+ owned-and-operated screens with\ndeterministic real-time audience intelligence from edge AI (vision, audio, speech).\n\nAvailable tool categories:\n- Partner Management: Register partners, get account info\n- Device Management: Register, list, update, delete devices\n- Impression Tracking: Record ad impressions (single or batch)\n- Analytics: Get performance analytics\n- Webhooks: Create, manage, and test webhook subscriptions\n- Inventory Discovery: Discover screens by venue, location, audience (NEW)\n- Campaign Management: Create/manage DOOH campaigns (NEW)\n- AdCP Signals: Get real-time deterministic audience signals (NEW)\n- AdCP Media Buy: Programmatic DOOH buying via AI agents (NEW)\n- Physical-World Intelligence: Query observations, semantic search, anomaly detection, cross-signal correlation, sensing configuration, dataset export, predictive analytics (NEW)\n\nAuthentication:\n- Stdio transport: Set PLATFORM_API_KEY\n- HTTP transport: Use Authorization: Bearer <api_key> header\n\nDiscovery is open. get_products takes no key at all — send a natural-language\nbrief and read the catalogue before you decide to transact. get_pricing,\nget_adcp_capabilities, register_partner, get_device_ads, the impression tools and\ndevice_heartbeat are likewise unauthenticated. Everything that MOVES something —\ncreate_media_buy, update_media_buy, sync_creatives, get_media_buy_delivery,\nprovide_performance_feedback, log_event, and all reporting — requires a key.\n\nAdCP discovery metadata is available through the server resources.", "tools": [ { "description": "[AdCP Signals] Activate an audience signal for DSP targeting.\n\nReturns an activation_key token for referencing this signal activation. Free-form\nTrillboards signal labels remain custom parameters. IAB Audience Taxonomy 1.1\nsegments are emitted only when registered IDs are supplied explicitly.\n\nWHEN TO USE:\n- Converting audience signals into actionable targeting parameters\n- Activating already-curated, registered IAB segment IDs for programmatic requests\n- Creating reusable targeting configurations\n\nRETURNS:\n- activation_key: Token for referencing this activation (24h expiry)\n- targeting: { iab_segments, iab_taxonomy_version, custom_params }\n- screen_count, provider, data_source, methodology\n\nEXAMPLE:\nUser: \"Activate the registered $100k-$149k household-income segment on my screens\"\nactivate_signal({\n signal_type: \"audience\",\n parameters: { iab_audience_segment_ids: [\"68\"] },\n screen_ids: [\"507f1f77bcf86cd799439011\"]\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "destinations": { "description": "Where to push activated segments", "items": { "additionalProperties": true, "properties": { "platform": { "type": "string" }, "seat_id": { "type": "string" }, "type": { "enum": [ "dsp", "dmp", "data_clean_room" ], "type": "string" } }, "type": "object" }, "type": "array" }, "parameters": { "additionalProperties": false, "description": "Signal parameters to activate as targeting", "properties": { "iab_audience_segment_ids": { "description": "Explicit registered IAB Audience Taxonomy 1.1 IDs; inferred labels are never auto-mapped", "items": { "pattern": "^(?:iab:)?[1-9]\\d*$", "type": "string" }, "maxItems": 50, "type": "array" }, "income": { "enum": [ "high", "upper_mid", "mid", "lower_mid", "low" ], "type": "string" }, "lifestyle": { "description": "Lifestyle segment key", "type": "string" }, "purchase_intent": { "enum": [ "high", "medium", "low" ], "type": "string" } }, "type": "object" }, "screen_ids": { "description": "Specific screens to activate on (optional, defaults to all partner screens)", "items": { "maxLength": 50, "minLength": 1, "type": "string" }, "maxItems": 500, "type": "array" }, "signal_agent_segment_id": { "maxLength": 120, "type": "string" }, "signal_type": { "description": "Type of signal to activate (e.g., \"audience\", \"venue\", \"behavior\")", "maxLength": 50, "minLength": 1, "type": "string" } }, "required": [ "signal_type", "parameters" ], "type": "object" }, "name": "activate_signal", "outputSchema": null }, { "description": "Detect anomalies in observation patterns. Alert when metrics deviate significantly from trailing averages.\n\nComputes trailing mean and standard deviation for a given metric\nfrom the observation_stream, then identifies observations that fall\nbeyond the configured sigma threshold (z-score based anomaly detection).\n\nWHEN TO USE:\n- Monitoring for unusual audience patterns (sudden spikes or drops in face count)\n- Detecting equipment anomalies (confidence drops indicating sensor issues)\n- Identifying unusual commerce or vehicle patterns\n- Finding outlier moments that may indicate events, incidents, or opportunities\n\nRETURNS:\n- anomalies: Array of anomalous observations with:\n - observation_id, device_id, venue_type, observed_at\n - metric_value: The observed value\n - z_score: How many standard deviations from the mean\n - direction: 'above' or 'below' the mean\n - payload: Full observation payload for context\n- baseline: { mean, stddev, sample_count, lookback_hours }\n- suggested_next_queries: Follow-up queries to investigate anomalies\n\nEXAMPLE:\nUser: \"Are there any unusual audience patterns at retail venues?\"\nanomaly_detect({\n metric: \"face_count\",\n venue_type: \"retail\",\n lookback_hours: 24,\n threshold_sigma: 2.0\n})\n\nUser: \"Detect anomalies in vehicle counts at this screen\"\nanomaly_detect({\n metric: \"vehicle_count\",\n screen_id: \"507f1f77bcf86cd799439011\",\n lookback_hours: 48,\n threshold_sigma: 2.5\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "lookback_hours": { "description": "Hours of historical data to compute baseline from (default: 24, max: 168)", "maximum": 168, "minimum": 1, "type": "number" }, "metric": { "description": "The metric to check for anomalies. Extracted from observation payload (e.g., face_count, vehicle_count, confidence, emotional_engagement, crowd_energy, noise_level)", "maxLength": 100, "minLength": 1, "type": "string" }, "screen_id": { "description": "Filter to a specific screen (mongo ID). Optional.", "maxLength": 100, "type": "string" }, "threshold_sigma": { "description": "Number of standard deviations to consider anomalous (default: 2.0, range: 1.0-5.0)", "maximum": 5, "minimum": 1, "type": "number" }, "venue_type": { "description": "Filter to a specific venue type. Optional.", "maxLength": 100, "type": "string" } }, "required": [ "metric" ], "type": "object" }, "name": "anomaly_detect", "outputSchema": null }, { "description": "Record multiple impressions in a single request (up to 100).\n\nWHEN TO USE:\n- Bulk reporting impressions from offline period\n- Efficient batch processing of impressions\n- When device was offline and needs to sync\n\nRETURNS:\n- success: Boolean indicating success\n- processed: Number of impressions processed\n- failed: Number of failed impressions\n- total_earnings: Total earnings credited\n- errors: Any error details for failed impressions\n\nEXAMPLE:\nUser: \"Sync the last hour of impressions\"\nbatch_impressions({\n impressions: [\n { fingerprint: \"P_abc123\", ad_id: \"507f1f77bcf86cd799439011\", duration_seconds: 15 },\n { fingerprint: \"P_abc123\", ad_id: \"507f1f77bcf86cd799439012\", duration_seconds: 10 }\n ]\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "impressions": { "description": "Array of impression objects (max 100)", "items": { "additionalProperties": false, "properties": { "ad_id": { "description": "Advertisement ID", "pattern": "^[0-9a-f]{24}$", "type": "string" }, "duration_seconds": { "description": "Display duration", "exclusiveMinimum": 0, "maximum": 3600, "type": "number" }, "fingerprint": { "description": "Device fingerprint", "maxLength": 100, "minLength": 1, "type": "string" }, "timestamp": { "description": "ISO 8601 timestamp", "format": "date-time", "type": "string" } }, "required": [ "fingerprint", "ad_id" ], "type": "object" }, "maxItems": 100, "minItems": 1, "type": "array" } }, "required": [ "impressions" ], "type": "object" }, "name": "batch_impressions", "outputSchema": null }, { "description": "Configure what a screen should sense using natural language. Generates and optionally pushes a sensing profile to the device.\n\nUses Gemini AI to interpret a natural language sensing intent and generate\na sensing profile that maps to available on-device ML models (BlazeFace,\nAgeGender, FER+, MoveNet, YAMNet, WhisperTiny, EfficientDet, YOLOv8-nano).\n\nWHEN TO USE:\n- Setting up a new screen to sense specific things (faces, vehicles, emotions, etc.)\n- Changing what a screen detects based on venue type or business needs\n- Configuring custom sensing for special events or campaigns\n- Translating business intent into ML model configuration\n\nRETURNS:\n- data: The generated sensing profile with:\n - profile_name, profile_type, description\n - models: Array of ML model IDs to activate\n - classes: COCO classes to detect (for object detection models)\n - thresholds: Confidence and alert thresholds\n - observation_families: What types of observations will be produced\n - capture_interval_ms, report_interval_ms: Timing configuration\n - estimated_fps_impact: CPU cost estimate\n - data_fields_produced: All data fields the profile will generate\n - reasoning: Why these models/classes were chosen\n - deployment_status: 'generated' | 'pushed' | 'push_failed'\n- metadata: { screen_id, auto_deploy, profile_id }\n- suggested_next_queries: Follow-up actions\n\nEXAMPLE:\nUser: \"Set up the lobby screen to detect foot traffic and emotions\"\nconfigure_sensing({\n screen_id: \"507f1f77bcf86cd799439011\",\n intent: \"Detect foot traffic patterns, count people, and measure emotional reactions to displayed content\",\n auto_deploy: false\n})\n\nUser: \"Configure this drive-through screen for vehicle counting\"\nconfigure_sensing({\n screen_id: \"507f1f77bcf86cd799439011\",\n intent: \"Count vehicles in drive-through lane, detect vehicle types, measure queue length\",\n auto_deploy: true\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "auto_deploy": { "description": "If true, automatically push the profile to the device. If false (default), generate only for review.", "type": "boolean" }, "intent": { "description": "Natural language description of what the screen should sense/detect/measure", "maxLength": 1000, "minLength": 1, "type": "string" }, "screen_id": { "description": "Screen ID (mongo ID) to configure sensing for", "maxLength": 100, "minLength": 1, "type": "string" } }, "required": [ "screen_id", "intent" ], "type": "object" }, "name": "configure_sensing", "outputSchema": null }, { "description": "Create a new advertising campaign targeting DOOH screens.\n\nWHEN TO USE:\n- Setting up a new ad campaign on available screens\n- Targeting specific venues, locations, or audience profiles\n- Allocating budget for programmatic DOOH buys\n\nRETURNS:\n- campaign_id: Unique campaign identifier (UUID)\n- name, status, budget, screen_count, dates\n\nCampaign starts in \"draft\" status. Use update_campaign to set status to \"active\".\n\nEXAMPLE:\nUser: \"Create a campaign targeting retail screens in NYC at $5 CPM\"\ncreate_campaign({\n name: \"NYC Retail Q1\",\n budget_cpm: 5.0,\n daily_budget_usd: 100,\n venue_types: [\"retail\"],\n targeting: { geo: { city: \"New York\", state: \"NY\" } },\n creative_url: \"https://cdn.example.com/ad.mp4\",\n start_date: \"2026-03-01\",\n end_date: \"2026-03-31\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "budget_cpm": { "description": "Bid CPM in USD (default: 4.0)", "exclusiveMinimum": 0, "maximum": 1000, "type": "number" }, "creative_duration": { "description": "Duration in seconds (default: 15)", "maximum": 120, "minimum": 1, "type": "integer" }, "creative_type": { "description": "Creative format", "enum": [ "video", "image", "vast" ], "type": "string" }, "creative_url": { "description": "URL to video/image creative asset", "format": "uri", "type": "string" }, "daily_budget_usd": { "description": "Daily budget cap in USD", "maximum": 100000, "minimum": 0, "type": "number" }, "end_date": { "description": "Campaign end date (ISO 8601)", "type": "string" }, "name": { "description": "Campaign name", "maxLength": 200, "minLength": 1, "type": "string" }, "screen_ids": { "description": "Specific screen IDs to target (optional, overrides venue/geo targeting)", "items": { "maxLength": 50, "minLength": 1, "type": "string" }, "maxItems": 500, "type": "array" }, "start_date": { "description": "Campaign start date (ISO 8601)", "type": "string" }, "targeting": { "additionalProperties": false, "description": "Additional targeting criteria", "properties": { "audience_profile": { "additionalProperties": false, "properties": { "income": { "type": "string" }, "lifestyle": { "type": "string" }, "min_attention": { "maximum": 1, "minimum": 0, "type": "number" } }, "type": "object" }, "geo": { "additionalProperties": false, "properties": { "city": { "maxLength": 100, "type": "string" }, "country": { "maxLength": 100, "type": "string" }, "lat": { "maximum": 90, "minimum": -90, "type": "number" }, "lng": { "maximum": 180, "minimum": -180, "type": "number" }, "radius_km": { "exclusiveMinimum": 0, "maximum": 500, "type": "number" }, "state": { "maxLength": 100, "type": "string" } }, "type": "object" }, "schedule": { "additionalProperties": false, "properties": { "days": { "description": "0=Sun..6=Sat", "items": { "maximum": 6, "minimum": 0, "type": "integer" }, "type": "array" }, "hours": { "description": "0-23", "items": { "maximum": 23, "minimum": 0, "type": "integer" }, "type": "array" } }, "type": "object" } }, "type": "object" }, "total_budget_usd": { "description": "Total campaign budget in USD", "maximum": 10000000, "minimum": 0, "type": "number" }, "venue_types": { "description": "Venue types to target: transit, retail, outdoor, office, etc.", "items": { "maxLength": 50, "type": "string" }, "maxItems": 20, "type": "array" } }, "required": [ "name" ], "type": "object" }, "name": "create_campaign", "outputSchema": null }, { "description": "Create an incrementality experiment for a campaign.\n\nSets up a geo-holdout, ghost ads, or propensity score matching experiment\nto causally measure DOOH advertising lift.\n\nWHEN TO USE:\n- Setting up a new A/B test before or during a campaign\n- Defining treatment and control DMAs for geo-holdout tests\n- Configuring experiment parameters (holdout %, MDE, power)\n\nRETURNS:\nThe created experiment object with experiment_id, status, and all parameters.\n\nEXAMPLE:\ncreate_experiment({\n campaign_id: \"camp_abc123\",\n experiment_type: \"geo_holdout\",\n treatment_dmas: [\"501\", \"504\"],\n control_dmas: [\"503\", \"505\"],\n holdout_pct: 0.15,\n target_mde: 0.10\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign identifier", "maxLength": 128, "minLength": 1, "type": "string" }, "control_dmas": { "description": "DMA codes for control group (no ads)", "items": { "maxLength": 20, "type": "string" }, "maxItems": 200, "type": "array" }, "experiment_type": { "description": "Experiment type: geo_holdout (matched DMAs), ghost_ads (PSA control), psm (propensity score matching)", "enum": [ "geo_holdout", "ghost_ads", "psm" ], "type": "string" }, "holdout_pct": { "description": "Fraction of devices to hold out (0.05-0.50). Default: 0.10", "maximum": 0.5, "minimum": 0.05, "type": "number" }, "target_alpha": { "description": "Significance level (0.05 or 0.01). Default: 0.05", "maximum": 0.1, "minimum": 0.001, "type": "number" }, "target_mde": { "description": "Minimum detectable effect (relative, e.g. 0.10 = 10% lift). Default: 0.10", "maximum": 1, "minimum": 0.01, "type": "number" }, "target_power": { "description": "Statistical power (0.80 or 0.90). Default: 0.80", "maximum": 0.99, "minimum": 0.5, "type": "number" }, "treatment_dmas": { "description": "DMA codes for treatment group (get ads)", "items": { "maxLength": 20, "type": "string" }, "maxItems": 200, "type": "array" } }, "required": [ "campaign_id", "experiment_type" ], "type": "object" }, "name": "create_experiment", "outputSchema": null }, { "description": "[AdCP Media Buy] Create a media buy (campaign) from an AdCP buy specification.\n\nCreates a campaign that targets DOOH screens based on the provided specification.\nReturns a media_buy_id for tracking and a creative_deadline for asset submission.\n\nWHEN TO USE:\n- Executing a programmatic DOOH buy via an AI agent\n- Creating campaigns from DSP trading desk agents\n- Automated media buying workflows\n\nRETURNS:\n- media_buy_id: Unique identifier for this media buy\n- campaign_id: Internal campaign identifier\n- creative_deadline: Deadline for creative asset submission\n- targeting_summary: What was targeted\n- budget_summary: Budget allocation details\n\nEXAMPLE:\nUser: \"Buy retail screens in NYC at $5 CPM for next week\"\ncreate_media_buy({\n name: \"NYC Retail Week 12\",\n buy_spec: {\n venue_types: [\"retail\"],\n geo: { city: \"New York\", state: \"NY\" },\n budget: { daily_usd: 500, bid_cpm: 5.0 },\n schedule: { start_date: \"2026-03-16\", end_date: \"2026-03-22\" }\n },\n creative: {\n url: \"https://cdn.example.com/creative.mp4\",\n type: \"video\",\n duration_seconds: 15\n },\n buyer_ref: \"agency-order-12345\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "brand": { "additionalProperties": true, "description": "Brand reference", "properties": { "domain": { "type": "string" }, "name": { "type": "string" } }, "type": "object" }, "buy_spec": { "additionalProperties": false, "description": "Buy specification (legacy)", "properties": { "audience_profile": { "additionalProperties": {}, "type": "object" }, "budget": { "additionalProperties": false, "properties": { "bid_cpm": { "type": "number" }, "daily_usd": { "type": "number" }, "total_usd": { "type": "number" } }, "type": "object" }, "geo": { "additionalProperties": false, "properties": { "city": { "type": "string" }, "country": { "type": "string" }, "lat": { "type": "number" }, "lng": { "type": "number" }, "radius_km": { "type": "number" }, "state": { "type": "string" } }, "type": "object" }, "schedule": { "additionalProperties": false, "properties": { "days": { "items": { "type": "number" }, "type": "array" }, "end_date": { "type": "string" }, "hours": { "items": { "type": "number" }, "type": "array" }, "start_date": { "type": "string" } }, "type": "object" }, "screen_ids": { "items": { "type": "string" }, "type": "array" }, "venue_types": { "items": { "type": "string" }, "type": "array" } }, "type": "object" }, "buyer_ref": { "description": "External reference ID from the buyer/agency", "maxLength": 200, "type": "string" }, "context": { "additionalProperties": {}, "type": "object" }, "creative": { "additionalProperties": false, "properties": { "duration_seconds": { "type": "number" }, "type": { "enum": [ "video", "image", "vast" ], "type": "string" }, "url": { "type": "string" } }, "type": "object" }, "end_time": { "description": "ISO 8601 end time", "type": "string" }, "idempotency_key": { "maxLength": 200, "type": "string" }, "name": { "description": "Media buy name", "maxLength": 200, "minLength": 1, "type": "string" }, "packages": { "description": "AdCP product packages to buy", "items": { "additionalProperties": true, "properties": { "bid_price": { "minimum": 0, "type": "number" }, "budget": { "anyOf": [ { "minimum": 0, "type": "number" }, { "additionalProperties": true, "properties": { "amount": { "type": "number" }, "currency": { "type": "string" } }, "type": "object" } ] }, "impressions": { "minimum": 0, "type": "number" }, "pricing_option_id": { "type": "string" }, "product_id": { "type": "string" }, "targeting_overlay": { "additionalProperties": {}, "type": "object" } }, "type": "object" }, "type": "array" }, "start_time": { "description": "ISO 8601 start time", "type": "string" }, "total_budget": { "additionalProperties": true, "properties": { "amount": { "type": "number" }, "currency": { "type": "string" } }, "type": "object" } }, "type": "object" }, "name": "create_media_buy", "outputSchema": null }, { "description": "Create a new webhook subscription for real-time events.\n\nWHEN TO USE:\n- Setting up real-time notifications for device events\n- Integrating with external systems\n- Monitoring ad playback and impressions\n\nAVAILABLE EVENTS:\n- device.online: When a device comes online\n- device.offline: When a device goes offline\n- impression.recorded: When an impression is logged\n- campaign.allocated: When a campaign is allocated to a device\n- payout.processed: When a payout is processed\n- programmatic.ad_started: When a programmatic ad begins playing\n- programmatic.ad_ended: When a programmatic ad finishes playing\n- programmatic.no_fill: When a programmatic ad request gets no fill\n- programmatic.error: When a programmatic ad request errors\n\nRETURNS:\n- webhook_id: Unique webhook identifier\n- url: The webhook endpoint URL\n- events: Subscribed events\n- secret: HMAC signing secret (if provided)\n- status: enabled/disabled\n\nEXAMPLE:\nUser: \"Set up a webhook for device status changes\"\ncreate_webhook({\n url: \"https://api.mycompany.com/trillboards/webhooks\",\n events: [\"device.online\", \"device.offline\", \"programmatic.error\"],\n secret: \"my-signing-secret-123\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "description": { "description": "Human-readable description for this webhook", "maxLength": 500, "type": "string" }, "events": { "description": "Events to subscribe to", "items": { "enum": [ "device.online", "device.offline", "impression.recorded", "campaign.allocated", "payout.processed", "programmatic.ad_started", "programmatic.ad_ended", "programmatic.no_fill", "programmatic.error", "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" ], "type": "string" }, "maxItems": 10, "minItems": 1, "type": "array" }, "secret": { "description": "HMAC signing secret for verifying webhook authenticity (optional but recommended)", "maxLength": 100, "type": "string" }, "url": { "description": "HTTPS endpoint URL to receive webhook events", "format": "uri", "type": "string" } }, "required": [ "url", "events" ], "type": "object" }, "name": "create_webhook", "outputSchema": null }, { "description": "Discover correlations between different signal types. Example: relationship between ad fill rate and audience attention for QSR venues.\n\nQueries the cross_signal_insights table for pre-computed correlations, or\ncomputes ad-hoc correlations from the observation_stream when no\npre-computed insight exists.\n\nWHEN TO USE:\n- Understanding relationships between different sensing signals\n- Finding which audience behaviors correlate with business outcomes\n- Discovering hidden patterns (e.g., crowd_energy vs purchase_intent)\n- Validating hypotheses about audience-venue-time relationships\n\nRETURNS:\n- data: Correlation analysis with:\n - signal_a, signal_b: The two signals being correlated\n - correlation_r: Pearson correlation coefficient (-1 to +1)\n - correlation_r2: R-squared (proportion of variance explained)\n - p_value: Statistical significance\n - sample_count: Number of data points used\n - effect_size: Cohen's d effect size\n - confidence_interval_lower, confidence_interval_upper: 95% CI bounds\n - insight_summary: Human-readable interpretation\n- metadata: { computation_method, window, filters_applied }\n- suggested_next_queries: Related correlation analyses to explore\n\nEXAMPLE:\nUser: \"Is there a correlation between audience attention and ad fill rate at QSR venues?\"\ncross_signal_correlate({\n signal_a: \"attention_score\",\n signal_b: \"ad_fill_rate\",\n filters: { venue_type: \"restaurant_qsr\" }\n})\n\nUser: \"How does crowd energy relate to purchase intent during lunch hours?\"\ncross_signal_correlate({\n signal_a: \"crowd_energy\",\n signal_b: \"purchase_intent\",\n filters: { daypart: \"lunch\" }\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "filters": { "additionalProperties": false, "description": "Optional filters to narrow the correlation analysis", "properties": { "daypart": { "description": "Filter by daypart: morning, lunch, afternoon, evening, night", "enum": [ "morning", "lunch", "afternoon", "evening", "night" ], "type": "string" }, "dma_code": { "description": "Filter by DMA code for geographic region", "maxLength": 20, "type": "string" }, "time_range": { "additionalProperties": false, "description": "Time range filter", "properties": { "end": { "description": "End time (ISO 8601)", "type": "string" }, "start": { "description": "Start time (ISO 8601)", "type": "string" } }, "type": "object" }, "venue_type": { "description": "Filter to a specific venue type", "maxLength": 100, "type": "string" } }, "type": "object" }, "signal_a": { "description": "First signal to correlate (e.g., face_count, attention_score, crowd_energy, emotional_engagement, vehicle_count, noise_level, purchase_intent, ad_fill_rate)", "maxLength": 100, "minLength": 1, "type": "string" }, "signal_b": { "description": "Second signal to correlate against signal_a", "maxLength": 100, "minLength": 1, "type": "string" } }, "required": [ "signal_a", "signal_b" ], "type": "object" }, "name": "cross_signal_correlate", "outputSchema": null }, { "description": "Soft-delete a device from the partner account.\n\nWHEN TO USE:\n- Removing a device that's been decommissioned\n- Cleaning up test devices\n- Removing a device that's been relocated to another partner\n\nRETURNS:\n- success: Boolean indicating success\n- device_id: The deleted device ID\n- message: Confirmation message\n\nEXAMPLE:\nUser: \"Remove the old lobby kiosk\"\ndelete_device({\n device_id: \"lobby-kiosk-old\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "device_id": { "description": "Your internal device identifier to delete", "maxLength": 100, "minLength": 1, "type": "string" } }, "required": [ "device_id" ], "type": "object" }, "name": "delete_device", "outputSchema": null }, { "description": "Delete a webhook subscription.\n\nWHEN TO USE:\n- Removing a webhook that's no longer needed\n- Cleaning up old integrations\n- Removing test webhooks\n\nRETURNS:\n- success: Boolean indicating success\n- webhook_id: The deleted webhook ID\n- message: Confirmation message\n\nEXAMPLE:\nUser: \"Delete the old webhook\"\ndelete_webhook({\n webhook_id: \"wh_mmmpdbvj_8b7c5a59296d\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "webhook_id": { "description": "Webhook ID to delete (wh_xxx format or legacy ObjectId)", "pattern": "^(wh_[a-z0-9]+_[a-f0-9]+|[a-f0-9]{24})$", "type": "string" } }, "required": [ "webhook_id" ], "type": "object" }, "name": "delete_webhook", "outputSchema": null }, { "description": "Describe a single API operation including its parameters,\nresponse shape, and error codes.\n\nWHEN TO USE:\n- Inspecting an endpoint's full contract before calling it.\n- Discovering which error codes an endpoint can return and how to recover.\n\nRETURNS:\n- operation: Full discovery record for the endpoint.\n- parameters: Raw OpenAPI parameter definitions.\n- request_body: Body schema (when applicable).\n- responses: Map of status code → description/schema.\n- linked_error_codes: Error catalog entries the endpoint can emit.\n\nEXAMPLE:\nAgent: \"How do I call the screen audience endpoint?\"\ndescribe_endpoint({\n path: \"/v1/data/screens/{screenId}/audience\",\n method: \"GET\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "method": { "description": "HTTP method (case-insensitive).", "maxLength": 16, "minLength": 1, "type": "string" }, "path": { "description": "The operation path (OpenAPI template form, e.g. \"/v1/data/screens/{screenId}/audience\").", "maxLength": 256, "minLength": 1, "type": "string" } }, "required": [ "path", "method" ], "type": "object" }, "name": "describe_endpoint", "outputSchema": null }, { "description": "Send a heartbeat signal from a device to report its status.\n\nWHEN TO USE:\n- Regular device health monitoring (every 30-60 seconds)\n- Reporting current playback status\n- Reporting errors or issues\n\nRETURNS:\n- success: Boolean indicating success\n- device_status: Current device status in system\n- next_heartbeat_seconds: Recommended interval for next heartbeat\n\nEXAMPLE:\nUser: \"Send heartbeat for device P_abc123\"\ndevice_heartbeat({\n fingerprint: \"P_abc123\",\n status: \"playing\",\n current_ad_id: \"507f1f77bcf86cd799439011\",\n uptime_seconds: 3600\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "current_ad_id": { "description": "Currently playing ad ID (if status is \"playing\")", "pattern": "^[0-9a-f]{24}$", "type": "string" }, "error_message": { "description": "Error message (if status is \"error\")", "maxLength": 500, "type": "string" }, "fingerprint": { "description": "Device fingerprint (e.g., \"P_abc123\")", "maxLength": 100, "minLength": 1, "type": "string" }, "status": { "description": "Current device status", "enum": [ "online", "playing", "idle", "error" ], "type": "string" }, "uptime_seconds": { "description": "Device uptime in seconds", "minimum": 0, "type": "integer" } }, "required": [ "fingerprint" ], "type": "object" }, "name": "device_heartbeat", "outputSchema": null }, { "description": "Discover available DOOH screens across the exchange network.\n\nWHEN TO USE:\n- Finding screens by venue type (retail, transit, office, etc.)\n- Finding screens in a specific city/state or within a radius\n- Finding screens with a specific audience profile (high income, professionals, etc.)\n- Getting an overview of available inventory with live audience data\n\nRETURNS:\n- screens: Array of screen objects with location, venue type, online status, and live audience data\n- total: Total matching screens\n- online_count: Number of currently online screens\n\nEach screen includes real-time audience data when available:\n- face_count, attention_score, income_level, mood, lifestyle\n- purchase_intent, crowd_density, ad_receptivity, dwell_time\n\nEXAMPLE:\nUser: \"Find retail screens in New York with high-income audience\"\ndiscover_inventory({\n venue_types: [\"retail\"],\n location: { city: \"New York\", state: \"NY\" },\n audience_profile: { income: \"high\" },\n limit: 20\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "audience_profile": { "additionalProperties": false, "description": "Filter screens by current audience characteristics", "properties": { "income": { "description": "Target income level", "enum": [ "high", "upper_mid", "mid", "lower_mid", "low" ], "type": "string" }, "lifestyle": { "description": "Target lifestyle segment (professional, student, fitness, luxury_shopper, tech_savvy, etc.)", "maxLength": 50, "type": "string" }, "min_attention": { "description": "Minimum attention score (0-1)", "maximum": 1, "minimum": 0, "type": "number" } }, "type": "object" }, "limit": { "description": "Maximum screens to return (default: 50, max: 200)", "maximum": 200, "minimum": 1, "type": "integer" }, "location": { "additionalProperties": false, "description": "Location filter — use city/state OR lat/lng/radius_km", "properties": { "city": { "description": "City name", "maxLength": 100, "type": "string" }, "lat": { "description": "Latitude for radius search", "maximum": 90, "minimum": -90, "type": "number" }, "lng": { "description": "Longitude for radius search", "maximum": 180, "minimum": -180, "type": "number" }, "radius_km": { "description": "Search radius in kilometers", "exclusiveMinimum": 0, "maximum": 500, "type": "number" }, "state": { "description": "State/province", "maxLength": 100, "type": "string" } }, "type": "object" }, "venue_types": { "description": "Filter by venue types: transit, retail, outdoor, health_beauty, point_care, education, office, entertainment, government, financial, residential", "items": { "maxLength": 50, "type": "string" }, "maxItems": 20, "type": "array" } }, "type": "object" }, "name": "discover_inventory", "outputSchema": null }, { "description": "Export exposed audience cohort to a DSP for retargeting.\n\nPushes MAID hashes from the campaign's exposed cohort to the specified DSP\n(The Trade Desk, DV360, or Meta). Creates or reuses a DSP segment.\n\nWHEN TO USE:\n- Activating DOOH-exposed audiences for retargeting on digital channels\n- Pushing cohorts to TTD, DV360, or Meta Custom Audiences\n- Measuring cross-channel retargeting lift\n\nRETURNS:\n- status: 'synced', 'no_cohort', 'credentials_missing', or 'empty_cohort'\n- destination: the DSP name\n- segmentId: internal segment ID\n- externalSegmentId: DSP-side segment ID\n- maidCount: number of MAIDs uploaded\n- accepted: number accepted by DSP\n\nSupported destinations: ttd, dv360, meta, cadent, mediaocean\n\nEXAMPLE:\nexport_cohort({\n campaign_id: \"camp_abc123\",\n destination: \"ttd\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign identifier", "maxLength": 128, "minLength": 1, "type": "string" }, "destination": { "description": "DSP destination: ttd (The Trade Desk), dv360 (Google DV360), meta (Meta/Facebook), cadent, mediaocean", "enum": [ "ttd", "dv360", "meta", "cadent", "mediaocean" ], "type": "string" } }, "required": [ "campaign_id", "destination" ], "type": "object" }, "name": "export_cohort", "outputSchema": null }, { "description": "Export observation data as a structured dataset. Supports filtering by time, geography, venue type, and observation family.\n\nQueries the relevant table based on the selected dataset type, applies\nfilters, and returns every matching row as structured data, a page at a time:\nup to 10,000 observation rows or 1,000 cross-signal insights per call, newest\nfirst. When more rows match, metadata.truncated is true and\nmetadata.next_cursor reads the next page: call again with the same dataset and\nfilters and cursor set to it, until truncated is false.\n\nWHEN TO USE:\n- Exporting audience data for external analysis\n- Building datasets for machine learning or reporting\n- Getting structured vehicle or commerce data for a specific time/place\n- Creating cross-signal datasets for correlation analysis\n\nRETURNS:\n- data: Array of dataset rows (schema varies by dataset type)\n- metadata: { row_count, export_id, dataset, filters_applied, time_range, truncated, next_cursor }\n- suggested_next_queries: Related exports or analyses\n\nDataset types:\n- observations: Raw observation stream data (all families)\n- audience: Audience-specific data (face_count, demographics, attention, emotion)\n- vehicle: Vehicle counting and classification data\n- cross_signal: Pre-computed cross-signal correlation insights\n\nEXAMPLE:\nUser: \"Export audience data from retail venues last week\"\nexport_dataset({\n dataset: \"audience\",\n filters: {\n time_range: { start: \"2026-03-09\", end: \"2026-03-16\" },\n venue_type: [\"retail\"]\n },\n format: \"json\"\n})\n\nUser: \"Get vehicle data near geohash 9q8yy\"\nexport_dataset({\n dataset: \"vehicle\",\n filters: {\n time_range: { start: \"2026-03-15\", end: \"2026-03-16\" },\n geo: \"9q8yy\"\n }\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "cursor": { "description": "The previous page's metadata.next_cursor, to read the next page (same dataset and filters).", "maxLength": 2000, "type": "string" }, "dataset": { "description": "Type of dataset to export", "enum": [ "observations", "audience", "vehicle", "cross_signal" ], "type": "string" }, "filters": { "additionalProperties": false, "description": "Filters to apply to the export", "properties": { "geo": { "description": "Filter by geohash-6 prefix", "maxLength": 12, "type": "string" }, "observation_family": { "description": "Filter by observation families (for observations dataset)", "items": { "maxLength": 50, "type": "string" }, "maxItems": 10, "type": "array" }, "time_range": { "additionalProperties": false, "description": "Time range filter (required for observations/audience/vehicle)", "properties": { "end": { "description": "End date/time (ISO 8601 or YYYY-MM-DD)", "type": "string" }, "start": { "description": "Start date/time (ISO 8601 or YYYY-MM-DD)", "type": "string" } }, "type": "object" }, "venue_type": { "description": "Filter by venue types", "items": { "maxLength": 50, "type": "string" }, "maxItems": 20, "type": "array" } }, "type": "object" }, "format": { "description": "Export format (default: json). Currently only JSON is supported.", "enum": [ "json" ], "type": "string" } }, "required": [ "dataset", "filters" ], "type": "object" }, "name": "export_dataset", "outputSchema": null }, { "description": "Find historically similar audience moments across the screen network using embedding similarity search. Input a natural-language description of the target moment.\n\nMoment embeddings are 768-D vectors generated from multi-modal observation data\n(visual, audio, environmental, social) via the MomentEmbeddingService. This tool\nembeds your query text and finds the closest real-world moments via approximate\nnearest-neighbour (ANN) cosine similarity over a Lance IVF_PQ index.\n\nCONSISTENCY: results are APPROXIMATE and EVENTUALLY CONSISTENT.\n- Approximate: retrieval is ANN, not an exhaustive scan (measured recall ~0.96\n against exact KNN), so an identical query may omit a borderline match.\n- Eventually consistent: the index is served from a replicated pool whose\n replicas refresh independently, so for up to 5 minutes after new moments are\n published, two identical calls may return slightly different result sets. The\n difference is confined to the VISIBILITY of newly-published moments; the\n relative ranking of already-visible ones does not change.\nDo not use this tool where a repeatable, exhaustive result set is required.\n\nWHEN TO USE:\n- Searching for historical moments similar to a target scenario\n- Finding \"moments like this one\" across different venues/times\n- Discovering when similar audience compositions or behaviors occurred\n- Planning ad placements based on past similar contexts\n\nRETURNS:\n- data: Array of matching observations with similarity scores\n - observation_id, observed_at, venue_type, device_id, screen_mongo_id\n - payload: full observation data\n - evidence_grade: quality of observation\n - similarity: cosine similarity score (0-1, higher = more similar)\n- metadata: { result_count, embedding_model, min_similarity_threshold }\n- suggested_next_queries: Follow-up queries\n\nEXAMPLE:\nUser: \"Find moments with high engagement in evening restaurants with families\"\nfind_similar_moments({ query: \"evening restaurant venue with families present, high emotional engagement and attention\" })\n\nUser: \"When did we see young adults highly engaged at transit screens?\"\nfind_similar_moments({ query: \"transit venue morning commute young adults high attention\" })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "limit": { "description": "Maximum results to return. Default: 10, max: 200.", "maximum": 200, "minimum": 1, "type": "integer" }, "min_similarity": { "description": "Minimum cosine similarity threshold (0-1). Default: 0.7. Lower values return more but less relevant results.", "maximum": 1, "minimum": 0, "type": "number" }, "query": { "description": "Natural-language description of the target moment. Be descriptive about venue, time, audience, behavior, and conditions.", "maxLength": 1000, "minLength": 1, "type": "string" }, "venue_type": { "description": "Filter results to a specific venue type. Optional.", "maxLength": 100, "type": "string" } }, "required": [ "query" ], "type": "object" }, "name": "find_similar_moments", "outputSchema": null }, { "description": "[AdCP] Get the seller agent's AdCP capabilities and supported protocols.\n\nReturns the full capability declaration for this AdCP DOOH seller agent.\nThis tool does NOT require authentication.\n\nWHEN TO USE:\n- Discovering what protocols the seller agent supports (Signals, Media Buy)\n- Understanding available audience signals and data methodology\n- Getting MCP endpoint and discovery URLs\n\nRETURNS:\n- supported_protocols: ['signals', 'media_buy']\n- inventory: DOOH format details, network size\n- audience_data: signal list, methodology, refresh rate\n- pricing: model, currency, floor CPM\n- discovery: well_known_url, mcp_endpoint", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": {}, "type": "object" }, "name": "get_adcp_capabilities", "outputSchema": null }, { "description": "Get analytics data for the partner account.\n\nWHEN TO USE:\n- Viewing overall performance metrics\n- Analyzing device performance\n- Generating reports on impressions and earnings\n- Comparing performance over time periods\n\nRETURNS:\n- summary: Overall stats (impressions, earnings, active_devices)\n- time_series: Data points over time\n- top_devices: Best performing devices\n- breakdown: Data grouped by requested dimension\n\nEXAMPLE:\nUser: \"Show me last week's analytics by device\"\nget_analytics({\n start_date: \"2026-01-01\",\n end_date: \"2026-01-07\",\n group_by: \"device\"\n})\n\nUser: \"Get monthly performance breakdown\"\nget_analytics({\n start_date: \"2025-12-01\",\n end_date: \"2025-12-31\",\n group_by: \"day\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "device_id": { "description": "Filter to a specific device (optional)", "maxLength": 100, "type": "string" }, "end_date": { "description": "End date in YYYY-MM-DD format (optional, defaults to today)", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "type": "string" }, "group_by": { "description": "How to group the analytics data", "enum": [ "day", "week", "month", "device" ], "type": "string" }, "start_date": { "description": "Start date in YYYY-MM-DD format (optional, defaults to 30 days ago)", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "type": "string" } }, "type": "object" }, "name": "get_analytics", "outputSchema": null }, { "description": "Get edge AI attention metrics for a campaign (FEIN-powered).\n\nThis is what makes DOOH attribution better than digital: Trillboards MEASURES\nviewability via FEIN edge AI instead of estimating it.\n\nWHEN TO USE:\n- Measuring actual human attention to ads (not just impressions)\n- Comparing attention-adjusted CPM (aCPM) vs standard CPM\n- Getting face count, dwell time, and emotion engagement data\n\nRETURNS:\n- impressions: total, uniqueDevices\n- attention: avgScore (0-1), medianScore, p90Score, avgDwellSeconds, avgFaceCount, qualifiedPct\n- economics: standardCpm, attentionCpm (aCPM), costPerAttentiveReach\n- emotion: avgEngagement (0-1), positiveEmotionPct\n\naCPM = total_media_cost / (SUM(attention_score * face_count) / 1000)", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign identifier", "maxLength": 128, "minLength": 1, "type": "string" } }, "required": [ "campaign_id" ], "type": "object" }, "name": "get_attention_metrics", "outputSchema": null }, { "description": "Get daily attribution timeseries for a campaign.\n\nWHEN TO USE:\n- Tracking attribution trends over time\n- Identifying which days had the strongest lift\n- Building attribution dashboards with daily granularity\n\nRETURNS:\nArray of daily data points, each with:\n- date, uniqueDevices, totalExposures, avgFrequency\n- exposedVisitors, controlVisitors, liftPct, incrementalVisits\n- costPerVisit, totalMediaCost, isSignificant\n\nEXAMPLE:\nget_attribution_timeseries({\n campaign_id: \"camp_abc123\",\n start_date: \"2026-03-01\",\n end_date: \"2026-03-10\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign identifier", "maxLength": 128, "minLength": 1, "type": "string" }, "end_date": { "description": "End date (YYYY-MM-DD). Optional, defaults to today.", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "type": "string" }, "start_date": { "description": "Start date (YYYY-MM-DD). Optional, defaults to campaign start.", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "type": "string" } }, "required": [ "campaign_id" ], "type": "object" }, "name": "get_attribution_timeseries", "outputSchema": null }, { "description": "Predict what the audience will look like at a screen at a specific time.\n\nWHEN TO USE:\n- Planning campaigns for specific time slots\n- Estimating audience composition before buying\n- Comparing audience at different times of day\n\nUses historical audience data to predict typical audience patterns.\n\nRETURNS:\n- predicted_face_count: Expected number of viewers\n- predicted_attention: Expected attention score\n- typical_income: Most common income level at that time\n- typical_lifestyle: Most common lifestyle segment at that time\n- confidence: Prediction confidence (0-1, based on sample count)\n- sample_count: Number of historical data points used\n\nEXAMPLE:\nUser: \"What's the typical audience at this screen on Monday at 3pm?\"\nget_audience_forecast({\n screen_id: \"507f1f77bcf86cd799439011\",\n hour: 15,\n day: 1,\n lookback_days: 30\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "day": { "description": "Day of week (0=Sunday, 1=Monday, ..., 6=Saturday)", "maximum": 6, "minimum": 0, "type": "integer" }, "hour": { "description": "Hour of day (0-23)", "maximum": 23, "minimum": 0, "type": "integer" }, "lookback_days": { "description": "Days of historical data to use (default: 30)", "maximum": 365, "minimum": 1, "type": "integer" }, "screen_id": { "description": "Screen ID to forecast", "maxLength": 50, "minLength": 1, "type": "string" } }, "required": [ "screen_id", "hour", "day" ], "type": "object" }, "name": "get_audience_forecast", "outputSchema": null }, { "description": "Find screens with similar audience profiles using pgvector similarity.\n\nUses 64-dimensional audience vectors with HNSW cosine similarity index\nto find screens whose audience demographics, attention, and behavioral\npatterns match a target screen.\n\nWHEN TO USE:\n- Expanding campaign reach to screens with similar audiences\n- Finding new inventory that matches a high-performing screen\n- Building lookalike audience segments for targeting\n\nRETURNS:\nArray of similar screens ranked by cosine similarity, each with:\n- screen_id, similarity (0-1), metadata (face_count, attention, income, lifestyle), last_seen\n\nEXAMPLE:\nget_audience_lookalike({\n screen_id: \"scr_abc123\",\n limit: 10,\n min_similarity: 0.8\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "country": { "description": "Filter by country (optional)", "maxLength": 100, "type": "string" }, "limit": { "description": "Maximum number of results (default: 20, max: 100)", "maximum": 100, "minimum": 1, "type": "integer" }, "min_similarity": { "description": "Minimum cosine similarity threshold 0-1 (default: 0.7)", "maximum": 1, "minimum": 0, "type": "number" }, "screen_id": { "description": "Source screen ID to find lookalikes for", "maxLength": 128, "minLength": 1, "type": "string" }, "venue_type": { "description": "Filter by venue type (optional)", "maxLength": 100, "type": "string" } }, "required": [ "screen_id" ], "type": "object" }, "name": "get_audience_lookalike", "outputSchema": null }, { "description": "Check current billing status including whether billing is set up, credit balance, Stripe customer ID, and payment method status. Use this to determine if billing setup is needed before making paid API calls.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": {}, "type": "object" }, "name": "get_billing_status", "outputSchema": null }, { "description": "Get comprehensive attribution summary for a DOOH campaign.\n\nWHEN TO USE:\n- Measuring overall campaign effectiveness (reach, footfall, sales lift)\n- Getting a high-level view of campaign attribution metrics\n- Checking statistical significance of attribution results\n\nRETURNS:\n- reach: uniqueDevices, totalImpressions, avgFrequency\n- footfall: exposedVisitors, controlVisitors, incrementalLiftPct, incrementalVisits\n- cost: totalMediaCost, costPerUniqueReach, costPerIncrementalVisit\n- quality: avgMatchConfidence, statisticalSignificance, isSignificant\n- dataFreshness: latestOutcomeAt, provisionalCount, finalizedCount\n\nReturns null if no attribution data exists for the campaign.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign identifier (UUID or string ID from create_campaign)", "maxLength": 128, "minLength": 1, "type": "string" } }, "required": [ "campaign_id" ], "type": "object" }, "name": "get_campaign_attribution", "outputSchema": null }, { "description": "Get geographic exposure heatmap data for a campaign.\n\nReturns lat/lng clusters with exposure counts and device reach,\nuseful for visualizing where ads were shown on a map.\n\nWHEN TO USE:\n- Visualizing campaign geographic coverage\n- Identifying hotspots of ad exposure\n- Analyzing geographic distribution of attributed foot traffic\n\nRETURNS:\nArray of geographic clusters (max 500), each with:\n- lat, lng (rounded to 3 decimal places)\n- uniqueDevices, totalExposures\n- avgConfidence (match confidence score)", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign identifier", "maxLength": 128, "minLength": 1, "type": "string" } }, "required": [ "campaign_id" ], "type": "object" }, "name": "get_campaign_heatmap", "outputSchema": null }, { "description": "Get detailed performance metrics for a campaign.\n\nWHEN TO USE:\n- Monitoring active campaign performance\n- Reviewing completed campaign results\n- Getting per-screen impression breakdowns\n\nRETURNS:\n- campaign_id, name, status, budget, dates\n- performance: impressions, spend_estimate_usd, avg_cpm, unique_screens, avg_latency_ms\n- screen_breakdown: per-screen impressions and CPM\n\nEXAMPLE:\nUser: \"How is my NYC retail campaign performing?\"\nget_campaign_performance({ campaign_id: \"550e8400-e29b-41d4-a716-446655440000\" })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign UUID returned from create_campaign", "maxLength": 100, "minLength": 1, "type": "string" } }, "required": [ "campaign_id" ], "type": "object" }, "name": "get_campaign_performance", "outputSchema": null }, { "description": "Get performance metrics for a video across the Trillboards DOOH network.\n\nWHEN TO USE:\n- Checking how a specific video performs across screens (plays, attention, audience size)\n- Analyzing which venue types and dayparts a video resonates best in\n- Finding the top-performing screens for a piece of content\n- Comparing content performance over different time windows\n\nRETURNS:\n- videoId, title, totalPlays, uniqueScreens\n- avgAttention (0-1), avgAudienceSize, avgDwellMs\n- venueDistribution: Array of { venue_type, plays }\n- daypartDistribution: Array of { daypart, plays }\n- topScreens: Top 10 screens by play count with attention scores\n- period: { start, end } date range\n\nEXAMPLE:\nUser: \"How is video dQw4w9WgXcQ performing on retail screens?\"\nget_content_performance({\n video_id: \"dQw4w9WgXcQ\",\n venue_type: \"retail\",\n days: 30\n})\n\nUser: \"Show me the last 7 days of performance for this video\"\nget_content_performance({\n video_id: \"abc123xyz\",\n days: 7\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "days": { "description": "Lookback window in days (default: 30, max: 90)", "maximum": 90, "minimum": 1, "type": "integer" }, "venue_type": { "description": "Optional venue type filter (e.g., \"retail\", \"transit\", \"bar\")", "maxLength": 100, "type": "string" }, "video_id": { "description": "YouTube video ID to query performance for", "maxLength": 200, "minLength": 1, "type": "string" } }, "required": [ "video_id" ], "type": "object" }, "name": "get_content_performance", "outputSchema": null }, { "description": "Get best-performing content recommendations for a venue type and optional time context.\n\nWHEN TO USE:\n- Deciding what content to schedule at a specific venue type\n- Finding content that drives the highest audience engagement at a location\n- Optimizing content rotation by daypart (morning, afternoon, evening, overnight)\n- Content programming decisions based on performance data\n\nRETURNS:\n- data: Array of recommended content ranked by performance score\n - videoId, title, contentCategory, durationSeconds\n - totalPlays, uniqueScreens\n - avgAttention (0-1), avgDwellMs\n - performanceScore (composite of attention, replay density, dwell time)\n- meta: { count, venue_type, daypart, limit }\n\nPerformance score formula: attention(40%) + replay_density(30%) + dwell_time(30%)\n\nEXAMPLE:\nUser: \"What content works best in bars during the evening?\"\nget_content_recommendations({\n venue_type: \"bar\",\n daypart: \"evening\",\n limit: 10\n})\n\nUser: \"Best performing content for transit screens\"\nget_content_recommendations({\n venue_type: \"transit\",\n limit: 20\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "daypart": { "description": "Optional daypart filter", "enum": [ "morning", "afternoon", "evening", "overnight" ], "type": "string" }, "limit": { "description": "Maximum recommendations to return (default: 10, max: 100)", "maximum": 100, "minimum": 1, "type": "integer" }, "venue_type": { "description": "Venue type to get recommendations for (required)", "maxLength": 100, "minLength": 1, "type": "string" } }, "required": [ "venue_type" ], "type": "object" }, "name": "get_content_recommendations", "outputSchema": null }, { "description": "Get per-creative attention breakdown for a campaign.\n\nWHEN TO USE:\n- A/B testing creative variants by attention score\n- Identifying which creative drives the most engagement\n- Comparing aCPM across creative assets\n\nRETURNS:\nArray of creatives ranked by attention score, each with:\n- creativeId, totalImpressions, uniqueDevices\n- avgAttentionScore (0-1), avgDwellSeconds, avgFaceCount\n- attentionCpm, avgEmotionEngagement, positiveEmotionPct, attentionQualifiedPct", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign identifier", "maxLength": 128, "minLength": 1, "type": "string" } }, "required": [ "campaign_id" ], "type": "object" }, "name": "get_creative_attention", "outputSchema": null }, { "description": "Get attribution performance by individual creative variant.\n\nLinks creative execution to attribution outcomes: which creative variant\ndrove the most store visits?\n\nWHEN TO USE:\n- Comparing creative A/B/C test performance on attribution outcomes\n- Finding the optimal creative x venue_type x daypart x weather combination\n- Identifying the creative with the highest visit rate\n\nRETURNS:\nArray of creatives ranked by store visits, each with:\n- creativeId, variant, totalVisits, avgVisitRate\n- attention: avgScore, avgDwell, avgEmotion, dominantEmotion\n- avgLiftPct, avgCostPerVisit\n- bestContext: { venueType, daypart, weather }\n- dateRange: { first, last, daysMeasured }", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign identifier", "maxLength": 128, "minLength": 1, "type": "string" } }, "required": [ "campaign_id" ], "type": "object" }, "name": "get_creative_attribution", "outputSchema": null }, { "description": "Get cross-channel customer journey data (Sankey flow) for a campaign.\n\nShows how users flow between channels: DOOH -> mobile -> web -> store.\n\nWHEN TO USE:\n- Visualizing the customer journey across DOOH and digital channels\n- Understanding channel transition patterns\n- Building Sankey diagrams of marketing funnels\n\nRETURNS:\n- flows: Array of { source, target, count } transitions between channels\n- channels: Array of { channel, touchpoints, uniqueDevices } distribution", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign identifier", "maxLength": 128, "minLength": 1, "type": "string" } }, "required": [ "campaign_id" ], "type": "object" }, "name": "get_cross_channel_journey", "outputSchema": null }, { "description": "Get statistics about available causal training data: total tuples, unique creatives, venue diversity, date range.\n\nQueries observation_stream for rows that have both a creative ID and a VAS\noutcome recorded, giving a picture of how much training data is available\nfor the causal prediction engine.\n\nWHEN TO USE:\n- Checking if enough data exists for reliable causal predictions\n- Understanding the diversity of training data (creatives, venues, time range)\n- Monitoring causal dataset health and growth\n- Planning data collection strategies\n\nRETURNS:\n- data: Dataset statistics\n - total_tuples: number of context-action-outcome records\n - unique_creatives: number of distinct creatives with VAS data\n - unique_venue_types: number of distinct venue types represented\n - date_range: { start, end } of available data\n - observations_per_creative: { min, max, mean, median } distribution\n- metadata: { query_window_days }\n- suggested_next_queries: Follow-up queries\n\nEXAMPLE:\nUser: \"How much causal training data do we have?\"\nget_dataset_stats({})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": {}, "type": "object" }, "name": "get_dataset_stats", "outputSchema": null }, { "description": "Get detailed information about a specific device.\n\nWHEN TO USE:\n- Checking status of a single device\n- Getting device configuration details\n- Debugging device issues\n\nRETURNS:\n- device_id: Your internal device ID\n- trillboards_device_id: Internal Trillboards ID\n- fingerprint: Device fingerprint\n- name: Device name\n- status: online/offline\n- last_seen: Last heartbeat timestamp\n- location: Location details\n- specs: Device specifications\n- stats: Impression and earnings stats\n\nEXAMPLE:\nUser: \"Get details for vending machine 001\"\nget_device({\n device_id: \"vending-001-nyc\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "device_id": { "description": "Your internal device identifier", "maxLength": 100, "minLength": 1, "type": "string" } }, "required": [ "device_id" ], "type": "object" }, "name": "get_device", "outputSchema": null }, { "description": "Get current ads scheduled for a device (for testing).\n\nWHEN TO USE:\n- Testing device ad delivery\n- Debugging which ads are being shown\n- Verifying ad targeting is working\n\nRETURNS:\n- ads: Array of advertisement objects\n- default_stream: Default content when no ads\n- schedule: Current ad schedule\n\nEXAMPLE:\nUser: \"What ads are showing on device P_abc123?\"\nget_device_ads({\n fingerprint: \"P_abc123\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "fingerprint": { "description": "Device fingerprint (e.g., \"P_abc123\")", "maxLength": 100, "minLength": 1, "type": "string" } }, "required": [ "fingerprint" ], "type": "object" }, "name": "get_device_ads", "outputSchema": null }, { "description": "Get incrementality/lift test results for a campaign.\n\nUses Bayesian (Beta-Binomial with 10K Monte Carlo samples) and frequentist\n(chi-square with Yates correction) methods for causal measurement.\n\nWHEN TO USE:\n- Proving causal DOOH advertising effectiveness\n- Getting both Bayesian and frequentist significance measures\n- Seeing treatment vs control group visit rates and lift\n\nRETURNS:\nArray of experiments, each with:\n- experimentId, type (geo_holdout/ghost_ads/psm), status\n- treatmentDmas, controlDmas\n- latestResult: treatment/control rates, lift%, incrementalVisits,\n pValue, posteriorProbPositive, expectedUplift, credibleInterval\n\nReturns empty array if no experiments exist for this campaign.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign identifier", "maxLength": 128, "minLength": 1, "type": "string" } }, "required": [ "campaign_id" ], "type": "object" }, "name": "get_incrementality", "outputSchema": null }, { "description": "Get real-time audience data for a specific screen.\n\nWHEN TO USE:\n- Checking current audience at a screen before buying\n- Monitoring audience during a live campaign\n- Getting detailed audience signals (attention, mood, purchase intent, demographics)\n\nRETURNS real-time data from edge AI sensors (refreshed every 10 seconds):\n- face_count: Number of people currently viewing\n- attention_score: How attentively the audience is watching (0-1)\n- income_level: Estimated income bracket (from Gemini Vision)\n- mood: Current audience mood\n- lifestyle: Primary lifestyle segment\n- purchase_intent: Purchase intent level\n- crowd_density: Estimated venue occupancy\n- ad_receptivity: How receptive the audience is to ads (0-1)\n- emotional_engagement: Emotional engagement score (0-1)\n- group_composition: Solo/couples/families/friends/work groups\n- signals_age_ms: How fresh the data is in milliseconds\n\nEXAMPLE:\nUser: \"What's the current audience at screen 507f1f77bcf86cd799439011?\"\nget_live_audience({ screen_id: \"507f1f77bcf86cd799439011\" })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "screen_id": { "description": "Screen ID to get live audience for", "maxLength": 50, "minLength": 1, "type": "string" } }, "required": [ "screen_id" ], "type": "object" }, "name": "get_live_audience", "outputSchema": null }, { "description": "[AdCP Media Buy] Get delivery/performance report for a media buy.\n\nReturns campaign performance with breakdowns by screen, venue, hour, and audience segment.\n\nWHEN TO USE:\n- Monitoring campaign delivery in real-time\n- Getting performance breakdowns for optimization\n- Reporting on campaign results\n\nRETURNS:\n- delivery: impressions, spend, avg_cpm, unique_screens, fill_rate\n- breakdowns: by_screen, by_venue, by_hour (top performers)\n\nEXAMPLE:\nget_media_buy_delivery({ media_buy_id: \"mbuy_abc123\" })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "breakdown_by": { "description": "Dimensions to break down by (legacy, prefer dimensions). Same single supported value.", "items": { "enum": [ "screen", "venue", "hour", "audience_segment" ], "type": "string" }, "type": "array" }, "dimensions": { "description": "Reporting dimensions to include. Only \"screen\" is supported; anything else is returned in dimensions_unsupported rather than silently dropped.", "items": { "enum": [ "screen", "venue", "hour", "audience_segment", "creative", "day" ], "type": "string" }, "type": "array" }, "media_buy_id": { "description": "Media buy ID", "maxLength": 100, "minLength": 1, "type": "string" } }, "required": [ "media_buy_id" ], "type": "object" }, "name": "get_media_buy_delivery", "outputSchema": null }, { "description": "[AdCP Media Buy] List media buys with status, budget, flight and optional delivery snapshots.\n\nStatus, budget and flight are read from the advertisements + placements spine the buy\nactually books on — not from a stored display string. A buy that its flight ended, or\nthat the pacing cron completed on goal, reports the truth here even though nothing\nrewrote it.\n\nWHEN TO USE:\n- Polling the buys you have open on this account\n- Confirming a buy left pending_creatives after sync_creatives\n- Getting a near-real-time delivery snapshot without a full delivery report\n\nRETURNS:\n- media_buys: each with media_buy_id, status, currency, total_budget, confirmed_at,\n revision and packages[]. status is the AdCP media-buy-status enum; the accepted\n values are listed on the status_filter parameter below.\n- pagination: cursor-based\n\nEXAMPLE:\nget_media_buys({ status_filter: [\"active\", \"pending_creatives\"], include_snapshot: true })\nget_media_buys({ media_buy_ids: [\"mbuy_1750000000000_ab12cd34\"] })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "context": { "additionalProperties": {}, "type": "object" }, "include_snapshot": { "description": "Include a delivery snapshot per package (impressions, spend, pacing_index). Read live off placements, so staleness_seconds is 0.", "type": "boolean" }, "media_buy_ids": { "description": "Specific media buy IDs. When omitted, returns a paginated set matching status_filter.", "items": { "maxLength": 100, "minLength": 1, "type": "string" }, "maxItems": 100, "minItems": 1, "type": "array" }, "pagination": { "additionalProperties": false, "properties": { "cursor": { "description": "Opaque cursor from a previous response", "maxLength": 500, "type": "string" }, "max_results": { "description": "Page size (1-100, default 50)", "maximum": 100, "minimum": 1, "type": "integer" } }, "type": "object" }, "status_filter": { "anyOf": [ { "enum": [ "pending_creatives", "pending_start", "active", "paused", "completed", "rejected", "canceled" ], "type": "string" }, { "items": { "$ref": "#/properties/status_filter/anyOf/0" }, "minItems": 1, "type": "array" } ], "description": "Single status or array of statuses. Defaults to ['active'] when media_buy_ids is omitted; no implicit filter when ids are given." } }, "type": "object" }, "name": "get_media_buys", "outputSchema": null }, { "description": "Get multi-touch attribution model results for a campaign.\n\nSupported models: time_decay, position_based, attention_weighted.\n\nWHEN TO USE:\n- Understanding how DOOH fits into the full marketing funnel\n- Seeing credit allocation across DOOH, mobile, web, and store channels\n- Quantifying DOOH's contribution to conversions\n\nRETURNS:\n- totalChains: number of multi-touch journeys found\n- avgTouchpoints: average touchpoints per chain\n- channelAttribution: { dooh, mobile, web, store } (each 0-1, sums to 1)\n- conversions: total conversion events\n- totalConversionValue: sum of conversion values (cents)\n- avgConfidence: average match confidence across chains\n\nReturns null if no multi-touch chains exist.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign identifier", "maxLength": 128, "minLength": 1, "type": "string" } }, "required": [ "campaign_id" ], "type": "object" }, "name": "get_multi_touch_attribution", "outputSchema": null }, { "description": "Get network-wide statistics across all partner screens.\n\nWHEN TO USE:\n- Getting a high-level overview of network performance\n- Checking how many screens are online\n- Reviewing total impressions and revenue estimates\n\nRETURNS:\n- total_screens, online_screens\n- impressions, total_auctions\n- revenue_estimate_usd, avg_cpm, fill_rate\n\nEXAMPLE:\nUser: \"How is my network performing this week?\"\nget_network_stats({ time_range: \"7d\" })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "time_range": { "description": "Time range for stats (default: 7d)", "enum": [ "today", "7d", "30d" ], "type": "string" } }, "type": "object" }, "name": "get_network_stats", "outputSchema": null }, { "description": "Get information about the authenticated partner account.\n\nWHEN TO USE:\n- Checking current partner status and stats\n- Verifying API key is working\n- Getting partner account details\n\nRETURNS:\n- partner_id: Partner identifier\n- company_name: Registered company name\n- status: Account status (active, suspended, etc.)\n- device_count: Number of registered devices\n- total_impressions: Lifetime impression count\n- earnings: Earnings summary\n\nEXAMPLE:\nUser: \"What's my partner account status?\"\nget_partner_info({})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": {}, "type": "object" }, "name": "get_partner_info", "outputSchema": null }, { "description": "Get machine-readable pricing for all Trillboards products. Returns graduated usage-based pricing, free tier thresholds, and committed-use discount tiers. No authentication required — use this to evaluate costs before integrating.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "product": { "description": "Optional: filter to a specific product (data_api, proof_of_play, attribution, data_marketplace, partner_platform, programmatic, fein_edge_ai)", "enum": [ "data_api", "proof_of_play", "attribution", "data_marketplace", "partner_platform", "programmatic", "fein_edge_ai" ], "type": "string" } }, "type": "object" }, "name": "get_pricing", "outputSchema": null }, { "description": "[AdCP Media Buy] Get available DOOH advertising products and packages.\n\nNO AUTHENTICATION REQUIRED. Discovery is open — read the catalogue first, get a\nkey when you want to transact.\n\nSend a natural-language `brief` and it is answered from what the screens\nactually observed: each product's `description` reports the hours people are\nreally in frame (in the screens' own local time), how long they dwell, the mood\n/ movement / gaze the on-device sensors reported, what the speech layer heard\npeople shopping for — and, explicitly, which of your words we cannot evidence.\nProducts are ordered by that evidence.\n\nWHEN TO USE:\n- Browsing available inventory before creating a campaign\n- Comparing pricing across venue types and locations\n- Understanding what's available in a specific market, at a specific time of day\n\nRETURNS:\n- products: Array of product packages with pricing, reach, and observed audience\n- Each product includes: name, description (free text answering your brief),\n venue_type, screen_count, pricing_options, and `observed` — the numbers\n behind the prose, present only where we measured something\n- brief_interpretation: how we read your brief, so you can see if we read it right\n\nEXAMPLE:\nUser: \"commuters who are bored and hungry around lunchtime\"\nget_products({\n brief: \"commuters who are bored and hungry around lunchtime\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "audience_profile": { "additionalProperties": false, "description": "Target audience characteristics", "properties": { "income": { "type": "string" }, "lifestyle": { "type": "string" }, "min_attention": { "maximum": 1, "minimum": 0, "type": "number" } }, "type": "object" }, "brief": { "description": "Natural language campaign brief for AI-driven inventory matching", "type": "string" }, "buying_mode": { "description": "AdCP buying mode (default: brief)", "enum": [ "brief", "wholesale", "refine" ], "type": "string" }, "filters": { "additionalProperties": true, "description": "Structured filters for wholesale/refine modes", "properties": { "budget_range": { "additionalProperties": false, "properties": { "currency": { "type": "string" }, "max": { "type": "number" }, "min": { "type": "number" } }, "type": "object" }, "channels": { "items": { "type": "string" }, "type": "array" }, "countries": { "items": { "type": "string" }, "type": "array" }, "delivery_type": { "type": "string" }, "format_types": { "items": { "type": "string" }, "type": "array" }, "venue_types": { "items": { "maxLength": 50, "type": "string" }, "maxItems": 20, "type": "array" } }, "type": "object" }, "market": { "description": "Market/city to get products for", "maxLength": 100, "type": "string" }, "pagination": { "additionalProperties": false, "properties": { "cursor": { "maxLength": 500, "type": "string" }, "max_results": { "maximum": 100, "minimum": 1, "type": "integer" } }, "type": "object" }, "venue_types": { "description": "Filter by venue types (legacy, prefer filters.venue_types)", "items": { "maxLength": 50, "type": "string" }, "maxItems": 20, "type": "array" } }, "type": "object" }, "name": "get_products", "outputSchema": null }, { "description": "Get Return on Ad Spend (ROAS) with transaction attribution data.\n\nCloses the ROAS loop: matches purchase events to DOOH exposures with\ntime-decay weighting, and computes attributed revenue and incremental ROAS.\n\nWHEN TO USE:\n- Measuring revenue directly attributable to DOOH advertising\n- Getting ROAS and incremental ROAS (iROAS) figures\n- Seeing sales lift between exposed and control groups\n\nRETURNS:\n- transactions: total, uniquePurchasers, totalRevenueCents, avgBasketCents\n- attribution: attributedTransactions, attributedRevenueCents, totalMediaCostCents, roas, iroas\n- salesLift: exposedPurchasers, controlPurchasers, incrementalTransactions, incrementalRevenueCents, salesLiftPct, posteriorProbPositive\n- timing: avgHoursToPurchase, medianHoursToPurchase\n\nReturns null if no transaction data exists.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign identifier", "maxLength": 128, "minLength": 1, "type": "string" } }, "required": [ "campaign_id" ], "type": "object" }, "name": "get_roas", "outputSchema": null }, { "description": "[AdCP Signals] Get real-time audience signals from DOOH screens.\n\nThis is an AdCP (Ad Context Protocol) compliant tool. It returns deterministic audience\nsignals captured by edge AI (vision + audio + speech) on available screens.\n\nWHEN TO USE:\n- Discovering available audience signals before buying inventory\n- Evaluating audience composition at specific venues or locations\n- Building targeting segments based on real-time audience data\n\nUnlike probabilistic data, these signals are DETERMINISTIC — captured by\non-device cameras and microphones, analyzed by ML Kit and Gemini Vision.\n\nRETURNS:\n- signals: Array of per-screen signal objects with demographics, venue, behavior, geo\n- metadata: total_screens, matching_screens, screens_with_live_data\n\nEXAMPLE (AdCP form — natural language):\nUser: \"What audience signals are available at retail locations?\"\nget_signals({ signal_spec: \"shoppers in retail venues, demographics and behavior\" })\n\nEXAMPLE (structured form):\nget_signals({\n signal_spec: {\n signal_types: [\"demographics\", \"behavior\"],\n filters: { venue_type: \"retail\" }\n }\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "pagination": { "additionalProperties": false, "properties": { "cursor": { "maxLength": 200, "type": "string" }, "max_results": { "maximum": 100, "minimum": 1, "type": "integer" } }, "type": "object" }, "signal_spec": { "anyOf": [ { "maxLength": 2000, "type": "string" }, { "additionalProperties": false, "properties": { "filters": { "additionalProperties": false, "properties": { "city": { "maxLength": 100, "type": "string" }, "income": { "type": "string" }, "lifestyle": { "type": "string" }, "state": { "maxLength": 100, "type": "string" }, "venue_type": { "maxLength": 50, "type": "string" } }, "type": "object" }, "signal_types": { "items": { "enum": [ "demographics", "venue", "geo", "behavior" ], "type": "string" }, "type": "array" } }, "type": "object" } ], "description": "Natural language description of the desired signals (AdCP form), or a structured Trillboards signal specification." } }, "type": "object" }, "name": "get_signals", "outputSchema": null }, { "description": "Query social attention contagion metrics from the observation stream. Returns windows where attention propagated between viewers (social amplification factor > 1).\n\nSocial attention data is produced by the AttentionGraphBuilder running on CTV\nedge devices, which models viewer attention as a directed graph and detects\nwhen one viewer looking at the screen triggers nearby viewers to also look\n(attention contagion / social amplification).\n\nWHEN TO USE:\n- Finding moments where social proof drove collective engagement\n- Identifying which venues or dayparts exhibit highest attention contagion\n- Understanding cascading attention patterns (cascade depth)\n- Correlating social amplification with ad effectiveness (VAS)\n\nRETURNS:\n- data: Array of observation_stream rows with socialAttention payload\n - payload.socialAttention.socialAmplificationFactor (SAF): ratio of actual-to-expected group attention (>1 = contagion detected)\n - payload.socialAttention.cascadeDepth: max depth of attention propagation chain\n - payload.socialAttention.viralAttentionScore: composite metric combining SAF and cascade depth\n - payload.socialAttention.contagionWindowMs: time window over which cascade occurred\n - payload.socialAttention.triggerViewerIndex: which viewer initiated the cascade\n- metadata: { result_count, time_range, min_saf_filter }\n- suggested_next_queries: Follow-up queries\n\nEXAMPLE:\nUser: \"Show me moments where attention went viral in bar venues\"\nget_social_attention({ min_saf: 2.0, venue_type: \"bar\" })\n\nUser: \"Find the strongest social amplification events this week\"\nget_social_attention({ min_saf: 3.0, time_range: { start: \"2026-03-09T00:00:00Z\", end: \"2026-03-16T00:00:00Z\" } })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "limit": { "description": "Maximum results to return. Default: 20, max: 200.", "maximum": 200, "minimum": 1, "type": "integer" }, "min_saf": { "description": "Minimum social amplification factor threshold. Default: 1.5. Higher values return only stronger contagion events.", "maximum": 100, "minimum": 0, "type": "number" }, "screen_id": { "description": "Filter by screen MongoDB ID. Optional.", "maxLength": 100, "type": "string" }, "time_range": { "additionalProperties": false, "description": "Time range filter. Defaults to last 24 hours.", "properties": { "end": { "description": "End time (ISO 8601)", "type": "string" }, "start": { "description": "Start time (ISO 8601)", "type": "string" } }, "type": "object" }, "venue_type": { "description": "Filter by venue type (e.g., \"bar\", \"restaurant_qsr\", \"transit\"). Optional.", "maxLength": 100, "type": "string" } }, "type": "object" }, "name": "get_social_attention", "outputSchema": null }, { "description": "Aggregate social attention metrics across screens and time periods. Shows which venues and dayparts have the highest social amplification.\n\nQueries observation_stream for social attention data and aggregates by the\nrequested dimension (venue, daypart, or screen), computing average SAF,\naverage cascade depth, average viral attention score, and event count.\n\nWHEN TO USE:\n- Understanding which venues generate the most social amplification\n- Comparing daypart effectiveness for social contagion\n- Identifying top-performing screens for attention cascading\n- Planning campaigns that leverage social proof\n\nRETURNS:\n- data: Array of aggregated rows, sorted by avg SAF descending\n - group_key: the dimension value (venue type, daypart, or screen ID)\n - avg_saf: average social amplification factor\n - avg_cascade_depth: average attention cascade depth\n - avg_viral_attention_score: average viral attention score\n - event_count: number of social attention events in the group\n- metadata: { group_by, time_range, total_events }\n- suggested_next_queries: Follow-up queries\n\nEXAMPLE:\nUser: \"Which venues have the highest social amplification this week?\"\nget_social_contagion_summary({ group_by: \"venue\", time_range: { start: \"2026-03-09\", end: \"2026-03-16\" } })\n\nUser: \"Show me social attention by daypart over the last 7 days\"\nget_social_contagion_summary({ group_by: \"daypart\" })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "group_by": { "description": "Dimension to group by: \"venue\", \"daypart\", or \"screen\". Default: \"venue\".", "enum": [ "venue", "daypart", "screen" ], "type": "string" }, "time_range": { "additionalProperties": false, "description": "Time range filter. Defaults to last 7 days.", "properties": { "end": { "description": "End time (ISO 8601)", "type": "string" }, "start": { "description": "Start time (ISO 8601)", "type": "string" } }, "type": "object" } }, "type": "object" }, "name": "get_social_contagion_summary", "outputSchema": null }, { "description": "[AdCP Protocol] Get the status of a previously issued AdCP task.\n\nEvery AdCP task Trillboards serves for an AUTHENTICATED caller is recorded and\nreturned a `task_id`. Poll that id here to read the task's terminal state and,\nwith `include_result: true`, its completion payload.\n\nTrillboards answers every AdCP task in-process, so a task is already\n`completed` by the time you hold its id — this tool exists so a buyer that\npolls does not hang, and so an async arm has somewhere to report from when one\nlands.\n\nTASK SCOPE: tasks are visible only to the account that created them. An id\nbelonging to another account, an id we never issued, or a poll with no\ncredential all answer identically — \"Task <id> not found\" — so the surface\ncannot be used to probe which ids exist.\n\nNOT RECORDED: read-only protocol and catalogue calls that AdCP does not model\nas tasks (get_adcp_capabilities, list_creative_formats, get_media_buys,\nlist_accounts), and any anonymous call, which has no account to scope to.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "account": { "additionalProperties": false, "properties": { "account_id": { "maxLength": 200, "type": "string" }, "brand": { "additionalProperties": false, "properties": { "brand_id": { "maxLength": 200, "type": "string" }, "domain": { "maxLength": 253, "type": "string" } }, "required": [ "domain" ], "type": "object" }, "operator": { "maxLength": 253, "type": "string" }, "sandbox": { "type": "boolean" } }, "type": "object" }, "context": { "additionalProperties": {}, "type": "object" }, "include_history": { "description": "Include conversation history. Trillboards tasks complete in-process and hold no multi-turn history, so this is accepted and has no effect.", "type": "boolean" }, "include_result": { "description": "Include the task's result payload when status is completed. Defaults to false for lightweight status-only polls.", "type": "boolean" }, "task_id": { "description": "Unique identifier of the task to retrieve, as issued in the `task_id` field of the originating task response.", "maxLength": 200, "minLength": 1, "type": "string" } }, "required": [ "task_id" ], "type": "object" }, "name": "get_task_status", "outputSchema": null }, { "description": "Get your current billing period usage summary with per-product breakdown and costs. Shows free tier consumption, paid usage, and total cost.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": {}, "type": "object" }, "name": "get_usage_summary", "outputSchema": null }, { "description": "Get delivery history for a webhook.\n\nWHEN TO USE:\n- Debugging failed webhook deliveries\n- Auditing webhook activity\n- Checking delivery success rates\n\nRETURNS:\n- deliveries: Array of delivery records with:\n - delivery_id: Unique delivery ID\n - event: Event type\n - status: success/failed\n - response_code: HTTP response code\n - response_time_ms: Response time\n - attempted_at: Attempt timestamp\n - error: Error message (if failed)\n- total: Total delivery count\n- success_rate: Percentage of successful deliveries\n\nEXAMPLE:\nUser: \"Show me failed deliveries for this webhook\"\nget_webhook_deliveries({\n webhook_id: \"wh_mmmpdbvj_8b7c5a59296d\",\n status: \"failed\",\n limit: 20\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "limit": { "description": "Maximum number of deliveries to return (default: 50, max: 100)", "maximum": 100, "minimum": 1, "type": "integer" }, "status": { "description": "Filter by delivery status", "enum": [ "all", "success", "failed" ], "type": "string" }, "webhook_id": { "description": "Webhook ID to get deliveries for (wh_xxx format or legacy ObjectId)", "pattern": "^(wh_[a-z0-9]+_[a-f0-9]+|[a-f0-9]{24})$", "type": "string" } }, "required": [ "webhook_id" ], "type": "object" }, "name": "get_webhook_deliveries", "outputSchema": null }, { "description": "[AdCP Accounts] List the accounts this credential can transact on.\n\nThis seller's account model is 'explicit': one API key IS one account, so this returns\nexactly one account — the partner behind the key. Use it to discover your account_id\nbefore any account-scoped call, and to confirm the account's status before you buy.\n\nWHEN TO USE:\n- Discovering the account_id to pass to account-scoped tasks\n- Checking your account is 'active' before creating a media buy\n- Introspecting what your key is permitted to do (accounts[].authorization.allowed_tasks)\n\nRETURNS:\n- accounts: AdCP Account objects (account_id, name, status, operator, brand, billing,\n account_scope) plus an authorization object naming the tasks this key may invoke\n- pagination: has_more is always false — one credential, one account\n\nEXAMPLE:\nlist_accounts({})\nlist_accounts({ status: \"active\" })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "account": { "additionalProperties": false, "description": "Exact account filter. Either account_id, or the natural key (brand.domain + operator). Returns empty when it does not match this credential's account — which is how you confirm the key you hold is the one you meant.", "properties": { "account_id": { "maxLength": 200, "type": "string" }, "brand": { "additionalProperties": false, "properties": { "brand_id": { "maxLength": 200, "type": "string" }, "domain": { "maxLength": 253, "type": "string" } }, "required": [ "domain" ], "type": "object" }, "operator": { "maxLength": 253, "type": "string" }, "sandbox": { "type": "boolean" } }, "type": "object" }, "context": { "additionalProperties": {}, "type": "object" }, "pagination": { "additionalProperties": false, "properties": { "cursor": { "maxLength": 500, "type": "string" }, "max_results": { "maximum": 100, "minimum": 1, "type": "integer" } }, "type": "object" }, "sandbox": { "description": "Filter by sandbox status — matched against the account's real state, not a stub. A sandbox account validates a buy exactly as a live one does (same errors, same codes) but books no placements and marks every response sandbox: true, so it is safe to exercise end to end. Sandbox is our classification, not buyer-settable: ask for a sandbox credential rather than sending sandbox on a live key.", "type": "boolean" }, "status": { "description": "Filter by account status. Omit to return the account in any status.", "enum": [ "active", "pending_approval", "rejected", "payment_required", "suspended", "closed" ], "type": "string" } }, "type": "object" }, "name": "list_accounts", "outputSchema": null }, { "description": "[AdCP Media Buy] List the creative formats this network actually accepts.\n\nEvery format is DERIVED from live per-screen capability (panel size, min/max spot\nlength, audio) — not a hand-written list. The set published here is exactly the set\nsync_creatives accepts: if a creative matches a format returned by this tool, it will\nnot be rejected for dimensions, duration or file size.\n\nWHEN TO USE:\n- Before building creative, to size it to the panels you are buying\n- To check whether an existing asset can run on this network\n- To find the panel sizes with the most reach (results are ordered by live screen count)\n\nRETURNS:\n- formats: AdCP Format objects (format_id, name, renders[].dimensions, assets[].requirements)\n- pagination: cursor-based; total_count is the full catalogue size\n- Each format carries ext.trillboards with the live screen count, the share of the\n network, how many of those screens have audio, and — for video — duration_coverage:\n how many screens accept a spot of at most 10/15/20/30/60/120/300 seconds. A long\n ceiling does not mean every screen at that size can play it, and this says so.\n\nEXAMPLE:\nUser: \"What sizes and lengths does this network take?\"\nlist_creative_formats({ pagination: { max_results: 20 } })\n\nUser: \"Can I run a 1080x1920 portrait video?\"\nlist_creative_formats({ format_ids: [{ agent_url: \"https://api.trillboards.com/mcp\", id: \"dooh_video_1080x1920\" }] })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "asset_types": { "description": "Filter to formats containing these asset types, e.g. ['video'] or ['image'].", "items": { "maxLength": 50, "type": "string" }, "minItems": 1, "type": "array" }, "context": { "additionalProperties": {}, "type": "object" }, "format_ids": { "description": "Return only these formats. Each entry is an AdCP structured format reference ({agent_url, id}), never a bare string.", "items": { "additionalProperties": false, "properties": { "agent_url": { "maxLength": 500, "type": "string" }, "duration_ms": { "type": "number" }, "height": { "type": "number" }, "id": { "maxLength": 200, "type": "string" }, "width": { "type": "number" } }, "required": [ "agent_url", "id" ], "type": "object" }, "minItems": 1, "type": "array" }, "is_responsive": { "description": "Filter for responsive formats. Every DOOH panel is a fixed pixel grid, so true matches nothing here.", "type": "boolean" }, "max_height": { "description": "Maximum render height in pixels (inclusive)", "type": "number" }, "max_width": { "description": "Maximum render width in pixels (inclusive)", "type": "number" }, "min_height": { "description": "Minimum render height in pixels (inclusive)", "type": "number" }, "min_width": { "description": "Minimum render width in pixels (inclusive)", "type": "number" }, "name_search": { "description": "Case-insensitive partial match on the format name", "maxLength": 200, "type": "string" }, "pagination": { "additionalProperties": false, "description": "Cursor-based pagination", "properties": { "cursor": { "description": "Opaque cursor from a previous response", "maxLength": 500, "type": "string" }, "max_results": { "description": "Page size (1-100, default 50)", "maximum": 100, "minimum": 1, "type": "integer" } }, "type": "object" }, "publisher_domain": { "description": "Resolve formats for this publisher. This agent derives formats from its own inventory only, so anything other than 'trillboards.com' returns an empty list with UNSUPPORTED_PUBLISHER_DOMAIN.", "maxLength": 253, "type": "string" } }, "type": "object" }, "name": "list_creative_formats", "outputSchema": null }, { "description": "[AdCP Creative] List the creatives this buyer has on file with us.\n\nOUR LIBRARY IS PER-BUY, AND THIS SAYS SO. AdCP's creative library models concepts,\nvariables, assignments and snapshots; ours does not have those. A creative here is\nthe one asset attached to a media buy by sync_creatives, so this is a projection of\nYOUR OWN buys — never someone else's assets, and never an invented concept_id to\nlook richer than we are.\n\nWHEN TO USE:\n- To confirm a creative you sent actually landed, and where it is in review\n- To see which media buy a creative is attached to (include_assignments: true)\n- Before cancelling a buy, to check what happens to its creative\n\nRETURNS:\n- creatives[]: creative_id, name, format_id ({agent_url, id}), status, created_date,\n updated_date. Status is 'pending_review' until the buy is servable, then 'approved'\n — every creative goes through the same moderation every other creative on this\n network goes through.\n- query_summary: total_matching + returned\n- pagination: cursor-based, with total_count\n\nEXAMPLE:\nUser: \"Did my creative go through?\"\nlist_creatives({ filters: { media_buy_ids: [\"mbuy_123\"] }, include_assignments: true })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "account": { "additionalProperties": false, "properties": { "account_id": { "maxLength": 200, "type": "string" }, "brand": { "additionalProperties": false, "properties": { "brand_id": { "maxLength": 200, "type": "string" }, "domain": { "maxLength": 253, "type": "string" } }, "required": [ "domain" ], "type": "object" }, "operator": { "maxLength": 253, "type": "string" }, "sandbox": { "type": "boolean" } }, "type": "object" }, "context": { "additionalProperties": {}, "type": "object" }, "ext": { "additionalProperties": {}, "type": "object" }, "fields": { "items": { "maxLength": 100, "type": "string" }, "maxItems": 100, "type": "array" }, "filters": { "additionalProperties": false, "description": "Narrow the result set. All fields optional.", "properties": { "creative_ids": { "items": { "maxLength": 100, "minLength": 1, "type": "string" }, "maxItems": 200, "type": "array" }, "format_ids": { "maxItems": 200, "type": "array" }, "media_buy_ids": { "items": { "maxLength": 100, "minLength": 1, "type": "string" }, "maxItems": 200, "type": "array" }, "status": { "anyOf": [ { "enum": [ "processing", "pending_review", "approved", "rejected", "archived" ], "type": "string" }, { "items": { "enum": [ "processing", "pending_review", "approved", "rejected", "archived" ], "type": "string" }, "minItems": 1, "type": "array" } ], "description": "AdCP creative-status: processing | pending_review | approved | rejected | archived" }, "tags": { "items": { "maxLength": 100, "type": "string" }, "maxItems": 50, "type": "array" } }, "type": "object" }, "include_assignments": { "description": "Include which media buys each creative is attached to.", "type": "boolean" }, "include_items": { "type": "boolean" }, "include_pricing": { "type": "boolean" }, "include_purged": { "type": "boolean" }, "include_snapshot": { "type": "boolean" }, "include_variables": { "type": "boolean" }, "include_webhook_activity": { "type": "boolean" }, "pagination": { "additionalProperties": false, "properties": { "cursor": { "maxLength": 500, "type": "string" }, "max_results": { "maximum": 100, "minimum": 1, "type": "integer" } }, "type": "object" }, "sort": { "additionalProperties": {}, "type": "object" }, "webhook_activity_limit": { "maximum": 1000, "minimum": 0, "type": "integer" } }, "type": "object" }, "name": "list_creatives", "outputSchema": null }, { "description": "List all devices registered to the partner account.\n\nWHEN TO USE:\n- Getting an overview of all connected devices\n- Finding devices by status (online/offline)\n- Auditing the device fleet\n\nRETURNS:\n- devices: Array of device objects\n- total: Total device count\n- online_count: Number of online devices\n- offline_count: Number of offline devices\n\nEXAMPLE:\nUser: \"Show me all my online devices\"\nlist_devices({\n status: \"online\",\n limit: 50\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "device_type": { "description": "Filter by device type", "enum": [ "vending_machine", "kiosk", "tablet", "display", "digital_signage", "other" ], "type": "string" }, "limit": { "description": "Maximum number of devices to return (default: 50, max: 100)", "maximum": 100, "minimum": 1, "type": "integer" }, "offset": { "description": "Pagination offset", "minimum": 0, "type": "integer" }, "status": { "description": "Filter by device status", "enum": [ "all", "online", "offline" ], "type": "string" } }, "type": "object" }, "name": "list_devices", "outputSchema": null }, { "description": "List every registered Trillboards API operation.\n\nWHEN TO USE:\n- First call in an agent session to learn what the API offers.\n- Filter to agent_safe=true to list only side-effect-free endpoints.\n- Narrow to a single surface (data-api, sdk-api, device-api, sensing-api,\n partner-api-generated, dsp-api-generated).\n\nRETURNS:\n- operations: Array of { surface, method, path, operation_id, summary,\n description, agent_safe, idempotent, cost_tier, tags, doc_url,\n example_request }\n- total_operations: Total count.\n- surfaces: Known surface identifiers.\n\nEXAMPLE:\nAgent: \"What read-only endpoints can I call?\"\nlist_endpoints({ agent_safe: true })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "agent_safe": { "description": "When true, return only endpoints flagged agent-safe.", "type": "boolean" }, "idempotent": { "description": "When true, return only endpoints flagged idempotent.", "type": "boolean" }, "surface": { "description": "Filter to one surface (e.g. \"data-api\").", "maxLength": 64, "type": "string" } }, "type": "object" }, "name": "list_endpoints", "outputSchema": null }, { "description": "List every error code in the Trillboards API error catalog.\n\nWHEN TO USE:\n- Understanding what error codes the API can return.\n- Building a client-side error handler that covers all cases.\n- Looking up error types, HTTP statuses, and documentation URLs.\n\nRETURNS:\n- object: \"list\"\n- data: Array of { code, type, http_status, description, doc_url }\n- total: Total number of error codes.\n\nEquivalent to GET /v1/errors but executed in-process (no HTTP round-trip).\n\nEXAMPLE:\nAgent: \"What error codes can the API return?\"\nlist_error_codes()", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": {}, "type": "object" }, "name": "list_error_codes", "outputSchema": null }, { "description": "[AdCP Protocol] List AdCP tasks belonging to your account, newest first.\n\nReturns `query_summary` (totals and a status breakdown), `tasks`, and\n`pagination`. Filter by status or task type. Scoped to the calling account —\nan unauthenticated call returns an empty page rather than another account's\ntasks.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "account": { "additionalProperties": false, "properties": { "account_id": { "maxLength": 200, "type": "string" }, "brand": { "additionalProperties": false, "properties": { "brand_id": { "maxLength": 200, "type": "string" }, "domain": { "maxLength": 253, "type": "string" } }, "required": [ "domain" ], "type": "object" }, "operator": { "maxLength": 253, "type": "string" }, "sandbox": { "type": "boolean" } }, "type": "object" }, "context": { "additionalProperties": {}, "type": "object" }, "filters": { "additionalProperties": false, "description": "Narrow the returned tasks.", "properties": { "status": { "description": "Single task status to match", "enum": [ "submitted", "working", "input-required", "completed", "canceled", "failed", "rejected", "auth-required", "unknown" ], "type": "string" }, "statuses": { "description": "Task statuses to match (enums/task-status.json)", "items": { "enum": [ "submitted", "working", "input-required", "completed", "canceled", "failed", "rejected", "auth-required", "unknown" ], "type": "string" }, "type": "array" }, "task_type": { "description": "Single task type to match", "enum": [ "create_media_buy", "update_media_buy", "media_buy_delivery", "sync_creatives", "build_creative", "activate_signal", "get_products", "get_signals", "create_property_list", "update_property_list", "get_property_list", "list_property_lists", "delete_property_list", "sync_accounts", "get_account_financials", "get_creative_delivery", "sync_event_sources", "sync_audiences", "sync_catalogs", "log_event", "get_brand_identity", "search_brands", "get_rights", "acquire_rights" ], "type": "string" }, "task_types": { "description": "Task types to match (enums/task-type.json)", "items": { "enum": [ "create_media_buy", "update_media_buy", "media_buy_delivery", "sync_creatives", "build_creative", "activate_signal", "get_products", "get_signals", "create_property_list", "update_property_list", "get_property_list", "list_property_lists", "delete_property_list", "sync_accounts", "get_account_financials", "get_creative_delivery", "sync_event_sources", "sync_audiences", "sync_catalogs", "log_event", "get_brand_identity", "search_brands", "get_rights", "acquire_rights" ], "type": "string" }, "type": "array" } }, "type": "object" }, "pagination": { "additionalProperties": false, "properties": { "limit": { "description": "Page size (max 100, default 50)", "maximum": 100, "minimum": 1, "type": "integer" }, "offset": { "description": "Rows to skip", "minimum": 0, "type": "integer" } }, "type": "object" } }, "type": "object" }, "name": "list_tasks", "outputSchema": null }, { "description": "List all webhook subscriptions for the partner account.\n\nWHEN TO USE:\n- Viewing all configured webhooks\n- Auditing webhook subscriptions\n- Finding a webhook to update or delete\n\nRETURNS:\n- webhooks: Array of webhook objects with:\n - webhook_id: Unique identifier\n - url: Endpoint URL\n - events: Subscribed events\n - enabled: Whether webhook is active\n - created_at: Creation timestamp\n - last_delivery: Last successful delivery time\n\nEXAMPLE:\nUser: \"Show me all my webhooks\"\nlist_webhooks({})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": {}, "type": "object" }, "name": "list_webhooks", "outputSchema": null }, { "description": "[AdCP Media Buy] Record a conversion or attribution event.\n\nRecords conversion events for post-campaign attribution analysis.\nEvents are deduplicated by event_id + event_type combination.\n\nWHEN TO USE:\n- Recording offline conversions (store visits, purchases)\n- Tracking post-view attribution events\n- Logging custom KPI events\n\nEXAMPLE:\nlog_event({\n media_buy_id: \"mbuy_abc123\",\n event: {\n event_id: \"conv_12345\",\n event_type: \"store_visit\",\n value_cents: 5000,\n screen_id: \"507f1f77bcf86cd799439011\",\n metadata: { store: \"NYC-001\", dwell_minutes: 12 }\n }\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "event": { "additionalProperties": false, "description": "Event data", "properties": { "event_id": { "description": "Unique event ID for dedup", "maxLength": 200, "minLength": 1, "type": "string" }, "event_source": { "description": "Source system for the event (e.g., mmp, pixel, postback, manual)", "type": "string" }, "event_type": { "description": "Event type: store_visit, purchase, app_install, website_visit, custom", "maxLength": 100, "minLength": 1, "type": "string" }, "metadata": { "additionalProperties": {}, "description": "Additional event metadata", "type": "object" }, "screen_id": { "description": "Attributed screen ID (optional)", "type": "string" }, "timestamp": { "description": "Event timestamp (ISO 8601, defaults to now)", "type": "string" }, "value_cents": { "description": "Event value in cents (USD)", "type": "number" } }, "required": [ "event_id", "event_type" ], "type": "object" }, "media_buy_id": { "description": "Media buy ID", "maxLength": 100, "minLength": 1, "type": "string" } }, "required": [ "media_buy_id", "event" ], "type": "object" }, "name": "log_event", "outputSchema": null }, { "description": "Predict the VAS (Viewability Attention Score) a specific creative would achieve at a given moment, based on historical data and causal modeling.\n\nUses the CausalPredictionService which:\n1. Embeds the moment description to find historically similar moments\n2. If >= 5 similar moments exist with the same creative, uses weighted-average prediction\n3. If insufficient data, falls back to Gemini generative prediction\n4. Always decomposes the prediction into causal factors\n\nWHEN TO USE:\n- Evaluating whether a creative will perform well in a specific context\n- A/B testing creative placement hypotheses before committing budget\n- Understanding which causal factors drive VAS for a creative\n- Comparing expected performance across different moment types\n\nRETURNS:\n- prediction: { predictedVAS (0-1), confidence (0-1), method ('historical'|'model'), sampleSize }\n- causal_factors: { audienceMatch, contextMatch, attentionState, socialPotential } (each 0-1)\n- metadata: { creative_id, moment_description }\n- suggested_next_queries: Follow-up queries\n\nEXAMPLE:\nUser: \"How would a coffee ad perform at a transit station during morning rush?\"\npredict_moment_quality({\n moment_description: \"transit venue, morning commute, 12 viewers, high attention, mostly 25-34 age range\",\n creative_id: \"coffee-brand-morning-30s\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "creative_id": { "description": "The creative/ad ID to predict performance for.", "maxLength": 200, "minLength": 1, "type": "string" }, "moment_description": { "description": "Natural-language description of the target moment context. Include venue type, time of day, audience size, demographics, attention level, etc.", "maxLength": 1000, "minLength": 1, "type": "string" } }, "required": [ "moment_description", "creative_id" ], "type": "object" }, "name": "predict_moment_quality", "outputSchema": null }, { "description": "Generate predictive insights from observation patterns. Predict whether a venue is likely to see increased foot traffic based on current patterns.\n\nUses historical observation_stream data to compute trend analysis via\nlinear regression on time-bucketed metrics. Generates predictions with\nconfidence intervals based on the observed trend, variance, and sample size.\n\nWHEN TO USE:\n- Predicting future audience patterns at a venue or screen\n- Forecasting foot traffic trends for campaign planning\n- Understanding whether metrics are trending up, down, or stable\n- Making data-driven decisions about inventory and pricing\n\nRETURNS:\n- prediction: The predicted trend and expected values\n - trend: 'increasing' | 'decreasing' | 'stable'\n - current_avg: Current average metric value\n - predicted_avg: Predicted average over the time horizon\n - change_pct: Expected percentage change\n - confidence_interval: { lower, upper } bounds\n- confidence: Overall prediction confidence (0-1)\n- supporting_data: Recent data points that inform the prediction\n - data_points: Array of { bucket, avg_value, sample_count }\n - total_observations: Total observations analyzed\n- methodology: Description of the prediction approach\n- suggested_next_queries: Follow-up queries to refine the prediction\n\nEXAMPLE:\nUser: \"Will this QSR venue see more foot traffic next week?\"\npredictive_query({\n question: \"Will foot traffic increase at QSR venues?\",\n venue_type: \"restaurant_qsr\",\n time_horizon: \"7d\"\n})\n\nUser: \"Predict audience attention trends for this screen\"\npredictive_query({\n question: \"What will audience attention look like?\",\n screen_id: \"507f1f77bcf86cd799439011\",\n time_horizon: \"3d\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "question": { "description": "Natural language question about the predicted trend or outcome", "maxLength": 500, "minLength": 1, "type": "string" }, "screen_id": { "description": "Filter predictions to a specific screen (mongo ID). Optional.", "maxLength": 100, "type": "string" }, "time_horizon": { "description": "How far ahead to predict (e.g., \"1d\", \"3d\", \"7d\", \"14d\"). Default: \"7d\", max: \"30d\"", "pattern": "^\\d+d$", "type": "string" }, "venue_type": { "description": "Filter predictions to a specific venue type. Optional.", "maxLength": 100, "type": "string" } }, "required": [ "question" ], "type": "object" }, "name": "predictive_query", "outputSchema": null }, { "description": "[AdCP Media Buy] Provide optimization signals from buyer agent.\n\nAccepts feedback from buyer agents for floor price adjustment and\ninventory optimization. Enables closed-loop optimization between\nbuyer and seller agents.\n\nWHEN TO USE:\n- Sending bid response feedback to optimize future pricing\n- Providing conversion data for bid price calibration\n- Adjusting floor prices based on demand signals\n\nEXAMPLE:\nprovide_performance_feedback({\n media_buy_id: \"mbuy_abc123\",\n feedback: {\n type: \"bid_response\",\n avg_bid_price_cpm: 6.5,\n fill_rate_percent: 72,\n preferred_hours: [8, 9, 10, 17, 18],\n quality_score: 0.85\n }\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "feedback": { "additionalProperties": false, "description": "Performance feedback data", "properties": { "avg_bid_price_cpm": { "type": "number" }, "fill_rate_percent": { "type": "number" }, "message": { "description": "Free-form feedback", "type": "string" }, "preferred_hours": { "items": { "maximum": 23, "minimum": 0, "type": "integer" }, "type": "array" }, "quality_score": { "description": "0-1 quality assessment", "maximum": 1, "minimum": 0, "type": "number" }, "type": { "description": "Type of feedback", "enum": [ "bid_response", "conversion", "quality", "pacing" ], "type": "string" } }, "required": [ "type" ], "type": "object" }, "media_buy_id": { "description": "Media buy ID", "maxLength": 100, "minLength": 1, "type": "string" } }, "required": [ "media_buy_id", "feedback" ], "type": "object" }, "name": "provide_performance_feedback", "outputSchema": null }, { "description": "Purchase committed-use credits at a discount. Three tiers: tier_500 ($500 → $625 credit, 25% bonus), tier_2000 ($2,000 → $3,100 credit, 55% bonus), tier_5000 ($5,000 → $10,000 credit, 100% bonus). Requires an active payment method.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "tier": { "description": "Credit purchase tier", "enum": [ "tier_500", "tier_2000", "tier_5000" ], "type": "string" } }, "required": [ "tier" ], "type": "object" }, "name": "purchase_credits", "outputSchema": null }, { "description": "Query the Trillboards API changelog for recent changes,\nbreaking changes, deprecations, and fixes.\n\nWHEN TO USE:\n- Check what has changed in the API before upgrading an integration.\n- Find breaking changes since a specific date.\n- Discover new features added to a specific API surface.\n\nPARAMETERS:\n- since (YYYY-MM-DD, optional): Only entries dated on or after this date.\n Unreleased entries are always included.\n- type (string, optional): Filter by change category. Accepts:\n \"breaking\" → changed + removed entries\n \"additive\" → added entries\n \"deprecation\" → deprecated entries\n \"fix\" → fixed entries\n Can be comma-separated: \"breaking,deprecation\"\n\nRETURNS:\n- object: \"list\"\n- data: Array of { version, date, type, surface, description }\n- total: Number of matching entries.\n\nEXAMPLE:\nAgent: \"What broke since April 1st?\"\nquery_changelog({ since: \"2026-04-01\", type: \"breaking\" })", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "since": { "description": "Only entries dated on or after this date (YYYY-MM-DD). Unreleased entries are always included.", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "type": "string" }, "type": { "description": "Filter by change category: \"breaking\", \"additive\", \"deprecation\", \"fix\". Comma-separated for multiple.", "maxLength": 100, "type": "string" } }, "type": "object" }, "name": "query_changelog", "outputSchema": null }, { "description": "Query the universal observation stream using natural language or structured filters. Returns multi-modal sensing data (audience, vehicle, environment, commerce) from physical-world observations across the screen network.\n\nWHEN TO USE:\n- Exploring raw observation data from edge AI sensors on screens\n- Filtering observations by venue type, device, time range, or geography\n- Getting audience, vehicle, environment, or commerce observation data\n- Answering natural language questions about what screens are sensing\n\nRETURNS:\n- data: Array of observation objects with device, venue, payload, confidence, model versions\n- metadata: { observation_count, time_range, coverage_pct, model_versions }\n- suggested_next_queries: Contextual follow-up queries\n\nEach observation includes:\n- observation_id, device_id, screen_mongo_id, venue_type\n- observed_at: Timestamp of the observation\n- observation_family: audience | vehicle | environment | commerce\n- payload: JSONB with model outputs (face_count, emotion, vehicle_count, etc.)\n- confidence: Model confidence score (0-1)\n- evidence_grade: Quality grade of the observation\n- model_versions: Which ML models produced this data\n\nEXAMPLE:\nUser: \"Show me audience observations at QSR venues in the last hour\"\nquery_observations({\n query: \"audience observations at QSR venues\",\n filters: {\n observation_family: [\"audience\"],\n venue_type: [\"restaurant_qsr\"],\n time_range: { start: \"2026-03-16T14:00:00Z\", end: \"2026-03-16T15:00:00Z\" }\n },\n limit: 50\n})\n\nUser: \"What are screens sensing right now?\"\nquery_observations({\n query: \"latest observations from all screens\",\n limit: 20\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "filters": { "additionalProperties": false, "description": "Structured filters to narrow results", "properties": { "device_id": { "description": "Filter to a specific device ID", "maxLength": 100, "type": "string" }, "geohash": { "description": "Filter by geohash-6 prefix for geographic area", "maxLength": 12, "type": "string" }, "observation_family": { "description": "Filter by observation family: audience, vehicle, environment, commerce", "items": { "maxLength": 50, "type": "string" }, "maxItems": 10, "type": "array" }, "screen_id": { "description": "Filter to a specific screen (mongo ID)", "maxLength": 100, "type": "string" }, "time_range": { "additionalProperties": false, "description": "Time range filter", "properties": { "end": { "description": "End time (ISO 8601)", "type": "string" }, "start": { "description": "Start time (ISO 8601)", "type": "string" } }, "type": "object" }, "venue_type": { "description": "Filter by venue type: retail, transit, office, restaurant_qsr, entertainment, healthcare, outdoor, etc.", "items": { "maxLength": 50, "type": "string" }, "maxItems": 20, "type": "array" } }, "type": "object" }, "limit": { "description": "Maximum observations to return (default: 100, max: 1000)", "maximum": 1000, "minimum": 1, "type": "integer" }, "query": { "description": "Natural language query describing what observations to find", "maxLength": 500, "minLength": 1, "type": "string" } }, "required": [ "query" ], "type": "object" }, "name": "query_observations", "outputSchema": null }, { "description": "Given a moment description, rank candidate creatives by predicted VAS performance.\n\nEvaluates each creative candidate against the described moment context using\nhistorical similarity and causal prediction. Returns a ranked list sorted by\npredicted VAS score, with confidence levels for each prediction.\n\nWHEN TO USE:\n- Choosing which creative to show at a specific moment/venue\n- Comparing multiple creatives for a campaign across different contexts\n- Optimizing creative rotation for maximum VAS\n- Pre-campaign creative selection based on audience and venue\n\nRETURNS:\n- rankings: Array sorted by predicted VAS (descending)\n - creativeId, predictedVAS (0-1), confidence (0-1), rank (1-N)\n- metadata: { candidate_count, moment_description }\n- suggested_next_queries: Follow-up queries\n\nEXAMPLE:\nUser: \"Which of these 3 creatives will perform best at a gym in the evening?\"\nrecommend_creative({\n moment_description: \"gym venue, evening, 6 viewers, high attention, mostly male 18-34\",\n creative_ids: [\"fitness-brand-30s\", \"energy-drink-15s\", \"tech-gadget-20s\"]\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "creative_ids": { "description": "Array of creative/ad IDs to rank. Maximum 20 candidates.", "items": { "maxLength": 200, "minLength": 1, "type": "string" }, "maxItems": 20, "minItems": 1, "type": "array" }, "moment_description": { "description": "Natural-language description of the target moment context.", "maxLength": 1000, "minLength": 1, "type": "string" } }, "required": [ "moment_description", "creative_ids" ], "type": "object" }, "name": "recommend_creative", "outputSchema": null }, { "description": "Record a single ad impression from a device.\n\nWHEN TO USE:\n- Reporting that an ad was displayed on a device\n- Recording impression with detailed metadata\n- Single impression events (for batch, use batch_impressions)\n\nRETURNS:\n- success: Boolean indicating success\n- impression_id: Unique impression identifier\n- earnings: Earnings credited for this impression\n\nEXAMPLE:\nUser: \"Record an impression for ad 507f1f77bcf86cd799439011\"\nrecord_impression({\n fingerprint: \"P_abc123\",\n ad_id: \"507f1f77bcf86cd799439011\",\n duration_seconds: 15\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "ad_id": { "description": "Advertisement ID (MongoDB ObjectId)", "pattern": "^[0-9a-f]{24}$", "type": "string" }, "duration_seconds": { "description": "How long the ad was displayed (seconds)", "exclusiveMinimum": 0, "maximum": 3600, "type": "number" }, "fingerprint": { "description": "Device fingerprint (e.g., \"P_abc123\")", "maxLength": 100, "minLength": 1, "type": "string" }, "metadata": { "additionalProperties": {}, "description": "Additional impression metadata", "type": "object" }, "timestamp": { "description": "ISO 8601 timestamp when impression occurred (optional, defaults to now)", "format": "date-time", "type": "string" } }, "required": [ "fingerprint", "ad_id" ], "type": "object" }, "name": "record_impression", "outputSchema": null }, { "description": "Register or update a device in the partner's network.\n\nWHEN TO USE:\n- Adding a new screen/kiosk/vending machine to the network\n- Updating device location or configuration\n- Re-registering a device after maintenance\n\nRETURNS:\n- device_id: Your internal device ID (echoed back)\n- trillboards_device_id: Internal Trillboards device ID\n- fingerprint: Device fingerprint (e.g., \"P_abc123\")\n- embed_url: URL to load in the device's WebView\n- status: Device status\n\nEXAMPLE:\nUser: \"Register a vending machine in NYC\"\nregister_device({\n device_id: \"vending-001-nyc\",\n name: \"NYC Office Lobby Vending\",\n device_type: \"vending_machine\",\n location: {\n lat: 40.7128,\n lng: -74.0060,\n city: \"New York\",\n state: \"NY\",\n venue_type: \"office\"\n }\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "device_id": { "description": "Your internal unique device identifier", "maxLength": 100, "minLength": 1, "type": "string" }, "device_type": { "description": "Type of device", "enum": [ "vending_machine", "kiosk", "tablet", "display", "digital_signage", "other" ], "type": "string" }, "location": { "additionalProperties": false, "description": "Device location information", "properties": { "address": { "description": "Street address", "maxLength": 200, "type": "string" }, "city": { "description": "City", "maxLength": 100, "type": "string" }, "country": { "description": "Country", "maxLength": 100, "type": "string" }, "lat": { "description": "Latitude", "maximum": 90, "minimum": -90, "type": "number" }, "lng": { "description": "Longitude", "maximum": 180, "minimum": -180, "type": "number" }, "state": { "description": "State/province", "maxLength": 100, "type": "string" }, "venue_type": { "description": "Venue type (office, retail, gym, etc.)", "maxLength": 100, "type": "string" }, "zip": { "description": "Postal code", "maxLength": 20, "type": "string" } }, "type": "object" }, "metadata": { "additionalProperties": {}, "description": "Additional custom metadata", "type": "object" }, "name": { "description": "Human-readable device name", "maxLength": 200, "type": "string" }, "specs": { "additionalProperties": false, "description": "Device specifications", "properties": { "browser": { "description": "Browser/WebView type", "maxLength": 100, "type": "string" }, "model": { "description": "Device model", "maxLength": 100, "type": "string" }, "orientation": { "enum": [ "landscape", "portrait" ], "type": "string" }, "os": { "description": "Operating system", "maxLength": 100, "type": "string" }, "screen_height": { "description": "Screen height in pixels", "exclusiveMinimum": 0, "type": "integer" }, "screen_width": { "description": "Screen width in pixels", "exclusiveMinimum": 0, "type": "integer" } }, "type": "object" } }, "required": [ "device_id" ], "type": "object" }, "name": "register_device", "outputSchema": null }, { "description": "Register a new partner organization with Trillboards.\n\nWHEN TO USE:\n- First-time setup for a new partner integration\n- Creating a new partner account to manage devices\n\nRETURNS:\n- partner_id: Unique partner identifier\n- api_key: API key for authenticated requests (store securely!)\n- status: Account status\n\nEXAMPLE:\nUser: \"Register my vending machine company\"\nregister_partner({\n company_name: \"Acme Vending Co\",\n email: \"[email protected]\",\n industry: \"vending\",\n expected_devices: 50\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "company_name": { "description": "Company or organization name", "maxLength": 200, "minLength": 1, "type": "string" }, "contact_name": { "description": "Primary contact person name (optional)", "maxLength": 100, "type": "string" }, "contact_phone": { "description": "Contact phone number (optional)", "maxLength": 20, "type": "string" }, "email": { "description": "Contact email for the partner account", "format": "email", "type": "string" }, "expected_devices": { "description": "Estimated number of devices to connect", "exclusiveMinimum": 0, "type": "integer" }, "industry": { "description": "Industry type (e.g., \"vending\", \"retail\", \"hospitality\")", "maxLength": 100, "type": "string" }, "website": { "description": "Company website URL (optional)", "format": "uri", "type": "string" } }, "required": [ "company_name", "email" ], "type": "object" }, "name": "register_partner", "outputSchema": null }, { "description": "Semantic search over content library using natural language queries and 768-D pgvector embeddings.\n\nWHEN TO USE:\n- Finding content by description or theme (\"upbeat music videos\", \"cooking shows\")\n- Discovering content similar to a concept or mood\n- Searching the content library without knowing exact titles or IDs\n- Content discovery for programmatic content scheduling\n\nRETURNS:\n- data: Array of matching content with similarity scores\n - videoId, title, contentCategory, description, durationSeconds\n - reviewStatus (approved/pending/rejected)\n - similarity (0-1, cosine similarity against query embedding)\n- meta: { count, query, limit, minSimilarity }\n\nEXAMPLE:\nUser: \"Find fitness and workout content\"\nsearch_content({\n query: \"fitness workout exercise gym\",\n limit: 10,\n min_similarity: 0.6\n})\n\nUser: \"Search for calming nature content suitable for medical offices\"\nsearch_content({\n query: \"calming nature scenes peaceful landscapes meditation\",\n min_similarity: 0.5\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "limit": { "description": "Maximum results to return (default: 20, max: 100)", "maximum": 100, "minimum": 1, "type": "integer" }, "min_similarity": { "description": "Minimum cosine similarity threshold (default: 0.5, range: 0-1)", "maximum": 1, "minimum": 0, "type": "number" }, "query": { "description": "Natural language search query (min 3 characters)", "maxLength": 500, "minLength": 3, "type": "string" } }, "required": [ "query" ], "type": "object" }, "name": "search_content", "outputSchema": null }, { "description": "Search screens by natural language scene description using pgvector.\n\nUses 768-dimensional Gemini embeddings on scene descriptions from FEIN edge AI\nto find screens matching a natural language query.\n\nWHEN TO USE:\n- Finding screens by audience context (\"families eating lunch in a food court\")\n- Contextual ad placement based on real-time scene understanding\n- Discovering inventory matching a specific audience scenario\n\nRETURNS:\nArray of matching screens ranked by semantic similarity, each with:\n- screen_id, mongo_screen_id, scene_description, contextual_relevance, similarity, created_at\n\nEXAMPLE:\nsemantic_audience_search({\n query: \"young professionals in a coffee shop looking at phones\",\n limit: 10\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "limit": { "description": "Maximum number of results (default: 20, max: 100)", "maximum": 100, "minimum": 1, "type": "integer" }, "min_similarity": { "description": "Minimum semantic similarity threshold 0-1 (default: 0.5)", "maximum": 1, "minimum": 0, "type": "number" }, "query": { "description": "Natural language description of the audience/scene to search for", "maxLength": 500, "minLength": 1, "type": "string" }, "since": { "description": "Time window for scene data (e.g., \"1h\", \"24h\", \"7d\"). Default: \"24h\"", "pattern": "^\\d+[hd]$", "type": "string" } }, "required": [ "query" ], "type": "object" }, "name": "semantic_audience_search", "outputSchema": null }, { "description": "Search observations by semantic similarity. Find moments that match a description like \"lunch rush at fast casual restaurants\" using vector embeddings.\n\nUses 768-dimensional Gemini embeddings on observation payloads to find\npromoted observations matching a natural language query via approximate\nnearest-neighbour (ANN) cosine similarity search over a Lance IVF_PQ index.\n\nCONSISTENCY: results are APPROXIMATE and EVENTUALLY CONSISTENT.\n- Approximate: retrieval is ANN, not an exhaustive scan (measured recall ~0.96\n against exact KNN), so an identical query may omit a borderline match.\n- Eventually consistent: the index is served from a replicated pool whose\n replicas refresh independently, so for up to 5 minutes after new observations\n are published, two identical calls may return slightly different result sets.\n The difference is confined to the VISIBILITY of newly-published observations;\n the relative ranking of already-visible ones does not change.\nDo not use this tool where a repeatable, exhaustive result set is required.\n\nTIME BOUND: searches the last 30 days by default. Pass filters.time_range to\nwiden or narrow it; the window actually applied is echoed in\nmetadata.time_range.\n\nWHEN TO USE:\n- Finding observations that match a conceptual description\n- Discovering contextual moments across the screen network\n- Searching for audience situations (\"families waiting in line\", \"professionals on coffee break\")\n- Finding commerce patterns (\"high purchase intent near checkout\")\n\nRETURNS:\n- data: Array of matching observations ranked by semantic similarity, each with:\n - observation_id, device_id, venue_type, observation_family\n - observed_at, payload, confidence, evidence_grade\n - similarity: Cosine similarity score (0-1, higher = more relevant)\n- metadata: { result_count, query_embedding_model, search_scope, time_range }\n- suggested_next_queries: Related semantic queries to explore\n\nEXAMPLE:\nUser: \"Find lunch rush moments at fast casual restaurants\"\nsemantic_search_observations({\n query: \"lunch rush at fast casual restaurants with high foot traffic\",\n filters: { venue_type: [\"restaurant_qsr\"] },\n limit: 20\n})\n\nUser: \"Find moments with high emotional engagement\"\nsemantic_search_observations({\n query: \"audience showing strong positive emotional reactions\",\n filters: { observation_family: [\"audience\"] },\n limit: 10\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "filters": { "additionalProperties": false, "description": "Additional structured filters to narrow semantic search", "properties": { "observation_family": { "description": "Filter by observation family: audience, vehicle, environment, commerce", "items": { "maxLength": 50, "type": "string" }, "maxItems": 10, "type": "array" }, "time_range": { "additionalProperties": false, "description": "Time range filter. Omitted ends default to the last 30 days (end = now, start = end - 30d) — the search is always time-bounded.", "properties": { "end": { "description": "End time (ISO 8601). Default: now", "type": "string" }, "start": { "description": "Start time (ISO 8601). Default: end - 30 days", "type": "string" } }, "type": "object" }, "venue_type": { "description": "Filter by venue type", "items": { "maxLength": 50, "type": "string" }, "maxItems": 20, "type": "array" } }, "type": "object" }, "limit": { "description": "Maximum results to return (default: 20, max: 100)", "maximum": 100, "minimum": 1, "type": "integer" }, "query": { "description": "Natural language description of the observation moments to search for", "maxLength": 500, "minLength": 1, "type": "string" } }, "required": [ "query" ], "type": "object" }, "name": "semantic_search_observations", "outputSchema": null }, { "description": "Set up pay-per-use billing with a Stripe payment method. Required after exceeding free tier limits. Pass a Stripe payment method token (pm_xxx) obtained from Stripe.js or Stripe Elements.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "payment_method_id": { "description": "Stripe payment method token (pm_xxx) from Stripe.js or Elements", "maxLength": 200, "minLength": 1, "type": "string" } }, "required": [ "payment_method_id" ], "type": "object" }, "name": "setup_billing", "outputSchema": null }, { "description": "[AdCP Accounts] Establish or confirm the account behind this credential.\n\nIMPORTANT — what this does NOT do: it does not provision a new account. This seller's\nnamespace is one account per API key, so a provisioning-mode entry (brand + operator +\nbilling) is LINKED to the account your key already owns and the response says so in\nwarnings[]. Two different brands on one key resolve to the SAME account_id. Register one\nagent per brand at https://api.trillboards.com/v1/partner/agent/register if you need\nper-brand separation.\n\nBILLING IS THE ONE SETTING THAT IS APPLIED. Send billing: 'operator' (we invoice you,\nbuying direct) or 'agent' (you are a buying agent consolidating across the brands you\nfront, and we invoice you for all of them — the marketplace-clearing model). The value is\nstored on the account, reported back by list_accounts, and reflected in action 'updated'.\nThe set we accept is exactly account.supported_billing from get_adcp_capabilities;\n'advertiser' is refused, with the reason, because we hold no billing relationship with a\nthird-party advertiser. One key is one account with one invoiced party, so a request\ndeclaring two different billing values applies neither and says so.\n\nEverything else is read-only and reports 'unchanged': payment terms, billing entity and\nnotification subscriptions are not per-account state on this platform, and anything sent\nthat was not applied is named in warnings[] rather than silently swallowed.\n\nWHEN TO USE:\n- The account-setup step at the start of a buying flow\n- Declaring how you want to be invoiced, before create_media_buy\n- Confirming your account_id and status before create_media_buy\n\nRETURNS:\n- accounts: per-entry result with account_id, action ('updated' | 'unchanged' | 'failed'),\n status, billing, account_scope, and warnings naming anything not applied\n\nEXAMPLE:\nsync_accounts({\n idempotency_key: \"8f1c...\",\n accounts: [{ brand: { domain: \"acme.example\" }, operator: \"agency.example\", billing: \"agent\" }]\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "accounts": { "description": "Per-account entries. Each uses ONE key shape: `account` (settings-update) or the flat brand + operator + billing trio (provisioning).", "items": { "additionalProperties": false, "properties": { "account": { "additionalProperties": false, "properties": { "account_id": { "maxLength": 200, "type": "string" }, "brand": { "additionalProperties": false, "properties": { "brand_id": { "maxLength": 200, "type": "string" }, "domain": { "maxLength": 253, "type": "string" } }, "required": [ "domain" ], "type": "object" }, "operator": { "maxLength": 253, "type": "string" }, "sandbox": { "type": "boolean" } }, "type": "object" }, "billing": { "description": "Who we invoice on this account. APPLIED and stored. 'operator' = you, buying direct; 'agent' = you are a buying agent consolidating across the brands you front. See account.supported_billing in get_adcp_capabilities for the accepted set — 'advertiser' is refused with a reason.", "enum": [ "operator", "agent", "advertiser" ], "type": "string" }, "billing_entity": { "additionalProperties": {}, "description": "Legal/tax details of the invoiced party. Not applied — see warnings.", "type": "object" }, "brand": { "$ref": "#/properties/accounts/items/properties/account/properties/brand" }, "notification_configs": { "items": { "additionalProperties": {}, "type": "object" }, "maxItems": 16, "type": "array" }, "operator": { "description": "Domain of the entity operating on the brand's behalf", "maxLength": 253, "type": "string" }, "payment_terms": { "enum": [ "net_15", "net_30", "net_45", "net_60", "net_90", "prepay" ], "type": "string" }, "preferred_reporting_protocol": { "maxLength": 50, "type": "string" }, "sandbox": { "type": "boolean" } }, "type": "object" }, "maxItems": 100, "type": "array" }, "context": { "additionalProperties": {}, "type": "object" }, "delete_missing": { "description": "Not supported — this seller never deletes an account from a sync.", "type": "boolean" }, "dry_run": { "description": "Echo what would happen without applying it. Reported back as dry_run.", "type": "boolean" }, "idempotency_key": { "description": "Client-generated key for safe retries. This operation has no side effects, so a replay returns the same result.", "maxLength": 200, "minLength": 1, "type": "string" }, "push_notification_config": { "additionalProperties": {}, "type": "object" } }, "required": [ "idempotency_key", "accounts" ], "type": "object" }, "name": "sync_accounts", "outputSchema": null }, { "description": "[AdCP Media Buy] Validate and sync creative assets for a media buy.\n\nValidates creative assets (resolution, duration, format) against screen specifications.\nReturns compatibility status for each screen in the campaign.\n\nWHEN TO USE:\n- Submitting creative assets before campaign launch\n- Checking if a creative meets screen requirements\n- Validating VAST tags\n\nEXAMPLE:\nsync_creatives({\n media_buy_id: \"mbuy_abc123\",\n creatives: [{\n url: \"https://cdn.example.com/ad.mp4\",\n type: \"video\",\n width: 1920,\n height: 1080,\n duration_seconds: 15,\n file_size_mb: 12\n }]\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "account": { "additionalProperties": false, "properties": { "account_id": { "maxLength": 200, "type": "string" }, "brand": { "additionalProperties": false, "properties": { "brand_id": { "maxLength": 200, "type": "string" }, "domain": { "maxLength": 253, "type": "string" } }, "required": [ "domain" ], "type": "object" }, "operator": { "maxLength": 253, "type": "string" }, "sandbox": { "type": "boolean" } }, "type": "object" }, "assignments": { "items": { "additionalProperties": true, "properties": { "creative_id": { "maxLength": 200, "minLength": 1, "type": "string" }, "media_buy_id": { "maxLength": 100, "minLength": 1, "type": "string" }, "package_id": { "maxLength": 200, "minLength": 1, "type": "string" } }, "required": [ "creative_id" ], "type": "object" }, "maxItems": 100, "type": "array" }, "context": { "additionalProperties": {}, "type": "object" }, "creative_ids": { "items": { "maxLength": 200, "minLength": 1, "type": "string" }, "maxItems": 200, "type": "array" }, "creatives": { "description": "Creative assets to validate", "items": { "additionalProperties": true, "properties": { "assets": { "additionalProperties": {}, "type": "object" }, "creative_id": { "maxLength": 200, "minLength": 1, "type": "string" }, "duration_seconds": { "type": "number" }, "file_size_mb": { "type": "number" }, "format_id": { "anyOf": [ { "additionalProperties": false, "properties": { "agent_url": { "maxLength": 500, "type": "string" }, "duration_ms": { "type": "number" }, "height": { "type": "number" }, "id": { "maxLength": 200, "type": "string" }, "width": { "type": "number" } }, "required": [ "agent_url", "id" ], "type": "object" }, { "type": "string" } ], "description": "AdCP creative format ID (e.g., dooh_landscape_1920x1080)" }, "format_kind": { "maxLength": 100, "type": "string" }, "height": { "type": "number" }, "name": { "maxLength": 300, "type": "string" }, "type": { "enum": [ "video", "image", "vast" ], "type": "string" }, "url": { "format": "uri", "type": "string" }, "width": { "type": "number" } }, "type": "object" }, "maxItems": 10, "minItems": 1, "type": "array" }, "delete_missing": { "type": "boolean" }, "dry_run": { "type": "boolean" }, "ext": { "additionalProperties": {}, "type": "object" }, "idempotency_key": { "maxLength": 200, "type": "string" }, "media_buy_id": { "description": "Media buy ID", "maxLength": 100, "minLength": 1, "type": "string" }, "push_notification_config": { "additionalProperties": {}, "type": "object" }, "validation_mode": { "maxLength": 50, "type": "string" } }, "required": [ "creatives" ], "type": "object" }, "name": "sync_creatives", "outputSchema": null }, { "description": "[AdCP Protocol] Get the status of a previously issued AdCP task.\n\nEvery AdCP task Trillboards serves for an AUTHENTICATED caller is recorded and\nreturned a `task_id`. Poll that id here to read the task's terminal state and,\nwith `include_result: true`, its completion payload.\n\nTrillboards answers every AdCP task in-process, so a task is already\n`completed` by the time you hold its id — this tool exists so a buyer that\npolls does not hang, and so an async arm has somewhere to report from when one\nlands.\n\nTASK SCOPE: tasks are visible only to the account that created them. An id\nbelonging to another account, an id we never issued, or a poll with no\ncredential all answer identically — \"Task <id> not found\" — so the surface\ncannot be used to probe which ids exist.\n\nNOT RECORDED: read-only protocol and catalogue calls that AdCP does not model\nas tasks (get_adcp_capabilities, list_creative_formats, get_media_buys,\nlist_accounts), and any anonymous call, which has no account to scope to.\n\nLEGACY NAME. Identical to `get_task_status`; this is the name the AdCP MCP\nbinding emits (`agent.protocol === \"mcp\" ? \"tasks_get\" : \"tasks/get\"`). Prefer\n`get_task_status` in new code.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "account": { "additionalProperties": false, "properties": { "account_id": { "maxLength": 200, "type": "string" }, "brand": { "additionalProperties": false, "properties": { "brand_id": { "maxLength": 200, "type": "string" }, "domain": { "maxLength": 253, "type": "string" } }, "required": [ "domain" ], "type": "object" }, "operator": { "maxLength": 253, "type": "string" }, "sandbox": { "type": "boolean" } }, "type": "object" }, "context": { "additionalProperties": {}, "type": "object" }, "include_history": { "description": "Include conversation history. Trillboards tasks complete in-process and hold no multi-turn history, so this is accepted and has no effect.", "type": "boolean" }, "include_result": { "description": "Include the task's result payload when status is completed. Defaults to false for lightweight status-only polls.", "type": "boolean" }, "task_id": { "description": "Unique identifier of the task to retrieve, as issued in the `task_id` field of the originating task response.", "maxLength": 200, "minLength": 1, "type": "string" } }, "required": [ "task_id" ], "type": "object" }, "name": "tasks_get", "outputSchema": null }, { "description": "[AdCP Protocol] List AdCP tasks belonging to your account, newest first.\n\nReturns `query_summary` (totals and a status breakdown), `tasks`, and\n`pagination`. Filter by status or task type. Scoped to the calling account —\nan unauthenticated call returns an empty page rather than another account's\ntasks.\n\nLEGACY NAME. Identical to `list_tasks`. Prefer `list_tasks` in new code.", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "account": { "additionalProperties": false, "properties": { "account_id": { "maxLength": 200, "type": "string" }, "brand": { "additionalProperties": false, "properties": { "brand_id": { "maxLength": 200, "type": "string" }, "domain": { "maxLength": 253, "type": "string" } }, "required": [ "domain" ], "type": "object" }, "operator": { "maxLength": 253, "type": "string" }, "sandbox": { "type": "boolean" } }, "type": "object" }, "context": { "additionalProperties": {}, "type": "object" }, "filters": { "additionalProperties": false, "description": "Narrow the returned tasks.", "properties": { "status": { "description": "Single task status to match", "enum": [ "submitted", "working", "input-required", "completed", "canceled", "failed", "rejected", "auth-required", "unknown" ], "type": "string" }, "statuses": { "description": "Task statuses to match (enums/task-status.json)", "items": { "enum": [ "submitted", "working", "input-required", "completed", "canceled", "failed", "rejected", "auth-required", "unknown" ], "type": "string" }, "type": "array" }, "task_type": { "description": "Single task type to match", "enum": [ "create_media_buy", "update_media_buy", "media_buy_delivery", "sync_creatives", "build_creative", "activate_signal", "get_products", "get_signals", "create_property_list", "update_property_list", "get_property_list", "list_property_lists", "delete_property_list", "sync_accounts", "get_account_financials", "get_creative_delivery", "sync_event_sources", "sync_audiences", "sync_catalogs", "log_event", "get_brand_identity", "search_brands", "get_rights", "acquire_rights" ], "type": "string" }, "task_types": { "description": "Task types to match (enums/task-type.json)", "items": { "enum": [ "create_media_buy", "update_media_buy", "media_buy_delivery", "sync_creatives", "build_creative", "activate_signal", "get_products", "get_signals", "create_property_list", "update_property_list", "get_property_list", "list_property_lists", "delete_property_list", "sync_accounts", "get_account_financials", "get_creative_delivery", "sync_event_sources", "sync_audiences", "sync_catalogs", "log_event", "get_brand_identity", "search_brands", "get_rights", "acquire_rights" ], "type": "string" }, "type": "array" } }, "type": "object" }, "pagination": { "additionalProperties": false, "properties": { "limit": { "description": "Page size (max 100, default 50)", "maximum": 100, "minimum": 1, "type": "integer" }, "offset": { "description": "Rows to skip", "minimum": 0, "type": "integer" } }, "type": "object" } }, "type": "object" }, "name": "tasks_list", "outputSchema": null }, { "description": "Send a test event to a webhook endpoint.\n\nWHEN TO USE:\n- Verifying webhook endpoint is working\n- Testing integration during development\n- Debugging webhook delivery issues\n\nRETURNS:\n- success: Boolean indicating delivery success\n- response_code: HTTP response code from endpoint\n- response_time_ms: Response time in milliseconds\n- error: Error message if delivery failed\n\nEXAMPLE:\nUser: \"Test my webhook with a device.online event\"\ntest_webhook({\n webhook_id: \"wh_mmmpdbvj_8b7c5a59296d\",\n event: \"device.online\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "event": { "description": "Event type to simulate (optional, defaults to device.online)", "enum": [ "device.online", "device.offline", "impression.recorded", "campaign.allocated", "payout.processed", "programmatic.ad_started", "programmatic.ad_ended", "programmatic.no_fill", "programmatic.error", "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" ], "type": "string" }, "webhook_id": { "description": "Webhook ID to test (wh_xxx format or legacy ObjectId)", "pattern": "^(wh_[a-z0-9]+_[a-f0-9]+|[a-f0-9]{24})$", "type": "string" } }, "required": [ "webhook_id" ], "type": "object" }, "name": "test_webhook", "outputSchema": null }, { "description": "[AdCP Media Buy] Update an existing media buy (campaign).\n\nModify budget, targeting, schedule, or status of an existing media buy.\n\nWHEN TO USE:\n- Adjusting campaign budget mid-flight\n- Pausing or resuming a campaign\n- Changing targeting parameters\n- Extending campaign dates\n\nEXAMPLE:\nupdate_media_buy({\n media_buy_id: \"mbuy_abc123\",\n updates: { status: \"paused\", budget: { daily_usd: 300 } }\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": true, "properties": { "account": { "additionalProperties": {}, "type": "object" }, "canceled": { "type": "boolean" }, "cancellation_reason": { "maxLength": 500, "type": "string" }, "context": { "additionalProperties": {}, "type": "object" }, "end_time": { "type": "string" }, "ext": { "additionalProperties": {}, "type": "object" }, "idempotency_key": { "maxLength": 200, "type": "string" }, "invoice_recipient": { "additionalProperties": {}, "type": "object" }, "media_buy_id": { "description": "Media buy ID to update", "maxLength": 100, "minLength": 1, "type": "string" }, "new_packages": { "items": { "additionalProperties": {}, "type": "object" }, "type": "array" }, "packages": { "items": { "additionalProperties": true, "properties": { "creative_assignments": { "items": { "additionalProperties": true, "properties": { "creative_id": { "maxLength": 200, "minLength": 1, "type": "string" } }, "required": [ "creative_id" ], "type": "object" }, "maxItems": 100, "type": "array" }, "package_id": { "maxLength": 100, "minLength": 1, "type": "string" }, "targeting_overlay": { "anyOf": [ { "additionalProperties": {}, "type": "object" }, { "type": "null" } ] } }, "required": [ "package_id" ], "type": "object" }, "type": "array" }, "paused": { "type": "boolean" }, "push_notification_config": { "additionalProperties": {}, "type": "object" }, "reporting_webhook": { "additionalProperties": {}, "type": "object" }, "revision": { "type": "integer" }, "start_time": { "anyOf": [ { "type": "string" }, { "const": "asap", "type": "string" } ] }, "updates": { "additionalProperties": false, "description": "Fields to update", "properties": { "budget": { "additionalProperties": false, "properties": { "bid_cpm": { "type": "number" }, "daily_usd": { "type": "number" }, "total_usd": { "type": "number" } }, "type": "object" }, "end_date": { "type": "string" }, "name": { "type": "string" }, "screen_ids": { "items": { "type": "string" }, "type": "array" }, "start_date": { "type": "string" }, "status": { "enum": [ "active", "paused", "cancelled" ], "type": "string" }, "targeting": { "additionalProperties": {}, "type": "object" } }, "type": "object" } }, "required": [ "media_buy_id" ], "type": "object" }, "name": "update_media_buy", "outputSchema": null }, { "description": "Update an existing webhook subscription.\n\nWHEN TO USE:\n- Changing the webhook endpoint URL\n- Adding or removing subscribed events\n- Enabling or disabling a webhook\n- Updating the webhook description\n\nRETURNS:\n- webhook_id: The updated webhook ID\n- url: Updated endpoint URL\n- events: Updated event subscriptions\n- enabled: Updated enabled status\n- updated_at: Update timestamp\n\nEXAMPLE:\nUser: \"Disable the webhook for maintenance\"\nupdate_webhook({\n webhook_id: \"wh_mmmpdbvj_8b7c5a59296d\",\n enabled: false\n})\n\nUser: \"Add impression events to my webhook\"\nupdate_webhook({\n webhook_id: \"wh_mmmpdbvj_8b7c5a59296d\",\n events: [\"device.online\", \"device.offline\", \"impression.recorded\"]\n})", "inputSchema": { "properties": {}, "type": "object" }, "name": "update_webhook", "outputSchema": null }, { "description": "Validate a proposed request payload against the registered\nZod schema for an operation, returning the exact canonical error envelope\nthe HTTP surface would emit.\n\nWHEN TO USE:\n- Before calling a write endpoint, to catch payload bugs locally.\n- Debugging 400 validation_error responses.\n\nRETURNS:\n- valid: true when the payload would pass Zod validation.\n- When invalid, the canonical { error: { type, code, message, param,\n doc_url, details[] } } envelope is included under `error`.\n\nEXAMPLE:\nvalidate_request({\n path: \"/v1/data/query\",\n method: \"POST\",\n payload: { dataset: \"inference_outcomes\", limit: 9999 }\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "method": { "maxLength": 16, "minLength": 1, "type": "string" }, "path": { "description": "Operation path (OpenAPI template form).", "maxLength": 256, "minLength": 1, "type": "string" }, "payload": { "description": "Shape is operation-dependent. GET → { query?, params? }. POST → body + optional { query?, params? }." } }, "required": [ "path", "method" ], "type": "object" }, "name": "validate_request", "outputSchema": null }, { "description": "Verify cryptographic proof of ad delivery or get campaign proofs.\n\nRequires either campaign_id or proof_payload (at least one must be provided).\n\nTwo modes:\n1. Verify a proof: pass proof_payload with signature fields to verify\n2. Get proofs: pass campaign_id to get Ed25519-signed proofs for a campaign\n\nUses Ed25519 signatures (v2) that can be independently verified by third parties\nusing the Trillboards public key.\n\nWHEN TO USE:\n- Verifying that ads were actually delivered to screens\n- Exporting cryptographically signed proof records for auditors\n- Getting proof-of-play data for campaign transparency reports\n\nRETURNS (verify mode):\n- valid: boolean, reason: string if invalid, version: 'v1' or 'v2'\n\nRETURNS (get proofs mode):\n- campaignId, totalImpressions, proofsReturned\n- proofs: Array of signed impression proofs\n- pagination: { limit, hasMore, nextCursor }\n- signatureVersion, publicKeyUrl\n\nEXAMPLE (verify):\nverify_proof_of_play({\n proof_payload: {\n signature: \"ed25519=abc123...\",\n timestamp: \"2026-03-10T15:30:00Z\",\n adId: \"ad_123\",\n impressionId: \"imp_456\",\n screenId: \"scr_789\",\n deviceId: \"dev_012\"\n }\n})\n\nEXAMPLE (get proofs):\nverify_proof_of_play({\n campaign_id: \"camp_abc123\",\n start_date: \"2026-03-01\",\n end_date: \"2026-03-10\"\n})", "inputSchema": { "$schema": "http://json-schema.org/draft-07/schema#", "additionalProperties": false, "properties": { "campaign_id": { "description": "Campaign ID to get proofs for (mutually exclusive with proof_payload)", "maxLength": 128, "type": "string" }, "cursor": { "description": "Pagination cursor from previous response (used with campaign_id)", "maxLength": 200, "type": "string" }, "end_date": { "description": "End date for proof query (YYYY-MM-DD, used with campaign_id)", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "type": "string" }, "limit": { "description": "Max proofs to return (default: 1000, used with campaign_id)", "maximum": 10000, "minimum": 1, "type": "integer" }, "proof_payload": { "additionalProperties": false, "description": "Proof data to verify (mutually exclusive with campaign_id). Must include: signature, timestamp, adId, impressionId, screenId, deviceId", "properties": { "adId": { "type": "string" }, "deviceId": { "type": "string" }, "impressionId": { "type": "string" }, "screenId": { "type": "string" }, "signature": { "description": "Signature string (ed25519=... or sha256=...)", "type": "string" }, "signatureVersion": { "description": "v1 or v2", "type": "string" }, "timestamp": { "description": "ISO 8601 timestamp", "type": "string" } }, "required": [ "signature", "timestamp" ], "type": "object" }, "start_date": { "description": "Start date for proof query (YYYY-MM-DD, used with campaign_id)", "pattern": "^\\d{4}-\\d{2}-\\d{2}$", "type": "string" } }, "type": "object" }, "name": "verify_proof_of_play", "outputSchema": null } ] }
Verify it yourselfcurl -s https://api.teppi.xyz/v1/evidence/sha256:abf5669d261278ac7fe6d755b1014c2317aa9fc317f0e6cc571804b2b45d46cf | sha256sum