Connector
Meta Ads, split every way Meta will split it
Facebook and Instagram advertising from one ad account. Campaigns, ad sets and ads with spend, delivery and conversions — and the twenty separate readings that turn a day's total into an answer.
“Facebook Ads” is mostly Instagram
One ad account delivers across both, and on most accounts four impressions in five land on Instagram. That is the first thing the overview says, because it is the thing nobody checks.
It is also why the card carries more than one measure. The cheaper placement and the better-converting one are frequently not the same placement, and a share-of-impressions chart on its own would talk a reader into moving the budget the wrong way. Switch the measure and watch the order change.
Reach is missing from this card on purpose: reach counts people, so adding it across placements counts anyone who saw both once per row. The API returns it where Meta will divide it honestly and nowhere else.
One connection is one ad account
Underneath it: campaigns, ad sets and ads with Meta's own effective_status, plus insights at any of the four levels and the actions array unpacked into rows you can filter.
Entities
Campaigns, ad sets and ads — name, objective, status, and the parent that owns them.
Insights
One row per entity per day, at account, campaign, adset or ad level.
Actions
Conversions keyed by destination and attribution window, not a nested array you have to unpack.
Summary
Totals, a zero-filled daily series, and every split, computed over the whole range server-side.
$ curl "…/meta-ads/summary?account_id=…&breakdown_sets=all \
&date_from=2026-08-18&date_to=2026-09-16" \
-H "Authorization: Bearer pk_live_…"
{ "data": {
"totals": { "spend": 4182.55, "impressions": 1204885,
"clicks": 18422, "conversions": 612 },
"series": [ { "date": "2026-08-18", "spend": 121.40 }, … ],
"period": { "reach": 1628, "frequency": 2.4, "cpp": 2.56 },
"by_set": { "placement": [ … ], "age_gender": [ … ],
"hourly_audience": [ … ] } } }20 readings of every day
Meta will not combine most of these with each other — age cannot be requested alongside placement, country cannot be requested alongside region — so covering them means one request per set. Each is its own sync resource, so it checkpoints, throttles and fails on its own.
Delivery
5Where and how it ran
total
the undivided reading
placement
publisher_platform, platform_position
device
impression_device
device_platform
app, mobile web, desktop
product
product_id
Audience
5Who saw it
age_gender
age, gender
country
country
region
region
comscore_market
comscore_market
frequency
frequency_value
Time
2When it ran
hourly_advertiser
hour · account's clock
hourly_audience
hour · viewer's clock
Creative
8Which asset won
asset_title
headline
asset_body
primary text
asset_description
description
asset_image
image
asset_video
video
asset_call_to_action
button
asset_link_url
destination
asset_format
how Meta assembled it
Four ways this API will quietly lie to you
None of these throws an error. Each produces a number that looks plausible and is wrong, which is why they survive so long in homemade integrations.
Never sum across breakdown sets
Each of the 20 sets is a complete reading of the same days. Add two together and you have doubled the spend. The API keeps them separate and labelled, and /summary aggregates server-side so you never hand-total them.
Never sum reach
Reach is deduplicated per person, so somebody who saw the ad on both platforms is one reach on the total row and one on each platform row. Pullsy fetches period reach over the period itself and serves it separately, rather than adding up days and reporting a number that is simply wrong.
Past retention, Meta goes quiet
Most breakdowns answer for 37 months, the hourly splits for 13, frequency for 6. Past the edge Meta returns an empty 200 rather than an error — which looks exactly like an account that did not spend. Pullsy clamps the window before asking.
Some splits are partial, and say so
The creative asset sets only report delivery where Meta was free to vary that asset, and comScore markets are sampled. They are honest for ranking which headline won, and dishonest as a share of total spend — so the API marks which is which.
Organic Instagram too?
Posts, reels and account insights are a separate connector — the ads API has nothing to say about them.
Further reading
Longer-form writing on this API, from the connector that reads it.
Point it at a live ad account
Connect one account on the trial and compare what comes back with what Ads Manager shows you.

