Skip to content

Audiences

Build, list, read and delete custom audiences. Audience creation is asynchronous: the create call returns immediately with a new id, and you poll the get endpoint until the audience reaches its completed lifecycle status. To run a completed audience on a recurring data window - rebuilt and optionally re-exported every cycle - see Schedules.

All audience endpoints are authenticated and JSON-only. Send Authorization: Bearer <token> and Accept: application/json on every call (plus Content-Type: application/json on the POST create). Reads use the read rate bucket (120 requests/min per caller); the create and delete use the write bucket (30 requests/min per caller).

Create Audience

POST /api/v2/analyses/audiences/create

Creates a custom audience for the authenticated user’s company from one or two datasets. Two datasets are combined with an operator. An optional crossvisitation block narrows the audience to people who visited selected points of interest; an optional crosspurchase block runs the built audience against the affinity purchase data. The audience is queued asynchronously; poll GET /api/v2/analyses/audiences/{id} for its status and results_count.

Auth: bearer token + Accept: application/json + Content-Type: application/json. Rate limit: write bucket (30 requests/min). Optional: Idempotency-Key header (see below).

The build counts toward your company’s monthly data-scan limit (see Usage). When the limit has been reached and is enforced, the call is refused with a 422 whose message names the limit and the date it resets, before anything is created or queued.

Body

FieldTypeRequiredDescription
namestringYesAudience name (max 255 chars).
operatorstringConditionalHow to combine two datasets: AND, OR, or NOTIN. Required when datasets holds two blocks; rejected (422) when it holds one. Fetch the accepted values from GET /api/v2/analyses/reference/common/operators.
project_idintegerNoA project id owned by your company to file the audience under.
datasetsobject[]YesOne or two dataset blocks (array of size 1 or 2).
crossvisitationobjectNoOptional POI crossvisitation analysis. Permission-gated - see below.
crosspurchaseobjectNoOptional cross purchase analysis run on the built audience. Permission-gated - see below.
analysesobjectNoThe frequency analyses to run as the audience builds - frequency (with its frequency_day_part sub-option), apps_frequency and web_frequency, all booleans - the same toggles as the Audience Manager and what the activation preview depends on. Permission-gated, each tied to its dataset type - see below.
datastreamsobject[]NoData stream visualizations to generate as the audience builds - see below.

An audience holds one or two datasets. A single dataset takes no operator; two datasets require an operator (AND, OR, or NOTIN). Each dataset is validated and company-scoped identically. A second dataset that is present but missing its type is rejected with 422.

Each datasets[i] block always carries a type, and (except for Cohorts and Demographics) a start_date and end_date. The remaining fields depend on the type. The type is one of the dataset types your company is entitled to, fetchable from GET /api/v2/analyses/reference/common/dataset-types.

Common to each datasets[i]:

FieldTypeRequiredDescription
typestringYesThe dataset type. Fetch the types your company is entitled to from GET /api/v2/analyses/reference/common/dataset-types - a type not enabled for your account is rejected with 422.
start_datestring (Y-m-d)Yes for all except Cohorts and DemographicsWindow start date.
end_datestring (Y-m-d)Yes for all except Cohorts and DemographicsWindow end date.
signal_providersstring[]Yes (all types except Cohorts and Demographics)BID values identifying the signal source. Fetch valid values from GET /api/v2/analyses/reference/common/signal-providers.
languagesstring[]NoLanguage codes. Fetch valid values from GET /api/v2/analyses/reference/common/languages.
locationobjectcountries required (all types except Cohorts, AffinityTransactions and ProfileAttributes){ countries[], states[], cities[], dmas[], zipcodes[] } (string arrays). countries come from GET .../reference/common/countries; states cascade via GET .../reference/common/states; cities cascade via GET .../reference/common/cities; dmas (POI and Origin only) come from GET .../reference/common/dmas.

Every key in a dataset block must be one the block’s type defines (the common keys above plus the type’s own fields below). Any other key - a misspelling, a key from another type, or a filter the type does not have - is rejected with 422 naming the key, never silently ignored. The same applies inside location.

WebDomain fields:

start_date must fall within the last 45 days of available data: web data lands with a ~48-hour delay, so the window ends two days ago (UTC). Older visitation data is archived and unreadable - an earlier start_date is rejected with 422. The window rolls forward one day at UTC midnight.

FieldTypeRequiredDescription
iab_category_codesinteger[]One of iab_category_codes / web_domainsIAB category ids. Fetch valid values from GET .../reference/web/iab-categories (and .../web/iab-subcategories).
web_domainsstring[]One of iab_category_codes / web_domainsWeb domains to target. Domains must exist in the catalog - fetch valid values from GET .../reference/web/domains; a domain outside the catalog is rejected with 422.
web_ref_domainsstring[]NoReferrer domains to target. Fetch valid values from GET .../reference/web/ref-domains.
device_typesstring[]NoWeb device type names. Fetch valid values from GET .../reference/web/device-types.
device_makesstring[]NoWeb device make names. Fetch valid values from GET .../reference/web/device-makes.
device_osesstring[]NoWeb device OS names. Fetch valid values from GET .../reference/web/device-oses.
browsersstring[]NoWeb browser names. Fetch valid values from GET .../reference/web/browsers.
max_devices_per_ipintegerNoMatch strictness: how many devices may share one household/IP. 1 (very strict) to 5 (more reach). Defaults to 3 (recommended).

CTV fields:

FieldTypeRequiredDescription
ctv_vendor_namesstring[]NoCTV vendor names. Fetch valid values from GET .../reference/ctv/vendors.
ctv_content_type_namesstring[]NoCTV content type names. Fetch valid values from GET .../reference/ctv/content-types.
ctv_content_genre_namesstring[]NoCTV content genre names. Fetch valid values from GET .../reference/ctv/content-genres.
ctv_channel_namesstring[]NoCTV channel names. Fetch valid values from GET .../reference/ctv/channel-names.
iab_codesarrayNoIAB codes. Fetch valid values from GET .../reference/web/iab-categories.
ctv_device_typesstring[]NoCTV device type names. Fetch valid values from GET .../reference/ctv/device-types.
ctv_device_makesstring[]NoCTV device make names. Fetch valid values from GET .../reference/ctv/device-makes.
ctv_device_osesstring[]NoCTV device OS names. Fetch valid values from GET .../reference/ctv/device-oses.
ctv_connection_typesstring[]NoCTV connection type names. Fetch valid values from GET .../reference/ctv/connection-types.
ctv_ispsstring[]NoCTV ISP names. Fetch valid values from GET .../reference/ctv/isps.
ctv_seriesstring[]NoCTV series names. Fetch valid values from GET .../reference/ctv/series.

Cohorts fields:

FieldTypeRequiredDescription
cohort_idintegerYesA completed cohort id owned by your company. Fetch valid ids from GET .../reference/cohorts/get-cohorts, or create one from your own cloud file via Create Cohort. (No dates or location.)

Apps fields:

FieldTypeRequiredDescription
app_idsinteger[]At least one of categories / taxonomies / bundle_ids / app_idsApp ids to target. Fetch valid values from GET .../reference/apps/bundle-ids.
bundle_idsstring[]At least one of categories / taxonomies / bundle_ids / app_idsApp bundle ids to target. Fetch valid values from GET .../reference/apps/bundle-ids.
categoriesarrayAt least one of categories / taxonomies / bundle_ids / app_idsApp category ids. Fetch valid values from GET .../reference/apps/categories.
taxonomiesarrayAt least one of categories / taxonomies / bundle_ids / app_idsApp taxonomy ids. Fetch valid values from GET .../reference/apps/taxonomies.
device_osstring[]NoApp device OS values. Fetch valid values from GET .../reference/apps/os.
refineobjectNoPost-build refinement: keep only the most active devices. Permission-gated, single-dataset audiences only - see Refine.

Apps location supports countries only: sending location.states, location.cities, location.dmas, or location.zipcodes on an Apps dataset is rejected with 422.

POI fields:

Targets people by the points of interest they physically visited. The POI catalogs cascade: segments -> categories (?segments[]) -> brands (?categories[]) -> locations (?brands[]). Unknown POI category, brand and location ids are rejected with 422.

FieldTypeRequiredDescription
categoriesinteger[]At least one of categories / analysisdata / locationsPOI category ids, as a FLAT list of integers ([12, 13]). An object here, such as [{"id": 12, "brands": [3]}], is rejected with 422. Fetch valid values from GET .../reference/poi/categories (cascades from .../poi/segments).
analysisdatainteger[]At least one of categories / analysisdata / locationsPOI brand ids. This is the brand field: there is no brands key on a POI block, and brands are never nested inside categories. Fetch valid values from GET .../reference/poi/brands.
locationsarrayAt least one of categories / analysisdata / locationsPOI location identifiers, interpreted per location_identifier_type. Fetch candidates from GET .../reference/poi/locations.
location_identifier_typestringNoHow locations are interpreted: none, location_id, external_id, store_id, placekey, h3_index, or h3_index_integer.
location.countriesstring[]YesCountry codes (at least one). From GET .../reference/common/countries.
location.statesstring[]NoState codes. Cascade via GET .../reference/common/states.
location.citiesstring[]NoCity names. Cascade via GET .../reference/common/cities.
location.dmasstring[]NoDMA market labels. From GET .../reference/common/dmas.
location.zipcodesstring[]NoZIP codes. Cascade from cities via GET .../reference/common/zipcodes (paginated).
signal_providersstring[]YesBID values identifying the signal source (at least one). From GET .../reference/common/signal-providers.
time_limitsobjectNo{ process: boolean, start: 0-23, end: 0-23 }. Hour-of-day window applied only when process is true.
day_limitsobjectNo{ process: boolean, days: integer[] }. Day-of-week filter applied only when process is true; days use ISO numbering (1 = Monday .. 7 = Sunday).
distance_limitsobjectNo{ process: boolean, distance: number, unit: "miles" | "kilometers" }. Radius applied only when process is true.
refineobjectNoPost-build refinement: keep only the most active devices. Permission-gated, single-dataset audiences only - see Refine.

The console’s audience-level quality filters (anomalous devices, GPS-only signals, anomalous POIs, GPS decimals) are not exposed on this API and default to off.

AffinityTransactions fields:

Targets people by what they actually bought. The purchase catalogs cascade: categories -> sub-categories (?categories[]) -> brands (?categories[], ?subcategories[]). Unknown category, sub-category, brand and demographic values are rejected with 422.

Affinity purchase data is United States only. location.countries is optional here and is always stored as ["USA"]; sending any other country code is rejected with 422, as is location.dmas (the type reads states, cities and postal codes only).

Affinity purchase data lands one week at a time, and a completed week is only fully loaded about eleven days after it ends. end_date therefore cannot run past the most recent fully-settled week - the latest Sunday that is at least 11 days before today (UTC) - and a later date is rejected with 422. This boundary advances by one week automatically each Thursday, so the newest selectable end date moves forward on its own; there is no fixed cut-off to track.

FieldTypeRequiredDescription
categoriesinteger[]At least one of categories / brandsAffinity purchase category ids. Fetch valid values from GET .../reference/affinity-transactions/categories.
brandsstring[]At least one of categories / brandsAffinity brand id strings. Fetch valid values from GET .../reference/affinity-transactions/brands.
subcategoriesstring[]NoSub-category strings (merchant category descriptions) cascading from categories. Fetch valid values from GET .../reference/affinity-transactions/subcategories. Picked without any brands, they are resolved to the brands they cover.
incomesstring[]NoIncome bands. Fetch valid values from GET .../reference/affinity-transactions/incomes.
agesstring[]NoAge bands. Fetch valid values from GET .../reference/affinity-transactions/ages.
gendersstring[]NoGender values. Fetch valid values from GET .../reference/affinity-transactions/genders.
ethnicitiesstring[]NoEthnicity values. Fetch valid values from GET .../reference/affinity-transactions/ethnicities.
channelsstring[]NoPurchase channel: B&M (in-store) and/or ONLINE.
spend_minnumberNoMinimum total spend (USD) across the date window.
spend_maxnumberNoMaximum total spend (USD) across the date window.
txn_minnumberNoMinimum number of transactions across the date window.
txn_maxnumberNoMaximum number of transactions across the date window.
analysis_spend_frequencybooleanNoAlso compute the spend distribution for the built audience. Defaults to false.
analysis_transactions_frequencybooleanNoAlso compute the transaction-count distribution for the built audience. Defaults to false.
max_devices_per_ipintegerNoMatch strictness: how many devices each shopper may expand to. 1 (very strict) to 5 (more reach). Defaults to 3 (recommended).

An AffinityTransactions dataset block:

{
  "type": "AffinityTransactions",
  "start_date": "2025-01-01",
  "end_date": "2025-03-31",
  "signal_providers": ["BID001"],
  "categories": [1],
  "subcategories": ["Eating Places, Restaurants"],
  "brands": ["501"],
  "incomes": ["100k-150k"],
  "channels": ["B&M"],
  "spend_min": 50,
  "txn_min": 2,
  "max_devices_per_ip": 3,
  "location": { "states": ["CA"] }
}

Demographics fields:

Targets people by their household demographic attributes. The four dictionaries are flat - no cascade - and at least one of them must carry a selection. Unknown values are rejected with 422.

This type carries no date window and no signal providers: sending start_date, end_date or signal_providers on a Demographics dataset is rejected with 422. Its location supports countries only, so location.states, location.cities, location.zipcodes and location.dmas are rejected too.

FieldTypeRequiredDescription
gendersstring[]At least one of genders / ages / marital_statuses / incomesGender values. Fetch valid values from GET .../reference/demographics/genders.
agesstring[]At least one of genders / ages / marital_statuses / incomesAge ranges. Fetch valid values from GET .../reference/demographics/ages.
marital_statusesstring[]At least one of genders / ages / marital_statuses / incomesMarital status values. Fetch valid values from GET .../reference/demographics/marital-statuses.
incomesstring[]At least one of genders / ages / marital_statuses / incomesIncome ranges. Fetch valid values from GET .../reference/demographics/incomes.
location.countriesstring[]YesCountry codes (at least one). From GET .../reference/common/countries.

A Demographics dataset block:

{
  "type": "Demographics",
  "genders": ["F"],
  "ages": ["25-34", "35-44"],
  "incomes": ["100k-150k"],
  "location": { "countries": ["USA"] }
}

Deidentified fields:

Delivers the deidentified signals themselves for a country and date window, rather than a targeted device list - so instead of filters it takes fields: which signal fields the delivery carries.

fields selects output columns only. It does not filter rows: there is no device, OS or platform filter on this type (fields.userDetails: ["deviceos"] adds the OS column to the delivery, it does not restrict the delivery to an OS). A filter-shaped key such as deviceos is rejected with 422.

fields is an object keyed by group (geoLocation, advertising, userDetails, ipDetails, privacy, general). Every group is optional - send only the groups you want, or omit fields entirely for the default shape. Fetch the fields and the group each belongs to from GET .../reference/deidentified/fields; an unknown field, or a field sent under a group it does not belong to, is rejected with 422.

This type is delivered on its own: an audience whose dataset is Deidentified takes exactly one dataset block, so pairing it with a second one (and therefore an operator) is rejected with 422.

Its location supports countries only, so location.states, location.cities, location.zipcodes and location.dmas are rejected. When location.countries includes USA, the date window may cover at most two weeks per delivery; a longer window is rejected with 422.

FieldTypeRequiredDescription
fieldsobjectNoWhich signal fields the delivery carries, keyed by group. Fetch the fields and their groups from GET .../reference/deidentified/fields.
signal_providersstring[]YesBID values identifying the signal source (at least one). From GET .../reference/common/signal-providers.
start_datestring (Y-m-d)YesWindow start.
end_datestring (Y-m-d)YesWindow end. At most two weeks after start_date when location.countries includes USA.
location.countriesstring[]YesCountry codes (at least one). From GET .../reference/common/countries.

A Deidentified dataset block:

{
  "type": "Deidentified",
  "start_date": "2026-01-05",
  "end_date": "2026-01-18",
  "signal_providers": ["BID001"],
  "fields": {
    "geoLocation": ["latitude", "longitude"],
    "ipDetails": ["ipisp"],
    "general": ["d_utc"]
  },
  "location": { "countries": ["USA"] }
}

ProfileAttributes fields:

Targets people by the profile attributes they carry. profile_attributes is a list of attribute rows, each one a category, a key under that category, and the values of that key to match. Rows are combined with AND - a device must match every row.

The attribute catalogs cascade: categories -> keys (?category_ids[]) -> values (?category_ids[], ?key). Each row is checked at all three levels: an unknown category, a key that does not belong to the row’s category, or a value that does not belong to the row’s category and key is rejected with 422 naming the exact row.

location is not applied to this dataset type. Profile attribute data carries no geography, so the builder discards the whole location block. location.countries is therefore optional - it is still accepted, for backward compatibility with integrations written when it was required, but it never filters anything. location.states, location.cities, location.zipcodes and location.dmas are rejected outright.

Profile attribute data is delivered quarterly. start_date and end_date must fall inside the delivered window published by GET .../reference/profile-attributes/recency-limits; a date outside it is rejected with 422. The stored window is expanded out to whole quarters - start_date to the first day of its quarter and end_date to the last day of its quarter.

FieldTypeRequiredDescription
profile_attributesobject[]YesAttribute rows (at least one), combined with AND.
profile_attributes[].category_idintegerYesAn attribute category id. Fetch valid values from GET .../reference/profile-attributes/categories.
profile_attributes[].keystringYesAn attribute key under that category. Fetch valid values from GET .../reference/profile-attributes/keys with ?category_ids[].
profile_attributes[].value_idsinteger[]YesValue ids of that key (at least one). Fetch valid values from GET .../reference/profile-attributes/values with ?category_ids[] and ?key.
signal_providersstring[]YesBID values identifying the signal source (at least one). From GET .../reference/common/signal-providers.
start_datestring (Y-m-d)YesWindow start, inside the delivered window.
end_datestring (Y-m-d)YesWindow end, inside the delivered window.
location.countriesstring[]NoAccepted but never applied - this dataset has no geography. Safe to omit.

A ProfileAttributes dataset block (no location needed):

{
  "type": "ProfileAttributes",
  "start_date": "2026-04-01",
  "end_date": "2026-06-30",
  "signal_providers": ["BID001"],
  "profile_attributes": [
    { "category_id": 1, "key": "auto_intent", "value_ids": [10, 12] },
    { "category_id": 2, "key": "credit_band", "value_ids": [30] }
  ]
}

Origin fields:

Targets people by their home location - where a device originates - rather than by the places it visited. Each device’s home is resolved once per week and placed by point-in-polygon against the ZIP code and DMA boundaries, so every filter below narrows that resolved home location.

Its only filters are geographic: beyond the common signal_providers, dates and location, it defines no key of its own.

Its data is weekly - a device’s home is resolved once per week, and there is no day in the data - so a sub-week window cannot exist. Any dates are accepted, and the window is widened to the whole Monday-to-Sunday weeks it touches: Tuesday to Friday builds, and is stored as, that full week.

Origin data exists for a limited set of countries. Fetch the covered set from GET .../reference/common/countries?datasetType=Origin; a country outside it is rejected with 422.

FieldTypeRequiredDescription
signal_providersstring[]YesBID values identifying the signal source (at least one). From GET .../reference/common/signal-providers?dataType=Origin.
start_datestring (Y-m-d)YesWindow start. Widened back to the Monday of its week.
end_datestring (Y-m-d)YesWindow end, on or after start_date. Widened forward to the Sunday of its week.
location.countriesstring[]YesCountry codes (at least one) with Origin coverage. From GET .../reference/common/countries?datasetType=Origin.
location.statesstring[]NoState codes. From GET .../reference/common/states.
location.citiesstring[]NoCity names. From GET .../reference/common/cities.
location.dmasstring[]NoDMA labels exactly as returned by GET .../reference/common/dmas - the label string, never a numeric code.
location.zipcodesstring[]NoZIP codes. From GET .../reference/common/zipcodes.

An Origin dataset block:

{
  "type": "Origin",
  "start_date": "2026-08-31",
  "end_date": "2026-09-13",
  "signal_providers": ["BID001"],
  "location": {
    "countries": ["USA"],
    "states": ["CA"],
    "dmas": ["803 - Los Angeles, CA"]
  }
}

Refine

The optional per-dataset refine object refines the audience after it is built: devices are ranked by a behavioral metric and only a subset is kept - the top X% (percentile), everyone at or above a minimum event count (threshold), or the top N devices (rank). The refined audience keeps its full data shape; results_count and every downstream activation reflect the refined device set.

Refine is available on POI and Apps datasets, and only for single-dataset audiences - a refine block on any other dataset type, or on either dataset of a two-dataset audience, is rejected with 422.

Refine is a gated feature. It requires additional permissions that your Account Manager can enable for your account. If a refine block is present and the feature is not enabled, the request is rejected with 403 (never silently ignored). Omitting the block entirely requires nothing.

FieldTypeRequiredDescription
typestringYesHow the subset is selected: percentile (keep the top X% by the metric), threshold (keep devices with at least value events), or rank (keep the top value devices).
metricstringYesThe behavioral metric to rank devices by. POI: visit_count or visit_days. Apps: app_usage_count or app_usage_days.
valuenumberYesMeaning depends on type: the percentage to keep for percentile (greater than 0 and less than 100), the minimum event count for threshold, or the number of devices for rank (whole number, at least 1).
fraud_cutoff_percentileintegerNoDrop outlier devices above this activity percentile (1-100, e.g. 99) before the cut, so bot-like devices do not crowd out the subset you keep.
max_valueintegerNoUpper bound on the metric, threshold type only - keeps devices between value and max_value events. Rejected with 422 on the other types.

A refined POI dataset block:

{
  "type": "POI",
  "start_date": "2025-01-01",
  "end_date": "2025-03-31",
  "signal_providers": ["BID001"],
  "categories": [101],
  "location": { "countries": ["USA"] },
  "refine": {
    "type": "percentile",
    "metric": "visit_count",
    "value": 10,
    "fraud_cutoff_percentile": 99
  }
}

Crossvisitation

The optional top-level crossvisitation object narrows the audience to people who physically visited selected points of interest (POIs) within a date window and optional time-of-day and distance limits. It sits alongside datasets in the body and is available only when the request contains a POI dataset - a crossvisitation block on any other dataset type is rejected. When the block is present it carries the same requirements as a POI dataset: a date window (start_date / end_date), at least one country, and exactly one category.

Crossvisitation is a gated feature. It requires additional permissions that your Account Manager can enable for your account. If a crossvisitation block is present and the feature is not enabled, the request is rejected with 403 (never silently ignored). Omitting the block entirely requires nothing.

POI id sources. Pick the POI values from the read-only Dataset Types - POI catalogs: categories from GET .../reference/poi/categories, brands from GET .../reference/poi/brands, and locations from GET .../reference/poi/locations. (Creating and managing the underlying POI data itself is the separate My POI Data surface.)

FieldTypeRequiredDescription
start_datestring (Y-m-d)YesStart of the visitation window.
end_datestring (Y-m-d)YesEnd of the visitation window.
poi_levelbooleanNoResolve at the individual-POI level rather than the parent brand/category.
filtersstring[]NoQuality filters: any of anomalous_devices, gps_only, anomalous_pois.
categoriesinteger[]Yes (exactly one)A single POI category id (see above). The block requires exactly one category.
brandsinteger[]NoPOI brand ids (see above).
locationsarrayNoPOI location identifiers, interpreted per location_identifier_type.
location_identifier_typestringNoHow locations are interpreted: none, location_id, external_id, store_id, placekey, h3_index, or h3_index_integer.
locationobjectcountries requiredGeographic scope { countries[], states[], cities[], dmas[], zipcodes[] } - countries needs at least one entry, the rest are optional. countries come from GET .../reference/common/countries.
time_limitsobjectNo{ process: boolean, start: 0-23, end: 0-23 }. Hour-of-day window applied only when process is true.
day_limitsobjectNo{ process: boolean, days: integer[] }. Day-of-week filter applied only when process is true; days use ISO numbering (1 = Monday .. 7 = Sunday).
distance_limitsobjectNo{ process: boolean, distance: number, unit: "miles" | "kilometers" }. Radius applied only when process is true.

Frequency analyses

The optional top-level analyses object runs the frequency analyses as the audience builds - the same toggles the Audience Manager offers. Each one stores, for every device in the audience, the number of distinct days it was seen on its dataset:

FieldTypeRequiredDescription
frequencybooleanNotrue runs the Visitation Frequency analysis: distinct days a device was seen at the POI dataset’s points of interest. Requires a POI dataset.
frequency_day_partbooleanNoThe Visitation Frequency by Day part sub-option: true buckets the Visitation Frequency by hour of the day instead of by visit day. Requires frequency: true, and is not available when the request holds an Apps dataset. A day-part audience cannot be previewed (hours are not visit counts); its activation applies the Day Part filter instead.
apps_frequencybooleanNotrue runs the Apps Frequency analysis: distinct days a device used the Apps dataset’s apps. Requires an Apps dataset.
web_frequencybooleanNotrue runs the Web Frequency analysis: distinct days a device visited the WebDomain dataset’s domains. Requires a WebDomain dataset; the activation preview supports it on single-dataset WebDomain audiences.

Send the flavour that matches your dataset when you may later want to activate only the devices seen on a minimum number of days (“2+ visits”). The analysis stores the distinct-day histogram that Preview Activation sums and that the freq_min / freq_max filter of Create Activation applies. An audience built without a frequency analysis cannot be previewed or filtered by frequency, and none can be added after the build. A two-dataset audience may carry more than one flavour, exactly as in the Audience Manager, but the preview only resolves an audience that carries exactly one.

The frequency analyses are a gated feature. They require additional permissions that your Account Manager can enable for your account. If any of them is true and the feature is not enabled, the request is rejected with 403 (never silently ignored). Omitting the object, or sending false, requires nothing.

Each flavour needs its dataset. frequency needs a POI block, apps_frequency an Apps block and web_frequency a WebDomain block: a flavour sent without its dataset is rejected with 422 naming it, and so is frequency_day_part without frequency or next to an Apps block. Any other key under analyses is rejected with 422 naming it.

{
  "name": "Coffee shop visitors - January",
  "datasets": [
    {
      "type": "POI",
      "start_date": "2026-01-01",
      "end_date": "2026-01-31",
      "signal_providers": ["BID001"],
      "categories": [101],
      "location": { "countries": ["USA"] }
    }
  ],
  "analyses": { "frequency": true }
}

Data Stream Visualizations

An audience can generate a set of charts while it builds - visitation patterns, dwell time, demographics, CTV and web breakdowns and so on - which are then viewed in the Intuizi console on the audience’s Data Streams tab.

Opt in with the optional top-level datastreams array. It takes the same shape as the one on activations, so a client that already speaks one speaks both:

FieldTypeRequiredDescription
datastreams[].idintegerYesThe data stream id, from the reference catalog below.
datastreams[].visualizing_statusbooleanNotrue to generate this stream’s visualizations. Omitted or false means the stream is listed but not generated.
{
  "name": "Airport visitors - September",
  "datasets": [ { "type": "POI", "start_date": "2026-09-01", "end_date": "2026-09-10" } ],
  "datastreams": [
    { "id": 21, "visualizing_status": true },
    { "id": 14, "visualizing_status": true }
  ]
}

The rendered charts are not returned by this API. There is no endpoint that serves a visualization payload and no PDF export. datastreams controls what gets built, and the results are read in the console. While the charts are drawn, the audience reads 109 Visualizing data streams, before 105 and 104 Completed, so keep polling through it (see Status Codes).

Where the ids come from. List what you may use, scoped to the dataset you are about to build:

GET /api/v2/analyses/reference/common/datastream-visualizations?dataset_type=POI

The list is scoped to the caller: every public stream, plus the private ones assigned to your company. Streams without an active visualization are never listed. Each item carries id, slug, name, dataset_types and visual_count.

Mismatches are rejected, not dropped. A stream that does not apply to this audience’s dataset types is a 422 naming the stream and the types it does support - it is not silently ignored, because a stream built against the wrong dataset produces a broken chart rather than an empty one. An id you are not permitted to use is reported the same way as one that does not exist.

Cross Purchase

The optional top-level crosspurchase object runs the built audience against the affinity purchase data: the audience’s devices are matched into purchase transactions within your date window, scoped to the target categories, sub-categories and brands you select. It sits alongside datasets in the body. Because it runs on the finished audience, it is available with any dataset combination - one or two datasets, any type. The analysis results are surfaced in the Audience Manager alongside the audience.

Cross purchase is a gated feature. It requires additional permissions that your Account Manager can enable for your account. If a crosspurchase block is present and the feature is not enabled, the request is rejected with 403 (never silently ignored). Omitting the block entirely requires nothing.

Target value sources. Pick the target values from the read-only Transactions catalogs: target_categories from GET .../reference/affinity-transactions/categories, target_subcategories from GET .../reference/affinity-transactions/subcategories, and target_brands from GET .../reference/affinity-transactions/brands.

FieldTypeRequiredDescription
start_datestring (Y-m-d)YesStart of the purchase window.
end_datestring (Y-m-d)YesEnd of the purchase window. The range may cover at most 2 calendar months, and cannot run past the most recent fully-settled purchase week - the latest Sunday at least 11 days before today (UTC), which advances each Thursday. A later date is rejected with 422.
target_categoriesinteger[]At least one of target_categories / target_subcategories / target_brandsAffinity category ids to scope the analysis to.
target_subcategoriesstring[]At least one of target_categories / target_subcategories / target_brandsAffinity sub-category strings (verbatim values from the reference read).
target_brandsstring[]At least one of target_categories / target_subcategories / target_brandsAffinity brand id strings.

A crosspurchase block on a request body:

{
  "name": "Coffee visitors vs dining purchases",
  "datasets": [ { "type": "POI", "...": "..." } ],
  "crosspurchase": {
    "start_date": "2025-01-01",
    "end_date": "2025-02-28",
    "target_categories": [1],
    "target_brands": ["501"]
  }
}
Collect the ids and values these filters expect from the Dataset Types endpoints first, then pass them in here. Only WebDomain, CTV, POI and Origin read the full location block (POI and Origin also take location.dmas); Apps, Demographics, Deidentified and ProfileAttributes read location.countries only; AffinityTransactions is United States only and reads location.states, location.cities and location.zipcodes; Cohorts takes neither dates nor location, and Demographics takes no dates.

WebDomain windows roll: start_date must fall within the last 45 days of available data at the moment you send the request - substitute a current window for the dates below.

curl -X POST "https://console.intuizi.com/api/v2/analyses/audiences/create" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: <UNIQUE_KEY>" \
  -d '{
    "name": "US auto-intenders on tech sites",
    "datasets": [
      {
        "type": "WebDomain",
        "start_date": "2026-07-01",
        "end_date": "2026-07-28",
        "signal_providers": ["BID001"],
        "iab_category_codes": [1, 4],
        "web_domains": ["example.com"],
        "device_types": ["Mobile"],
        "browsers": ["Chrome"],
        "languages": ["en"],
        "location": { "countries": ["USA"] }
      }
    ]
  }'

Response

The create response is the freshly queued audience (status Initiating, results_count 0).

{
  "status": "success",
  "code": 201,
  "message": "Resource created successfully.",
  "data": [
    {
      "id": 88,
      "name": "US auto-intenders on tech sites",
      "status": { "id": 100, "name": "Initiating" },
      "is_cohort": false,
      "is_lookalike": false,
      "results_count": 0,
      "created_at": "2025-01-01 12:00:00"
    }
  ]
}

Idempotency

The optional Idempotency-Key header makes a create safe to retry. The key is caller-generated: any unique string up to 255 characters (a UUID v4 is typical), one per logical create - reuse it only when retrying that same request. The first request with a given key runs normally and the successful (2xx) response is cached per caller. A retry with the same key and the same body replays the stored response verbatim with an Idempotency-Replayed: true header, so no duplicate audience is created. A retry with the same key but a different body returns 409 Conflict. See Idempotency for the full replay semantics and the eight endpoints that honor the header.

List Audiences

GET /api/v2/analyses/audiences/index

Lists the audiences owned by the authenticated user’s company, most recent first, paginated.

Auth: bearer token + Accept: application/json. Rate limit: read bucket (120 requests/min).

Query parameters

FieldTypeRequiredDescription
per_pageintegerNoItems per page. Defaults to 25, capped at 100.
pageintegerNoPage number (standard pagination).
searchstringNoOptional free-text filter on the audience name (case-insensitive contains).
curl "https://console.intuizi.com/api/v2/analyses/audiences/index?per_page=25" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Accept: application/json"

Response

{
  "status": "success",
  "code": 200,
  "message": "Resources fetched successfully.",
  "data": {
    "items": [
      {
        "id": 88,
        "name": "Coffee Buyers NYC",
        "status": { "id": 104, "name": "Completed" },
        "is_cohort": false,
        "is_lookalike": false,
        "results_count": 482311,
        "is_activation_allowed": true,
        "eligibility": {
          "allowed": true,
          "reasons": [],
          "metrics": {"unique_eids": 482311, "unique_scids": null, "eid_scid_ratio": null, "is_affinity": false}
        },
        "totals": {"uniques": 482311, "visits": 1203440, "avg_uniques": 16077, "avg_visits": 40114},
        "source_audience": null,
        "created_by": { "name": "Jane Doe", "email": "jane.doe@acme.example" },
        "project": { "id": 4, "name": "Retail 2025" },
        "operator": "AND",
        "dataset": [
          { "analysis_type": "WebDomain", "start_date": "01/01/2025", "end_date": "03/31/2025" },
          { "analysis_type": "Apps", "start_date": "01/01/2025", "end_date": "03/31/2025" }
        ],
        "created_at": "2025-01-01 12:00:00",
        "updated_at": "2025-01-10 09:30:00"
      }
    ],
    "pagination": {
      "current_page": 1,
      "per_page": 25,
      "total": 1,
      "last_page": 1
    }
  }
}

Get Audience

GET /api/v2/analyses/audiences/{id}

Retrieves a single audience by id.

The same audience is also readable at GET /api/v2/my-data/audiences/{id} for backward compatibility. The two responses differ by two fields: this /analyses/audiences/{id} read includes the operator field (the two-dataset combination mode) and totals (the flat metric whitelist), while the /my-data/audiences/{id} read has neither - it returns eligibility but not totals.

Auth: bearer token + Accept: application/json. Rate limit: read bucket (120 requests/min).

Path parameters

FieldTypeRequiredDescription
idintegerYesThe audience id to fetch.
curl "https://console.intuizi.com/api/v2/analyses/audiences/88" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Accept: application/json"

Response

created_by is always an object (empty {} when no creator resolves), never null. is_lookalike is true when this audience is the result of a Lookalike Model run - false for every ordinarily-built audience. is_activation_allowed is the verdict of the activation eligibility engine - the same gates the console UI, the activation endpoints and the scheduler apply:

Gate (reasons[].code)Rule
minimum_devicesat least 500 unique devices (1,000 for lookalike outputs)
affinity_device_coverageaudiences containing AffinityTransactions data: unique EIDs must exceed 2x unique SCIDs
scid_count_unavailableAffinity audience built before SCID totals were stored - duplicate and rebuild it
audience_expireda notice, not a block: standard audiences whose latest dataset end date is older than 90 days cannot be delivered as MAIDs or IPs (mapping keys are retained for 90 days). blocks_identifiers = ["MAID", "IP"]; activation with an EID / SCID / HEM pricing model is allowed, a MAID or IP pricing model is rejected with 422. Affinity, lookalikes and cohorts are exempt

When blocked, eligibility.reasons[] carries the code, a human message, the threshold used and the observed aggregate counts (for Affinity: unique_eids, unique_scids, eid_scid_ratio, required_unique_eids). eligibility.notices[] has the same shape plus blocks_identifiers: rules that only apply to some output identifiers. They leave allowed true; the activation create rejects a pricing model whose identifiers fall in blocks_identifiers. eligibility.metrics always returns unique_eids, unique_scids (null when the audience has no Affinity data), eid_scid_ratio and is_affinity. totals is the same metric whitelist the console shows (keys vary by dataset type, e.g. uniques, scids, transactions, amount, visits, signals, unique_eips). Only aggregates are returned - never raw SCIDs or device identifiers. dataset is a trimmed summary with one entry per dataset block (one or two entries). A Cohorts entry also carries cohort, the cohort it reads. operator carries the combination mode for a two-dataset audience (AND, OR, or NOTIN), and is null for a single-dataset audience.

Two fields say what an audience was built from, so you can follow it by id instead of by name:

  • source_audience - the seed audience a Lookalike Model was built from (the source_audience_id it was created with). null for every other audience.
  • dataset[].cohort - on a Cohorts entry, the cohort it reads. Get Cohort then says how that cohort was created (source) and, for one built from an audience, which audience (source_audience).

Each is { "id", "name" }, or null when the audience or cohort it points to has been deleted or does not belong to your company - so an id you get here is always one you can fetch.

"source_audience": null,
"operator": "AND",
"dataset": [
  { "analysis_type": "Cohorts", "start_date": "", "end_date": "", "cohort": { "id": 42, "name": "Loyalty program members" } },
  { "analysis_type": "CTV", "start_date": "01/27/2026", "end_date": "07/27/2026" }
]

The read returns the datasets and operator only. A crossvisitation block or an analyses object sent on create is not echoed back here - they live outside the public dataset shape and do not round-trip on read.

recipe_hash and normalized_payload are the canonical recipe stamped at create time: the same hash a prior Estimate Audience Size call returned for the identical payload, and the normalized body it was computed from. Both are null for audiences created in the console UI or before this field existed.

{
  "status": "success",
  "code": 200,
  "message": "Resource fetched successfully.",
  "data": [
    {
      "id": 88,
      "name": "Coffee Buyers NYC",
      "status": { "id": 104, "name": "Completed" },
      "is_cohort": false,
      "is_lookalike": false,
      "results_count": 482311,
      "is_activation_allowed": true,
      "eligibility": {
        "allowed": true,
        "reasons": [],
        "metrics": {"unique_eids": 482311, "unique_scids": null, "eid_scid_ratio": null, "is_affinity": false}
      },
      "totals": {"uniques": 482311, "visits": 1203440, "avg_uniques": 16077, "avg_visits": 40114},
      "source_audience": null,
      "created_by": { "name": "Jane Doe", "email": "jane.doe@acme.example" },
      "project": { "id": 4, "name": "Retail 2025" },
      "operator": "AND",
      "dataset": [
        { "analysis_type": "WebDomain", "start_date": "01/01/2025", "end_date": "03/31/2025" },
        { "analysis_type": "Apps", "start_date": "01/01/2025", "end_date": "03/31/2025" }
      ],
      "recipe_hash": null,
      "normalized_payload": null,
      "created_at": "2025-01-01 12:00:00",
      "updated_at": "2025-01-10 09:30:00"
    }
  ]
}

Estimate Audience Size

POST /api/v2/analyses/audiences/estimate

Answers “how many devices would this audience hold?” without creating an audience. The request body is identical to Create Audience - same fields, same validation, same 422 responses - and the estimate runs the same build pipeline, so the numbers match what a create with this payload would produce. Nothing appears in the Audience Manager and no export, cohort, schedule, or activation is triggered.

The estimate is asynchronous and takes roughly as long as a real audience build. Poll GET /api/v2/analyses/audiences/estimate/{id} until status is completed, blocked, or failed.

Because it runs the same build, an estimate scans the same data a create would and counts toward your company’s monthly data-scan limit, reported under the estimate operation type on Usage. When the limit has been reached the call is refused with the same 422 a create receives, before anything is queued.

The response carries recipe_hash: a canonical hash of the datasets + operator recipe. Creating an audience with the identical payload stamps the same hash on the audience (returned by Get Audience), proving the created audience matches the estimated recipe. The name and project_id are not part of the hash - renaming does not invalidate an estimate.

Auth: bearer token + Accept: application/json + Content-Type: application/json. Rate limit: write bucket (30 requests/min). Optional: Idempotency-Key header (see below).

Body

The body of Create Audience, unchanged: name and datasets required, operator required for two dataset blocks, optional project_id and analyses (checked exactly as on create; an estimate never runs an analysis, and the flags change neither the estimate nor its recipe_hash). Every dataset block rule on this page applies verbatim.

curl -X POST "https://console.intuizi.com/api/v2/analyses/audiences/estimate" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Coffee Buyers NYC (probe)",
    "datasets": [{ "type": "Cohorts", "cohort_id": 7 }]
  }'

Response

201 with the queued estimate. estimate is null until the run completes.

{
  "status": "success",
  "code": 201,
  "message": "Resource created successfully.",
  "data": [
    {
      "id": 12,
      "status": "pending",
      "name": "Coffee Buyers NYC (probe)",
      "recipe_hash": "sha256:5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8",
      "normalized_payload": {
        "name": "Coffee Buyers NYC (probe)",
        "operator": "Single",
        "datasets": [{ "cohort_id": 7, "type": "Cohorts" }]
      },
      "estimate": null,
      "status_message": null,
      "project_id": null,
      "created_at": "2026-08-24 12:00:00",
      "updated_at": "2026-08-24 12:00:00"
    }
  ]
}

Get Audience Estimate

GET /api/v2/analyses/audiences/estimate/{id}

Retrieves one size estimate with its status and, once completed, the numbers.

status walks pending -> processing -> one of three terminal states: completed (the estimate object holds the numbers), blocked (the recipe cannot be answered - estimate.blocked is { code, reason }, e.g. OUT_OF_COVERAGE with the available date window), or failed (status_message explains).

On completed, estimate carries: uniques (approximate distinct device count - the same counting method real audience totals use, with a standard error of about 2.3%), visits / signals / unique_eips where the dataset types produce them, the full totals row a create would have shown, providers (signal providers present in the result), as_of (when the numbers were computed), query_metrics (runtime and data scanned), method and exact (how the count was produced), and the echoed canonical recipe_hash.

Auth: bearer token + Accept: application/json. Rate limit: read bucket (120 requests/min).

Path parameters

FieldTypeRequiredDescription
idintegerYesThe estimate id from Estimate Audience Size.
curl "https://console.intuizi.com/api/v2/analyses/audiences/estimate/12" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Accept: application/json"

Response

{
  "status": "success",
  "code": 200,
  "message": "Resource fetched successfully.",
  "data": [
    {
      "id": 12,
      "status": "completed",
      "name": "Coffee Buyers NYC (probe)",
      "recipe_hash": "sha256:5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8",
      "normalized_payload": {
        "name": "Coffee Buyers NYC (probe)",
        "operator": "Single",
        "datasets": [{ "cohort_id": 7, "type": "Cohorts" }]
      },
      "estimate": {
        "uniques": 482311,
        "visits": 1203440,
        "signals": null,
        "unique_eips": null,
        "number_of_days": 30,
        "method": "approx_distinct",
        "exact": false,
        "as_of": "2026-08-24T12:34:56Z",
        "providers": ["<provider-bid>"],
        "query_metrics": { "total_queries": 9, "total_data_scanned_bytes": 1073741824, "total_runtime_ms": 412000 },
        "canonical_hash": "sha256:5e884898da28047151d0e56f8dc6292773603d0d6aabbdd62a11ef721d1542d8",
        "totals": { "uniques": 482311, "visits": 1203440 },
        "blocked": null
      },
      "status_message": null,
      "project_id": null,
      "created_at": "2026-08-24 12:00:00",
      "updated_at": "2026-08-24 12:07:00"
    }
  ]
}

A blocked estimate keeps status: "blocked" and explains itself:

{
  "estimate": {
    "uniques": null,
    "blocked": {
      "code": "OUT_OF_COVERAGE",
      "reason": "No POI signal data is available for 2020-01-01..2020-02-01. POI data is available 2024-01 to 2026-07. Adjust the date range to overlap the available window."
    }
  }
}

Delete Audience

POST /api/v2/analyses/audiences/delete-by-id

Soft-deletes an audience and queues the downstream cleanup.

Auth: bearer token + Accept: application/json + Content-Type: application/json. Rate limit: write bucket (30 requests/min).

Body

FieldTypeRequiredDescription
idintegerYesThe audience id to delete. Must be owned by your company.
curl -X POST "https://console.intuizi.com/api/v2/analyses/audiences/delete-by-id" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "id": 88 }'

Response

{
  "status": "success",
  "code": 200,
  "message": "Resource deleted successfully.",
  "data": []
}

Create Lookalike Audience

POST /api/v2/analyses/audiences/create-lookalike

Builds a Lookalike Model from a completed seed audience. The result is a new audience (is_lookalike: true) that goes through the normal polling lifecycle - poll GET /api/v2/analyses/audiences/{id} for its status. Lookalike Models are a gated feature: accounts without the capability receive 403 - it requires additional permissions which need to be approved by your Account Manager. The seed audience must be a Completed audience owned by your company, must not itself be a lookalike, and must hold at least 1,000 devices by default.

Auth: bearer token + Accept: application/json + Content-Type: application/json. Rate limit: write bucket (30 requests/min by default). Optional: Idempotency-Key header (see Idempotency).

Body

FieldTypeRequiredDescription
namestringYesName of the Lookalike Model and its result audience.
source_audience_idintegerYesThe seed audience id this model learns from. Must be owned by your company, Completed, not itself a lookalike, and hold at least 1,000 devices by default.
configobjectYesModel configuration - see the fields below.
config.target_sizeintegerYesHow many devices the output audience should contain. 1 to 4,000,000 by default.
config.geo.countriesstring[]YesCountries the candidate universe is restricted to (at least one). Candidates come from Origin data, which covers only some countries, and the create accepts any country code: a run in which none of the countries has Origin data fails after it is created, and when only some do, the others are left out of the model without an error. Start from the Origin list, GET .../reference/common/countries?datasetType=Origin.
config.geo.statesstring[]NoStates the candidate universe is restricted to.
config.signalsstring[]YesData families the model learns from (at least one): poi, apps, demographics, transactions, profile_attributes. They do not all describe the same thing - see Data families below. (web and ctv are withdrawn; requests naming them are rejected with 422.)
config.exclude_seed_devicesbooleanYesWhen true, the seed audience’s own devices are removed from the output audience.
config.contrast_audience_idintegerNoA second completed audience used as negative examples the model contrasts against. Must belong to your company, be Completed, not be a lookalike, and differ from source_audience_id. Omit for an automatic geo-matched sample.
config.expand_eidsbooleanYesWhen true, each output device is expanded across its linked identifiers.

Data families

The families differ in what they observe and over what period. Both matter when you read a model’s results, so they are worth knowing before you choose.

FamilyWhat it observesGrainWindow
poiPhysical visits to placesDeviceLast full calendar month
appsMobile app usageDeviceLast full calendar month
demographicsAge, income, gender, marital statusDeviceCurrent state, no window
transactionsCard transaction behaviourDeviceOne finalized calendar month
profile_attributesHousehold/person profile of the device’s ONE primary person, read from two catalogs at once: the AA consumer layer (household income and net worth, investments, home ownership, dwelling, education, generation, marital status, household composition, occupation) and the Vision Marketing layer (age band, household size, income band, home ownership and value, education, children, lifestyle flags) - one person per deviceDeviceCurrent state, latest quarterly profile refresh
webWeb browsing (withdrawn; models built before 2026-08-29 still report it)HouseholdTrailing 7 complete days

web is household-derived, which is the one asymmetry to keep in mind. Browsing is observed against a household’s IP address and attributed to the devices in that household, capped at the few devices most associated with the address. A device’s web activity therefore means “browsing seen at this device’s household”, not “browsing done by this device”. Every other family is observed on the device itself.

web also reads a trailing 7 days rather than a calendar month, because browsing is a recency signal. Two families in one model can describe different periods.

Selecting more families is not automatically better. A family only helps when the seed audience’s own devices are covered by it, and coverage varies a great deal between audiences. The completed model reports how much of each cohort each family actually reached, so you can see what a given run drew on.

Reading a completed model back returns a feature_families object recording exactly that:

"feature_families": {
  "registry_version": "2026-08-27.1",
  "included": [
    {
      "name": "web",
      "period": "2026-08-21..2026-08-27",
      "coverage": {
        "seed": 28.85,
        "candidates": 60.2,
        "devices_with_signal": 978047
      }
    }
  ]
}

period is the exact date range the family read, which is what makes a run reproducible for families whose window moves. Families measured over a fixed calendar month omit it - the table above already says what window each family uses.

coverage reports the share of your seed devices and of the candidates (the pool the model scored) that carried the family’s signal. The percentages are the useful part when a model underperforms: a family that reached only a small share of your seed had little to learn from, whatever its coverage of the wider candidate pool. feature_families is null for audiences that are not lookalike models, and for models created before this was recorded.

The read also names the seed the model was built from, so you can read the seed back with Get Audience - for example to see which datasets and date windows it holds:

"is_lookalike": true,
"source_audience": { "id": 14988, "name": "Coffee Buyers NYC" }

| notification | boolean | No | Whether to send an email on completion. Defaults to true. |

curl -X POST "https://console.intuizi.com/api/v2/analyses/audiences/create-lookalike" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Idempotency-Key: <UNIQUE_KEY>" \
  -d '{
    "name": "API Lookalike",
    "source_audience_id": 14988,
    "config": {
      "target_size": 100000,
      "geo": { "countries": ["USA"], "states": [] },
      "signals": ["poi", "apps"],
      "exclude_seed_devices": true,
      "contrast_audience_id": null,
      "expand_eids": false
    }
  }'

Response

The create response is the freshly queued result audience (status Initiating).

{
  "status": "success",
  "code": 201,
  "message": "Resource created successfully.",
  "data": [
    {
      "id": 15021,
      "name": "API Lookalike",
      "status": { "id": 100, "name": "Initiating" },
      "is_lookalike": true,
      "source_audience_id": 14988
    }
  ]
}

Cancel Lookalike

POST /api/v2/analyses/audiences/cancel-lookalike

Requests cooperative cancellation of an in-flight Lookalike Model run: the job checks the cancellation flag at its next checkpoint and stops there rather than being killed immediately. A finished run cannot be cancelled. Until the run reaches that checkpoint the audience keeps reading 108 Modeling. When it stops, the audience ends at 400 Error, which is final and never reaches 104, and an audience.failed webhook is sent. Audience Manager shows the status as Cancelled on request. A cancel that arrives once the result is already being published is ignored, and the run completes at 104.

Auth: bearer token + Accept: application/json + Content-Type: application/json. Rate limit: write bucket (30 requests/min by default).

Body

FieldTypeRequiredDescription
idintegerYesThe lookalike audience id to cancel - the id returned by Create Lookalike Audience.
curl -X POST "https://console.intuizi.com/api/v2/analyses/audiences/cancel-lookalike" \
  -H "Authorization: Bearer <YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{ "id": 15021 }'

Response

{
  "status": "success",
  "code": 200,
  "message": "Cancellation requested.",
  "data": []
}