> ## Documentation Index
> Fetch the complete documentation index at: https://docs.semicola.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Property lists and audiences

> Include and exclude lists of websites, apps and CTV apps, and first-party audiences, for an advertiser

A **property list** is a named list of typed identifiers (websites, mobile apps, CTV apps) owned
by one advertiser. Its `purpose` is `include` (only buy on these) or `exclude` (never buy on
these).

## How lists are enforced

Enforcement happens when products are selected: at discovery and when a campaign goes live.

* **Exclude lists** are enforced by Semicola. Products whose publisher website domain (or a
  subdomain of it) is on a list leave discovery, and a campaign that still has such a product
  staged won't go live; the error names each product and the list. App and CTV properties without
  a website domain aren't matched. A list with `filters.channels_any` applies only to products on
  those channels.
* **Include lists** go to sellers that declare property-list support in their capabilities, as
  `targeting_overlay.property_list` on every package of a media buy (and as `property_list` on
  discovery once the seller is known to support it). Sellers that don't declare support never
  receive it. Creating an include list, replacing its identifiers, or attaching it to a campaign
  re-sends it to the advertiser's live media buys (`cascadeSummary`); a failed buy is logged and
  doesn't undo the change.

The seller resolves the reference at `GET /lists/{listId}` on the API origin, with the bearer
token carried in the reference. The answer is the ADCP `GetPropertyListResponse` (paginated with
`max_results` and `cursor`; cache it for 24 hours).

## Identifiers and resolution

Pass `domains` (shorthand for `type: "domain"`), typed `identifiers`, or both: 1 to 100,000 per
request, canonicalized and deduplicated. Website domains always resolve. App and CTV identifiers
resolve when they appear on products this account has been offered; the rest come back in
`unresolvedIdentifiers` and won't target. Only resolved identifiers are stored, so the
unresolved list appears on the create or update response and not on later reads. Always check
`resolutionSummary`.

`PUT` replaces the whole identifier set (there is no incremental add or remove). `DELETE`
archives the list.

## Check before you commit

`POST /api/v2/buyer/property-lists/check` sorts candidates into `ok`, `modify` (canonicalized,
for example `www.` removed), `remove` (duplicates) and `assess` (manual review). Every app and
CTV identifier lands in `assess`. Semicola isn't connected to the AgenticAdvertising.org property
registry yet, so domains can't be registry-confirmed or registry-blocked: clean domains land in
`assess` too. Checks that include a domain return a `reportId`, readable for 7 days.

## Audiences

`POST /api/v2/buyer/advertisers/{advertiserId}/audiences/sync` adds members (an `externalId` plus
an email, a phone with its `+` country code, their SHA-256 hashes, or universal ids), removes
members by `externalId`, or deletes an audience. Raw email and phone are normalized and hashed
before anything is stored. The call returns `202` with a `taskId` for `GET /tasks/{taskId}`.
`uploadedCount` is the stored member count; `matchedCount` stays empty because matching happens at
the seller.

A campaign's `audienceConfig` (`targetAudienceIds`, `suppressAudienceIds`) adds audiences; with
`deleteMissing: true` it replaces the set. They reach sellers that declare audience targeting as
`audience_include` and `audience_exclude`.
