---
title: "Frequency capping via API"
description: "The 18 capping types and the entity each belongs to, the typed campaign/banner capping endpoints, the generic capping family on advertisers, campaigns, banners and placements, and the five capping subjects."
type: "reference"
audience: [network-manager, admin]
keywords: [api, capping, frequency, frequency capping, click capping, no-click capping, action capping, subject, evenDistribution, flat, 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.

# Frequency capping via API

Frequency, click, no-click, action and request capping over REST: which capping types each entity
accepts, the two endpoint families that set them, and the subjects that decide what counts as a
user. 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.

## 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.

## Capping

Two endpoint families coexist and they do **not** share a vocabulary. Pick one per integration.
A banner also has a shortcut of its own, `POST /rest-api/banner/{bannerId}/capping/frequency.do`
(and its `DELETE`, which removes every capping rule of the banner); it takes `amount` (required),
`periodType`, `period` and `flat`, named as in the generic family.

### The capping types

There are **18** capping types. They are plain names with no numeric IDs — send the name.
Each carries a category that decides which entity endpoint accepts it:

| Category | Types |
|---|---|
| `CAMPAIGN` | `CAMPAIGN_REQUEST`, `CAMPAIGN_FREQUENCY`, `CAMPAIGN_CLICKS`, `CAMPAIGN_ACTIONS`, `CAMPAIGN_NO_CLICK`, `CAMPAIGN_DSP_FREQUENCY`, `CAMPAIGN_DSP_FREQUENCY_MONTH`, `CAMPAIGN_DSP_RECENCY` |
| `BANNER` | `BANNER_REQUEST`, `BANNER_FREQUENCY`, `BANNER_CLICKS`, `BANNER_ACTIONS`, `BANNER_NO_CLICK` |
| `PLACEMENT` | `PLACEMENT_REQUEST`, `PLACEMENT_FREQUENCY`, `PLACEMENT_CLICKS`, `PLACEMENT_ACTIONS` |
| `ADVERTISER` | `ADVERTISER_FREQUENCY` |

> **Warning:** the three `CAMPAIGN_DSP_*` types are **rejected for every caller**: a create or
> update that names one is a `400` (`errors.type`: *CAMPAIGN_DSP_FREQUENCY capping is not set
> through this operation.*), whatever the role. They exist to carry DSP settings from the console,
> not as storable cappings, so they cannot be created or updated through any API path. The
> effective campaign ceiling is therefore the five non-DSP campaign types.

### Typed capping (campaign and banner)

One set of four operations per capping kind — `frequency-capping`, `click-capping`,
`no-click-capping`, `action-capping` — on campaigns and banners:

```
GET    /rest-api/campaign/{campaignId}/frequency-capping.do          read
POST   /rest-api/campaign/{campaignId}/frequency-capping/set.do      create
POST   /rest-api/campaign/{campaignId}/frequency-capping/update.do   update
DELETE /rest-api/campaign/{campaignId}/frequency-capping.do          remove every record of this kind
```

The same four exist for `banner/{bannerId}/…`. There is no typed endpoint for *request*
capping, even though `CAMPAIGN_REQUEST` and `BANNER_REQUEST` exist — use the generic family for
those.

Parameters: `period` and `periodType` (`SECOND`, `MINUTE`, `HOUR`, `DAY`, `WEEK`, `MONTH`,
`YEAR`) define the window — required on `set.do`, optional on `update.do`, where leaving them
out keeps the stored window; `amount` is optional (omit it for a window with no
event cap); `evenDistribution` spreads delivery across the window; `subject` identifies the
user and defaults to `USER_COOKIE`. Campaign `update.do` additionally requires `id`.
All fields, with descriptions and an example request:
[`POST /rest-api/campaign/{campaignId}/frequency-capping/set.do`](https://epom.com/ad-server/docs/api/capping.md#post-rest-apicampaigncampaignidfrequency-cappingsetdo)
— the other kinds and the banner level are listed next to it.

```bash
curl -X POST "https://<your-network-domain>/rest-api/campaign/2001/frequency-capping/set.do?$AUTH" \
  -d "amount=3" \
  -d "period=24" -d "periodType=HOUR" \
  -d "subject=USER_COOKIE" \
  -d "evenDistribution=true"
# → {"success":true,"id":501}
```

> **Warning:** `set.do` behaves differently on the two entity levels. On a **campaign** it
> creates a new record each time, so two calls with different values leave two coexisting caps;
> to change one, call `update.do` with its `id`. On a **banner** `set.do` and `update.do` are the
> same method: it upserts by `subject`, so a banner holds at most one cap per (kind, subject)
> pair and a second call overwrites the first.

> **Corner case:** three of the four kinds also answer on a camelCase alias
> (`/frequencyCapping`, `/clickCapping`, `/actionCapping`). **No-click capping does not** —
> `/no-click-capping` is the only spelling that works.

> **Corner case:** `GET` on a kind with no records returns an empty array `[]` (a missing campaign
> or banner is the `404`). `DELETE` removes **every** record of that kind on the entity, not one,
> and answers success when there was none.

### Generic capping (all four entity levels)

| Method | Path | Purpose |
|---|---|---|
| GET/POST | `/rest-api/advertiser/capping/{advertiserId}.do` | List / create advertiser capping |
| GET/POST | `/rest-api/campaign/capping/{campaignId}.do` | List / create campaign capping |
| GET/POST | `/rest-api/banner/capping/{bannerId}.do` | List / create banner capping |
| GET/POST | `/rest-api/placement/capping/{placementId}.do` | List / create placement capping |
| GET | `/rest-api/campaign/capping/bulk.do` | Cappings for many campaigns |
| POST | `/rest-api/capping/{cappingId}.do` | Update one capping record by ID |
| POST | `/rest-api/capping/delete.do` | Bulk delete |

Create parameters: `type` (a capping type name), `amount`, `period`, `periodType` and `flat`
are all **required**; `subject` is optional. `amount` must be 0–8,388,607 and `period` 1–255.
All fields, with descriptions and an example request:
[`POST /rest-api/campaign/capping/{campaignId}.do`](https://epom.com/ad-server/docs/api/capping.md#post-rest-apicampaigncappingcampaigniddo).

> **Warning:** the two families name the same field differently. The typed endpoints call it
> **`evenDistribution`**; the generic ones call it **`flat`**. Neither accepts the other's name.
> `amount` is optional on the typed endpoints and required on the generic ones.

> **Corner case:** each entity endpoint checks the *category* of the type you send and rejects a
> mismatch with "Capping type is incompatible with entity". It does **not** apply the narrower list the UI's
> capping-type combo shows, so the API accepts types the UI hides — all four `PLACEMENT_*` on a
> placement, for instance, where the combo may show three.

> **Corner case:** `POST /rest-api/capping/{cappingId}.do` is the one write endpoint with **no**
> category check — it passes `null` for the category. It is a full replace: `amount`, `period`
> and `periodType` are overwritten unconditionally; `subject` is the only field preserved when
> omitted. Each capping kind numbers its records separately, so the `type` you send decides which
> kind the ID is looked up in — send the wrong `type` and you address a different record.

> **Corner case:** the banner and campaign `…-capping/update.do` endpoints change only what you
> send: `period` and `periodType` may be left out to keep them. `update.do` never creates a
> rule: a banner `update.do` for a subject that has no rule of that kind, and a campaign
> `update.do` naming a capping `id` the campaign does not have, are a `404` naming the missing
> rule — create it with `set.do`. The campaign `…-capping.do` reads return `subject` with each
> rule, and an empty array `[]` when the campaign has no rule of that kind (a missing campaign
> is the `404`).

> **Corner case:** bulk delete takes colon-joined `id:TYPE` pairs, not bare IDs:
> `ids=501:CAMPAIGN_FREQUENCY&ids=502:BANNER_CLICKS`. The type is structurally required for the
> same table reason. A malformed pair fails the whole call with a generic error rather than a
> field error, and the permission check runs per ID and aborts the batch before any delete.

> **Corner case:** update and bulk delete reach only cappings of entities you may change —
> update access to the capping's advertiser, campaign or banner (or to the site, for a
> placement capping). A capping of anyone else's entity is a `403`, and an id that is not a
> capping of the given type is a `404`. One refused id in a bulk delete deletes nothing.

> **Corner case:** every capping write — create, update and delete, through these endpoints
> and in the console — needs the section permission enabled, as the capping lists need it to
> read: *Manage Inventory Capping* for a placement capping, *Manage Capping & Limitations*
> for an advertiser, campaign or banner capping. Without it the call is a `403` naming the
> permission; a role holding it read-only sees the caps and gets that refusal when it tries to
> change one. The list reads say the same instead of answering an empty list, and the bulk read
> is a `400` naming any `campaignIds` it does not know.

The four create calls (`POST …/capping/{entityId}.do`) answer the new record under
`capping` — `{"success":true,"capping":{"id":501,"type":"CAMPAIGN_FREQUENCY",…}}` — so its
`id` is at hand for a later update or delete.

### Capping subjects

`subject` picks what counts as "a user". Five values:

| `subject` | Meaning | Extra permission |
|---|---|---|
| `USER_COOKIE` | Cookie-based user — the default | none |
| `USER_SERVER_SIDE` | Server-side storage | none |
| `USER_MIXED` | Cookie plus server-side storage | none |
| `IP` | IP address | Capping IP Subject |
| `LES_IP` | Last external source IP | Capping Last External Source IP Subject |

> **Corner case:** a call that sets `subject=IP` needs *Capping IP Subject* and one that sets
> `subject=LES_IP` needs *Capping Last External Source IP Subject*, on the typed campaign and banner
> endpoints and on the generic family alike; without it the call is a `403` naming the permission
> and nothing is saved.

The full type/subject matrix as the UI presents it is in [Capping matrix](https://epom.com/ad-server/docs/reference/capping-matrix.md).

## 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)
- [Targeting rules via API](https://epom.com/ad-server/docs/api/targeting-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)
- [Generated reference: capping](https://epom.com/ad-server/docs/api/capping.md)
- [Capping matrix](https://epom.com/ad-server/docs/reference/capping-matrix.md)
- [Frequency capping (UI guide)](https://epom.com/ad-server/docs/guides/delivery/frequency-capping.md)