Tools that only read data
Data coverage
Which analytics modules this organization has (entitlements) and which actually have data flowing, with the latest date per surface. CALL THIS FIRST in a new session, and any time you are unsure whether a data surface exists for this org — entitled-but-empty and has-data-but-lapsed are both real states, and every other tool's availability follows from what this returns.
Data coverage › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Metric definitions
What this organization's custom metric slots (metric_1..metric_10) count, with each metric's name, abbreviation, description, type and display format — plus whether its conversion numbers come from its CRM or from ad-platform pixels. Read this BEFORE interpreting or ranking by any metric_N column: the slots mean different things per organization (for CRM-source orgs metric_1 is typically MQLs from Salesforce/HubSpot, not a platform pixel conversion).
Metric definitions › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Context pack
The full operating contract for this API as one markdown document: how the platform defines its metrics (Monday-start weeks, ROAS as total revenue over total spend, rate metrics recomputed from summed components rather than averaged, the display-format and ad-network vocabularies), the grounding rules your answers must follow, the BigQuery marts behind each tool with their documented columns and grains, and the full tool reference. LOAD THIS ONCE at the start of a session, before answering any question about this organization's numbers — it is what stops a correct-looking figure from being computed the wrong way. It is static per deployment: cache it against the returned meta.version and re-fetch only when that changes.
Context pack › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Ad performance summary
Organization-wide paid-ad totals for one window: spend, impressions, clicks, ctr, cpm, cpc, roas, fatigue_score and this organization's custom metrics (metric_1..metric_10). This is the grounding call for "how are we doing" — start here, then drill in with the per-entity tools. Optional filters narrow to one product, network, ad account or campaign. Omit both dates for the default window: the last 30 complete days ending yesterday. Recompute rates (ctr, cpc, cpm, roas) from summed numerators and denominators — ROAS is total revenue ÷ total spend over the window. Never average the per-row rate columns. Read get_metric_definitions before interpreting or comparing any metric_N column: the slots mean different things per organization.
Ad performance summary › Request Body
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
product_idFilter to one product id from the org context.
ad_network_idFilter to one network: facebook_ads | google_ads | tiktok_ads | linkedin_ads | bingads.
account_idFilter to one ad account id.
campaign_idFilter to one campaign id.
Ad performance summary › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Daily ad performance
Per-day paid-ad performance series for a window, filterable to one product, network, ad account, campaign, ad set or ad. Use it for trends, pacing and "what changed on
Daily ad performance › Request Body
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
product_idFilter to one product id from the org context.
ad_network_idFilter to one network: facebook_ads | google_ads | tiktok_ads | linkedin_ads | bingads.
account_idFilter to one ad account id.
campaign_idFilter to one campaign id.
adset_idFilter to one ad set id.
ad_idFilter to one ad id.
Daily ad performance › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Performance by ad account
Paid-ad performance rolled up per ad account, including this organization's custom KPI counts and values. Use it to compare accounts or to find which account carries the spend. For any 'top / most / best by X' question pass sort_by AND limit: the full row set is ranked server-side before the slice, so the answer arrives in one call instead of several narrowing ones. An invalid sort_by comes back with the list of valid columns, so you can retry in one step. Omit both dates for the default window: the last 30 complete days ending yesterday. Recompute rates (ctr, cpc, cpm, roas) from summed numerators and denominators — ROAS is total revenue ÷ total spend over the window. Never average the per-row rate columns.
Performance by ad account › Request Body
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
product_idFilter to one product id from the org context.
ad_network_idFilter to one network: facebook_ads | google_ads | tiktok_ads | linkedin_ads | bingads.
account_idFilter to one ad account id.
campaign_idFilter to one campaign id.
sort_bySort rows by this column, descending, before returning. Best on numeric metric columns: spend, impressions, clicks, ctr, cpc, cpm, roas, metric_1..metric_10 (for CRM-source orgs metric_1 = MQLs — see get_metric_definitions). An invalid value returns the list of valid columns so you can retry in one step.
limitMax rows to return after sorting (default 50, max 200).
Performance by ad account › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Performance by campaign
Paid-ad performance rolled up per campaign — "top campaigns", "which campaigns are underperforming", "where did the spend go". Filter to one network or account first when the question is scoped that way. For any 'top / most / best by X' question pass sort_by AND limit: the full row set is ranked server-side before the slice, so the answer arrives in one call instead of several narrowing ones. An invalid sort_by comes back with the list of valid columns, so you can retry in one step. Omit both dates for the default window: the last 30 complete days ending yesterday. Recompute rates (ctr, cpc, cpm, roas) from summed numerators and denominators — ROAS is total revenue ÷ total spend over the window. Never average the per-row rate columns.
Performance by campaign › Request Body
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
product_idFilter to one product id from the org context.
ad_network_idFilter to one network: facebook_ads | google_ads | tiktok_ads | linkedin_ads | bingads.
account_idFilter to one ad account id.
campaign_idFilter to one campaign id.
sort_bySort rows by this column, descending, before returning. Best on numeric metric columns: spend, impressions, clicks, ctr, cpc, cpm, roas, metric_1..metric_10 (for CRM-source orgs metric_1 = MQLs — see get_metric_definitions). An invalid value returns the list of valid columns so you can retry in one step.
limitMax rows to return after sorting (default 50, max 200).
Performance by campaign › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Performance by ad set
Paid-ad performance rolled up per ad set, optionally inside one campaign (campaign_id) or for one ad set (adset_id). Use it after a campaign-level answer, to see which audience or placement inside the campaign is doing the work. For any 'top / most / best by X' question pass sort_by AND limit: the full row set is ranked server-side before the slice, so the answer arrives in one call instead of several narrowing ones. An invalid sort_by comes back with the list of valid columns, so you can retry in one step. Omit both dates for the default window: the last 30 complete days ending yesterday. Recompute rates (ctr, cpc, cpm, roas) from summed numerators and denominators — ROAS is total revenue ÷ total spend over the window. Never average the per-row rate columns.
Performance by ad set › Request Body
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
product_idFilter to one product id from the org context.
ad_network_idFilter to one network: facebook_ads | google_ads | tiktok_ads | linkedin_ads | bingads.
account_idFilter to one ad account id.
campaign_idFilter to one campaign id.
adset_idFilter to one ad set id.
sort_bySort rows by this column, descending, before returning. Best on numeric metric columns: spend, impressions, clicks, ctr, cpc, cpm, roas, metric_1..metric_10 (for CRM-source orgs metric_1 = MQLs — see get_metric_definitions). An invalid value returns the list of valid columns so you can retry in one step.
limitMax rows to return after sorting (default 50, max 200).
Performance by ad set › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Performance by ad
Paid-ad performance rolled up per individual ad. Ad grain exists for facebook_ads, linkedin_ads and tiktok_ads only — other networks do not report it, so an empty result for google_ads or bingads is expected rather than a data problem. For CRM-source organizations these rows are CRM-attributed at ad grain and match the platform's Ads page, which makes this THE authoritative source for per-ad and per-creative MQL ranking: rank by metric_1 (see get_metric_definitions). Never take that ranking from get_creative_fatigue or get_creative_leaderboard — their conversion columns are platform-pixel and near zero by design for those organizations. For any 'top / most / best by X' question pass sort_by AND limit: the full row set is ranked server-side before the slice, so the answer arrives in one call instead of several narrowing ones. An invalid sort_by comes back with the list of valid columns, so you can retry in one step. Omit both dates for the default window: the last 30 complete days ending yesterday.
Performance by ad › Request Body
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
product_idFilter to one product id from the org context.
ad_network_idFilter to one network: facebook_ads | google_ads | tiktok_ads | linkedin_ads | bingads.
account_idFilter to one ad account id.
campaign_idFilter to one campaign id.
adset_idFilter to one ad set id.
sort_bySort rows by this column, descending, before returning. Best on numeric metric columns: spend, impressions, clicks, ctr, cpc, cpm, roas, metric_1..metric_10 (for CRM-source orgs metric_1 = MQLs — see get_metric_definitions). An invalid value returns the list of valid columns so you can retry in one step.
limitMax rows to return after sorting (default 50, max 200).
Performance by ad › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Performance by keyword
Keyword-level performance with match_type, for google_ads and bingads only (the social networks have no keyword grain, so filtering this to one of them returns nothing by design). Filter with campaign_id / adset_id to scope to one ad group, or keyword_id for a single keyword. For any 'top / most / best by X' question pass sort_by AND limit: the full row set is ranked server-side before the slice, so the answer arrives in one call instead of several narrowing ones. An invalid sort_by comes back with the list of valid columns, so you can retry in one step. Omit both dates for the default window: the last 30 complete days ending yesterday.
Performance by keyword › Request Body
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
product_idFilter to one product id from the org context.
ad_network_idFilter to one network: facebook_ads | google_ads | tiktok_ads | linkedin_ads | bingads.
account_idFilter to one ad account id.
campaign_idFilter to one campaign id.
adset_idFilter to one ad set id.
keyword_idFilter to one keyword id.
sort_bySort rows by this column, descending, before returning. Best on numeric metric columns: spend, impressions, clicks, ctr, cpc, cpm, roas, metric_1..metric_10 (for CRM-source orgs metric_1 = MQLs — see get_metric_definitions). An invalid value returns the list of valid columns so you can retry in one step.
limitMax rows to return after sorting (default 50, max 200).
Performance by keyword › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Performance by geography
Country-level spend, clicks and conversions, rolled up either by ad account (level="account", the default) or by campaign (level="campaign"). country_code narrows to a single country. Coverage depends on what each network reports geographically, so a country missing from the rows means "not reported", not "zero". Omit both dates for the default window: the last 30 complete days ending yesterday.
Performance by geography › Request Body
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
product_idFilter to one product id from the org context.
ad_network_idFilter to one network: facebook_ads | google_ads | tiktok_ads | linkedin_ads | bingads.
account_idFilter to one ad account id.
campaign_idFilter to one campaign id.
levelRollup grain: 'account' (default) or 'campaign'.
country_code^[A-Za-z]{2,3}$Filter to one country, as its 2- or 3-letter code (e.g. US).
Performance by geography › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Fatigued ads
Ads whose creative fatigue score is elevated, highest first — the tool for "which ads are burning out / need a refresh". The score adds a CTR-decay component (up to 50), an impression-pressure component (up to 30) and a creative-age component (up to 20), and an ad younger than 7 days always scores 0. min_score defaults to 30; only ads with spend in the window are considered, and at most 200 rows come back. This reads engagement and delivery metrics plus PLATFORM-PIXEL conversions: for CRM-source organizations the conversion columns here are near zero by design, so never rank creatives by MQL or lead volume with this tool — use get_ads_performance. Omit both dates for the default window: the last 30 complete days ending yesterday.
Fatigued ads › Request Body
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
ad_network_idFilter to one network: facebook_ads | google_ads | tiktok_ads | linkedin_ads | bingads.
min_scoreMinimum fatigue score to include, 0-100 (default 30).
Fatigued ads › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Creative leaderboard
Per-creative leaderboard with winner / mid / loser labels, trend, spend, CTR, KPI count, cost per KPI and the extracted creative attributes (visual style, messaging angle, density, specificity, human presence, subject elements) — the tool for "what is working creatively" and "what do our winners have in common". window_days accepts only 30, 60, 90 or 120 (attributes are precomputed nightly for those windows); it takes no start_date/end_date. Its metrics are ad-platform reported, so for CRM-source organizations the KPI columns are near zero by design — rank creatives by MQL with get_ads_performance instead. Requires the Creative module: without it this returns a clean "not part of this organization's plan" refusal rather than empty data.
Creative leaderboard › Request Body
window_daysLookback window in days. Only 30, 60, 90 and 120 exist (the attributes are precomputed nightly for those windows); default 90.
sortRanking column (default cost_per_kpi). cost_per_kpi orders cheapest-first (best first); spend, ctr and kpis order highest-first.
limitRows to return (default 25, max 100).
Creative leaderboard › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
All channels
Cross-channel performance from the unified channel_daily mart, which unions paid ads, email, organic social, GA4 web sessions, ecommerce orders and Signal conversions onto ONE canonical channel grain: Paid Search, Paid Social, Paid Other, Organic Search, Organic Social, Email, Direct, Referral, Affiliate, Other. This is the tool for channel mix, blended CAC/ROAS and any "which channel" question — the per-platform tools cannot be added up into these numbers. mode=overview returns per-channel spend, impressions, clicks, sends, delivered, opens, reach, views, engagements, followers, sessions and key_events, plus a picked conversions and revenue with cac and roas, the native reach/engagement metric with its label, a per-platform breakdown and prior-period deltas, with a totals row spanning all channels. mode=daily returns the per-day, per-channel spend / sessions / conversions / revenue series. conversions is picked orders → Signal → GA4 key events and revenue order_revenue → signal_revenue → ga4_revenue, applied consistently across channels, so the comparison is like for like — say which basis you are quoting. There are no filters beyond the window. Omit both dates for the default window: the last 30 complete days ending yesterday. If you bucket the daily series into weeks, use MONDAY-start weeks, the boundary the rest of this product uses.
All channels › Request Body
modeoverview = per-channel totals with deltas and a totals row; daily = the per-day, per-channel series.
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
All channels › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
GA4 web analytics
Google Analytics 4 web analytics for this organization. Pick the mode for the question: summary (sessions / users / conversions totals), daily (per-day series), traffic_sources (by source and medium), campaigns (by GA4 campaign), channels (GA4's default channel grouping), engagement (sessions, bounce and duration by channel), key_events (GA4 conversion events), landing_pages, or geo_devices (device category and geography). These are GA4's own session-scoped, GA4-attributed numbers: they will NOT tie out to ad-platform clicks or to the paid-ads tools, and GA4 channel groupings are not the Bellaso channel groupings — use get_channels for cross-channel comparison and say which source you are quoting. property_id limits to one property when several are connected. Omit both dates for the default window: the last 30 complete days ending yesterday. Weeks are MONDAY-start if you bucket the daily series.
GA4 web analytics › Request Body
modeWhich GA4 cut to return — see the tool description for each.
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
property_id^[A-Za-z0-9_-]+$Limit to one GA4 property id. Omit (or pass "all") to cover every connected property.
GA4 web analytics › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Email marketing
Email marketing analytics from the email_campaigns mart. Pick the mode: summary (sends, delivered, opens, clicks, unsubscribes, bounces with prior-period deltas), daily (per-day series), campaigns (the per-campaign table — sortable with sort_by/sort_dir, searchable with search over subject and campaign name, paged with limit/offset), subject_lines (subject leaderboard plus open/click rates broken out by subject feature, length bucket, weekday, hour and split test; min_sends gates who reaches the leaderboard), or filter_options (all-time campaign types, lists, sources and the available date range — call this first when you need a valid filter value). Filters: campaign_type (exact), list_name (substring), source (exact). Open rates are inflated by privacy proxies on some clients — treat click-through and CTOR as the reliable engagement signals, and never present open rate as a deliverability measure. Omit both dates for the default window: the last 30 complete days ending yesterday.
Email marketing › Request Body
modeWhich email cut to return — see the tool description for each.
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
campaign_type^[^'\\]+$Filter to one campaign type (exact match; get the available values from mode=filter_options).
list_name^[^'\\]+$Filter to campaigns sent to a list whose name CONTAINS this text (substring match).
source^[^'\\]+$Filter to one email source/connector (exact match).
sort_bycampaigns mode: sort column — sent_at | sends | delivered | unique_opens | unique_clicks | open_rate | click_rate | ctor | unsub_rate | bounce_rate | campaign_name | subject (default sent_at). An invalid value returns the allowed list.
sort_dirSort direction for the table mode (default desc).
limitTable mode: rows to return, 1-500 (default 25).
offsetTable mode: rows to skip, for paging (default 0).
searchcampaigns mode: case-insensitive match on the subject or campaign name.
min_sendssubject_lines mode: minimum total sends before a subject enters the leaderboard (default 100; 0 removes the gate). Lower it for a low-volume sender.
Email marketing › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Organic social
Organic (unpaid) social analytics from the organic_social_daily and organic_social_posts marts — Facebook Pages and Instagram Business accounts today. Pick the mode: summary (followers, follower_change, reach, views, engagements, likes/comments/shares/saves, link_clicks, posts_published and engagement_rate, with prior-period deltas), daily (per-day series), accounts (per-account rollup with the latest follower count, ordered by reach), posts (the per-post table — sortable with sort_by/sort_dir, searchable with search over the caption, filterable by media_type, paged with limit/offset), or filter_options (all-time platforms, accounts, media types and the available date range). followers is the LATEST per-account count inside the window, never a sum — do not add it across days or accounts. These are unpaid metrics only: paid social lives in the ads tools, and get_channels is what compares the two. Filters: platform (facebook | instagram), account_id (exact). Omit both dates for the default window: the last 30 complete days ending yesterday.
Organic social › Request Body
modeWhich organic-social cut to return — see the tool description for each.
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
platformFilter to one platform.
account_id^[^'\\]+$Filter to one social account id (exact; get ids from mode=accounts or mode=filter_options).
sort_byposts mode: sort column — published_at | reach | views | likes | comments | shares | saves | engagements | engagement_rate (default published_at). An invalid value returns the allowed list.
sort_dirSort direction for the table mode (default desc).
limitTable mode: rows to return, 1-500 (default 25).
offsetTable mode: rows to skip, for paging (default 0).
searchposts mode: case-insensitive match on the post caption.
media_type^[^'\\]+$posts mode: filter to one media type (e.g. IMAGE, VIDEO, CAROUSEL_ALBUM, REEL, STORY).
Organic social › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Performance forecast
Projected daily performance from the forecast mart (BigQuery AI.FORECAST fitted over recent actuals), organization-wide or filtered to one product, network, account or campaign. mode=summary (default) returns projected totals for the window; mode=daily returns the projected per-day series. These are MODEL PROJECTIONS, not observed data: label them as forecasts, never add them into an actuals total, and do not present a projected value as something that happened. The mart holds a short FORWARD horizon (about a week ahead, rebuilt nightly), and the window simply selects which of those days come back — a window entirely in the past returns nothing, which is expected rather than a failure. Omit both dates for the default window: the last 30 complete days ending yesterday.
Performance forecast › Request Body
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
product_idFilter to one product id from the org context.
ad_network_idFilter to one network: facebook_ads | google_ads | tiktok_ads | linkedin_ads | bingads.
account_idFilter to one ad account id.
campaign_idFilter to one campaign id.
modesummary (default) = projected totals for the window; daily = the projected per-day series.
Performance forecast › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Signal CAC by channel
Cost per attributed conversion from Signal's spend-attribution mart, by date, attribution model, channel and campaign: spend, credited_conversions and CAC. Use it for "what does a conversion cost by channel" once Signal is tracking conversions. Rows exist ONLY where credited conversions join ad spend on matching campaign names, so an empty result is a valid state — it means nothing has joined yet, not that CAC is zero and not that the tool failed. Because credit is split by attribution model, always state which model a CAC figure comes from. Requires the Signal spend/CAC mart: without the entitlement this returns a plan refusal rather than empty rows.
Signal CAC by channel › Request Body
start_date^\d{4}-\d{2}-\d{2}$Since date, YYYY-MM-DD (default: 90 days ago). The window always runs from here through the latest available day; there is no end_date.
Signal CAC by channel › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Financials (books)
Financials read straight from this organization's books (QuickBooks or Xero). Pick the report: kpis (monthly revenue, COGS and margins), pl (P&L rows by account), balances (balance-sheet lines including cash), ar_aging (receivables by age bucket), ap_aging (payables by age bucket), or marketing_bridge (ad spend against revenue: MER, blended CAC, spend as a percentage of revenue). since sets the earliest month, default 13 months back. These are ACCOUNTING numbers on the organization's own calendar and recognition rules — they will not match ad-platform revenue columns, and marketing_bridge is the intended place to compare the two. Requires the Margin module and a synced accounting connector; without it you get a plan refusal, and with no synced books an explicit "no accounting data" answer.
Financials (books) › Request Body
reportWhich financial report to return — see the tool description for each.
since^\d{4}-\d{2}-\d{2}$Earliest month to include, YYYY-MM-DD (default: 13 months back).
Financials (books) › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Marketing mix model results
The latest COMPLETED marketing-mix-model run per outcome KPI and model type (Meridian and/or Robyn): model fit (R², NRMSE), per-channel contribution share, ROI and marginal ROI, plus any stored budget-optimization output. outcome_variable filters to one KPI. These are MODEL ESTIMATES over a training window, not measured attribution: report them as modeled contribution, quote the fit statistics alongside any ROI you cite, and note the run's completed_at — a stale run describes an old media mix. Contribution shares answer "what is driving outcomes", while get_channels answers "what did each channel actually spend and produce". Requires Compass.
Marketing mix model results › Request Body
outcome_variableFilter to one outcome variable (the KPI the model was trained to explain). Omit to get every outcome the org has trained.
Marketing mix model results › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Run a report template
Run a versioned, deterministic report template. The same template over the same window always produces identical tables — the fetches are fixed and the math is precomputed — so prefer this over assembling the same story by hand from several tools. Templates: performance_recap (this period against the previous one, top campaigns, biggest movers), budget_pacing (expected vs actual spend for the current budget period), signal_attribution (credit by channel and model plus CAC), creative_review (winners and losers with attribute insights), finance_snapshot (P&L KPIs plus the marketing bridge). Each template reads the same gated tools you would call yourself: a multi-source template (performance_recap, creative_review, finance_snapshot) fills the sections it can and leaves the rest empty, while a single-source one (budget_pacing) comes back as a plain failure carrying the reason — for example "no budget period covers this date". The payload is designed to be rendered as tables: summarize the headline movements and name the window, do not restate every row. Omit both dates for the default window: the last 30 complete days ending yesterday.
Run a report template › Request Body
templateWhich report template to run.
start_date^\d{4}-\d{2}-\d{2}$Window start, YYYY-MM-DD (inclusive). Omit both dates for the default window: the last 30 complete days ending yesterday.
end_date^\d{4}-\d{2}-\d{2}$Window end, YYYY-MM-DD (inclusive).
Run a report template › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
List management connections
The ad-platform connections this organization can apply changes through, as { id, platform, name }. Call this BEFORE changes_draft: a draft must name one of these ids, and any other id is refused. Returns identifiers only — never tokens, credentials or account contents.
List management connections › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
List change sets
This organization's change sets, newest first, with their workflow status — including ones drafted by people in the app, not just by this endpoint. Use it to check whether a set you submitted has been approved, rejected or applied. Optionally filter by status.
List change sets › Request Body
statusOnly return change sets in this workflow state.
limitMax change sets to return, newest first (default 50, max 200).
List change sets › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Get a change set
One change set with its proposed items and its approval history (who approved or rejected it, and any comment). Use it after list_change_sets to read exactly what a set contains, or to see why a reviewer sent it back.
Get a change set › Request Body
change_set_id^[0-9a-fA-F]{8}-[0-9… · requiredThe change set to read.
Get a change set › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
List audiences
This organization's saved intent audiences, newest first, with the query each was built from, its filters, its status and its ContactBased feed id. Call this before creating one: audiences are capped per organization, and an existing audience can usually be refined with audience_update_filters instead.
List audiences › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
List conversion page rules
This organization's conversion page rules: URL patterns that make a pageview count as a conversion (for thank-you pages and other no-form conversions). Read these before adding one — a rule name must be unique per site, and an overlapping pattern double-counts.
List conversion page rules › Request Body
site_id^[0-9a-fA-F]{8}-[0-9…Only return rules for this tracked site.
List conversion page rules › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
List form groups
This organization's form groups — sets of step form names treated as ONE form, so a multi-step form counts as a single conversion instead of one per step. Read these before grouping, to see which step names are already claimed.
List form groups › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
List attribution models
This organization's Signal attribution models, with each model's type, lookback window and whether it is active or the default. Read this before adding one — models are computed side by side, so a near-duplicate mostly adds noise.
List attribution models › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
List Signal sessions
List recent Signal sessions for the organization (operational Supabase state). Optional site_id filter. recorded_only limits to playable replays (ready/partial). Does not return signed playback URLs.
List Signal sessions › Request Body
site_id^([0-9a-fA-F]{8}-[0-…recorded_onlylimitcursor_started_atcursor_id^([0-9a-fA-F]{8}-[0-…device_classclient_ospage_containslanding_onlyhas_form_submitList Signal sessions › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Get Signal session
Fetch one Signal session plus its chunk index (hashes and sizes, no signed URLs). Playback grant is a separate tool.
Get Signal session › Request Body
session_id^([0-9a-fA-F]{8}-[0-… · requiredGet Signal session › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.
Grant Signal session playback URLs
Mint short-lived signed GET URLs for every chunk of a playable session. Expiry is at most 5 minutes and never past recording_expires_at. Deleted/expired/unavailable sessions return denied.
Grant Signal session playback URLs › Request Body
session_id^([0-9a-fA-F]{8}-[0-… · requiredGrant Signal session playback URLs › Responses
The tool ran
oktooldataThe tool's payload — byte-identical to what the same tool returns over MCP.