Frequency capping via API
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.
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, the hash-authentication parameters
(an X-Api-Key header works the same) — see the API overview 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 a400(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
— the other kinds and the banner level are listed next to it.
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.dobehaves 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, callupdate.dowith itsid. On a bannerset.doandupdate.doare the same method: it upserts bysubject, 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-cappingis the only spelling that works.
Corner case:
GETon a kind with no records returns an empty array[](a missing campaign or banner is the404).DELETEremoves 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.
Warning: the two families name the same field differently. The typed endpoints call it
evenDistribution; the generic ones call itflat. Neither accepts the other’s name.amountis 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}.dois the one write endpoint with no category check — it passesnullfor the category. It is a full replace:amount,periodandperiodTypeare overwritten unconditionally;subjectis the only field preserved when omitted. Each capping kind numbers its records separately, so thetypeyou send decides which kind the ID is looked up in — send the wrongtypeand you address a different record.
Corner case: the banner and campaign
…-capping/update.doendpoints change only what you send:periodandperiodTypemay be left out to keep them.update.donever creates a rule: a bannerupdate.dofor a subject that has no rule of that kind, and a campaignupdate.donaming a cappingidthe campaign does not have, are a404naming the missing rule — create it withset.do. The campaign…-capping.doreads returnsubjectwith each rule, and an empty array[]when the campaign has no rule of that kind (a missing campaign is the404).
Corner case: bulk delete takes colon-joined
id:TYPEpairs, 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 a404. 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
403naming 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 a400naming anycampaignIdsit 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=IPneeds Capping IP Subject and one that setssubject=LES_IPneeds Capping Last External Source IP Subject, on the typed campaign and banner endpoints and on the generic family alike; without it the call is a403naming the permission and nothing is saved.
The full type/subject matrix as the UI presents it is in Capping matrix.