Skip to content
AdCrunch
Esc
↑↓navigate↵open⌘Jpreview

Stored read: List insights

Available on: Meta TikTok Google Ads

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 reports no reach, so reach, cpp and frequency read 0 on every Google Ads row. 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
provider one for each ad platform provider
advertiser one for each ad account provider, advertiserId
an entity type one for each entity of that type provider, advertiserId, entityId, type

An entity type is the name its provider uses — campaign, adset at Meta, ad_group at TikTok and Google Ads, ad, and so on.

A breakdown deeper than campaign needs a provider or an entity filter, because the levels below a campaign differ per platform. breakdown=adset with no provider is refused with 400 invalid_request, and its issue names the breakdowns that are available.

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.

GET/observe/insights
Authorization
AuthorizationBearer token · headerrequired

Send Authorization: Bearer <credential>.

Use an API key (acr_…), from the AdCrunch console under Settings → API keys.

The credential names the organization, and no operation takes an organization parameter.

See https://docs.adcrunch.dev/api/authentication.

Query parameters
advertiserIdstring

Filter rows to a single advertiser. Short-circuits the per-org advertiser fan-out and verifies the advertiser belongs to the caller's organization.

matches ^(acc_)[\s\S]{0,}$
breakdownstring

Group results by this level. Use a provider-native entity type (campaign, adset, ad_group, line_item, asset_group, keyword, ad, …) or provider/advertiser. Omit to aggregate every matching row into one result.

Allowed:provideradvertisercampaignadsetadgroupad_groupad_group_adinsertion_orderline_itemasset_groupkeywordaudiencelisting_groupadcreative
currencystring

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.

matches ^[A-Za-z]{3}$
cursorstring

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.

min length 1
entityIdstring

Filter to a single entity (any type), or — combined with an entity-type breakdown — scope the breakdown to that entity’s subtree.

entityTypestring

Filter rows to a single provider-native entity type.

intervalstring

Bucket the time series at this granularity. Omit to collapse to a single row per group.

Allowed:dayweekmonth
limitinteger

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.

min 1 · max 500 · default: 100
providerstring

Restrict to a single provider. Ignored when an entity filter (advertiserId, etc.) is provided — that filter already pins the provider.

relativestring
selectstring | string[]

Metric columns to include on each row, as a comma-separated string (e.g. spend,clicks,ctr) or repeated values. Defaults to spend,impressions.

sincestring
untilstring
Responses
200

One page of the matching rows. This page is the last one, so it carries no nextCursor.

dataobject[]required

One row for each group. An empty array means no data matched, which is a normal answer and not a failure.

Show properties
Array of object
advertiserIdstring

The advertiser this row belongs to, prefixed acc_. Present when breakdown is advertiser or an entity type.

currencystring | nullrequired

The ISO 4217 currency the money in this row is expressed in. It is the account currency when every row in the group shares one, the currency you asked for when you sent currency, and null when the group mixes two or more account currencies. A null here means the money in this row was added up across currencies and cannot be compared — send currency to make it comparable.

datestring

The first day of the period, YYYY-MM-DD. Present only when you send interval. A week is dated by its Monday, a month by its first day.

entityIdstring

The entity this row belongs to, as the bare id its provider gives it. Present when breakdown is an entity type.

providerstring

The ad platform: meta, tiktok or gads. Present when breakdown is set to anything. https://docs.adcrunch.dev/connect/providers lists every provider and what each one reports.

typestring

The provider entity type of entityId, for example campaign, adset, ad_group or ad. Present when breakdown is an entity type.

spendnumber

Money spent, in the row’s currency.

clicksnumber

Clicks.

impressionsnumber

Impressions.

ctrnumber

Click-through rate, as a percentage: clicks ÷ impressions × 100. A ctr of 1.5 means 1.5%.

cpcnumber

Cost per click: spend ÷ clicks.

cpmnumber

Cost per thousand impressions: spend ÷ impressions × 1000.

cppnumber

Cost per thousand people reached: spend ÷ reach × 1000. Google Ads reports no reach, so this reads 0 there.

cpanumber

Cost per conversion: spend ÷ conversions.

roasnumber

Return on ad spend: conversion value ÷ spend.

reachnumber

People reached. Google Ads does not report it, so it reads 0 there.

frequencynumber

Impressions ÷ reach. Google Ads reports no reach, so this reads 0 there.

conversionsnumber

Conversions, as the provider counts them.

conversion_valuenumber

The value attributed to those conversions, as money.

action_add_to_cartnumber

Add-to-cart actions. Meta only; other providers read 0.

action_add_to_cart_valuenumber

The value attributed to those add-to-cart actions. Meta only.

action_purchasenumber

Purchases. Meta only; other providers read 0.

action_purchase_valuenumber

The value attributed to those purchases. Meta only.

action_initiate_checkoutnumber

Checkouts started. Meta only; other providers read 0.

action_initiate_checkout_valuenumber

The value attributed to those checkouts. Meta only.

nextCursorstring

Send this value as cursor to get the next page. It is absent on the last page.

400

The request does not match the schema of this operation: a field is missing or has the wrong type, or the body is not valid JSON. error is invalid_request, and issues names each field. Nothing was changed. Or AdCrunch cannot use the cursor: it cannot read it, or the cursor belongs to a different query. Then error is invalid_cursor. Send the nextCursor of the previous page with no change, or omit cursor to get the first page.

Any of:
object
issuesobject[]required

One entry for each field that does not match.

Show properties
Array of object
instringrequired

The part of the request that holds the field.

Allowed:bodycookieheadersparamsquery
messagestringrequired

A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.

pathstringrequired

A JSON Pointer into that part of the request, such as /filename. An empty string is the whole part.

errorstringrequired

A stable code for the failure. This is the field to branch on. It does not change for a given failure.

Allowed:invalid_request
messagestringrequired

A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.

object
errorstringrequired

A stable code for the failure. This is the field to branch on. It does not change for a given failure.

Allowed:invalid_cursor
messagestringrequired

A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.

401

No API key, or one that does not resolve. See the security scheme. error is unauthorized.

errorstringrequired

A stable code for the failure. This is the field to branch on. It does not change for a given failure.

Allowed:unauthorized
messagestringrequired

A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.

403

The caller does not hold observe:read. error is forbidden.

errorstringrequired

A stable code for the failure. This is the field to branch on. It does not change for a given failure.

Allowed:forbidden
messagestringrequired

A sentence to show a person. Written to say what to do next. Reworded whenever it can be said better, so never branch on it.

Request
curl -X GET "https://api.pr-701.adcrunch.dev/observe/insights" \
  -H "Authorization: Bearer YOUR_TOKEN"
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"
    }
  ]
}