Skip to content
Preview, then Activate
.md

Preview, then Activate

A worked agent session for the frequency filter: confirm the audience is ready, preview exactly what a frequency range would export, then activate exactly that range - with the server proving the two match. Every call below is a plain MCP tools/call; the argument objects are shown as the agent sends them and the results as excerpts of what comes back.

The numbers are from a real run. The only thing that changes between runs is the ids.

Before you start: a connected agent (Getting started) and a 104 Completed audience that was built with a frequency analysis: analyses: {"frequency": true} (POI), {"apps_frequency": true} (Apps) or {"web_frequency": true} (WebDomain) on create_audience, or the matching toggle in the Audience Manager. Audiences built without one carry no frequency distribution and are refused by the preview - the filter is never approximated, and no analysis can be added after the build.

1. Confirm the audience is ready

get_audience  {"id": 88}
{
  "id": 88,
  "name": "Kubota Test Audience US L30",
  "status": { "id": 104, "name": "Completed" },
  "is_activation_allowed": true,
  "results_count": 205188
}

status.id must be 104 and is_activation_allowed should be true - the frequency filter does not change the eligibility gates, so an audience that is blocked here stays blocked whatever range you pick.

2. Preview the range

Ask for the range you intend to export. The response is the exact device count the Audience Manager shows as Limit Audience for the same Freq. Range: the audience’s stored frequency histogram (distinct visit days -> devices) summed over the inclusive [freq_min, freq_max] range, which is the same predicate the export applies. Nothing is created, queued, exported, scheduled or billed, so preview as many ranges as the conversation needs.

preview_activation  {"audience_id": 88, "freq_min": 2, "freq_max": 31}
{
  "audience": { "id": 88, "status": { "id": 104, "name": "Completed" }, "is_activation_allowed": true },
  "dataset_type": "POI",
  "analysis_type": "frequency",
  "recency": [ { "dataset_type": "POI", "start_date": "07/01/2026", "end_date": "07/31/2026" } ],
  "source_count": 205188,
  "histogram_total": 208389,
  "filtered_count": 21656,
  "frequency_bounds": { "min": 1, "max": 31 },
  "histogram": [ { "index": 1, "counts": 186733 }, { "index": 2, "counts": 12904 }, "..." ],
  "applied_filters": { "freq_limit": true, "freq_min": 2, "freq_max": 31 },
  "filter_hash": "sha256:d6c9da3215a0f9d8902bab24c5e1b579f52cb11b6cbb76ca7ab8a032e0e1151b",
  "method": "histogram_sum",
  "as_of": "2026-08-20 23:18:11"
}

How to read it:

  • filtered_count is exact - 21,656 devices were seen on 2 or more distinct days. This is the number to tell the user.
  • An open-ended “N+” range is freq_min: N with freq_max set to frequency_bounds.max. “1+” therefore returns histogram_total.
  • source_count is the audience total shown on the audience itself (an approximate distinct count) and histogram_total the exact histogram sum, so the two can differ slightly. Quote filtered_count, not a difference.
  • recency is the audience’s own date window, echoed read-only. It is not a preview input: to count against another window, build (or estimate_audience_size) a new audience.
  • Keep filter_hash - it is the proof for step 3. Only audience_id, freq_min and freq_max are accepted; any other field is rejected rather than ignored.

3. Activate exactly that range

Discover the destination as usual - lookup_reference with dataset common and catalogs endpoint-connections, then pricing-models and datastreams for that connection’s partner_id (see the Tools Reference). Then send the same audience_id, freq_min and freq_max you previewed, with freq_limit: true and the filter_hash unchanged:

create_activation  {
  "audience_id": 88,
  "endpoint_connection_id": 12,
  "pricing_model_id": 3,
  "datastreams": [ { "id": 7, "status": true } ],
  "description": "Kubota 2+ visit days",
  "freq_limit": true,
  "freq_min": 2,
  "freq_max": 31,
  "filter_hash": "sha256:d6c9da3215a0f9d8902bab24c5e1b579f52cb11b6cbb76ca7ab8a032e0e1151b",
  "idempotency_key": "kubota-2plus-2026-08-25"
}
{
  "id": 501,
  "status": { "id": 100, "name": "Initiating" },
  "audience": { "id": 88, "name": "Kubota Test Audience US L30" },
  "filters": { "freq_limit": true, "freq_min": 2, "freq_max": 31 },
  "filter_hash": "sha256:d6c9da3215a0f9d8902bab24c5e1b579f52cb11b6cbb76ca7ab8a032e0e1151b"
}

The server recomputes the hash for the requested range on the audience as it is stored now. A different range, or an audience that was rebuilt since the preview, is rejected - the activation never applies anything other than what was previewed. When that happens, run preview_activation again and use the fresh hash.

4. Poll and read back

get_activation  {"id": 501}

Poll until data[0].status.id is 104 (Completed) - 105 DataStreaming comes first and means delivery is still in progress. The read echoes filters and filter_hash, so any later reader can see which range the export applied. Delivered data lands at the destination configured on the endpoint connection. In this run the delivered file held exactly 21,656 device ids - the previewed count.

Rules for the agent

  • Never send freq_min / freq_max without an explicit freq_limit; the request is rejected. freq_limit: false with bounds is an explicit “export the whole audience”.
  • A preview refusal (“not supported for this audience”) means the audience has no usable frequency distribution - it was built without the Frequency analysis, is a lookalike or cohort, uses a day-part frequency, or carries more than one frequency analysis. Say so; do not estimate a count. If it was built without one, the fix is a new create_audience with the analyses key that matches its dataset.
  • Recency is fixed by the audience definition. Do not try to pass dates.
  • Preview is a read (120 requests/min per token); create is a write (30 requests/min). Pass an idempotency_key on the create so a retry can never activate twice.