Skip to main content

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

FieldTypeNotes
campaignIdstringStable campaign identifier
advertiserIdstringOwning advertiser
namestringCampaign name (max 255)
statusenumDRAFT, ACTIVE, PAUSED, COMPLETED, ARCHIVED
campaignTypeDECISIONED | ROUTEDImmutable after creation
flightDatesobject{ startDate, endDate } ISO dates
budgetobject{ total, currency, dailyCap?, pacing? }
mediaBudgetobjectbudget.total - sum(fees[].amount) — what’s actually available for media
feesarrayFee line items (typically a single Scope3 margin fee)
allocatedBudgetnumberSum of active media buy budgets
unallocatedBudgetnumbermediaBudget.total - allocatedBudget
pacingPeriodsobjectOptional time-windowed pacing schedule with weight or budget mode
constraintsobjectChannel and country constraints
performanceConfigobjectOptimization goals (event-based or metric-based)
optimizationApplyModeAUTO | MANUALInherits advertiser default if unset
audiencesarrayTarget and suppress audiences
mediaBuysarrayMedia buys spawned at execution (post-DRAFT)
creativeFormatsobject{ required, covered, missing } — surfaces formats still needing creatives
discoveryIdstringDiscovery session feeding product selection (DRAFT only)
productCountnumberSelected products (DRAFT only — after execute, products are inside media buys)
frequencyCapsarrayBuyer-side caps for this campaign

Lifecycle

1

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

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

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

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

COMPLETED

Reaching flightDates.endDate or full delivery transitions the campaign to COMPLETED.

Common operations

Create a campaign

curl -X POST https://api.agentic.scope3.com/api/buyer/campaigns \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "advertiserId": 12345,
    "name": "Q2 2026 — Tech Launch",
    "campaignType": "DECISIONED",
    "flightDates": { "startDate": "2026-05-15T00:00:00Z", "endDate": "2026-07-15T23:59:59Z" },
    "budget": { "total": 100000, "currency": "USD", "pacing": "even" },
    "brief": "Premium video for tech-savvy professionals",
    "constraints": { "channels": ["ctv", "video"], "countries": ["US", "CA"] }
  }'

List / get campaigns

curl "https://api.agentic.scope3.com/api/buyer/campaigns?advertiserId=12345&status=ACTIVE&includeMediaBuys=true" \
  -H "Authorization: Bearer $SCOPE3_API_KEY"

curl https://api.agentic.scope3.com/api/buyer/campaigns/cmp_987654321 \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
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:
curl -X POST https://api.agentic.scope3.com/api/buyer/campaigns/cmp_987654321/auto-select-products \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "maxProducts": 8, "minBudgetPerProduct": 2500 }'
Iterate with ADCP-style refinement:
{
  "refine": [
    { "scope": "request", "ask": "more video, less display" },
    { "scope": "product", "id": "prod_xyz789", "action": "more_like_this" },
    { "scope": "product", "id": "prod_xyz790", "action": "omit" }
  ]
}

Execute / pause / reactivate

# Launch a DRAFT (or COMPLETED) campaign — turns selected products into media buys and submits to ADCP
curl -X POST https://api.agentic.scope3.com/api/buyer/campaigns/cmp_987654321/execute \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "debug": false }'

# Pause every media buy on the campaign
curl -X POST https://api.agentic.scope3.com/api/buyer/campaigns/cmp_987654321/pause \
  -H "Authorization: Bearer $SCOPE3_API_KEY"

# Resume a PAUSED campaign
curl -X POST https://api.agentic.scope3.com/api/buyer/campaigns/cmp_987654321/reactivate \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
The execute response reports 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:
{
  "mediaBuys": [
    {
      "action": "update",
      "mediaBuyId": "mb_abc123",
      "packages": [{ "packageId": "pkg_1", "budget": 15000, "pacing": "asap" }],
      "optimizationGoals": [
        { "kind": "metric", "metric": "completed_views", "target": { "kind": "cost_per", "value": 0.08 } }
      ]
    },
    { "action": "cancel", "mediaBuyId": "mb_def456", "reason": "underperforming" }
  ]
}
Always confirm optimizationGoals with the buyer before changing them — silent goal changes break optimization continuity.

Live ADCP status

curl https://api.agentic.scope3.com/api/buyer/campaigns/cmp_987654321/media-buy-status \
  -H "Authorization: Bearer $SCOPE3_API_KEY"
This polls the sales agents directly and persists any status changes. Useful right after execution while waiting on publisher approvals.

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:
{
  "kind": "event",
  "event_sources": [
    { "event_source_id": "website_pixel", "event_type": "purchase", "value_field": "value" }
  ],
  "target": { "kind": "cost_per", "value": 25.0 }
}
Target kindMeaning
cost_perTarget CPA (events) or CPM-like rate (metrics)
per_ad_spendTarget ROAS — value per dollar spent (events only)
maximize_valueNo target — maximize total event value within budget
threshold_rateMaintain a minimum rate of the metric (metrics only)
Supported metrics: 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

Use PUT /api/buyer/campaigns/:id with the mediaBuys[] array. Allowed actions: update (default — modify), cancel (cancel running), delete (archive).
{
  "mediaBuys": [
    {
      "action": "update",
      "mediaBuyId": "mb_abc123",
      "packages": [
        { "packageId": "pkg_1", "budget": 15000, "pacing": "even" }
      ],
      "optimizationGoals": [
        { "kind": "metric", "metric": "completed_views", "target": { "kind": "cost_per", "value": 0.08 } }
      ],
      "updated_reason": "Mid-flight optimization based on early performance"
    }
  ]
}

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[]:
{
  "success": false,
  "errors": [
    {
      "mediaBuyId": "mb_abc123",
      "salesAgentId": "agent_xyz",
      "message": "Sales agent returned 422: invalid format for product"
    }
  ]
}
Pass 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 proportionally
  • budget — explicit dollar amount per period
Gaps between periods are treated as pauses (no spend). On execute, each product becomes one package per period with proportional budget.
Pacing periods can only be modified on DRAFT campaigns. After execution, the package split is locked in. See the pacing periods workflow guide for full mode-by-mode examples.

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": [
  { "max_impressions": 5, "window": { "interval": 7, "unit": "days" } }
]
When frequencyCaps is provided on update, it replaces all existing non-archived caps. See Frequency caps for the full configuration surface.

DECISIONED vs ROUTED

DECISIONEDROUTED
OptimizationScope3 RL allocates and optimizesPass-through; no Scope3 optimization
CredentialsScope3 platform credentialsCustomer credentials
Product selectionAuto-select + manualManual
Use caseProgrammatic with Scope3 as buyerExisting buyer with Scope3 as orchestration layer
Choose at creation; the choice is immutable.

Creative

Manifest-based creatives uploaded under the campaign

Pacing periods

Time-windowed spend intensity

Frequency caps

Buyer-side cross-publisher caps