Stored read: List insights
Gives aggregated metric rows for your organization: what an ad account, a campaign, an ad group or an ad spent over a date range, and what it returned.
Each row carries the metrics you name in select. The default metrics are spend and impressions. Each row also carries a currency.
A metric a provider does not report reads 0, and never null. Google Ads and OpenAI report no reach, so reach, cpp and frequency read 0 on every row of theirs. Compare those three inside one provider only.
Date range
A date range is required. Send since, and optionally until, both written YYYY-MM-DD. Or send relative: last_7_days, last_15_days or last_month. A request with neither is refused with 400 invalid_request.
Set interval to day, week or month to get one row for each period, each carrying a date. A week is dated by its Monday, a month by its first day. Omit interval to get one row for the whole range.
Filters and groups
advertiserId, entityId, entityType and provider are filters: they decide which rows are read. breakdown is separate: it decides how the rows are grouped, and which columns name the group.
| breakdown | Rows | Each row also carries |
|---|---|---|
| omitted | one, for everything that matched | nothing else |
| a concept | one for each entity of that level, at every provider | provider, advertiserId, entityId, type |
| provider | one for each ad platform | provider |
| advertiser | one for each ad account | provider, advertiserId |
| a provider entity type | one for each entity of that type | provider, advertiserId, entityId, type |
Concepts
A concept names one level with the same word at every provider. There are five: campaigns, ad-groups, ads, creatives and asset-groups, the names of the entity resources of this API.
| Concept | Meta | TikTok | Google Ads |
|---|---|---|---|
| campaigns | campaign | campaign | campaign |
| ad-groups | adset | adgroup | ad_group |
| ads | ad | ad | ad_group_ad |
| creatives | creative | — | — |
| asset-groups | — | — | asset_group |
breakdown=ad-groups answers one row for each ad group of each provider together. Each row keeps the word of its provider in type: adset on a Meta row, adgroup on a TikTok row. A provider that does not have the concept adds no row. A concept is valid with or without provider. entityType takes a concept too.
Provider entity types
A provider entity type is the word of one provider: campaign, adset at Meta, adgroup at TikTok, ad_group at Google Ads, ad, and so on. It reads only the rows that carry that word, so breakdown=ad reads the ads of Meta and TikTok, and not the ad_group_ad rows of Google Ads.
A provider entity type below campaign needs a provider or an entity filter. breakdown=adset with no provider is refused with 400 invalid_request, and its issue names the breakdowns that are available. Send breakdown=ad-groups to read that level at every provider.
Money
Money is in whole units of the row’s currency, with decimals: a spend of 1284.57 is 1,284.57. It is the unit a budget takes on an entity, so a budget and a spend compare directly. The Mutations API and a Campaign Plan take the same unit.
Money comes back in the account currency of the rows it came from, and each row says which in its currency. A group that mixes two account currencies answers currency: null — the money in it was added across currencies and cannot be compared.
Send currency — an ISO 4217 code such as USD — to make them comparable. AdCrunch converts each day at the European Central Bank rate of that day, before adding the rows up, and every row then answers that currency.
Advertisers
Omit advertiserId to read every advertiser of your organization in one call. Send it to read one, and AdCrunch then also makes sure your organization owns it. An advertiserId your organization does not own answers an empty list, not a failure.
Paging
The answer is one page, { data, nextCursor }, of at most limit rows (100 by default, 500 at most). When it holds nextCursor, more rows exist: send it back as cursor, with the same parameters, to get the next page.
The rows are in one order across every provider: the period (with an interval), then the advertiser and the entity of the breakdown, then the provider. So a page never splits one group, and the pages of a portfolio read hold no more than limit rows however many providers you connect.
The rows always come from what AdCrunch holds. A live read belongs to one advertiser, and no provider aggregates an organization.
Request
- Base URL: https://api.adcrunch.dev
- URL: https://api.adcrunch.dev/observe/insights
- Auth: HTTP bearer
Query parameters
Filter rows to a single advertiser. Short-circuits the per-org advertiser fan-out and verifies the advertiser belongs to the caller's organization.
Group results by this level. Send a concept to read one level at every provider: campaigns, ad-groups, ads, creatives or asset-groups. For example, ad-groups reads Meta adset, TikTok adgroup and Google Ads ad_group together. Each row keeps the word of its provider in type. A concept is valid with or without provider, and a provider that does not have the concept adds no row. A provider-native entity type (campaign, adset, adgroup, ad_group, ad_group_ad, ad, …) reads the word of one provider. Below campaign, a native type needs provider or an entity filter. provider and advertiser group by the ad platform and by the ad account. Omit breakdown to aggregate every matching row into one result.
Display currency (ISO 4217, e.g. USD). When provided, monetary metrics are converted from each row’s account currency using the ECB reference rate of the row’s own date, before any aggregation. Omit to get unconverted account-currency values — pass it whenever the organization has advertisers in more than one currency.
The nextCursor of the previous page. Omit it to get the first page. Send it with no change, and with the same filters as the request that answered it: a cursor from a different query gets a 400 invalid_cursor. Do not build or change a cursor.
Filter to a single entity (any type), or — combined with a concept or an entity-type breakdown — scope the breakdown to that entity’s subtree.
Filter rows to one level. Send a concept (campaigns, ad-groups, ads, creatives or asset-groups) to read that level at every provider, or a provider-native entity type to read the word of one provider.
Bucket the time series at this granularity. Omit to collapse to a single row per group.
The greatest number of rows on the page, from 1 to 500. The default is 100. A greater value gets a 400, with error of invalid_request.
Response
One page of the matching rows. This page is the last one, so it carries no nextCursor.
Example response
{
"data": [
{
"advertiserId": "acc_1203456789012345",
"currency": "EUR",
"entityId": "120210000000000",
"impressions": 184213,
"provider": "meta",
"spend": 1284.57,
"type": "campaign"
},
{
"advertiserId": "acc_4829301756",
"currency": "EUR",
"entityId": "20481523697",
"impressions": 46902,
"provider": "gads",
"spend": 612.4,
"type": "campaign"
}
]
}Changes
No recorded changes to this operation across all 1 revision of this API.