Ads

Ads

Create, boost and measure campaigns on nine ad networks with one set of endpoints, from Meta and Google to LinkedIn, TikTok, ChatGPT and Whop.

Pozy runs paid campaigns on nine ad networks through one set of /v1/ads endpoints. You connect an ad account once, then create campaigns, boost posts, build audiences, send conversions and read spend with the same request shapes everywhere. Each network keeps its own rules, and the pages in this section say where they differ.

#Supported networks

Network Account platform platform on ad endpoints Connect with
Meta Ads (Facebook, Instagram, Messenger, Threads, WhatsApp placements) metaads facebook or instagram OAuth, classic or business login
Google Ads (Search, Display, Performance Max, Demand Gen) googleads google OAuth
TikTok Ads tiktokads tiktok OAuth
LinkedIn Ads linkedinads linkedin OAuth, reuses the LinkedIn token when one is connected
Pinterest Ads pinterestads pinterest OAuth, reuses the Pinterest token
X Ads xads twitter OAuth, created from a connected X account
Reddit Ads redditads reddit OAuth
ChatGPT Ads openaiads openai API key from ChatGPT Ads Manager

An ad connection is its own connected account with its own accountId. It sits in a profile next to the posting accounts, and it counts once toward pricing however many ad accounts it can reach.

Reddit

Organic Reddit publishing is paused, but Reddit Ads is a separate connection and works normally.

#How the pieces fit

Every network nests ads in three levels. Pozy uses the same three names for all of them, and maps each one to the network's own object.

Pozy level Id field on an ad Meta Google TikTok LinkedIn X
Campaign platformCampaignId Campaign Campaign Campaign Campaign group Campaign
Ad set platformAdSetId (adSetId) Ad set Ad group Ad group Campaign Line item
Ad platformAdId, plus Pozy's _id Ad Ad (or asset group on Performance Max) Ad Creative Promoted post

A few more objects show up around them:

  • Ad account (adAccountId): the account the network bills, such as act_1234567890 on Meta or a customer id on Google. One connection can reach many.
  • Creative: the headline, body, media, call to action and link. On Meta you can build one on its own and reuse it with existingCreativeId.
  • Audience: a list of people you upload or a segment the network builds for you. See Audiences.

POST /v1/ads/create builds the whole tree in one call. POST /v1/ads/boost wraps an organic post in the same tree. GET /v1/ads/tree reads it back with metrics rolled up per level.

#Connect an ad account

#Start the connection

Call GET /v1/connect/{platform}/ads with the profileId. platform is one of facebook, instagram, linkedin, tiktok, twitter, pinterest, googleads or redditads. ChatGPT Ads connects with an API key instead, through POST /v1/connect/openai-ads/credentials.

curl "https://api.pozy.ai/v1/connect/googleads/ads?profileId=66b2e19d8c3f5a7e9d0b1c2a&redirect_url=https://app.example.com/ads/connected" \
  -H "Authorization: Bearer $POZY_API_KEY"

The first time, the response carries an authUrl. Open it in a browser. When the user finishes, they land on your redirect_url. LinkedIn and Pinterest skip this step when the profile already has a posting account with the ads permissions.

#Read the connection

Call the same endpoint again. It now answers alreadyConnected: true with the accountId of the ad connection. Branch on that field rather than on the URL.

#Pick an ad account

Call GET /v1/ads/accounts?accountId=... to list the ad accounts the connection reaches. Each accounts[].id is the adAccountId every other ads call takes.

adAccountId or adAccountIds on the connect call limit the sync to the ad accounts you name. The full flow, with hosted and headless options, is in Connecting accounts.

#What each network supports

Capability Meta Google TikTok LinkedIn Pinterest X Reddit ChatGPT
Create a campaign Yes Yes Yes Yes Yes Yes Yes Yes
Boost an existing post Yes – Yes (Spark Ads) Yes Yes Yes Yes –
Pause, resume, change budget Yes Yes Yes Yes Yes Yes Yes Yes
Edit targeting after launch Yes Campaign-level Yes Yes – – Yes –
Swap the creative on a live ad Yes Search text Yes New media – – – –
Duplicate a campaign Yes – Yes Yes – – – –
Targeting search Yes Yes Yes Yes Interests Yes Yes – (countries only)
Reach estimate or forecast Yes – – Yes Yes Yes – –
Audiences Yes Customer Match Yes Yes Yes Yes Target only –
Conversions API Yes Yes Yes Yes Yes – Yes Yes
Pixels and tags Yes Google tag Yes Insight Tag Yes Yes – Yes
Lead forms Yes – – Yes – – – –
Product catalogs Yes – – – – – – –
Automated rules Yes Yes Yes Yes Yes Yes Yes –
Reporting Yes Yes Yes Yes Yes Yes Yes Yes
Demographic breakdowns Per ad and campaign – Per ad Firmographics – – – –

A field a network cannot honor is rejected at create time with a 400 that names it. Pozy never drops a field quietly.

#Money and units

  • Budgets and bids are whole units of the ad account's currency: 75 on a USD account is $75.00. Never cents, never micros.
  • Each campaign node reports its currency. Pozy never converts between currencies, so do not add spend across ad accounts that bill differently.
  • Raw reports from a network (Google GAQL rows, Keyword Planner, Meta live insights) keep that network's units. Google's micros, for example, divide by 1,000,000.

#Reviews and statuses

Every network reviews ads before they deliver. A successful create means the ad exists, not that it runs. Each ad carries three separate fields:

Field Answers Values
status Is it delivering? active, paused, pending_review, rejected, completed, cancelled, error
configuredStatus What did you set on this ad? ACTIVE, PAUSED
reviewStatus What did the network's review decide? in_review, approved, rejected, with_issues

status inherits from parents: an active ad under a paused campaign reads paused. Deleted ads stay in the tree as cancelled, so their past spend keeps counting.

#Retries

Ad creates and boosts are not idempotent on the networks' side. A blind retry after a timeout can launch a second campaign that spends. Send an Idempotency-Key header on every create, boost and duplicate, and reuse it on retries. See Idempotency.

#Pricing

Managed ads bill per active ad per month. The first 500 active ads in a workspace are free, then each costs $0.01 per month. Only ads that are running or in review count: paused, ended, rejected and deleted ads do not, and the count is metered daily, so pausing a campaign takes its ads off the meter the same day. There is no percentage of ad spend. The spend itself is billed by the network to the ad account's own payment method.

Active ads Monthly cost
400 Free
1,000 $5
5,000 $45
50,000 $495

See Pricing for every other meter and how they roll up on one invoice.

#Webhook events

Subscribe to these to react to reviews, delivery problems, budgets and new leads without polling. Payloads are in the events reference.

Event When it fires
account.ads.initial_sync_completed Ads initial sync completed.
account.ads.sync_failed Ads sync failed.
account.ads.sync_recovered Ads sync recovered.
lead.received Lead received.
ad.status_changed Ad status changed.
ad.review.approved Ad review approved.
ad.review.rejected Ad review rejected.
ad.delivery_issue Ad delivery issue.
campaign.budget.depleted Campaign budget depleted.
ad_account.status_changed Ad account status changed.
ad.video.processed Ad video processed.
ad_rule.triggered Ad rule triggered.

#Endpoints

The ads surface is large. These are the calls most integrations start with; each network page lists its own.

Endpoint What it does
GET /v1/connect/{platform}/ads Connect ads for a platform
GET /v1/ads/accounts List ad accounts
POST /v1/ads/create Create standalone ad
POST /v1/ads/boost Boost post as ad
GET /v1/ads/tree Get campaign tree
GET /v1/ads List ads
GET /v1/ads/{adId} Get ad details
PUT /v1/ads/{adId} Update ad
PUT /v1/ads/{adId}/status Pause or resume a single ad
PUT /v1/ads/campaigns/{campaignId}/status Pause or resume a campaign
GET /v1/ads/{adId}/analytics Get ad analytics
GET /v1/ads/timeline Get daily account metrics
GET /v1/ads/targeting/search Search targeting options
POST /v1/ads/audiences Create custom audience

The full list, grouped by tag, is in the API reference.