Meta Ad Metrics API Reference

Pull Meta ad performance per campaign, ad set, or ad for any date range.

Overview: This endpoint returns spend, impressions, clicks, CTR, CPC, and CPM for your Meta campaigns, ad sets, or ads over a date range you choose. Values come from the same data as the Top Performing Campaigns widget on your Hermon dashboard, so numbers line up with what you see in the app. Only campaigns selected in your Meta Ads settings (under a selected ad account) are included.

Get Ad Metrics

Returns one row per entity at the requested level that had spend in the period, ordered by spend (highest first).

GET/api/external/meta/ad-metrics

Query Parameters

ParameterTypeRequiredDescription
fromstring (YYYY-MM-DD)requiredStart of the reporting period (inclusive). A calendar date in your Meta ad account’s timezone.
tostring (YYYY-MM-DD)requiredEnd of the reporting period (inclusive). Must not be earlier than from.
levelstring (enum)requiredWhich entities to return: campaign, ad_set, or ad.
campaign_idstring (UUID)optionalHermon campaign id (the id returned on a campaign row). Limits results to that campaign. Only allowed when level is ad_set or ad.
ad_set_idstring (UUID)optionalHermon ad set id (the id returned on an ad set row). Limits results to that ad set. Only allowed when level is ad.
pageintegeroptionalPage number for pagination. Default: 1
limitintegeroptionalNumber of items per page. Default: 10, Max: 100
Drilling down: call level=campaignfirst, then pass a campaign row's id as campaign_id with level=ad_set, and an ad set row's id as ad_set_id with level=ad. Filters take Hermon ids, not Meta IDs. Without a filter, every ad set or ad across all selected campaigns is returned.

Code Examples

curl -X GET "https://api.hermon.io/api/external/meta/ad-metrics?from=2026-09-01&to=2026-09-30&level=campaign" \
  -H "x-api-key: sk_live_your_key_here"

Response Fields

FieldTypeDescription
idstring (UUID)Hermon id of the campaign, ad set, or ad. Pass it back as campaign_id or ad_set_id to drill down.
meta_idstringThe entity’s ID in Meta Ads Manager.
namestringEntity name as synced from Meta.
campaign_idstring (UUID)Hermon id of the parent campaign. Present on ad set and ad rows.
campaign_meta_idstringMeta ID of the parent campaign. Present on ad set and ad rows.
campaign_namestringName of the parent campaign. Present on ad set and ad rows.
ad_set_idstring (UUID)Hermon id of the parent ad set. Present on ad rows only.
ad_set_meta_idstringMeta ID of the parent ad set. Present on ad rows only.
ad_set_namestringName of the parent ad set. Present on ad rows only.
spendnumberTotal ad spend in the period, converted to your organization’s currency.
currencystring | nullISO currency code for spend, cpc, and cpm (your organization’s currency).
impressionsintegerTotal impressions in the period.
clicksintegerTotal clicks in the period.
ctrnumber | nullClick-through rate in percent: clicks ÷ impressions × 100. null when impressions is 0.
cpcnumber | nullCost per click: spend ÷ clicks. null when clicks is 0.
cpmnumber | nullCost per 1,000 impressions: spend × 1000 ÷ impressions. null when impressions is 0.
How rates are calculated: ctr, cpc, and cpm are computed from the summed spend, clicks, and impressions over the whole period — they are not averages of daily rates. When the denominator is 0, the value is null. Reach is not returned: Meta reports it as unique people per day, so it cannot be added up across days or entities.

Response Example — level=campaign

json
{
  "status": "success",
  "message": "Meta ad metrics fetched successfully",
  "data": [
    {
      "id": "6f1c2a4e-8b1d-4c3a-9e2f-1a2b3c4d5e6f",
      "meta_id": "120210000000001",
      "name": "Webinar Funnel",
      "spend": 400,
      "currency": "EUR",
      "impressions": 20000,
      "clicks": 215,
      "ctr": 1.07,
      "cpc": 1.86,
      "cpm": 20
    },
    {
      "id": "9a8b7c6d-5e4f-4a3b-8c2d-1e0f9a8b7c6d",
      "meta_id": "120210000000002",
      "name": "Retargeting",
      "spend": 50,
      "currency": "EUR",
      "impressions": 2000,
      "clicks": 30,
      "ctr": 1.5,
      "cpc": 1.67,
      "cpm": 25
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 2,
    "totalPages": 1,
    "hasNext": false,
    "hasPrev": false
  }
}

Response Example — level=ad with ad_set_id

json
{
  "status": "success",
  "message": "Meta ad metrics fetched successfully",
  "data": [
    {
      "id": "3d2c1b0a-9f8e-4d7c-b6a5-4f3e2d1c0b9a",
      "meta_id": "120210000000301",
      "name": "Video A",
      "campaign_id": "6f1c2a4e-8b1d-4c3a-9e2f-1a2b3c4d5e6f",
      "campaign_meta_id": "120210000000001",
      "campaign_name": "Webinar Funnel",
      "ad_set_id": "b1a2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "ad_set_meta_id": "120210000000201",
      "ad_set_name": "Lookalike 1%",
      "spend": 180,
      "currency": "EUR",
      "impressions": 9000,
      "clicks": 90,
      "ctr": 1,
      "cpc": 2,
      "cpm": 20
    },
    {
      "id": "7e6d5c4b-3a2f-4e1d-9c8b-7a6f5e4d3c2b",
      "meta_id": "120210000000302",
      "name": "Carousel B",
      "campaign_id": "6f1c2a4e-8b1d-4c3a-9e2f-1a2b3c4d5e6f",
      "campaign_meta_id": "120210000000001",
      "campaign_name": "Webinar Funnel",
      "ad_set_id": "b1a2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
      "ad_set_meta_id": "120210000000201",
      "ad_set_name": "Lookalike 1%",
      "spend": 100,
      "currency": "EUR",
      "impressions": 5000,
      "clicks": 65,
      "ctr": 1.3,
      "cpc": 1.54,
      "cpm": 20
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 10,
    "total": 2,
    "totalPages": 1,
    "hasNext": false,
    "hasPrev": false
  }
}

Error Responses

400Missing or invalid parameters
json
{
  "status": "error",
  "message": "ad_set_id is only supported for level ad"
}
401Missing or invalid API key
json
{
  "status": "error",
  "message": "Invalid or revoked API key"
}
404Campaign or ad set not found in your workspace
json
{
  "status": "error",
  "message": "Meta campaign not found"
}
429Rate limit exceeded
json
{
  "status": "error",
  "message": "Rate limit exceeded for this organization. Retry after the number of seconds in the Retry-After header."
}