control_media_buy applies operational changes authorized by the terms currently accepted for the MediaBuy. It requires the current revision for optimistic concurrency. The accepted envelope includes proposal-bound commercial_terms.change_terms[]: when the current available_actions[] projection links a self_serve or conditional_self_serve action through change_term_id, a request inside that term’s typed constraints is already authorized even if it changes the original numeric value. The accepted term is the authority; product allowed_actions[] is only advisory.
Supported controls include:
- pause, resume, and an already-permitted unilateral cancellation;
- total, aggregate-daily, and package budget controls;
- budget allocation, pacing, bidding, and shared frequency capping;
- package targeting, catalog references, keyword, impression, and optimization controls;
- MediaBuy display-name metadata; and
- reporting-webhook configuration (include a buyer-supplied
operation_id; see Reporting webhooks).
Transaction boundary
Onecontrol_media_buy request is atomic under the supplied MediaBuy
revision. That fence covers only the operational fields in this request.
sync_creatives has a separate idempotency and atomicity boundary and
cannot join this transaction, but an assignment change it commits does
advance the MediaBuy revision. A control request that carries a revision read
before that sync is rejected with CONFLICT, so re-read before retrying.
name is revision-checked non-commercial metadata. Changing it updates the
shared trafficking display label and increments MediaBuy revision, but does not
change the accepted commercial terms or create an accepted-proposal successor.
Consequently, a targeting patch that removes a placement used by an
existing creative assignment cannot be performed as control followed by sync
without a race window. Use the update_media_buy compatibility facade to send
the targeting patch and complete assignment replacement in one transaction. The
same facade is required for inline-only sellers, because they do not advertise
sync_creatives as a later creative path.
Within each package targeting_overlay is a request-only per-dimension patch.
Omitting a dimension preserves its effective value, a non-null value replaces
it, and null clears it. Sellers return the resulting targeting through strict
readback schemas: cleared dimensions are absent and null never appears in
package state or capability/discovery output.
Commercial amendment followed by operational control is also a saga, not one
transaction. If accept_proposal applies the amendment and a subsequent
control fails, the amended commercial snapshot remains accepted. Re-read the
MediaBuy and its new revision before retrying control. A compatibility request
that requires commercial and operational fields to succeed together must be
handled atomically through update_media_buy, not silently decomposed.
Root canceled: true is mutually exclusive with every package and other
control; a mixed compact request is invalid before mutation. Within a package,
canceled: true is likewise mutually exclusive with that package’s other
fields. This differs from the compatibility facade, where root cancellation
takes precedence and other fields are ignored with a warning.
Catalog controls accept only IDs previously managed through sync_catalogs.
They cannot atomically ingest an inline catalog body, and a catalog synchronized
before a later failed control remains on the account. This task also cannot add
the compatibility facade’s artifact_webhook, recreate a per-package initial
pause atomically with purchase, or author an exact initial
committed_metrics set.
Request schema: /schemas/3.3.0-beta.0/media-buy/control-media-buy-request.json
null removes an aggregate or package cap. A media-buy budget_cap_timezone change starts at the next boundary under the previously effective timezone; package controls never carry their own timezone.
Root frequency-cap changes also apply immediately without resetting the shared
counter. Prior qualifying exposures in the resulting window continue to count;
adding or removing packages does not subtract aggregate history. Set
frequency_cap: null to remove the root cap. Package targeting caps remain
separate and independently binding. Root changes require
update_media_buy_frequency_cap; package changes require
update_frequency_caps.
When an otherwise valid control has no negotiated change right, the seller returns ACTION_NOT_ALLOWED with reason: "not_supported_on_buy". When a structured seller policy caused that buy-specific denial, the seller SHOULD also populate details.decline_reason unless disclosure would expose private thresholds or enforcement controls. A negotiated right whose opaque condition cannot yet be evaluated returns reason: "condition_unresolved" on the current protocol surface and remains absent from available_actions[]; released 3.1 callers receive the compatible not_supported_on_buy reason. Structural denials such as wrong_status, not_supported_on_product, mode_mismatch, and condition_unresolved SHOULD omit decline_reason.
When the buy has the right but the request exceeds its typed constraints, the seller returns REQUOTE_REQUIRED. Its details SHOULD follow error-details/requote-required.json: envelope_field identifies the breached paths, change_term_id identifies the accepted right when one governed the request, and optional decline_reason classifies a safely disclosable seller-policy dimension. The buyer uses that reason to inform recovery: it may select a corresponding typed refinement when one exists, or rely on the buyer-safe message, a free-text ask, or human negotiation. The buyer then reads accepted_proposal_id from get_media_buys, passes it to refine_proposals to create a draft amendment, finalizes that draft into a committed hold, and applies it through accept_proposal. This pointer survives SDK restart and moves atomically after each accepted amendment.
A completed in-envelope control MAY include warnings[] for non-blocking observations, such as a material inventory shortfall forecast observed after the applied control. A continuing condition is also readable as an indicator through get_media_buys. Failed and submitted controls never carry this warning surface. Flight-date changes are not controls; a flight_change_creates_pacing_risk warning belongs on the completed accept_proposal response that applies the amendment.
canceled: true is direct only when the accepted cancellation policy already grants the caller that right. A cancellation requiring counterparty agreement uses refine_proposals with change_kind: "cancellation".
Seller-initiated cancellation does not call a buyer tool. The seller advances the MediaBuy revision and records cancellation.canceled_by: "seller"; get_media_buys is the normative recovery surface. A durable compact-lifecycle resource-status webhook is intentionally not inferred from the per-operation async callback and remains 4.0 work. Separately, a 3.2 seller advertising the experimental account.change_feed capability with media_buy coverage emits generic account-anchored account.change_recorded, which tells the buyer to drain the feed and repair through get_media_buys rather than carrying status itself.