Ads

Audiences

Build customer lists, lookalikes, website, engagement and company audiences on each ad network, upload hashed members and target them.

An audience is a set of people you target or exclude. Some you fill yourself by uploading emails (customer lists). Others the network fills from a pixel, a seed list or engagement with your Page or videos. Create every type with POST /v1/ads/audiences, then put its platformAudienceId in audienceInclude or audienceExclude on a create.

#Upload a customer list

#Create the audience

curl -X POST https://api.pozy.ai/v1/ads/audiences \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "accountId": "66b2e19d8c3f5a7e9d0b1c2d",
    "adAccountId": "act_1234567890",
    "name": "Customers - last 12 months",
    "type": "customer_list",
    "description": "Paid at least once since November 2025"
  }'

Creates are not idempotent. Do not retry one automatically: list the audiences first to see whether it exists.

#Upload members

Send plaintext email (and on Meta, phone in E.164) per row, up to 10,000 rows per request.

Add users
curl -X POST https://api.pozy.ai/v1/ads/audiences/66e5b2c3d4f5a6b7c8d9e0f1/users \
  -H "Authorization: Bearer $POZY_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "users": [ { "email": "maria@example.com" }, { "email": "sam@example.org", "phone": "+14155551234" } ] }'
Response
{ "message": "Users added", "numReceived": 2, "numInvalid": 0 }

#Target it

Read platformAudienceId from GET /v1/ads/audiences?accountId=...&adAccountId=... and send it in audienceInclude or audienceExclude on POST /v1/ads/create.

#Hashing and matching

You send plain values. Pozy normalizes them (trims, lowercases emails, formats phones) and hashes them with SHA-256 before they leave Pozy, so the networks never receive raw contact details. You do not need to hash anything yourself.

Network Matches on Per request Upload behavior Notes
Meta Email and phone 10,000 Adds Remove people with DELETE /v1/ads/audiences/{audienceId}/users (Meta only).
Google (Customer Match) Email 10,000 Adds Matching takes 10 minutes to 24 hours. Google only serves a list once enough members match; upload at least 5,000.
TikTok Email 10,000 Adds Created on TikTok with the first upload. Takes up to 48 hours before it can be targeted.
LinkedIn Email 10,000 Replaces the whole list Every upload is the full list, so a contact list tops out at 10,000 members.
Pinterest Email 10,000 Adds Created on Pinterest with the first upload.
X (Tailored Audiences) Email 10,000 Adds Needs at least 100 matched active users before it can be targeted; size reads 0 until then.
Reddit – – – Build custom audiences in Reddit Ads Manager and target them by id. Creates return 422.
ChatGPT – – – No custom audiences.

A phone on a network that matches on email only is ignored. A row that cannot be read counts in numInvalid.

Consent

Only upload people who agreed to be contacted this way. Each network's terms for customer lists apply to you, and the hashed upload does not change that.

#Audience types

type on POST /v1/ads/audiences picks what the audience is built from.

type Network Built from Key fields
customer_list Meta, Google, TikTok, LinkedIn, Pinterest, X Emails (and phones on Meta) you upload customerFileSource on Meta
lookalike Meta People similar to a seed audience sourceAudienceId (the seed's platformAudienceId), country, ratio 0.01 to 0.2
website Meta Pixel visitors pixelId, retentionDays, optional urlContains or a raw Meta rule
meta_engagement Meta People who engaged with a Page, an Instagram account or a video engagementSource (page, instagram, video), sourceId, retentionDays 1 to 365, optional event
saved_targeting Meta A stored targeting spec, no members spec. Use it later as savedTargetingId.
company_list LinkedIn Companies by name, domain, website or Page URL companies (up to 300,000 rows, at least 1,000 recommended)
engagement LinkedIn People who engaged with ads, Pages or events sourceType, trigger, lookbackDays (30 to 365), engagementSources (up to 50)
website_retargeting LinkedIn Insight Tag visitors matching URL rules matchRules with matchType (EXACT, STARTS_WITH, CONTAINS, ENDS_WITH), up to 50 rules
tiktok_engagement TikTok People who engaged with your ads or videos source, sourceIds, identityId
pinterest_engagement Pinterest People who engaged with your Pins engagementType, pinIds

Using a type on the wrong network's account returns 422. Meta's meta_engagement and LinkedIn's engagement are different audiences with different fields.

#Lookalikes on Meta

Upload members to the seed list first, then create the lookalike from it. Meta builds it from the seed's matched members, so check the seed's size with GET /v1/ads/audiences/{audienceId} before you create. ratio: 0.01 is the closest 1% of the country.

Lookalike
{
  "accountId": "66b2e19d8c3f5a7e9d0b1c2d",
  "adAccountId": "act_1234567890",
  "name": "Lookalike 1% US - customers",
  "type": "lookalike",
  "sourceAudienceId": "23851234567890123",
  "country": "US",
  "ratio": 0.01
}

#LinkedIn company lists

Company lists target or exclude whole companies. Each row needs at least one of name, domain, website or linkedinPageUrl. LinkedIn matches rows against its company graph within 48 hours. To change the list, send the complete new list to POST /v1/ads/audiences/{audienceId}/companies: it replaces the old one.

#LinkedIn website retargeting

The audience fills only once the site has the LinkedIn Insight Tag installed and reporting visits (Pixels and tags). You can create it before the tag is live.

#Manage audiences

Job Call
List with size and status GET /v1/ads/audiences?accountId=...&adAccountId=...
Read one with fresh numbers GET /v1/ads/audiences/{audienceId}
Rename or edit PUT /v1/ads/audiences/{audienceId} (name and description; spec only on saved targeting)
Delete DELETE /v1/ads/audiences/{audienceId}

audience.id is Pozy's id, used in the paths above. platformAudienceId is the network's id, used in targeting and as a lookalike seed. Audiences build asynchronously on every network: a size or member read right after an upload can be empty. Read again after a minute instead of uploading again.

#Errors

Error Cause Fix
422 on /users The audience is not a customer_list (or is a LinkedIn company list) Upload rows only to customer lists. Company lists use /companies.
422 "Audience has no platform ID" The network has not accepted the audience yet Read it again and retry once platformAudienceId is set.
422 on create The type does not exist on that network Use a type from the table above.
400 with type: "platform_error" The network rejected a rule or source (for example an ineligible engagement source on Meta) Read the network's message in platformError.

#Endpoints

Endpoint What it does
GET /v1/ads/audiences List custom audiences
POST /v1/ads/audiences Create custom audience
GET /v1/ads/audiences/{audienceId} Get audience details
PUT /v1/ads/audiences/{audienceId} Update an audience
DELETE /v1/ads/audiences/{audienceId} Delete custom audience
POST /v1/ads/audiences/{audienceId}/users Add users to audience
DELETE /v1/ads/audiences/{audienceId}/users Remove users from audience
POST /v1/ads/audiences/{audienceId}/companies Replace audience companies