Overview
A Campaign is a single coherent media plan owned by an Advertiser. It defines flight dates, budget, optimization goals, audiences, creative requirements, and (after execution) the resulting media buys with publishers. In v2, the campaign is the focal object. Discovery sessions, products, creatives, audiences, frequency caps, and pacing schedules all attach to a campaign. Execution turns selected products into one or more media buys per sales agent.Two campaign types:
DECISIONED campaigns use Scope3 optimization to allocate budget and optimize media buys. ROUTED campaigns pass through to the sales agent using the customer’s own credentials with no Scope3 optimization layer. Type is immutable after creation.Key fields
| Field | Type | Notes |
|---|---|---|
campaignId | string | Stable campaign identifier |
advertiserId | string | Owning advertiser |
name | string | Campaign name (max 255) |
status | enum | DRAFT, ACTIVE, PAUSED, COMPLETED, ARCHIVED |
campaignType | DECISIONED | ROUTED | Immutable after creation |
flightDates | object | { startDate, endDate } ISO dates |
budget | object | { total, currency, dailyCap?, pacing? } |
mediaBudget | object | budget.total - sum(fees[].amount) — what’s actually available for media |
fees | array | Fee line items (typically a single Scope3 margin fee) |
allocatedBudget | number | Sum of active media buy budgets |
unallocatedBudget | number | mediaBudget.total - allocatedBudget |
pacingPeriods | object | Optional time-windowed pacing schedule with weight or budget mode |
constraints | object | Channel and country constraints |
performanceConfig | object | Optimization goals (event-based or metric-based) |
optimizationApplyMode | AUTO | MANUAL | Inherits advertiser default if unset |
audiences | array | Target and suppress audiences |
mediaBuys | array | Media buys spawned at execution (post-DRAFT) |
creativeFormats | object | { required, covered, missing } — surfaces formats still needing creatives |
discoveryId | string | Discovery session feeding product selection (DRAFT only) |
productCount | number | Selected products (DRAFT only — after execute, products are inside media buys) |
frequencyCaps | array | Buyer-side caps for this campaign |
Lifecycle
DRAFT — plan and configure
Create the campaign with
flightDates, budget, campaignType, and optional brief/constraints. Attach a discovery session, select products, attach audiences, configure pacing periods.Upload creatives
Use
GET /api/buyer/campaigns/:campaignId/creatives/formats to see required formats, then upload manifest-based creatives via POST /api/buyer/campaigns/:campaignId/creatives/create (multipart). Listing manifests is GET /api/buyer/campaigns/:campaignId/creativeManifest. Inspect creativeFormats.missing to confirm coverage.Execute → ACTIVE
POST /api/buyer/campaigns/:id/execute launches a DRAFT (or COMPLETED) campaign — it creates one media buy per sales agent for each selected product, packages them per pacing period, and submits to ADCP. The campaign transitions DRAFT → ACTIVE.PAUSE / resume
POST /api/buyer/campaigns/:id/pause halts spend across all media buys. To resume a PAUSED campaign, call POST /api/buyer/campaigns/:id/reactivate — this is a separate endpoint from execute and is the only way to bring a paused campaign back to ACTIVE.Common operations
Create a campaign
List / get campaigns
GET returns the campaign augmented with creativeFormats so you can flag any missing formats before execution.
Auto-select products
For DECISIONED campaigns with a discovery session, let Scope3 pick a balanced product set:Execute / pause / reactivate
success, previousStatus, newStatus, and structured errors[] when individual media buy submissions fail. Pass debug: true to surface the raw ADCP request/response payloads in error details.
execute and reactivate are distinct endpoints. execute launches a DRAFT or COMPLETED campaign for the first time (or relaunches it). reactivate is the only way to bring a PAUSED campaign back to ACTIVE.Update a running campaign
PUT /api/buyer/campaigns/:id accepts partial updates. The mediaBuys[] array on update lets you act on individual media buys in one call:
Live ADCP status
Media buys and packages
Media buys are not a directly-creatable resource — they’re spawned by the platform when a campaign executes. Each media buy represents one ADCP transaction with one sales agent. You read their status and tune them via the campaign update endpoint. Hierarchy: Campaign → Media Buy (one per sales agent) → Package (one per product per pacing period) → Delivery.Media buy status
status is one of DRAFT, PENDING_APPROVAL, INPUT_REQUIRED, ACTIVE, PAUSED, COMPLETED, CANCELED, FAILED, REJECTED, ARCHIVED. For multi-agent campaigns, the surfaced status is the most restrictive across agents — e.g. one ACTIVE and one PENDING_APPROVAL reports as PENDING_APPROVAL. INPUT_REQUIRED indicates a seller needs additional information before approval can proceed.
Status updates flow via:
- Webhooks from sales agents (preferred — near-real-time)
- Polling via
GET /api/buyer/campaigns/:campaignId/media-buy-status, which queries each agent and persists changes
Optimization goals at the media-buy level
Goals are applied to every package in a media buy at execution time. Each goal is either event-based or metric-based:| Target kind | Meaning |
|---|---|
cost_per | Target CPA (events) or CPM-like rate (metrics) |
per_ad_spend | Target ROAS — value per dollar spent (events only) |
maximize_value | No target — maximize total event value within budget |
threshold_rate | Maintain a minimum rate of the metric (metrics only) |
clicks, views, completed_views, viewed_seconds, attention_seconds, attention_score, engagements, follows, saves, profile_visits.
Packages
When a media buy executes, products turn into packages — one per product, multiplied by the number of pacing periods. Each package carries its own budget, pacing strategy (even, asap, front_loaded), bid price, and optimization goals. Delivery metrics roll up per-package: impressions, spend, clicks.
Updating media buys via the campaign update endpoint
UsePUT /api/buyer/campaigns/:id with the mediaBuys[] array. Allowed actions: update (default — modify), cancel (cancel running), delete (archive).
Cascade behavior
- Campaign pause halts every media buy and package
- Campaign reactivate brings them back to ACTIVE (post-flight if dates allow)
- Creative manifest update re-syncs to every media buy that uses the format
- Property list update propagates to packages without a full re-execute
- Frequency caps on the campaign or advertiser are enforced across all media buys
Failures and debug
When a media buy fails to execute (publisher rejection, ADCP error),POST /api/buyer/campaigns/:id/execute returns structured errors[]:
debug: true on execute to include the full ADCP request, response, and A2A debug logs in each error entry.
Pacing periods
pacingPeriods defines time-windowed spend intensity within the campaign flight. Two modes:
weight— relative weights (e.g. 3.0 = 3x normal); budget is distributed proportionallybudget— explicit dollar amount per period
Frequency caps
Buyer-side frequency caps configured on the campaign are enforced by Scope3 across all publishers in the campaign — distinct from publisher-side caps that live in package overlays.frequencyCaps is provided on update, it replaces all existing non-archived caps. See Frequency caps for the full configuration surface.
DECISIONED vs ROUTED
| DECISIONED | ROUTED | |
|---|---|---|
| Optimization | Scope3 RL allocates and optimizes | Pass-through; no Scope3 optimization |
| Credentials | Scope3 platform credentials | Customer credentials |
| Product selection | Auto-select + manual | Manual |
| Use case | Programmatic with Scope3 as buyer | Existing buyer with Scope3 as orchestration layer |
Related concepts
Creative
Manifest-based creatives uploaded under the campaign
Pacing periods
Time-windowed spend intensity
Frequency caps
Buyer-side cross-publisher caps