Insights
Insights report delivery, spend and conversions at five levels: your organization, an ad account, a campaign, an ad set or an ad.
Endpoints
GET https://api.adzen.ai/v1/ad-manager/organization/insights
GET https://api.adzen.ai/v1/ad-manager/ad_accounts/{id}/insights
GET https://api.adzen.ai/v1/ad-manager/campaigns/{id}/insights
GET https://api.adzen.ai/v1/ad-manager/ad_sets/{id}/insights
GET https://api.adzen.ai/v1/ad-manager/ads/{id}/insightsThe path {id} is the prefixed id (cmpn_412) or the bare number (412).
The organization and ad account levels include archived campaigns.
Headers
| Header | Required | Value |
|---|---|---|
Authorization | Yes, unless you send X-API-Key | Bearer YOUR_API_KEY. You can send X-API-Key: YOUR_API_KEY instead. If both are sent, X-API-Key is used. |
Query parameters
| Parameter | Type | Required | Rules |
|---|---|---|---|
start_date | string | Yes | YYYY-MM-DD, the first day, included. |
end_date | string | Yes | YYYY-MM-DD, the last day, included. Not before start_date. At most 93 days from start_date, counting both ends. |
time_zone | string | No | An IANA zone, like America/New_York or Asia/Kolkata, up to 64 characters. Default: your organization’s time zone, or UTC when it has none. Dates and periods are in this zone. |
granularity | string | No | total (default), month, day or hour. |
breakdowns | string | No | Comma-separated, any of ad_account, campaign, ad_set, ad, surface, invalid_reason. Each row then carries the matching key. |
attribution_time_basis | string | No | conversion (default) dates each conversion by its event_time. click dates it by the time of its click. |
Unknown query parameters are ignored, so a misspelled parameter takes its default.
Example request
curl 'https://api.adzen.ai/v1/ad-manager/campaigns/cmpn_412/insights?start_date=2026-11-02&end_date=2026-11-08&time_zone=America/New_York&granularity=day&breakdowns=ad,surface' \
-H 'Authorization: Bearer YOUR_API_KEY'Response
{
"object": "list",
"data": [
{
"object": "insight",
"start_time": 1793595600,
"end_time": 1793682000,
"ad_id": "ad_2864",
"surface": "static",
"impressions": 182400,
"viewed_impressions": 91350,
"clicks": 1120,
"invalid_clicks": 64,
"spend_micros": 2740500000,
"conversions": 41,
"conversion_value_micros": 1435000000,
"attributed_sales_micros": 1050000000,
"ctr": 0.012260536398467433,
"cpc_micros": 2446875,
"cpm_micros": 30000000,
"cvr": 0.03660714285714286,
"cpa_micros": 66841463,
"roas": 0.5236270753512133,
"final": true
}
],
"has_more": false
}Each response holds every row for the request. A period, object or surface with no activity has no row: a missing
row means zero. A level with no campaigns or ads returns an empty data.
Rows are sorted by start_time, then by the breakdown values.
Row keys
| Field | Type | Description |
|---|---|---|
object | string | Always insight. |
start_time | integer | The period’s start, Unix seconds, included. |
end_time | integer | The period’s end, Unix seconds, excluded. |
ad_account_id | string or null | With the ad_account breakdown only. acct_61. |
campaign_id | string or null | With the campaign breakdown only. cmpn_412. |
ad_set_id | string or null | With the ad_set breakdown only. adset_8271. Every ad created through the Ads API has an ad set. |
ad_id | string or null | With the ad breakdown only. ad_2864. |
surface | string or null | With the surface breakdown only. static, ugc or ai. |
invalid_reason | string or null | With the invalid_reason breakdown only. See Invalid clicks. |
With the invalid_reason breakdown, each period has one row per reason. A
reason row carries only invalid_clicks. Every other metric is on the row
whose invalid_reason is null. Without this breakdown, all invalid clicks
are in invalid_clicks.
Periods
start_time and end_time are UTC instants. Days and months follow
time_zone.
granularity | One row covers |
|---|---|
total | start_date 00:00 to the day after end_date, 00:00 |
month | One calendar month, cut to the requested dates. The first and last months can be partial. |
day | One day, midnight to midnight |
hour | One UTC hour |
An hour row is one UTC hour. Each hour counts in the day or month, in
time_zone, that it starts in.
Metrics
| Metric | Type | Definition |
|---|---|---|
impressions | integer | Ads served. See Impressions. |
viewed_impressions | integer | Ads on screen. For ugc this equals impressions. |
clicks | integer | Valid clicks. |
invalid_clicks | integer | Clicks filtered out. Break down by invalid_reason to see why. |
spend_micros | integer | What you are charged, in USD micros. |
conversions | integer | Conversions you sent through POST /conversions, attributed to valid clicks. Every event_name counts. |
conversion_value_micros | integer | The value of those conversions, in USD micros. |
attributed_sales_micros | integer | The value of the purchase conversions, in USD micros. |
ctr | number or null | clicks / viewed_impressions |
cpc_micros | integer or null | spend_micros / clicks |
cpm_micros | integer or null | spend_micros / viewed_impressions × 1000 |
cvr | number or null | conversions / clicks |
cpa_micros | integer or null | spend_micros / conversions |
roas | number or null | conversion_value_micros / spend_micros |
final | boolean | true once the row can no longer change. See Finality. |
ctr, cvr and roas are unrounded floating-point numbers. cpc_micros,
cpm_micros and cpa_micros are whole micros, rounded half up. Each is
computed from the row’s own totals. Each is null when its denominator is 0.
Errors
{
"error": {
"type": "invalid_request_error",
"code": "too_many_rows",
"message": "this request matches too many rows; narrow the dates, use a coarser granularity, or ask for fewer breakdowns",
"param": null
}
}| Status | code | When | Retry? |
|---|---|---|---|
400 | invalid_value | A parameter fails its rules: a missing or malformed date, end_date before start_date, more than 93 days, an unknown granularity, breakdown or attribution_time_basis, or a time_zone that is not an IANA zone or is longer than 64 characters. param names the parameter. | No. Fix the request. |
400 | invalid_query | The query string cannot be read. | No. Fix the request. |
400 | too_many_rows | The response would hold more than 20,000 rows. | No. Narrow the dates, use a coarser granularity, or ask for fewer breakdowns. |
400 | scope_too_large | The level holds more than 20,000 campaigns or ads. | No. Ask per ad account or per campaign. |
401 | invalid_api_key, missing_api_key | The key is missing or invalid, or is a key for another Adzen product. With Authorization: Bearer, or with no key, the body is the error envelope with type authentication_error. With X-API-Key, the body is {"error": "Unauthorized", "message": "invalid API key"}, with no type or code. | No. Fix the key. |
403 | The request comes from an IP address outside the US. | No. Send from the US. | |
404 | not_found | The id does not exist, is outside the key’s ad accounts, or carries another object’s prefix (acct_412 on /campaigns). | No. |
429 | rate_limit_exceeded | Over a rate limit. | Yes, after Retry-After seconds. |
503 | upstream_unavailable | Insights are briefly unavailable. | Yes, after a short wait. |
Rate limits
600 requests per minute per endpoint, per key. 1,200 requests per minute per key
across the whole Ads API. Requests with granularity=hour that are at ad set
or ad level, or that break down by ad_set or ad, also share a limit of 30
per minute per key. See
Rate limits.
Freshness
Impressions and clicks are updated every 5 minutes. spend_micros includes
the current, unfinished hour. An accepted conversion appears within about 5
minutes.
Finality
A row is final, and final is true, 30 days after its end_time. A row
with a non-null invalid_reason is final 72 hours after its end_time. Until
then, request the period again to get updated numbers.
Statements
An ad account’s monthly statement total equals its spend_micros for that
calendar month in your organization’s time zone, rounded half up to the cent;
see Budgets and billing.