Advertisers and campaigns via API
API endpoints, curl examples and corner cases for creating, reading, updating, copying, moving and deleting advertisers and campaigns.
The demand side of the account starts here: create the advertiser, then its campaigns, then banners inside them. This page covers the advertiser and campaign endpoints, the fields that change how they behave, copy and move, and the corner cases that trip scripts. Examples append $AUTH, the hash-authentication parameters (an X-Api-Key header works the same), and send parameters form-encoded unless noted — see the API overview for authentication and Entities via API for the corner cases every entity shares.
Who this is for
Network managers and advertisers who create or maintain advertisers and campaigns from a script, and admins. Several campaign settings apply only when your role holds the matching permission — see the corner cases below.
Advertisers
| Method | Path | Purpose |
|---|---|---|
| GET | /rest-api/advertisers.do | List all accessible advertisers, ordered by id (filters: advertisingCategories, filter[…]; offset / limit; fields). Returns a bare array, not an envelope |
| GET | /rest-api/advertisers/{advertiserId}.do | Get one advertiser |
| GET | /rest-api/advertisers-tree.do | Full advertiser → campaign → banner tree. On a large network read it in pages with start (entries to skip, 0 or more) and limit (1 or more; anything else is a 400) — advertisers ordered by id, a page shorter than limit is the last |
| GET | /rest-api/advertiser/{advertiserId}/campaigns.do | Campaigns of one advertiser |
| POST or PUT | /rest-api/advertisers/update.do | Create (no id) or update (with id). Both verbs are mapped and behave identically |
| DELETE | /rest-api/advertisers/{advertiserId}/delete.do | Delete advertiser |
Create an advertiser:
curl -X POST "https://<your-network-domain>/rest-api/advertisers/update.do?$AUTH" \
-d "name=Northwind Media" \
-d "contactName=Dana Whitfield" \
-d "contactEmail=dana@northwind.example" \
-d "active=true"
# → {"success":true,"id":1001}
A create needs name; everything else is optional. Send active explicitly: left out, it
takes the network’s default for new entities (newEntities.active in
GET /rest-api/network/settings.do). enableLimits=true creates the advertiser’s limit record
when it has none and needs Manage Capping & Limitations; it is not a stored field and is never
listed in ignoredFields. Several advertiser fields apply only with a role permission — see
Activation, approval, status.
All fields, with descriptions and an example request:
POST /rest-api/advertisers/update.do.
Corner case: validation failures on this endpoint come back as a 400 with a per-field map, one key per rejected field:
{"success":false,"errors":{"contactEmail":"Please provide a valid email address (with domain)","name":"Required"}}. Readerrorskey by key — every failing field is listed, not only the first.
Corner case:
adsHostneeds the Set Ad Serving Domain (Campaigns) permission. Without it the field is ignored — an existing advertiser keeps its domain and a new one gets your own user’s ad-serving domain, as in the console. With it, the value must be one of the network’s ad-serving domains (the list the console’s picker offers, also returned byGET /rest-api/adsHosts.do) or blank for the system default; anything else fails witherrors.adsHost. Sending back the domain the advertiser already has is always accepted.
Campaigns
| Method | Path | Purpose |
|---|---|---|
| GET | /rest-api/campaigns.do | List all accessible campaigns, ordered by id (filters: active, advertiserId, labels, filter[…]; offset / limit; fields) |
| GET | /rest-api/campaign/{campaignId}.do | Get one campaign — every field update.do writes, under the same name (autoTagLandingUrl, maxActionPriceOverride, campaignAliasForActionTracking, allowNewPlacementsAutolinking, …); creation_time is the creation day at midnight |
| POST | /rest-api/campaign/create.do | Create (requires advertiserId) |
| POST | /rest-api/campaign/{campaignId}/update.do | Update |
| POST | /rest-api/campaign/{campaignId}/delete.do | Delete |
| POST | /rest-api/campaign/{campaignId}/{operation}/{advertiserId}.do | Copy or move to another advertiser (operation = COPY or MOVE) |
| POST | /rest-api/campaigns/copy/bulk/{advertiserId}.do | Bulk copy campaigns |
| GET | /rest-api/campaigns/priorities.do | List valid priority values |
| POST | /rest-api/campaigns/labels.do | Add, replace or remove labels on many campaigns — see Bulk labels |
curl -X POST "https://<your-network-domain>/rest-api/campaign/create.do?$AUTH" \
-d "advertiserId=1001" \
-d "name=Brand Awareness Q3" \
-d "priority=STANDARD_MEDIUM" \
-d "weight=50" \
-d "active=true"
A copy answers with the new ids in created and, in copies, each copy’s id, name and
whether it starts active. Pass name to name the copy — with copyCount above 1 the later
copies become <name> 2, <name> 3… — or leave it out to keep the source’s name (with _copy
appended when the target advertiser already has a campaign of that name). A campaign copy
starts switched off unless preserveActive=true.
Every copy operation — campaign (copyCount), banner (copyCount, also per campaign in the
bulk form), bulk campaign copy (numberOfCopies), copy-placement and zone copy (count) —
makes 1 to 20 copies per call; anything else is a 400 naming the parameter and the limit,
and nothing is copied. If a banner copy fails after some copies were saved, the answer is a 500
naming the copy that failed, with created listing the copies that do exist (per campaign in the
bulk form, next to failed). The bulk campaign copy takes a JSON array of
{companyId, companyName, banners: [{itemId, link, active}]} (item_id is accepted too);
banners is required — send [] to copy a campaign without its banners — and a campaign whose
copy fails is listed in failedCampaignIds with success: false. The bulk banner copy/move
(/rest-api/banner/{bannerId}/{operation}/bulk.do) needs campaignIds, refuses an unknown
or deleted campaign before copying anything, takes exactly one campaign for MOVE, and
lists a campaign whose copy failed in failed.
priority takes one of six values — GET /rest-api/campaigns/priorities.do returns
exactly this list:
| Value | Meaning |
|---|---|
PREMIUM | Highest band; served ahead of everything below it |
STANDARD_HIGH | Upper standard band |
STANDARD_MEDIUM | Middle standard band |
STANDARD_LOW | Lower standard band |
NON_GUARANTEED | Served only when no higher band fills |
HOUSE_ADS | Lowest band — your own filler inventory |
Note: the
statusarray andhasTrafficin campaign reads describe recent traffic, not the on/off switch —activeis the switch.status-not-activemeans switched off or no traffic in the last ~6 hours, soactive=truewithstatus-not-activeis normal for an idle or newly created campaign;status-finishedmeans the campaign’s limits have ended it (end date passed, total or action limit reached). Traffic data is refreshed hourly.
Only advertiserId is required. Beyond priority, the settings that change how a campaign
delivers are its optimization mode — pick one of ctrOptimization, ecpmOptimization and
cpaOptimization (the last with cpaOptimizationActions) — enableActions to track
conversions, and the auto-linking pair allowNewPlacementsAutolinking + autolinkCategories
(mind the spelling, below). labelUpdateType decides what the labels you send do: ADD,
OVERWRITE, REMOVE or CLEAR.
All fields, with descriptions and an example request:
POST /rest-api/campaign/create.do and
POST /rest-api/campaign/{campaignId}/update.do.
Corner case: out-of-range input is a
400naming the field, not a silent clamp or a500.weightis0–32767;exchangeRateis0.001–999.999;maxActionPriceOverrideis0–9999999.9999;nameis never blank — a blank one is a400— and at most 512 characters;targetTemplateNameis at most 50 characters;cpaOptimizationActionsmust name actions that exist.
Corner case:
nameis optional on create. Leave it out and the campaign is created and namedCampaign <id>after the id it receives. Anamethat is sent but blank is still a400.
Warning: the auto-link category filter is
autolinkCategories— a lowercasel, repeated publisher-category IDs, on campaigns and on banners alike. The camelCaseautoLinkCategoriesis only how a campaign reads them back; sent as a parameter it binds nothing, the call still succeeds and the name comes back inignoredFields, so a script that spells it that way auto-links against no categories at all.
Note:
onlyOneBannerPerPageandonlyThisCampaignOnPageare two different settings, not two spellings of one — the first caps a campaign to one creative per page impression, the second reserves the page for that campaign. Send both if you mean both.
Note: the names you send and the names you read back differ on this entity.
GET /rest-api/campaign/{campaignId}.doreturns auto-linking twice — asallowNewPlacementsAutolinking, the name you write, and as the oldernewPlacementsAutoLinking— but reads the categories back asautoLinkCategorieswhile the parameter you write isautolinkCategories. Don’t feed a campaign’s own JSON straight back intoupdate.do: the renamed keys are not read there.
Copy and move take options the endpoint table can’t show: copyCount (how many copies),
keepBannersLinked, dontCopyBanners, pauseBanners and preserveActive. Only keepBannersLinked
applies to MOVE: it re-assigns the same campaign, with its id and its banners, to the target
advertiser, and the banners lose their placement links unless keepBannersLinked=true. The
others, and name, are for COPY. A target advertiser that is deleted is a 400.
Warning:
{operation}is bound to an enum and is case-sensitive — it must beCOPYorMOVEin capitals. Lowercasecopyis rejected before the handler runs:400 {"success":false,"message":"Invalid value 'copy' for parameter 'operation'. Expected type: Operation"}. The same applies to the banner copy/move paths.
Corner case: if you omit
activeon create, the campaign inherits the network’s Default activity status preference, which ships as active. On a network whose administrator has turned that preference off, the same script creates inactive campaigns. Passactiveexplicitly rather than relying on it — and note that the flag is dropped for callers without the Manage Campaigns’ Active Status permission, after which the network default applies anyway.
Campaign settings that need a permission
Campaign settings the console shows only with a role permission are applied only with that
permission enabled. Without it the setting is left as stored (on create: at its default), the
rest of the call is saved, and the parameter is listed in ignoredFields as not permitted —
whether or not it would have changed the value, so a client that echoes the whole object back
keeps working.
| Field | Permission |
|---|---|
weight | Manage Campaign Weight |
priority | Manage Priority |
ctrOptimization | Set “CTR Optimization” |
cpaOptimization, cpaOptimizationActions | Set “CPA Optimization” |
ecpmOptimization | Set “eCPM Optimization” |
exchangeRate, allowImpressionAndClicksPricingUrlOverriding | Event Tracking Price Overriding |
selfServeCampaignType | Manage Self-Serve Campaign Type |
onlyOneBannerPerPage | Set “Only one banner from this campaign per page” |
onlyThisCampaignOnPage, showBannersOfOneCampaignAtTheSamePageAlias | Set “Only this campaign on page” and Set “Only this campaign on page” Alias |
campaignAliasForActionTracking | Set Campaign Alias For Action Tracking |
allowNewPlacementsAutolinking, autolinkCategories | Auto-linking settings |
allowUseForTemplate, targetTemplateName | Templates |
labels, labelUpdateType | Campaign Labels |
enableActions, allowActionPricingUrlOverriding, maxActionPriceOverride | Manage Action Tracking |