---
title: "Estimate audience reach"
method: POST
path: "/v1/ads/targeting/reach-estimate"
tags: ["Ad Targeting"]
---

# Estimate audience reach

`POST /v1/ads/targeting/reach-estimate`

Returns a normalized pre-flight audience-size estimate for a targeting spec,
before any campaign is created. Backed by each platform's native reach API
(Meta `delivery_estimate`, LinkedIn `audienceCounts`, X `audience_summary`,
Pinterest `audience_sizing`).

Platforms without a usable pre-flight reach API (Google Search/Display, TikTok)
return `available: false` with no bounds, so clients can hide or grey out the
estimate rather than treat the absence as an error.

## Request body

- object
  - `accountId` string, required — Zernio social account ID on the target ad platform (the estimate runs against its platform).
  - `adAccountId` string, required — Required. The platform ad-account ID the reach call runs against (Meta act_..., LinkedIn numeric sponsoredAccount ID, Pinterest ad-account ID, X account ID) - every backing reach API is scoped to one ad account. Get it from GET /v1/ads/accounts.
  - `spec` TargetingSpec, required — Normalized, platform-agnostic ad-targeting spec. Every field is optional, an empty object targets the platform's default broadest audience. Field names are camelCase and identical across `POST /v1/ads/create` (the `targeting` object), `POST /v1/ads/targeting/reach-estimate`, and `saved_targeting` audiences, so a spec resolved once can be reused verbatim. Entity ids (`regions[].key`, `cities[].key`, `zips[].key`, `metros[].key`, `interests[].id`, `behaviors[].id`) are the platform's opaque identifiers resolved via `GET /v1/ads/targeting/search`. A spec is therefore meaningful only for the platform it was built against, except the portable fields (`countries`, `ageMin`/`ageMax`, `gender`, `incomeTier`, `languages`) which carry across platforms. Fields a platform cannot honour are rejected at create time with `INVALID_FIELD_VALUE` naming the offending field (not silently dropped).
    - `countries` string[] — ISO 3166-1 alpha-2 country codes (e.g. ['US']).
    - `regions` object[] — Region/state targeting. `key` is the platform location ID from /v1/ads/targeting/search?dimension=geo&geoType=region.
      - `key` string, required
      - `name` string
    - `cities` object[] — City targeting. Optional `radius` + `distanceUnit` extend beyond the city limits; both must be set together or both omitted. `radius` is only honoured on platforms whose capability map allows city radius (Meta).
      - `key` string, required
      - `name` string
      - `radius` number — Radius around the city. Requires distanceUnit. Meta enforces a minimum city radius (~17 km / 10 mi); smaller values resolve to a 0-size audience and the ad fails at launch. For a tighter catchment use customLocations (lat/lng), which allows a smaller radius.
      - `distanceUnit` 'mile' | 'kilometer' — Required if radius is set.
    - `zips` object[] — Postal/ZIP targeting. `key` is the platform's postal location ID (e.g. Meta `US:94304`). Supported on Meta, Google, TikTok, Pinterest, X.
      - `key` string, required
      - `name` string
    - `metros` object[] — DMA / metro-area targeting. `key` is the platform's metro ID (e.g. Meta `DMA:807`).
      - `key` string, required
      - `name` string
    - `customLocations` object[] — Point-radius (lat/lng) targeting (Meta custom_locations / Google proximity). Honoured only where the capability map allows radius (Meta).
      - `latitude` number, required
      - `longitude` number, required
      - `radius` number, required — Positive radius around the point.
      - `distanceUnit` 'mile' | 'kilometer', required
      - `name` string
      - `address` string — Optional label, sent to Meta as `address_string`. latitude/longitude take precedence for the pin location.
    - `excludedLocations` object — Geo to exclude from the audience. Mirrors the inclusion geo shape: excluded cities can carry a radius catchment and excluded custom (lat/lng) pins are supported, both on Meta (excluded_geo_locations).
      - `countries` string[]
      - `regions` object[]
        - `key` string, required
        - `name` string
      - `cities` object[] — Cities to exclude. Optional `radius` + `distanceUnit` exclude a catchment around the city (both must be set together or both omitted); Meta honours the radius on excluded cities.
        - `key` string, required
        - `radius` number — Radius around the excluded city. Requires distanceUnit.
        - `distanceUnit` 'mile' | 'kilometer' — Required if radius is set.
      - `zips` object[]
        - `key` string, required
        - `name` string
      - `places` object[] — Named points of interest to exclude. `key` from /v1/ads/targeting/search.
        - `key` string, required
      - `neighborhoods` object[] — Named neighbourhood areas to exclude. `key` from /v1/ads/targeting/search.
        - `key` string, required
      - `customLocations` object[] — Point-radius (lat/lng) pins to exclude (Meta excluded_geo_locations.custom_locations). Mirrors the inclusion customLocations shape.
        - `latitude` number, required
        - `longitude` number, required
        - `radius` number, required — Positive radius around the point.
        - `distanceUnit` 'mile' | 'kilometer', required
        - `name` string
        - `address` string — Optional label, sent to Meta as `address_string`. latitude/longitude take precedence for the pin location.
    - `ageMin` integer
    - `ageMax` integer
    - `gender` 'all' | 'male' | 'female' — Restrict by gender. 'all' (default) targets everyone. Applied on Meta, TikTok and Pinterest. Ignored on Google, LinkedIn and X.
    - `incomeTier` 'top_5' | 'top_10' | 'top_10_25' | 'top_25_50' — Normalized household-income tier (ZIP/percentile based). Meta and TikTok express all four. Google maps only `top_10` (its INCOME_RANGE_90_UP); other tiers on Google, and any income tier on LinkedIn / X / Pinterest, are rejected. On Meta, income/zip targeting requires the relevant `specialAdCategories` to be unset (housing/employment/credit ads cannot use it).
    - `languages` string[] — Language codes restricting the audience by language. On Meta, ISO 639-1 codes (e.g. ['en']); a bare code targets all regional variants ("en" = all English), or use a region-qualified code ("en_GB", "pt_BR") for a specific one. Unknown codes are rejected.
    - `interests` object[] — Interest entities from /v1/ads/targeting/search?dimension=interest. Each carries the platform's opaque id.
      - `id` string, required
      - `name` string
    - `behaviors` object[] — Behaviour entities from /v1/ads/targeting/search?dimension=behavior. Supported on Meta and TikTok.
      - `id` string, required
      - `name` string
    - `industries` string[] — LinkedIn B2B only. Industry URN id fragments.
    - `companySizes` string[] — LinkedIn B2B only.
    - `seniorities` string[] — LinkedIn B2B only.
    - `jobFunctions` string[] — LinkedIn B2B only.
    - `audienceInclude` string[] — Platform audience IDs to include.
    - `audienceExclude` string[] — Platform audience IDs to exclude.
  - `optimizationGoal` string — Optional. The optimization goal the estimate should assume (platform's own vocabulary, e.g. Meta `REACH`, `LINK_CLICKS`, `OFFSITE_CONVERSIONS`). Some platforms vary the estimate by goal; omit to use the platform default.

## Response `200`

Normalized reach estimate

- object
  - `available` boolean, required — Whether a pre-flight estimate is available on this platform. False for Google and TikTok.
  - `lower` integer, nullable — Lower bound of the estimated reachable audience. Present only when available.
  - `upper` integer, nullable — Upper bound of the estimated reachable audience. Present only when available.
  - `daily` integer, nullable — Optional estimated daily reach/results at the given budget, when the platform returns it.
  - `currency` string, nullable — Currency of any monetary fields in the estimate, when applicable.
  - `estimateReady` boolean, nullable — Meta only. False when Meta is still computing the estimate (the audience is too new); retry shortly.

## Other responses

- `400` — Missing required fields or a targeting field the platform cannot honour
- `401` — Unauthorized
- `403` — Ads access required. Legacy plans need the Ads add-on; included by default on usage-based plans.
- `404` — Resource not found

---

[API](https://skmtc.net/zernio/apis/zernio-api.md) · [All operations](https://skmtc.net/zernio/apis/zernio-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/zernio/zernio-api/revisions/f81ca70ea6b9/schema)
