---
title: "Search targeting options"
method: GET
path: "/v1/ads/targeting/search"
tags: ["Ad Targeting"]
---

# Search targeting options

`GET /v1/ads/targeting/search`

Resolve a human-readable query into the platform's opaque targeting ids used in
the `TargetingSpec` (`countries`/`regions`/`cities`/`zips`/`metros` geo keys, and
`interests`/`behaviors` entity ids) on `POST /v1/ads/create`,
`POST /v1/ads/targeting/reach-estimate`, and `saved_targeting` audiences.

The `dimension` param selects what is searched:

- `geo`: locations, further scoped by `geoType`
- `interest`
- `behavior`
- `income`
- `language`: Google-only
- `workPosition`, `workEmployer`, `workIndustry`: the Meta-only work demographics, whose
  ids feed `TargetingSpec.workPositions`/`workEmployers`/`workIndustries`
- `industry`, `jobFunction`, `seniority`, `companySize`: the LinkedIn-only B2B facets, whose
  URNs feed `TargetingSpec.industries`/`jobFunctions`/`seniorities`/`companySizes`

Availability of each dimension varies by platform (e.g. behaviours are Meta/TikTok only).
Work industries are a fixed ~30-entry Meta catalog with no server-side query,
so `workIndustry` matching, ranking and `limit` happen in Zernio. `language`
is likewise a fixed, checked-in table of Google's targetable
`language_constant` rows (id, ISO code, name) matched by name or code, capped
at 20, with no network call; its ids feed `TargetingSpec.languages`.

Results are normalized across platforms into a single shape, so the same client code
consumes Meta, TikTok, LinkedIn, X, Pinterest, and Google results.

TikTok geo searches return every matching level in one list (`type` is
`country`, `region`, `city`, `district`, or `metro` for DMA areas), and
`geoType` is not applied. Results are scoped to the advertiser's targetable
markets. A `country` result's id is its ISO 3166-1 alpha-2 code, for
`targeting.countries`; every other id is TikTok's numeric location id,
usable in `regions`/`cities`/`metros` keys on `POST /v1/ads/create`.

LinkedIn geo searches also return every matching level in one list, and
neither `geoType` nor `countryCode` is applied: LinkedIn's typeahead only
returns a name and a URN per result, with no level or country field to
filter on. A result whose URN is a country Zernio holds a code for has
`type: country` and its ISO 3166-1 alpha-2 code as the id, for
`targeting.countries`. Every other result has `type: region` and keeps
its `urn:li:geo:*` URN as the id, usable as a `regions[].key` on
`POST /v1/ads/create`, `POST /v1/ads/boost` and
`POST /v1/ads/targeting/reach-estimate` (LinkedIn puts countries and
regions in the same `locations` facet, so both target the same way).

LinkedIn B2B searches (`industry`, `jobFunction`, `seniority`, `companySize`) return the
full URN to pass straight back, so no URN id fragment has to be assembled by hand:
`urn:li:industry:4`, `urn:li:function:8`, `urn:li:seniority:6`,
`urn:li:staffCountRange:(51,200)`. Only `industry` is a server-side name search
(LinkedIn's typeahead finder). LinkedIn exposes no typeahead for job functions,
seniorities and company sizes, so Zernio fetches each whole table (26, 10 and 9 entries),
caches it, and does the matching, ranking and `limit` cutoff itself. Those three never
carry `audienceSize`, and `countryCode` and `geoType` are not applied to any of the four.

Google geo searches resolve against Google's geoTargetConstants and return
every matching level in one list; `geoType` is not applied (Google's
`target_type` is an open taxonomy that does not map one-to-one onto the
`geoType` enum), so filter client-side on the returned `type` (`country`,
`region`, `city`, `zip`, `metro`, or the lowercased Google target type for
rarer levels). `countryCode` scopes the search to one country. A `country`
result's id is its ISO 3166-1 alpha-2 code, for `targeting.countries`;
every other id is Google's numeric criterion id, usable as a
`regions`/`cities`/`zips`/`metros` `key` on `POST /v1/ads/create`. Google
city radius is not supported (pass a `customLocations` lat/lng pin for a
radius); country targeting also accepts plain ISO codes via `countries`
with no search call.

Pinterest resolves against three whole-catalog endpoints (interests, locations,
regions) with no server-side query or pagination, so matching, ranking and the
`limit` cutoff all happen in Zernio; the catalog is independent of any ad account
and results never carry `audienceSize`. Names come back localized to the connected
Pinterest account's language (there is no way to force a locale), so match against
whatever language that account returns.

`geoType` routes to a different Pinterest catalog:

- `country` and `metro_area` read the locations catalog (`type` is `country` or `metro`)
- `region` reads the regions catalog (`type` is `region`, its id a `regions[].key` on
  `POST /v1/ads/create`)
- `all` and the default `city` merge both catalogs with honest per-entry `type`s, since
  Pinterest has no city-level catalog and `city` is an alias for `all`, not a literal
  city search
- `zip`, `subcity`, `neighborhood`, `place` and `geo_market` return a 400: Pinterest
  exposes no postal-code catalog, pass postal codes directly as
  `targeting.zips: [{ key }]` on `POST /v1/ads/create`

For geo queries, `q` should contain only the locality name (e.g. `"Amsterdam"`,
not `"Amsterdam, NL"`). Use `countryCode` to disambiguate.

## Query parameters

- `accountId` string, required
- `q` string, required
- `dimension` 'geo' | 'interest' | 'behavior' | 'income' | 'language' | 'workPosition' | 'workEmployer' | 'workIndustry' | 'industry' | 'jobFunction' | 'seniority' | 'companySize'
- `geoType` 'all' | 'country' | 'country_group' | 'region' | 'city' | 'subcity' | 'neighborhood' | 'place' | 'zip' | 'metro_area' | 'geo_market'
- `countryCode` string
- `limit` integer

## Response `200`

Matching targeting options (normalized)

- object
  - `results` object[]
    - `id` string, required — The platform's opaque id. Use as a geo `key` (regions/cities/zips/metros) or an entity `id` (interests/behaviors) in TargetingSpec. A `country` result is the exception on every platform: its id is the ISO 3166-1 alpha-2 code, which is what `targeting.countries` takes.
    - `name` string, required — Human-readable label.
    - `type` string, required — What the result is (e.g. city, region, country, zip, metro, location, interest, behavior, income, industry, jobFunction, seniority, companySize).
    - `path` string[] — Optional breadcrumb of parent labels (e.g. ['United States', 'California', 'Los Angeles']). Disambiguates same-named results.
    - `audienceSize` integer, nullable — Optional estimated reachable users for this option, when the platform returns it.
    - `countryCode` string — ISO-3166 alpha-2 of the country a sub-country geo result (city, region, zip, metro) belongs to, when the platform reports it (Meta does). Useful to know whether a location falls under the EU DSA disclosure rules before creating the ad.

## Other responses

- `400` — Missing or invalid query parameters
- `401` — Unauthorized
- `403` — Ads access required. Legacy plans need the Ads add-on; included by default on usage-based plans.
- `404` — The account or requested resource was not found or is not accessible. An account ID may have been disconnected and removed. Read GET /v1/accounts for current account IDs.
- `409` — The account exists but is inactive or needs reconnection. Reconnect it, then read GET /v1/accounts for its current account ID before retrying. Code: ads_connection_required.

## Changes

- **2026-09-25** `2c04683ce694` — 8 info
  - added the optional property `details/adAccountId` to the response with the `404` status
  - added the optional property `details/adAccountId` to the response with the `409` status
  - added the optional property `details/createdObjects` to the response with the `404` status
  - added the optional property `details/createdObjects` to the response with the `409` status
  - …4 more
- **2026-09-22** `106013ac73b8` — 1 info
  - added the optional property `results/items/countryCode` to the response with the `200` status
- **2026-09-16** `3e6ddf2a99ea` — 2 info
  - added the optional property `details/budgetScope` to the response with the `404` status
  - added the optional property `details/budgetScope` to the response with the `409` status
- **2026-09-15** `0dba7d004d75` — 4 info
  - added the optional property `details/quotaExhausted` to the response with the `404` status
  - added the optional property `details/quotaExhausted` to the response with the `409` status
  - added the optional property `details/quotaScope` to the response with the `404` status
  - added the optional property `details/quotaScope` to the response with the `409` status
- **2026-09-14** `a23eb241746a` — 1 info
  - added the new enum value `country_group` to the `query` request parameter `geoType`

[Full history](https://skmtc.dev/zernio/apis/zernio-api/changes/v1/ads/targeting/search/get.md)

---

[API](https://skmtc.dev/zernio/apis/zernio-api.md) · [All operations](https://skmtc.dev/zernio/apis/zernio-api/llms.txt) · [OpenAPI document](https://skmtc.dev/zernio/apis/zernio-api/revisions/b2325332041a?raw)
