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.

Measure
Where the impressions went
Instagram78%Facebook21%Messenger1%
Instagram feed184,220
Instagram Reels141,680
Facebook feed74,310
Instagram Stories68,940
Facebook video feeds21,480
Other placements (2)12,850

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": [ … ] } } }
breakdown_sets=all returns every split in one request, which is how a dashboard draws them without asking twenty times.

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

5

Where 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

5

Who saw it

  • age_gender

    age, gender

  • country

    country

  • region

    region

  • comscore_market

    comscore_market

  • frequency

    frequency_value

Time

2

When it ran

  • hourly_advertiser

    hour · account's clock

  • hourly_audience

    hour · viewer's clock

Creative

8

Which 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.

The Instagram connector

Point it at a live ad account

Connect one account on the trial and compare what comes back with what Ads Manager shows you.