Skip to main content
A media buy is one AdCP transaction with one seller for one campaign, in the campaign’s currency. A package is one product inside that buy, with its own budget, pacing, optional bid price, flight and targeting overlay.
Media buys don’t exist until you stage products onto a campaign. A campaign with nothing staged has no media buys.

Stage a buy

Staging puts products on the campaign’s draft buy for that seller. It contacts no seller.
save_media_buy with fromProposalId stages every product in a seller’s proposal and splits the budget by the proposal’s allocations. Pass seller:<name> to use that seller’s current proposal.
There is one draft buy per seller on a campaign (per seller and channel group when the campaign defines groups; then each staging call names its channelGroupId): staging again for the same seller replaces its lines. The result reports each staged buy, the campaign budget’s allocated and unallocated amounts, and productsSkipped with a reason for each product it couldn’t stage, for example “Product is no longer offered.” or a product priced in a currency other than the campaign’s. If no budget is left unallocated, staging is refused: raise the campaign budget or remove a staged buy. To drop a draft buy, call save_media_buy with mediaBuyId and isArchived: true. A campaign whose autonomy.inventorySelection is automatic refuses manual staging (409 CONFLICT, details.reason: "automatic_inventory_selection"); its products come from auto-select.

Launch

Launching the campaign (POST /api/v2/buyer/campaigns/{id}/execute, or asking Semi to launch) sends each draft buy to its seller. See Campaigns → Launch for the preconditions. What happens next depends on the seller: an immediate ACTIVE, or PENDING_APPROVAL while the seller reviews. The media buy lifecycle has every status and transition.

Read buys and packages

A media buy carries status (the platform status) and adcpStatus (what the seller last reported), pendingAt and pendingReason when it’s waiting on someone, errorCode, errorOwner and sourceMessage when it failed, budget, currency, startTime and endTime, the seller’s own id (upstreamMediaBuyId) once it has one, pausedBy (buyer or campaign) and a revision. A package carries productId and productName, pricingOptionId, pricingModel, rate, budget, pacing (even, asap or front_loaded), bidPrice, startTime, endTime, targetingOverlay, plannedImpressions, pacingPeriod when the buy was split by pacing periods, and a status of active, paused or canceled. Budgets are what you set, in the campaign currency. A split of each buy’s budget into media and platform fee isn’t shown on buys.

Change a live buy

update_media_buy (PATCH /api/v2/buyer/media-buys/{id}) changes the buy’s name and endTime, and per package the budget, pacing, bidPrice and targeting overlay. Add a reason; it travels with the change. Pass expectedRevision to refuse the update if someone else changed the buy first. On a live buy the change goes to the seller. If the seller must approve it, the result carries an update proposal and the buy shows a pendingChange until the seller decides. A buy can have only one pending change at a time. Only draft, active and paused buys can be changed; on a draft the change applies at once, with no seller involved.

Pause and resume

  • One buy: save_media_buy with mediaBuyId and isPaused: true (or false to resume), or POST /media-buys/{id}/pause and POST /media-buys/{id}/reactivate. The rest of the campaign keeps running, and the seller is told.
  • Every buy on a campaign: pause or reactivate the campaign. Buys paused by the campaign show pausedBy: "campaign"; a buy you paused on its own stays paused when the campaign reactivates.

Creatives on a buy

Creatives attach to the campaign (see Creatives). If a seller accepts a buy before a required creative is attached, the buy is ACTIVE with the operational status pending_creatives until you add it.