Browse the help center

Price rules, bid floors and pricing via API

Price adjustment rules on advertisers, campaigns and banners, country bid floors on placements, sites and banners, self-serve CPM floor rates, and the corner cases of entity pricing and CSV pricing uploads.

Reference network manager admin

Price adjustment rules, country bid floors and CPM floor rates over REST, plus the corner cases of entity pricing — country and action prices, CSV uploads, site and placement payment models. 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.

Price adjustment rules

Rules that multiply or override the gross price when a condition matches, on three levels — replace {level} with banner, campaign or advertiser. Ten operations per level:

GET    /rest-api/price-adjustment-rules/{level}/{entityId}/list.do
POST   /rest-api/price-adjustment-rules/{level}/{entityId}/create.do
GET    /rest-api/price-adjustment-rules/{level}/rule/{ruleId}.do
POST   /rest-api/price-adjustment-rules/{level}/rule/{ruleId}/update.do
DELETE /rest-api/price-adjustment-rules/{level}/rule/{ruleId}/delete.do
GET    /rest-api/price-adjustment-rules/{level}/condition-subjects.do
GET    /rest-api/price-adjustment-rules/{level}/condition-operators.do
GET    /rest-api/price-adjustment-rules/{level}/action-types.do
POST   /rest-api/price-adjustment-rules/{level}/{entityId}/enable.do
POST   /rest-api/price-adjustment-rules/{level}/{entityId}/disable.do

A rule is a condition plus an action:

ParameterValues today
conditionSubjectPLACEMENT — the only subject currently offered
conditionOperatorIS — the only operator currently offered
conditionValueThe ID of the entity to match
actionTypeMULTIPLY (gross × actionValue) or SET (gross := actionValue)
actionValueThe number the action applies
curl -X POST "https://<your-network-domain>/rest-api/price-adjustment-rules/campaign/2001/create.do?$AUTH" \
  -d "conditionSubject=PLACEMENT" \
  -d "conditionOperator=IS" \
  -d "conditionValue=4001" \
  -d "actionType=MULTIPLY" \
  -d "actionValue=1.5"

All fields, with descriptions and an example request: POST /rest-api/price-adjustment-rules/campaign/{entityId}/create.do — the advertiser and banner levels have the same operations.

The three discovery endpoints exist so a client can render the pickers without hardcoding those lists — worth calling if you build a UI on top, since the subject and operator sets are expected to grow.

Corner case: creating a rule auto-enables price adjusting on the entity. Rules cascade at serve time in the order advertiser → campaign → banner, so a banner-level rule is applied last and effectively wins. Rules only load for serving while the entity’s switch is on — disable.do pauses them all without deleting any; enable.do resumes them. Both need Manage Price Adjusting and update access to the owning advertiser.

Bid floors

Country-level minimum CPMs on placements, sites and banners:

MethodPathPurpose
GET/rest-api/bid-floor/placement/{placementId}.doRead placement bid floors
POST/rest-api/bid-floor/placement/{placementId}/update.doSet (country* = ISO alpha-2 code or * for the global default, bidFloor*)
POST/rest-api/bid-floor/placement/{placementId}/delete.doRemove (country*)
GET / POST / POST/rest-api/bid-floor/site/{siteId}.do, …/update.do, …/delete.doThe same three for sites
GET / POST / POST/rest-api/bid-floor/banner/{bannerId}.do, …/update.do, …/delete.doSame for banners (the OpenRTB DSP creative’s floor)

All three answer with HTTP status codes — 404 for a missing or deleted entity (the message names it, e.g. Placement 4001 not found.) or bid floor, 403 without update access or Bid Floor Management (the message names which), 400 for an unknown country or a floor outside 0–1,000,000. The site and placement bodies keep their success:false and error text. Every write on the three is recorded in the action log.

curl -X POST "https://<your-network-domain>/rest-api/bid-floor/placement/4001/update.do?$AUTH" \
  -d "country=US" -d "bidFloor=0.50"

All fields, with descriptions and an example request: POST /rest-api/bid-floor/placement/{placementId}/update.do.

Corner case: delete.do with country=* does not delete the global floor — it sets it to zero (the answer says Global bid floor cannot be removed. The bid floor has been set to 0 instead.) and leaves the country entries as they are. Pass a specific country code to remove one country’s entry; a country with no entry, or an entity with no bid floor at all, is a 404.

Two more endpoints under the same tag serve self-serve CPM floor rates rather than placement bid floors: GET /rest-api/floorCPMs.do lists floor rates filtered by campaign type, operating system, world region and country codes, and GET /rest-api/floorCPMs/suggest.do computes a suggested rate for one advertiser, adjusted by that advertiser’s selfServeCpmFloorAdjustment multiplier. Country codes in suggest.do’s geo parameter may be prefixed with - to exclude rather than include.

Entity pricing itself (CPM/CPC/CPA rates, country pricing) lives on the entity endpoints — see the pricing rows in Entities CRUD and the …/pricing.do and …/pricing/{countryCode}.do paths under banner, campaign, placement and site, and the …/pricing/batch.do CSV upload under banner, campaign and placement. GET /rest-api/campaign/{campaignId}/pricing.do marks the answer with pricingSet: a campaign whose pricing was never set answers {"campaignId":2001,"pricingSet":false} instead of a 404. GET /rest-api/banner/{bannerId}/pricing.do of a CPA banner lists the prices set through bannerPricing/actionPricing.do as globalActionPricing (actionName, actionKey, price), the campaign read’s name, leaving out deleted actions. DELETE /rest-api/campaign/{campaignId}/pricing.do answers {"success":true}, also when there was no pricing to remove.

Corner case — which action a placement country price is for. GET /rest-api/placements/{placementId}/pricing.do keeps countryPricing as the list of {"US": 2.25} pairs it always returned, which cannot say which conversion action a CPA price belongs to. Read countryPricingDetails instead: the same prices as {"country":"US","actionId":34,"actionName":"Signup","price":2.25}, where a row without actionId prices every action (actionName is left out for an action you cannot see). A CPA placement also returns useGlobalActionPricing and globalActionPricing, the per-action prices for every country. The call answers 404 for a missing or deleted placement and 403 without a share on its site.

Corner case — placement “Use general pricing” and CSV upload. The CPA checkbox of the placement Pricing card is POST /rest-api/placements/{placementId}/pricing/use-global-action-pricing.do with useGlobalActionPricing=true|false; a placement without fixed pricing, or priced other than CPA, is a 400. The card’s Upload CSV is POST /rest-api/placements/{placementId}/pricing/batch.do: send the file as countryPrices (multipart) or, from a client that cannot upload files such as the AI assistant, its text as countryPricesCsv — exactly one of the two. The layout is the console’s: Country,Price for CPM/CPC, a header starting with _ and one column per action name (or All) for CPA. The upload merges — countries not in the file keep their prices — and answers 200 with applied / rejected (and the older csvErrors / csvWarnings) naming the rows it stored and skipped; a header that matches no layout is a 400 and changes nothing. Both calls need the placement to have fixed pricing already, Manage Site Payment Model enabled and update access to the site; the upload also needs Manage Pricing.

Corner case — campaign and banner pricing CSV take text too. POST /rest-api/campaign/{campaignId}/pricing/batch.do and POST /rest-api/banner/{bannerId}/pricing/batch.do take the same choice as the placement operation above — the file as countryPrices (multipart) or, from a client that cannot upload files such as the AI assistant, its text as countryPricesCsv — exactly one of the two (see below for how both merge and report results).

Corner case — site fixed pricing. POST /rest-api/sites/{siteId}/pricing.do with paymentModel=FIXED_PRICE behaves like the site’s Pricing card in the console: it never touches the pricing of the site’s placements, and a placement with prices of its own keeps them. Switching pricingType deletes the site’s country and action prices (as confirming a pricing-type change in the console does) and clears the global price unless you send one; keeping the same pricingType keeps them. The whole call is one transaction: if any part is refused or fails — e.g. a pricingType your role may not set, which is a 403 naming the permission — nothing is deleted.

Corner case — site and placement pricing.do replace a list only when you send it. Both POST /rest-api/sites/{siteId}/pricing.do and POST /rest-api/placements/{placementId}/pricing.do take a JSON body, not form parameters — its fields are listed under POST /rest-api/sites/{siteId}/pricing.do and POST /rest-api/placements/{placementId}/pricing.do. A countryPricing list replaces the country prices that apply to every action (per-action CPA country prices are kept; an empty list removes the rest), and an advertiserPricing list replaces the per-advertiser shares. Leave a list out and it is kept as it is — changing only the base price or revenueShare does not touch them. revenueShare may be left out to keep the stored share, but is required (400) when the entity has none yet. Fields the chosen paymentModel does not use (e.g. price with REVENUE_SHARE) are listed in ignoredFields. Every check runs before anything is written: a malformed entry ([{}], a null price, an unknown country or advertiser, a price outside 0–1,000,000) is a 400 naming the field in errors, and a refused pricingType is a 403 — either way nothing changes. On a placement, enablePricingOverride alone switches custom pricing off or on without touching the prices. minMarginType (NONE, ABSOLUTE or PERCENT) and minMarginValue set the minimum gap between the advertiser price and the publisher payout: they apply to FIXED_PRICE only, are enforced on CPM links only and need Manage Minimum Margin enabled; leave them out to keep the stored setting.

Corner case — prices are required and bounded. Every price you write — …/pricing.do, …/pricing/{countryCode}.do, …/campaignPricing/actionPricing.do, …/bannerPricing/actionPricing.do on campaigns, banners, placements and sites — must be between 0 and 1,000,000. The country and action price calls also require price: leaving it out is a 400 naming it (a 0 country price would override the base price). An out-of-range price is a 400 and nothing is stored. …/pricing.do on campaigns and banners is a partial update — only the fields you send change (a banner’s useGlobalActionPricing included). Deleting a country price that does not exist is a 404. On a campaign that is not priced CPA, actionKey / actionName on a country price are listed in ignoredFields; on a CPA banner a country price can take an actionId, and on any other banner it is listed in ignoredFields.

Corner case — CSV uploads merge. …/pricing/batch.do on campaigns, banners and placements adds and updates the countries in the file and keeps the prices of every country the file leaves out. The answer splits the file by line: applied lists every stored price as {line, country, actionId, price} (actionId only for a CPA action column), and rejected lists every line — or part of a line — that was not, as {line, reason}; line 1 is the header. A rejected row changes nothing, and the rest of the file is still applied. The same rows also appear, as text, in csvErrors / csvWarnings (Line #3: …), kept for older clients. In a semicolon- or tab-separated file a price may use a decimal comma (1,50). …/pricing/FIXED_PRICE/remove.do and …/cpm-thresholds/delete.do likewise remove the country prices or country thresholds together with the site-level record, or nothing.

Corner case — campaign pricing is a partial update. POST /rest-api/campaign/{campaignId}/pricing.do changes only the fields you send — price, paymentModel, pricingType, useGlobalActionPricing and the optimization fields keep their stored values when left out (an empty price clears the global price). Switching pricingType needs that pricing type’s permission, as in the console, or the call is a 403 and nothing changes. A switch that goes through deletes the campaign’s country and action prices and its global price, exactly as confirming a pricing-type change on the console’s Pricing card does; send price in the same call to set the new type’s global price. Re-sending the current pricingType deletes nothing; useGlobalActionPricing is returned by the matching GET. The campaign’s max payout per conversion is maxActionPriceOverride on /rest-api/campaign/{campaignId}/update.do: omit it to keep the ceiling, send it empty to remove it (as clearing the console field does), and note that 0 is a ceiling of zero, not “no ceiling”.

Corner case — pricing an action you cannot see. The calls that price by conversion action — …/campaignPricing/actionPricing.do, …/bannerPricing/actionPricing.do, and …/pricing/{countryCode}.do on campaigns (actionKey / actionName), placements and sites (actionId) — accept only an action you would see in the console’s action list: every action with Actions view at All level, otherwise the ones shared with you. Any other action is a 404, the same answer as an action that does not exist, and nothing is written. Deleting a placement or site country price by actionId also accepts a deleted action you can see, so a price left behind on it can still be removed.

Corner case — Great Britain is UK. Country prices and CPM thresholds for Great Britain are stored under UK, the code the ad server resolves British traffic to. Send either GB or UK — setting, updating and deleting (DELETE …/pricing/GB.do) all reach the same row — but reads return UK. Country codes are case-insensitive everywhere a price or threshold is written: us and US are the same row, and gb is Great Britain too.

Related pages

Please disable Adblock
Are you using adblock? Disable it and reload the page to proceed to the destination page.

A registration has already been submitted from this page. Please try again in 10 minutes.