update_media_buy, Semicola sends the change to the seller. If the seller applies it at once, the buy
updates and you’re done. If the seller has to approve it first, the change becomes an update
proposal: a pending change that moves from PENDING to APPROVED or REJECTED.
While a proposal is PENDING you can poll it or cancel it. Once it’s resolved, it’s final.
How a proposal starts
update_media_buy (or PATCH /api/v2/buyer/media-buys/{id}) returns the buy and an updateProposal:
updateProposal is null when the seller applied the change straight away. While a proposal is
pending, the buy carries a pendingChange listing only the fields whose pending value differs from the
live one (budget, endTime), so you can show “live” and “proposed” side by side.
One pending change per buy. A second update_media_buy on the same buy is refused with CONFLICT
(”… already has a change waiting for the seller’s approval. Cancel update proposal … or wait for the
seller to decide.”) until the first is resolved or cancelled.
Poll a proposal
PENDING proposal asks the seller for the status of its task. If the seller is
unreachable, the proposal stays PENDING and the next poll asks again.
A proposal the seller hasn’t decided within 72 hours expires: it becomes
REJECTED with
rejectionReason: "expired", and you get a notification.
Cancel a proposal
Cancelling resolves the proposal as
REJECTED with rejectionReason: "cancelled_by_buyer" and frees
the buy for a corrected update. It doesn’t recall a request already sent to the seller. If the
seller’s decision lands first, the seller’s decision wins and cancel returns the resolved proposal.
Cancelling a proposal that’s already resolved returns CONFLICT.
Cancellations show in Activity as a media buy update.