Skip to main content
PUT /api/v2/buyer/campaigns/:campaignId Accepts mode-specific campaign updates. For platform-managed campaigns, the mediaBuys[] array lets you update, cancel, or delete individual media buys and their packages in a single call. For a separately write-enrolled directed campaign, the strict directed branch forwards one explicit AdCP patch to the connected provider and reconciles the one-to-one mirror.

Request

Parameters

Always confirm optimization_goals with the buyer before changing them — silent goal changes break optimization continuity.

Directed update (alpha)

Read-only mirror refresh remains available without write enrollment:
An upstream mutation requires the separate directed-write gate, subscription governance, and this strict shape:
mediaBuy must contain at least one AdCP update field. The campaign URL resolves the connected account and upstream identity, so nested account, media_buy_id, idempotency_key, and revision fields are rejected. Use root expectedRevision for optimistic concurrency. The root currency must match the subscription governance currency. A synchronous provider result returns { campaign, directedWrite } with directedWrite.status: "CONFIRMED". If the provider accepted the write but the mirror cannot yet prove it, the endpoint returns 202 Accepted with the raw write result’s status AWAITING_CONFIRMATION; poll the campaign or use the read-only refresh branch. Replaying the same idempotency key and body is safe. A different body with the same key is a conflict and is never dispatched. TikTok’s first write canary accepts only { "paused": true } or { "canceled": true, "cancellation_reason": "..." }. Resume, package mutations, schedule/bid changes, and every other update fail closed. Its current revision is not an authoritative compare-and-swap token, so Interchange does not evaluate budget mutations against a potentially stale sibling-package snapshot. TikTok has no native cancellation-reason field; Interchange retains cancellation_reason as audit metadata alongside the directed write.

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. Every budget is gross (fee-inclusive), so the comparison is direct: live media buys can never allocate more than budget.total. Lowering budget.total below what live media buys have already allocated is rejected with INSUFFICIENT_MEDIA_BUDGET — the error names the new total and the committed allocation so you know what to shrink or cancel first. Lowering into headroom (new total at or above the current allocation) succeeds on its own. To reduce the campaign and its live media buys together, put both changes in one request: the new budget.total plus explicit mediaBuys[].packages[].budget reductions. The request is validated against the projected post-update allocation and applied atomically — if a package reduction cannot be applied, the campaign-level budget.total is not lowered.
Lower into headroom — budget change alone
Reduce campaign budget and live packages in one call

Response

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:

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.
  • 403 FEATURE_NOT_ENABLED — a directed mutation was requested for a customer without the separate write alpha.
  • 409 CONFLICT — a directed idempotency key was reused for a different body or expectedRevision is stale.
  • 409 INSUFFICIENT_MEDIA_BUDGET — the requested budget.total is below the projected live media buy allocation, even after applying the package budget reductions included in the same request. The error names the new total and the committed allocation.
  • 409 PRICING_NOT_CONFIGURED — the budget change involves media buys whose fee terms cannot be determined, so the projected allocation cannot be computed. details.unpricedBuyIds names the buys; resolve pricing for them first.
  • 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