Facebook Ads Insights API: Fields, Breakdowns, Limits

By Mika ReyesPublished 5 min read

The short answer

The Facebook Ads Insights API is the insights edge on every Marketing API ad object: GET /act_{id}/insights, or the same edge on a campaign, ad set, or ad. Choose fields, a level, breakdowns, and a date_preset or time_range. Large queries run as async report runs. Data goes back 37 months, and Meta removed 7-day and 28-day view attribution in January 2026. Adeli returns daily spend per ad account in one call.

The Facebook Ads Insights API is the insights edge of Meta's Marketing API. You call GET /act_{ad-account-id}/insights, or the same edge on a campaign, ad set, or ad, and choose four things: the fields (metrics), the level to aggregate at, any breakdowns, and a date range. Big queries run as asynchronous report runs, data goes back 37 months, and Meta removed the 7-day and 28-day view attribution windows on January 12, 2026.

This guide covers each parameter, the async workflow, and the retention and rate limits that break reporting jobs. It's part of our Meta Ads API series, and it's about paid ads. For organic Page metrics, see the Facebook Page Insights API.

What do you need before you start?

  • A token with ad account access. Meta's Insights API guide lists ads_read. An app that holds ads_management can read the accounts it manages too.
  • An ad account ID in act_<digits> form, or the ID of a campaign, ad set, or ad.
  • Conversion tracking, if you want results beyond clicks. Purchases and leads only show up when the Meta Pixel, the Conversions API, or instant forms record them.

How do I call the Facebook Ads Insights API?

Send a GET to the insights edge of any ad object with a fields list. Without parameters, Meta returns basic metrics for roughly the last 30 days.

curl -G "https://graph.facebook.com/v26.0/act_$AD_ACCOUNT_ID/insights" \
  --data-urlencode "fields=campaign_name,spend,impressions,reach,clicks,ctr,cpm,actions" \
  --data-urlencode "level=campaign" \
  --data-urlencode "date_preset=last_7d" \
  --data-urlencode "access_token=$ACCESS_TOKEN"

The response has a data array with one row per object at the requested level, each with date_start and date_stop, plus cursor paging. Metric values come back as strings, so parse spend as a decimal before you add it up.

The four edges, from Meta's guide:

Edge Returns
/act_{ad-account-id}/insights The whole account, or any level below it with level
/{campaign-id}/insights One campaign
/{ad-set-id}/insights One ad set
/{ad-id}/insights One ad

How do level and breakdowns work?

level sets which object each row represents, and breakdowns split each row by a dimension such as age or placement. Use level on the account edge to get every campaign, ad set, or ad in one call instead of looping over IDs.

  • level takes account, campaign, adset, or ad.
  • breakdowns split rows by audience or delivery: age, gender, country, region, publisher_platform, platform_position, device_platform, and hourly options. Only some combinations work together; Meta's breakdowns page lists them.
  • action_breakdowns split the actions field, by action_type by default.
  • filtering keeps only rows that match, such as [{"field":"ad.impressions","operator":"GREATER_THAN","value":0}] to skip ads that never delivered.

Hourly breakdowns don't support unique fields: reach and frequency return 0 when you use them.

How do I set the date range?

Use date_preset for a relative window or time_range for exact dates, and time_increment to split the window into days. From the ad account insights reference:

Parameter Format Notes
date_preset today, yesterday, last_7d, last_28d, last_30d, last_90d, this_month, maximum, and more Default last_30d. Ignored if time_range is set.
time_range {"since":"2026-10-01","until":"2026-10-25"} Dates only, no Unix timestamps.
time_ranges A list of time_range objects One result set per range. Overrides the other three.
time_increment 1 to 90, monthly, or all_days 1 gives one row per day. Default all_days.

Insights are reported in the ad account's time zone, so "yesterday" depends on where the account is set, not where your server runs.

Which attribution windows still work?

The default attribution window is 7-day click plus 1-day view, and the 7-day and 28-day view windows return no data since January 12, 2026. Meta's out-of-cycle changelog announced the removal on October 13, 2025, for all API versions.

  • action_attribution_windows still accepts 1d_click, 7d_click, 28d_click, 1d_view, and 1d_ev (engaged view), among others.
  • use_unified_attribution_setting=true reports each ad set's own attribution setting, which is what Ads Manager shows. Since June 10, 2025, Meta applies this behavior to attributed values regardless of the parameter.

If your reports used 7d_view or 28d_view, conversion counts fell on January 12, 2026, when those windows started returning no data. Attribution also explains other mismatches with your own data:

"Ads Manager results can include multiple conversions by the same person." Jon Loomer, Meta ads consultant, How Meta Ads Attribution Works in 2026 (March 10, 2026)

Put that next to any conversion count you show your customers, so a figure higher than their CRM's doesn't read as an error.

How do async report runs work?

For large queries, POST to the same insights edge, poll the report run until it completes, then read its results. Meta recommends trying a synchronous call first and switching to async when it times out. The steps, from Meta's limits and best practices page:

  1. Start the job. POST /act_{id}/insights with the same parameters returns a report_run_id.
  2. Poll the run. GET /{report_run_id} until async_status is Job Completed and async_percent_completion is 100. Other statuses include Job Failed and Job Skipped, which means resubmit.
  3. Read the results. GET /{report_run_id}/insights, paging with the cursors.
curl -X POST "https://graph.facebook.com/v26.0/act_$AD_ACCOUNT_ID/insights" \
  -F "level=ad" \
  -F "fields=ad_id,spend,impressions,clicks,actions" \
  -F 'time_range={"since":"2026-01-01","until":"2026-09-30"}' \
  -F "time_increment=1" \
  -F "access_token=$ACCESS_TOKEN"

An async job can take up to an hour, and a report_run_id expires after 30 days, so don't store it as a permanent reference.

What are the data retention and rate limits?

Meta keeps 37 months of ads insights, less for some breakdowns, and throttles by app and by ad account. Plan your backfills and nightly syncs around these:

Limit Value
Overall history 37 months; older start dates return error 3018
Unique-count fields with breakdowns, hourly breakdowns 13 months
frequency_value breakdown 6 months
reach with breakdowns, older than 13 months Omitted from standard queries; async jobs allow 10 such requests per ad account per day
Freshness Refreshes every 15 minutes; final 28 days after reporting
Rate limit error Code 4; subcode 1504022 under heavy global load
Too much data in one call Code 100, subcode 1487534

Watch the x-fb-ads-insights-throttle header on every response. It reports app_id_util_pct and acc_id_util_pct, and Meta's advice is to back off well before either reaches 100. Its tips for the data-per-call error: shorten the date range, request fewer fields, and avoid account-level queries with high-cardinality breakdowns. Our Meta Ads API guide covers the access tiers that set these limits.

Is there a faster way to do this?

Adeli returns one row per day of spend, impressions, clicks, and conversions for a customer's ad account, or any campaign, ad set, or ad in it, from one call. Adeli holds the Meta app and its reviews and manages each customer's token, so you skip the permissions and throttle headers above. The endpoint is daily insights:

curl -G "https://app.tryadeli.com/api/v1/ads/insights" \
  -H "Authorization: Bearer $ADELI_API_KEY" \
  --data-urlencode "accountId=$ACCOUNT_ID" \
  --data-urlencode "adAccountId=act_1234567890" \
  --data-urlencode "objectId=120210000000000001" \
  --data-urlencode "since=2026-10-01" \
  --data-urlencode "until=2026-10-25"

Leave out objectId for the whole account, and leave out the dates for the last 28 days. For a dashboard, campaign tree returns every campaign, ad set, and ad with spend, impressions, reach, clicks, ctr, cpc, and cpm rolled up at each level, and an object that didn't deliver reports zeroes instead of disappearing.

Adeli stores no campaign structure or metrics, so every figure is as fresh as Meta's response. When Meta throttles an ad account, Adeli returns 429 rate_limited with a Retry-After header. The same API key reads organic analytics for Instagram, Facebook, TikTok, and YouTube, so paid and organic numbers can sit in one report. Pricing is per customer profile.

faq

Frequently asked questions

What is the difference between ads_read and ads_management for insights?

Meta's Insights guide lists ads_read as the permission for reading ad performance. The ads_management permission also covers reading the ad accounts a person can manage, so an app that already manages campaigns can read their insights with it. Both need Advanced Access for customers' ad accounts.

Why don't my Ads Insights API numbers match Ads Manager?

The usual causes are the attribution setting, the time zone, and freshness. Set use_unified_attribution_setting to true to use each ad set's attribution, compare in the ad account's time zone, and remember that recent days can still change, because Meta keeps updating insights for up to 28 days.

How often does Facebook ads insights data update?

Meta says insights refresh every 15 minutes and stop changing 28 days after they're reported. Metrics can keep moving for a couple of days after an ad finishes, so a nightly sync should re-read at least the last 28 days.

How far back can I query Facebook ads insights?

37 months. A time range that starts further back returns error 3018. Breakdowns of unique metrics and hourly breakdowns keep 13 months, and the frequency_value breakdown keeps 6 months.

Power your next project
with one ads & social media API

Give your users publishing, scheduling, and analytics through one integration your team can actually maintain.

Try with agents

Start with free credits. No credit card required.