Skip to main content
PUT /api/v2/buyer/campaigns/:campaignId Accepts partial updates to a campaign. The mediaBuys[] array lets you update, cancel, or delete individual media buys and their packages in a single call.

Request

curl -X PUT https://api.interchange.io/api/v2/buyer/campaigns/cmp_987654321 \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "mediaBuys": [
      {
        "action": "update",
        "mediaBuyId": "mb_abc123",
        "packages": [{ "packageId": "pkg_1", "budget": 15000, "pacing": "even" }],
        "optimization_goals": [
          { "kind": "metric", "metric": "completed_views", "target": { "kind": "cost_per", "value": 0.08 } }
        ],
        "updated_reason": "Mid-flight optimization based on early performance"
      },
      { "action": "cancel", "mediaBuyId": "mb_def456", "reason": "underperforming" }
    ]
  }'

Parameters

FieldTypeRequiredNotes
namestringNoRename the campaign (max 255)
budgetobjectNo{ total, currency, dailyCap?, pacing? }
pacingPeriodsobjectNoAppend periods; returns a pacingCascadeResult in the response
frequencyCapsarrayNoReplaces all existing non-archived caps
mediaBuys[]arrayNoPer-media-buy actions (see below)
mediaBuys[].actionenumYes (per entry)update (default — modify), cancel (cancel running), delete (archive)
mediaBuys[].mediaBuyIdstringYes (per entry)Target media buy
mediaBuys[].packagesarrayNoPer-package budget, pacing, bid overrides
mediaBuys[].packageIdsarrayNoScope a cancel to specific packages only
mediaBuys[].creative_idsarrayNoOverride auto-sync. [] clears all creatives. Only valid with action: "update"
mediaBuys[].optimization_goalsarrayNoEvent- or metric-based goals applied to every package
Always confirm optimization_goals with the buyer before changing them — silent goal changes break optimization continuity.

Reducing campaign budgets

Lower an executed campaign’s spend through this campaign update endpoint. Do not archive and rebuild a media buy just to reduce its budget. When budget.total is reduced below the current live package allocation, Scope3 automatically generates proportional mediaBuys[].packages[].budget reductions for live packages so the post-update package allocation fits inside the new media budget. Explicit package budgets always win. If the request includes mediaBuys[].packages[].budget for a package, Scope3 uses that amount and proportionally scales only the remaining eligible packages. The update is atomic for generated package reductions: if Scope3 cannot apply one of the generated seller budget updates, the campaign-level budget.total is not lowered.
Reduce campaign and live package budgets
{
  "budget": { "total": 50000, "currency": "USD" }
}
Reduce campaign budget with explicit package overrides
{
  "budget": { "total": 50000, "currency": "USD" },
  "mediaBuys": [
    {
      "action": "update",
      "mediaBuyId": "mb_abc123",
      "packages": [{ "packageId": "pkg_1", "budget": 12000 }]
    }
  ]
}

Response

{
  "campaign": {
    "campaignId": "cmp_987654321",
    "advertiserId": "12345",
    "name": "Q2 2026 Tech Launch",
    "status": "ACTIVE",
    "campaignType": "DECISIONED",
    "optimizationApplyMode": "MANUAL",
    "mediaBuyRefs": [
      { "mediaBuyId": "mb_abc123", "status": "ACTIVE" },
      { "mediaBuyId": "mb_def456", "status": "CANCELED" }
    ],
    "createdAt": "2026-05-01T09:00:00Z",
    "updatedAt": "2026-05-15T12:00:00Z"
  }
}
When the request includes pacingPeriods, the response also carries a pacingCascadeResult block at the top level alongside campaign, summarizing the per-media-buy outcome of pushing appended periods to live media buys. See the Pacing periods guide for that shape, append-only rules, and unsupported-agent fallback. When one or more media buy updates require seller approval (e.g. a seller-managed storefront), the server returns 202 Accepted with a proposals array instead of the campaign object:
{
  "proposals": [
    {
      "proposalId": "prop_abc123",
      "mediaBuyId": "mb_abc123",
      "status": "PENDING_SELLER_APPROVAL"
    }
  ]
}

Errors

  • 400 VALIDATION_ERROR — a creative_ids entry is not linked to the campaign or does not match a format the media buy’s products accept (the field is not silently filtered); or creative_ids was supplied with cancel/delete.
  • 400 INSUFFICIENT_MEDIA_BUDGET — the requested campaign media budget is still below projected live allocations after applying explicit and generated package budget reductions.
  • 404 NOT_FOUND — campaign or referenced mediaBuyId not found.
See Errors for the full error contract.

Get campaign

Read the current resource first

Get media buy status

Poll live ADCP status

Pacing periods

Append-only pacing cascade

Campaign overview

Fields, lifecycle, and concepts