---
title: "Targeting rules via API"
description: "The targeting endpoint pattern on all six entity levels, all 41 creatable dimensions with their create parameters, INCLUDE/EXCLUDE/MATCH/NOT_MATCH, the three permission checks, value lookups, curl examples, preset groups and category rules."
type: "reference"
audience: [network-manager, admin]
keywords: [api, targeting, pretargeting, dimensions, rule, include, exclude, match, presets, preset groups, value lookups, dmp, category rules, curl]
---

Fetch the complete documentation index at: https://epom.com/ad-server/docs/llms.txt. Use this file to discover all available pages before exploring further. Append .md to any documentation page URL to get its markdown version.

# Targeting rules via API

Targeting rules (demand side) and pretargeting rules (supply side) over REST: the one endpoint
pattern every entity level shares, the parameters of each of the 41 creatable dimensions, the
permission checks, the value lookups, worked examples, preset groups and category rules. Examples
append [`$AUTH`](https://epom.com/ad-server/docs/api.md#the-auth-shorthand), the hash-authentication parameters (an
`X-Api-Key` header works the same) — see the [API overview](https://epom.com/ad-server/docs/api.md) for authentication. Capping,
limits and pricing are on their own pages — see [Targeting, capping and limits via
API](https://epom.com/ad-server/docs/api/targeting-capping-limits.md).

## Who this is for

Developers who script delivery control for a network — network managers, and
publisher or advertiser users whose role holds the permissions named below. The calls behave the
same for every role; what differs is which entities and dimensions your role may change.

## Targeting: the endpoint pattern

Targeting rules exist on six entity levels. Demand side: **advertiser**, **campaign**,
**banner**. Supply side (pretargeting): **site**, **zone**, **placement**. Each level has the
same eight management operations:

```
GET    /rest-api/{entity}/{entityId}/targetings.do                     list rules (filters: targetType, rule)
GET    /rest-api/{entity}/{entityId}/targeting/{targetId}.do           get one rule
DELETE /rest-api/{entity}/{entityId}/targeting/{targetId}/delete.do    delete one rule
DELETE /rest-api/{entity}/{entityId}/targetings.do                     delete all rules (filters: targetType, rule)
POST   /rest-api/{entity}/{entityId}/targeting/enable.do               enable targeting on the entity
POST   /rest-api/{entity}/{entityId}/targeting/disable.do              disable targeting on the entity
POST   /rest-api/{entity}/{entityId}/targeting/operation-between-rule-types.do   AND / OR between rule types
GET    /rest-api/{entity}/{entityId}/targeting/types.do                dimensions available to you
```

plus one `POST …/targeting/{dimension}/create.do` per dimension and sixteen `values.do`
lookups. `{entity}` is `advertiser`, `campaign`, `banner`, `site`, `zone` or `placement` —
singular in the path.

| Level | Operations | Create endpoints |
|---|---|---|
| `advertiser`, `campaign`, `banner` | 64 each | 40 |
| `placement` | 63 | 39 |
| `site`, `zone` | 62 each | 38 |

The difference is entirely entity blocking: every one of the 38 ordinary dimensions exists on
all six levels, and only the three blocking dimensions are restricted (see the table below).
The operations are the eight above, the create endpoints and the sixteen lookups.

Every create call takes a `rule` parameter: `INCLUDE` (whitelist) or `EXCLUDE`
(blacklist). It is required everywhere except on `browser` at the advertiser, campaign, site and
zone levels, where leaving it out gives `INCLUDE`. `MATCH` / `NOT_MATCH` compare a pattern and are
accepted on `channel` only — on any other dimension they are a `400`.

> **Corner case:** values are checked the way the console's form checks them, and a value
> outside its range is a `400` naming the field and the range, with nothing created:
> `ipFrom`/`ipTo` must be IP addresses (`10.0.0.300` is refused rather than read as `0.0.0.0`,
> which would widen the rule to almost every address), `timeFrom`/`timeTo` are `HH:mm` or
> `HH:mm:ss` from `00:00` to `24:00` (also on `date-time`; see the note below the dimension
> tables), browser,
> hardware and platform ranks and `deviceRam` are 1–999999, `deviceReleaseYear` is 1992 to
> next year, `priceBand` 0–99999, screen width and height 0–9999, and `cookieName` /
> `cookieValue` must not be blank. `mobileCarriers` is required, and the carriers of one call
> are created together. A comma-separated id list (`placementId`, `siteId`, `advertiserIds`)
> with something that is not a number is a `400` naming it.

> **Note:** creating a rule **auto-enables targeting** on the entity if it was disabled — the
> first successful create switches `enableTargeting` on. You don't need a separate enable call.

> **Corner case:** demand-side calls require the *Manage Demand Targeting* user permission
> plus UPDATE access to the entity; supply-side calls (site, zone, placement) require
> *Manage Supply Pre-targeting* instead — the demand permission does not open them.
> `targeting/types.do` reflects your per-dimension permissions — a dimension missing
> from its output will be rejected on create, and a rule of that dimension cannot be
> deleted either: `403` on the single delete, and on the delete-all call nothing at all
> is deleted. The `403` message names what is missing — the dimension and its permission
> (`Your role cannot use DATE_TIME targeting: it lacks the TARGETING_DAY_TIME permission.`),
> the user permission (`MANAGE_DEMAND_TARGETING`) or the access to the entity.

> **Corner case:** creating a rule that already exists is idempotent: `200`, no second rule
> is stored, and the answer is the stored rule (its `id`) marked `"alreadyExisted": true`.
> A multi-value create (several `countryCode`s) saves the new values and answers the list,
> the values that were already there marked the same way. A rule that differs — the same
> value with the other `rule` (`INCLUDE` / `EXCLUDE`) — is a new rule. A call that stores nothing
> new does not switch targeting on either: on an entity whose targeting is off, re-posting a rule
> it already holds leaves it off.

## Targeting dimensions

Forty-one dimensions are creatable over REST. The path segment is kebab-case; the `targetType`
filter on `targetings.do` uses the **enum name** instead, and for six dimensions the two do not
resemble each other — those are called out in the tables.

Parameters marked `*` are required. `rule` is required on every create except `browser`.
The tables name what each dimension needs; all fields of a create call, with descriptions and an
example request, are in the generated [targeting rules reference](https://epom.com/ad-server/docs/api/targeting-rules.md) —
for example
[`POST /rest-api/campaign/{campaignId}/targeting/country/create.do`](https://epom.com/ad-server/docs/api/targeting-rules-campaign.md#post-rest-apicampaigncampaignidtargetingcountrycreatedo).
Each level has its own reference page:
[advertiser](https://epom.com/ad-server/docs/api/targeting-rules-advertiser.md), [campaign](https://epom.com/ad-server/docs/api/targeting-rules-campaign.md),
[banner](https://epom.com/ad-server/docs/api/targeting-rules-banner.md), [site](https://epom.com/ad-server/docs/api/targeting-rules-site.md),
[zone](https://epom.com/ad-server/docs/api/targeting-rules-zone.md), [placement](https://epom.com/ad-server/docs/api/targeting-rules-placement.md); the endpoints
shared by every level are on [Targeting Rules API endpoints](https://epom.com/ad-server/docs/api/targeting-rules.md).

| Group | Dimension segments |
|---|---|
| Geography | `country`, `browser-country`, `location`, `ip-range` |
| Time | `time-range`, `day-of-week`, `date-time` |
| Device & browser | `operating-system`, `browser`, `device-format`, `device-vendor`, `device-ram`, `device-release-year`, `screen-resolution`, `hardware-rank`, `platform-rank`, `browser-rank` |
| Network & connection | `mobile-carrier`, `connection-type`, `wifi-traffic`, `proxy`, `protocol`, `traffic-source` |
| Context | `domain`, `app-package`, `channel`, `language`, `is-web-app`, `incognito-mode` |
| Data & API | `custom` (custom parameters), `cookie-value`, `api-json-field`, `price-band`, `traffic-risk-score`, `dmp` (audience segments) |
| Presets | `preset-domain`, `preset-app-package`, `preset-ip-ranges` |
| Entity blocking | `site`, `placement` (demand side: block sites/placements); `advertiser` (placement level only: block advertisers) |

### Geographic

| Segment | `targetType` | Create parameters |
|---|---|---|
| `country` | `COUNTRY` | `countryCode*` (array of ISO alpha-2), `rule*` |
| `browser-country` | `BROWSER_COUNTRY` | `countryCode*` (array), `rule*` |
| `location` | `LOCATION` | `countryCode*`, `rule*`, `regionName`, `cityName` |
| `language` | `LANGUAGE` | `languageCode*`, `rule*` |
| `mobile-carrier` | `MOBILE_CARRIER` | `rule*`, `mobileCarriers*` (array; names as `targeting/mobile-carrier/bycountry/values.do` lists them) |

### Temporal

| Segment | `targetType` | Create parameters |
|---|---|---|
| `time-range` | `TIME_RANGE` | `timeFrom*`, `timeTo*`, `rule*`, `clientLocalTime` |
| `day-of-week` | `DAY_OF_WEEK` | `dayOfWeek*` (`MONDAY`…`SUNDAY`), `rule*` |
| `date-time` | `DATE_TIME` — labelled **Day and Time** | `timeFrom*`, `timeTo*`, `rule*`, `dayOfWeek` (array), `clientLocalTime` |

`clientLocalTime` is optional on both and defaults to `false` — the ad server's time, not the
visitor's. On `date-time`, `dayOfWeek` is optional too: left out, the rule covers every day. The
path `…/targeting/datetime/create.do` is accepted as an alias of `date-time`.

> **Corner case:** `timeFrom` and `timeTo` take `HH:mm` or `HH:mm:ss`, from `00:00` to `24:00`.
> The seconds are dropped — `09:00:30` is stored as 09:00 — and `24:00` is the end of the day
> (stored as minute 1440; the ad server matches it like `23:59`), so `18:00` to `24:00` covers
> the evening. `25:00`, `24:30`, `24:00:01`, a minute or second of `60` and anything that is not
> a time are a `400` naming the field: `timeTo must be a time from 00:00 to 24:00 (HH:mm[:ss]),
> got 25:00.`

### Device and browser

| Segment | `targetType` | Create parameters |
|---|---|---|
| `operating-system` | `OPERATING_SYSTEM` | `operatingSystem*` (25 values), `rule*`, `version`, `relation` (required when `version` is sent) |
| `browser` | `BROWSER` | `browser*` (69 values), `rule` (required on banner and placement), `browserVersion`, `relation` |
| `device-format` | `DEVICE_FORMAT` | `deviceFormat*` (`DESKTOP`, `TABLET`, `MOBILE`, `SMART_TV`), `rule*` |
| `device-vendor` | `DEVICE_VENDOR` | `deviceVendor*` (39 values), `rule*` |
| `screen-resolution` | `RESOLUTION` | `relation*`, `screenWidth*`, `screenHeight*`, `rule*` |
| `protocol` | `PROTOCOL` | `protocol*` (`HTTP`, `HTTPS`), `rule*` |
| `wifi-traffic` | `WIFI_TRAFFIC` | `rule*` |
| `is-web-app` | `IS_WEB_APP` | `rule*` |
| `incognito-mode` | `INCOGNITO_MODE` | `rule*` |

`relation` is `LOWER`, `GREATER`, `LOWER_EQUAL`, `GREATER_EQUAL` or `EQUAL` everywhere it
appears. `operatingSystem` covers desktop, mobile and connected-TV platforms
(`SAMSUNG_TIZEN`, `LG_WEB_OS`, `ROKU_TV_OS`, `AMAZON_FIRE_TV`, `APPLE_TV`, `ANDROID_TV` among
them); `browser` covers in-app webviews (`FACEBOOK_APP`, `TIKTOK_APP`, `INSTAGRAM_APP`, …) as
well as browsers. Get the exact current lists from `…/targeting/operating-system/values.do`
and `…/targeting/browser/values.do` rather than hardcoding them.

> **Corner case:** the three boolean dimensions — `wifi-traffic`, `is-web-app`,
> `incognito-mode` — take **no value parameter at all**. `rule=INCLUDE` means "only this
> traffic", `rule=EXCLUDE` means "never this traffic". There is nothing else to send.

> **Corner case:** `browser` is the one create endpoint where `rule` is **optional** — on the
> advertiser, campaign, site and zone levels; on banner and placement it is required like
> everywhere else. Every other dimension rejects a create without it.

### Device scores and specs

| Segment | `targetType` | Create parameters |
|---|---|---|
| `device-release-year` | `DEVICE_RELEASE_YEAR` | `deviceReleaseYear*` (integer), `rule*`, `relation` |
| `device-ram` | `DEVICE_RAM` | `deviceRam*` (integer), `rule*`, `relation` |
| `browser-rank` | `BROWSER_RANK` | `browserRank*` (integer), `rule*`, `relation` |
| `hardware-rank` | `HARDWARE_RANK` | `hardwareRank*` (integer), `rule*`, `relation` |
| `platform-rank` | `PLATFORM_RANK` | `platformRank*` (integer), `rule*`, `relation` |
| `price-band` | `PRICE_BAND` | `priceBand*` (number), `rule*`, `relation` |

`relation` is optional on the advertiser, campaign, site and zone levels and **required** on
banner and placement. Left out, it is `GREATER_EQUAL` on `device-release-year`, `device-ram` and
`traffic-risk-score` and `LOWER_EQUAL` on the three ranks and `price-band` — so send it, rather
than rely on a default that differs by dimension.

### Content and apps

| Segment | `targetType` | Create parameters |
|---|---|---|
| `domain` | `DOMAIN` | `domain*`, `rule*` |
| `channel` | `CHANNEL` | `channel*`, `rule*` |
| `app-package` | `APP_PACKAGE` | `appPackage*`, `rule*` |
| `cookie-value` | `COOKIE_VALUE` | `cookieName*`, `cookieValue*`, `rule*` |
| `custom` | `CUSTOM` — labelled **Custom Parameter** | `customValue*`, `rule*`, `customType`, `operation`, `parameter` |

`custom` is the most configurable of the set: `customType` is `EXPRESSION`, `VALUE`, `ONE_OF`
or `SUBSTRING`, and `operation` is one of `EQUALS`, `NOT_EQUALS`, `CONTAINS`, `NOT_CONTAINS`,
`GREATER`, `GREATER_OR_EQUALS`, `LESS`, `LESS_OR_EQUALS`, `IN`, `NOT_IN`. `parameter` names the
custom parameter to read.

### Network

| Segment | `targetType` | Create parameters |
|---|---|---|
| `ip-range` | `IP_RANGE` | `ipFrom*`, `ipTo*`, `rule*` |
| `proxy` | `PROXY` | `proxy*` (`VPN`, `TOR`, `DCH`, `PUB`, `WEB`, `SES`), `rule*` |
| `connection-type` | `CONNECTION_TYPE` | `connectionType*` (`UNKNOWN`, `DIALUP`, `CABLE_DSL`, `CORPORATE`, `CELLULAR`, `WI_FI`), `rule*` |
| `traffic-source` | `TRAFFIC_SOURCE` | `trafficSource*`, `rule*` — `trafficSource` currently has exactly one value, `HEADER_BIDDING` |

### Presets

Preset targeting references a reusable group by ID rather than carrying values inline. Note
that two of the three path segments are singular where the enum name is plural.

| Segment | `targetType` | Create parameters |
|---|---|---|
| `preset-domain` | `PRESET_DOMAINS` | `domainGroupId*` (integer), `rule*` |
| `preset-app-package` | `PRESET_APP_PACKAGES` | `appPackageGroupId*` (integer; `presetApplicationPackageGroupId*` on the banner level), `rule*` |
| `preset-ip-ranges` | `PRESET_IP_RANGES` | `presetIpRangesGroupId*` (integer; `ipRangesGroupId` is accepted as the same value, and one of the two is required), `rule*` |

### Data, API and risk

| Segment | `targetType` | Create parameters |
|---|---|---|
| `api-json-field` | `API_JSON_FIELD` | `apiUrl*`, `jsonField*` (`jsonFieldName*` on the banner level), `jsonFieldValue*`, `rule*` |
| `traffic-risk-score` | `TRAFFIC_RISK_SCORE` | `riskLevel*`, `rule*`, `relation`, `riskCategory` (array) |

`riskLevel` is `NOT_SCORED`, `LOW`, `LIKELY`, `HIGH`, `VERY_HIGH` or `CERTAIN` (the enum also
holds the internal states `SERVICE_DISABLED` and `ERROR`, which the API does not list as accepted
values). `riskCategory` takes any of 25 fraud categories (`HIGH_RISK_IP`, `APP_SPOOFING`,
`DATACENTER`, `CLICK_FARM`, `TOR`, …) — the generated
[targeting-rules reference](https://epom.com/ad-server/docs/api/targeting-rules.md) lists them in full.

### Entity blocking

These three are the only asymmetric dimensions, and they are not offered in the UI's
add-targeting combo either — they are reached through the blocked-entity screens.

| Segment | `targetType` | Levels | Create parameters |
|---|---|---|---|
| `site` | `BLOCKED_SITES` | advertiser, campaign, banner | `siteId*`, `rule*` |
| `placement` | `BLOCKED_PLACEMENTS` | advertiser, campaign, banner | `placementId*`, `rule*` |
| `advertiser` | `BLOCKED_ADVERTISERS` | **placement only** | `advertiserIds*`, `rule*` |

The three take several ids in one comma-separated parameter (`siteId=11,12`,
`placementId=…`, `advertiserIds=…`). The answer lists the ids blocked now in `created` and those
that already were in `alreadyTargeted`; an unknown or deleted id refuses the whole call and
nothing is created. A created target also switches the entity's targeting on. On a placement,
every advertiser must also be one you may update (an update share, or campaign update at *All*
level).

Read an advertiser's blocked inventory back with:

```
GET /rest-api/target/advertiser/{advertiserId}/blocked-placements.do
GET /rest-api/target/advertiser/{advertiserId}/blocked-sites.do
```

### Two dimensions the API cannot create

There are **43** targeting types; 41 have a create endpoint. The two without one are:

| `targetType` | Label | Where it lives |
|---|---|---|
| `BLOCKED_BANNERS` | Blocked Banners | UI only — supply-side blocked-entity screens |
| `BLOCKED_CAMPAIGNS` | Blocked Campaigns | UI only — supply-side blocked-entity screens |

Both still appear in the `targetType` filter enum on `targetings.do`, so rules created in
the UI are readable and deletable over the API — just not creatable.

> **Note:** three counts describe the same enum and are easy to confuse. **43** rule types
> exist. **41** have a REST create endpoint (all but the two banner/campaign blocking
> types — `POST .../targeting/dmp/create.do` covers DMP audience segments too). **38**
> appear in the UI's add-targeting picker — that list excludes all five blocking
> types, which are reached from the blocked-entity screens instead. See
> [Targeting dimensions](https://epom.com/ad-server/docs/reference/targeting-dimensions.md) for the UI-side view.

## Rules: `INCLUDE`, `EXCLUDE`, `MATCH`, `NOT_MATCH`

The `rule` parameter accepts four values. `MATCH` and `NOT_MATCH` compare a pattern and are
meaningful on `channel` only:

| Rule | Meaning | Accepted on |
|---|---|---|
| `INCLUDE` | Whitelist — serve only on matching traffic | Every dimension |
| `EXCLUDE` | Blacklist — never serve on matching traffic | Every dimension |
| `MATCH` | Pattern match against the value | `channel` only |
| `NOT_MATCH` | Inverse pattern match | `channel` only |

> **Corner case:** `MATCH` / `NOT_MATCH` apply to Channel targeting only. On any other
> dimension the create call refuses them with a `400` naming the dimension (`rule MATCH applies
> to channel targeting only; use INCLUDE or EXCLUDE for DOMAIN.`).

## Permissions

Three separate checks run on every targeting call, and they are easy to conflate:

| Check | Demand side (advertiser, campaign, banner) | Supply side (site, zone, placement) |
|---|---|---|
| User-level permission | *Manage Demand Targeting* | *Manage Supply Pre-targeting* |
| Entity access | UPDATE on the entity, via campaign sharing | UPDATE on the entity, via inventory sharing |
| Per-dimension permission | `TARGETING_<DIMENSION>` | `PRETARGETING_<DIMENSION>` |

> **Corner case:** on sites, zones and placements the user-level permission is *Manage Supply
> Pre-targeting*, not *Manage Demand Targeting*. A supply-side role needs only the pretargeting
> permissions.

`GET …/targeting/types.do` returns the dimensions your role may use on that entity, already
filtered. A dimension missing from its output will be rejected on create with `403`, so use it
for discovery rather than hardcoding the list of forty-one.

## Value lookups

Enumerated values are served by sixteen lookup endpoints that are **identical on all six entity
levels**:

```
GET …/targeting/browser/values.do
GET …/targeting/browser/chrome/values.do        (also /firefox, /ie, /safari — version lists)
GET …/targeting/connection-type/values.do
GET …/targeting/country/region/values.do
GET …/targeting/country/region/city/values.do
GET …/targeting/device-format/values.do
GET …/targeting/device-vendor/values.do
GET …/targeting/language/values.do
GET …/targeting/mobile-carrier/values.do
GET …/targeting/operating-system/values.do
GET …/targeting/operating-system/{osName}/versions.do
GET …/targeting/screen-resolution/values.do
GET …/targeting/traffic-source/values.do
```

Three more are global — no entity in the path:

```
GET /rest-api/targeting/operating-system/values.do
GET /rest-api/targeting/operating-system/{osName}/versions.do
GET /rest-api/targeting/mobile-carrier/bycountry/values.do
```

The other dimensions take free-form or enum values documented in the tables above; they have no
lookup endpoint.

The geography, language and DMP lists also exist without an entity in the path, so a
script can look them up before it has anything to target. They need *Manage Demand
Targeting* or *Manage Supply Pre-targeting* (read-only is enough):

```
GET /rest-api/targeting/country/values.do                              {"US": "United States", ...}
GET /rest-api/targeting/country/region/values.do?countryCode=US        region names
GET /rest-api/targeting/country/region/city/values.do?countryCode=US&regionName=California
GET /rest-api/targeting/language/values.do                             {"en": "English", ...}
GET /rest-api/targeting/dmp/values.do                                  [{"dmp": "FIRST_PARTY", "name": "First-Party"}, ...]
GET /rest-api/targeting/dmp/{dmp}/segments.do?parentId=                one level of the segment tree
```

An unknown `countryCode` answers `400`. The country list comes from the geo service; when that
service does not answer, `country/values.do` and `mobile-carrier/bycountry/values.do` answer
`503` rather than an empty object — retry it. `dmp/values.do` lists only the DMPs your role
holds the permission of, and `dmp/{dmp}/segments.do` answers `403` for any other DMP. Each
segment entry carries `id`, `title` and `segment` — `false` marks a folder: pass its `id`
as `parentId` to open it. Only entries with `segment: true` can be targeted.

## Targeting examples

Target a campaign at the US and Germany:

```bash
curl -X POST "https://<your-network-domain>/rest-api/campaign/2001/targeting/country/create.do?$AUTH" \
  -d "countryCode=US" -d "countryCode=DE" \
  -d "rule=INCLUDE"
```

`countryCode` can also be one comma-separated value (`countryCode=US,DE`); each code is
trimmed and upper-cased. The same holds for `country/create.do` and `browser-country/create.do`
on sites, zones and placements — every level takes several codes in one call.

Only serve on Windows 10 or newer:

```bash
curl -X POST "https://<your-network-domain>/rest-api/campaign/2001/targeting/operating-system/create.do?$AUTH" \
  -d "operatingSystem=WINDOWS" \
  -d "version=10" -d "relation=GREATER_EQUAL" \
  -d "rule=INCLUDE"
```

`version` is one of the entries of `operating-system/{osName}/versions.do`: its `version`
value (`10.0`, `16.-1`) or its `versionTitle` (`10`, `iOS 16.x.x`). Anything else answers
`400` with the list of valid versions, and so does a `version` on an OS that has no version
list (Linux, Chrome OS…) — the rule is never saved as "every version". A `version` needs a
`relation` (`EQUAL`, `GREATER_EQUAL`, …): without one the ad server would ignore the version,
so it is a `400` too. The versions list names each version once (Android 12 and 12L share
`12.-1`), and a saved OS rule reads back `operatingSystem`, `relation` and `version` next to its
encoded `value`. Browsers differ: a
`browserVersion` on a browser without version targeting (the ones the console offers no
version field for) is not applied — the rule is saved on the whole browser, and the answer
lists `browserVersion` in `ignoredFields` with the reason in `ignoredFieldReasons`. On a browser
that does take a version, a `browserVersion` the server cannot read is still a `400`.

Business hours only, in the visitor's local time:

```bash
curl -X POST "https://<your-network-domain>/rest-api/campaign/2001/targeting/time-range/create.do?$AUTH" \
  -d "timeFrom=09:00" -d "timeTo=17:00" \
  -d "clientLocalTime=true" \
  -d "rule=INCLUDE"
```

List, then delete a rule — note that the filter takes the **enum name**, not the path segment:

```bash
curl "https://<your-network-domain>/rest-api/campaign/2001/targetings.do?$AUTH&targetType=COUNTRY"
curl -X DELETE "https://<your-network-domain>/rest-api/campaign/2001/targeting/987/delete.do?$AUTH"
```

Delete every EXCLUDE rule on a campaign, or every rule when you leave the filters out:

```bash
curl -X DELETE "https://<your-network-domain>/rest-api/campaign/2001/targetings.do?$AUTH&rule=EXCLUDE"
# → {"success":true,"deleted":3}
```

Targeting stays enabled after the rules are gone, as in the console.

A rule read back (`targeting/{targetId}.do`, `targetings.do`) carries, next to the stored
`value`, the fields its create operation takes — under the same names, with enums as names — so
it can be compared with what you sent. `value` itself is the internal encoding and
is kept only for existing clients.

> **Corner case:** a threshold rule sent without `relation` (possible on every level but banner and
> placement) is saved with a default, which
> the read shows: `LOWER_EQUAL` for the browser, hardware and platform ranks and the price band,
> `GREATER_EQUAL` for device RAM, release year and traffic risk. `date-time` without
> `dayOfWeek` covers every day. The preset IP ranges group is `presetIpRangesGroupId` on
> every entity (`ipRangesGroupId` is accepted too).

Serve when **any** rule type matches instead of all of them:

```bash
curl -X POST "https://<your-network-domain>/rest-api/campaign/2001/targeting/operation-between-rule-types.do?$AUTH" \
  -d "operator=OR"
# → {"success":true,"operationBetweenRuleTypes":"OR"}
```

Rules of one type always combine with OR; `operator` decides how the types combine
(`AND`, the default, or `OR`). It needs the *Manage Operation Between TargetingRule Types*
permission on top of the side's targeting permission.

Target a DMP audience segment:

```bash
curl -X POST "https://<your-network-domain>/rest-api/campaign/2001/targeting/dmp/create.do?$AUTH" \
  -d "dmp=FIRST_PARTY" -d "dmpSegmentId=4812" \
  -d "rule=INCLUDE"
```

`dmpSegmentId` is an `id` from `dmp/{dmp}/segments.do`. A segment of another DMP, or one
that does not exist, answers `400`; a DMP your role has no permission for answers `403`.

## Preset groups

Presets are reusable lists (domains, app packages, IP ranges) referenced by preset targeting
rules. Each family has eight operations. The three families are *almost* symmetrical, and the
differences are all in the path:

| Purpose | Domains | App packages | IP ranges |
|---|---|---|---|
| List groups | `GET /rest-api/preset-domain/group/list.do` | `GET /rest-api/preset-app-package/group/list.do` | `GET /rest-api/preset-ip-ranges/ip-ranges/list.do` |
| Create/rename a group | `POST …/group/save.do` | `POST …/group/save.do` | `POST …/group/save.do` |
| Bulk upload entries | `POST …/group/upload-domains.do` | `POST …/upload-packages.do` | `POST …/group/upload-ip-ranges.do` |
| Add one entry | `POST …/domain/add.do` | `POST …/add.do` | `POST …/ip-range/add.do` |
| List entries of a group | `GET …/domain/all-by-group.do` | `GET …/all-by-group.do` | `GET …/ip-range/all-by-group.do` |
| Delete one entry | `DELETE …/domain/delete.do` | `DELETE …/delete.do` | `DELETE …/ip-range/delete.do` |
| Empty a group | `DELETE …/group/clear.do` | `DELETE …/group/clear.do` | `DELETE …/group/clear.do` |
| Delete a group | `DELETE …/group/delete.do` | `DELETE …/group/delete.do` | `DELETE …/group/delete.do` |

> **Corner case:** adding an entry a group already has is a `400` naming it, on all three
> families, and nothing is added.

> **Corner case:** the entry paths differ per family. Domains nest under `/domain/`, IP ranges
> under `/ip-range/`, and app-package entries sit directly under `/preset-app-package/` with no
> sub-segment. The IP-range group list is `/ip-ranges/list.do`, not `/group/list.do`.

## Category rules (rules engine)

Separate from targeting rules, the rules engine pairs inventory and demand by category or
label. Rules are created globally, then attached per entity — 55 operations in all:

| Method | Path | Purpose |
|---|---|---|
| POST | `/rest-api/rule/create.do` | Create a rule |
| GET | `/rest-api/rules.do` | List rules |
| GET | `/rest-api/rule/{ruleId}.do` | Get a rule |
| POST | `/rest-api/rule/{ruleId}/update.do`, `/delete.do` | Update / delete |
| POST | `/rest-api/rule/{ruleId}/matches/add.do`, `/matches/remove.do` | Manage match conditions |
| POST | `/rest-api/rules/{entity}/{entityId}/add.do`, `/remove.do`, `/enable.do`, `/disable.do` | Attach/detach/toggle on advertiser, campaign, banner, placement, site, zone. POST only — a `GET` gets 405 |
| GET | `/rest-api/rules/{entity}/{entityId}/get.do` | The entity's rule groups and `rulesEnabled` — the groups are listed whether or not rules are switched on |
| GET | `/rest-api/rules/{entity}/available-types.do`, `/available-rules.do`, `/show-details.do` | Discovery |

`{entity}` is `advertiser`, `campaign`, `banner`, `placement`, `site` or `zone` — all six, with
the same eight operations each.

> **Corner case:** `add.do` takes `ruleIds`, `include` and `operator`; if any id in `ruleIds`
> is not an existing rule the call is a `400` naming the unknown ids and no group is created.
> The answer carries `rulesEnabled`; when the entity's rules are switched off it adds a
> `warning` — the group is saved but does nothing until `enable.do`.
> `remove.do?ruleGroupId=…` deletes the group only if it belongs to the entity in the path —
> a group of another entity, or an unknown id, is a `404` and nothing is deleted.
> Reading needs view rights on the entity: `get.do` is a `403` without them, and
> `show-details.do?ruleGroupId=…` answers only for a group attached to an entity of the path's
> type that you may view — any other id is a `404`. Neither needs *Manage Rules*.

## Related

- [Targeting, capping and limits via API](https://epom.com/ad-server/docs/api/targeting-capping-limits.md) — the overview
- [API overview](https://epom.com/ad-server/docs/api.md)
- [Frequency capping via API](https://epom.com/ad-server/docs/api/capping-api.md)
- [Delivery limits via API](https://epom.com/ad-server/docs/api/limits-api.md)
- [Price rules, bid floors and pricing via API](https://epom.com/ad-server/docs/api/price-rules-and-floors-api.md)
- [Entities CRUD](https://epom.com/ad-server/docs/api/entities-crud.md)
- [Generated reference: targeting rules](https://epom.com/ad-server/docs/api/targeting-rules.md)
- [Targeting dimensions reference](https://epom.com/ad-server/docs/reference/targeting-dimensions.md)
- [Add targeting (UI guide)](https://epom.com/ad-server/docs/guides/targeting/add-targeting.md)