Zernio
APIFor you
Zernio
APIFor you
Platforms

Meta Ads

Overview

Set up

Connect

Build

CampaignsAd setsCreativesCreative libraryPreviewsBoost a postLead Gen Forms

Target

TargetingCustom Audiences

Ad types

Creative testingConversion campaignsCatalog adsMessaging & call adsClick-to-WhatsApp adsReach & frequency

Measure

InsightsMeta PixelsConversions APIAd URL tracking tags

Operate

Duplicate & lifecycleAccount & ops readsAd LibraryAd comments

Reference

Enums, limits & error codes
Dashboard
OverviewPlatformsAPI ReferenceResources
Meta Ads

Targeting

Target Meta ads by country, city, region, ZIP, age, gender and interests, and resolve Meta's opaque location and interest ids with GET /v1/ads/targeting/search.


Target with flat fields on POST /v1/ads/create: country, city, region, ZIP, metro, age, gender, income, interests, behaviours and custom audiences. You can also exclude locations and audiences.

Cities, regions and interests are opaque Meta ids. Resolve them with GET /v1/ads/targeting/search first.

Targeting fields

POST /v1/ads/messaging and POST /v1/ads/call take the same flat fields (and rawTargeting). POST /v1/ads/boost and reach estimates take them inside a targeting object.

FieldTypeMeaning
ageMin, ageMaxnumber13 to 65.
genderstringall (default), male or female.
countriesstring[]ISO 3166-1 alpha-2 codes. Defaults to ["US"] when no other geo field is present.
citiesobject[]{ key, radius?, distance_unit? }. key comes from the search below; radius and distance_unit (kilometer or mile) go together. Meta enforces a minimum radius of about 17 km (10 miles); a smaller one resolves to an empty audience and the ad fails at launch.
regionsobject[]{ key } from a search with geoType=region.
zipsobject[]{ key } from a search with geoType=zip, for example US:94304.
metrosobject[]{ key } from a search with geoType=metro_area, for example DMA:807.
customLocationsobject[]{ latitude, longitude, radius, distanceUnit } for a point-radius catchment tighter than a city radius.
excludedLocationsobjectGeo to leave out, mirroring the include shape: countries, regions, cities (with radius and distance_unit), zips, places, neighborhoods and customLocations.
interestsobject[]{ id, name } from a search with dimension=interest.
behaviorsobject[]{ id, name } from a search with dimension=behavior.
workPositions, workEmployers, workIndustriesobject[]{ id, name } from a search with dimension=workPosition, workEmployer or workIndustry. Meta only, and not interchangeable with LinkedIn's job title and industry URNs.
userOsstring[]Meta only. Operating systems and version ranges, e.g. iOS_ver_14.0_and_above or Android. Emitted as user_os.
userDevicestring[]Meta only. Device models, e.g. iPhone. Emitted as user_device.
audienceInclude, audienceExcludestring[]The platformAudienceId of a custom audience or lookalike to target, or to hold back from the ad.
languagesstring[]A bare code (en) targets every regional variant; a region-qualified code (en_GB) targets one.
incomeTierstringtop_5, top_10, top_10_25 or top_25_50, a household-income band by ZIP percentile. Meta rejects it on a housing, employment or credit ad, which is what specialAdCategories declares.
placementsobjectManual placements; omit for Meta's automatic placements. Values are in the reference.
savedTargetingIdstringA saved_targeting audience whose spec is the base; inline fields merge on top.
rawTargetingobjectA Meta-native targeting spec (geo_locations, flexible_spec, excluded_custom_audiences), for fields the flat surface does not expose.
advantageAudiencenumberMeta's Advantage+ audience expansion: 0 (default) keeps targeting strict, 1 lets Meta expand beyond the fields you sent. Meta requires the field on every ad set create, so Zernio sends 0 for you, except when rawTargeting is present: then send advantageAudience yourself or put targeting_automation in the raw spec.

On POST /v1/ads/create these sit at the top level. On POST /v1/ads/boost they live inside targeting, and cities there spell the unit distanceUnit.

Do not combine cities with the countries that contain them. Meta returns a "locations overlap" error because the city is already inside the country.

Drop the country, or scope countries to a different one.

Portable fields (countries, ageMin/ageMax, gender, incomeTier, languages) carry across platforms unchanged. Every other field is meaningful only for the platform it was built against.

A field a platform cannot honour is rejected at create time with INVALID_FIELD_VALUE naming it, not silently dropped.

Look up city and region keys

Call GET /v1/ads/targeting/search with accountId, q, dimension=geo and geoType. Pass the returned id as key.

countryCode disambiguates names that exist in several countries.

The older GET /v1/ads/interests is a deprecated alias of the interest search.

import Zernio from '@zernio/node';

const zernio = new Zernio();

const { data: search } = await zernio.adtargeting.searchAdTargeting({
  query: {
    accountId: '66b2e19d8c3f5a7e9d0b1c2d',
    q: 'Amsterdam',
    dimension: 'geo',
    geoType: 'city',
    countryCode: 'NL'
  }
});

const cityKey = search.results[0].id;

Response (200):

{
  "results": [
    {
      "id": "2759794",
      "name": "Amsterdam",
      "type": "city",
      "path": ["Netherlands", "North Holland", "Amsterdam"],
      "audienceSize": null
    }
  ]
}

Then use the key on the create request, replacing countries.

EU targeting also needs the DSA beneficiary and payer, unless the ad account has defaults set:

{
  "budgetType": "lifetime",
  "endDate": "2027-03-31T23:59:00Z",
  "cities": [{ "key": "2759794", "radius": 25, "distance_unit": "kilometer" }],
  "dsaBeneficiary": "Acme BV",
  "dsaPayor": "Acme BV"
}

geoType accepts all, country, region, city (the default), subcity, neighborhood, place, zip, metro_area and geo_market.

dimension also resolves:

  • interest, behavior and income
  • the Meta-only workPosition, workEmployer and workIndustry
  • language, which reads Google's language table and returns nothing on Meta

Estimate reach

POST /v1/ads/targeting/reach-estimate returns Meta's delivery_estimate before you create anything.

accountId, adAccountId and spec are all required. spec carries the fields above, nested.

const { data: estimate } = await zernio.adtargeting.estimateAdReach({
  body: {
    accountId: '66b2e19d8c3f5a7e9d0b1c2d',
    adAccountId: 'act_1234567890',
    spec: {
      countries: ['NL'],
      ageMin: 25,
      ageMax: 54,
      interests: [{ id: '6003107902433', name: 'Interior design' }]
    }
  }
});

Response (200), trimmed:

{
  "available": true,
  "lower": 412000,
  "upper": 585000,
  "estimateReady": true
}

estimateReady: false means Meta is still computing the estimate, which happens on a brand-new audience. Retry shortly.

An empty spec estimates the platform's broadest audience.

optimizationGoal (Meta's own vocabulary, such as REACH or LINK_CLICKS) narrows the estimate to the goal the ad set will use.

If it fails

A 400 with type: "platform_error" on create is Meta rejecting the geo combination:

{
  "error": "Invalid parameter: Your cities and countries overlap",
  "type": "platform_error",
  "platform": "meta",
  "platformError": { "code": 100 }
}

Remove the country that already contains the city.

A 404 on the search means the account's platform does not support the requested dimension.

Related

  • Campaigns: the create request these fields go on.
  • Audiences: customer lists, lookalikes and saved targeting.
  • Reference: the placements values and special ad categories.
  • Search targeting options and Estimate audience reach: every parameter.
Was this page helpful?

Lead Gen Forms

Create a Meta instant form with POST /v1/ads/lead-forms, attach it to an ad, and receive the leads by webhook or by polling.

Custom Audiences

Create Meta customer list, website, lookalike, engagement and saved targeting audiences with POST /v1/ads/audiences, and fill a customer list with hashed uploads.

On this page

Targeting fieldsLook up city and region keysEstimate reachIf it failsRelated