
One AdCP media buy, task by task: a seller’s walkthrough
An AdCP media buy is a short sequence of tool calls from a buyer agent to your sales agent: discover, propose, book, traffic, approve, report and adjust. Each step has a task name, a request shape and a set of answers you are allowed to give. This walkthrough follows one guaranteed display buy from the seller’s side, using the 3.1 task names most buyers send today and noting where 3.2 differs.
The examples reuse the run-of-site display product from our guide to making inventory agent-ready for AdCP. Both JSON requests below validate against the 3.1.30 and 3.2.8 schemas.
Which task names apply in 3.1 and 3.2?
Most steps use the same task in both versions. Three differ, because 3.2 added a compact lifecycle that a seller can advertise alongside the 3.x facades:
| Step | 3.1 | 3.2, if the seller advertises it |
|---|---|---|
| Discover products | get_products | list_products, request_proposals |
| Negotiate and hold | get_products with buying_mode: "refine" | refine_proposals, decline_proposals |
| Book | create_media_buy | buy_products, accept_proposal |
| Change a live buy | update_media_buy | control_media_buy |
get_adcp_capabilities, sync_creatives, list_creatives, get_media_buys and get_media_buy_delivery are common to both. The 3.x facades stay valid throughout 3.x, and the open-source Prebid Sales Agent still targets AdCP 3.1.1.
Step 1: How does a buyer agent discover what you support?
The first call is get_adcp_capabilities. Your answer decides everything after it:
adcp.supported_versionslists every release you serve, such as["3.0", "3.1"]. The buyer pins one withadcp_version, and you echo the release you served.supported_protocolsincludesmedia_buy. The spec says a media-buy seller should also returnaccount(withsupported_billing) andmedia_buy.portfolio, whosepublisher_domainslists the domains you represent.specialismsare the compliance claims you make, such assales-guaranteed,sales-non-guaranteedorsales-proposal-mode.- In 3.2,
media_buy.lifecycle_toolslists the compact tools you serve. If it is absent, buyers use the facades.
Declare only what you implement. Graders and buyers both treat a capability as a promise.
Before buying, the buyer also needs an account: sync_accounts to declare a brand and operator, or list_accounts to find a seller-assigned account_id, depending on your account model.
Step 2: What happens when a buyer sends a brief?
In 3.1 the buyer calls get_products. buying_mode is required and takes one of three values:
brief: you curate products against a natural-language brief.wholesale: the buyer wants your raw product feed; no brief is allowed.refine: the buyer iterates on products and proposals from an earlier response.
A brief request for a scooter launch in India might look like this:
{
"adcp_version": "3.1",
"buying_mode": "brief",
"brief": "Two-week launch for a new electric scooter. Adults 25 to 44 in Delhi NCR and Mumbai, mobile web, display and short video, guaranteed delivery preferred.",
"brand": { "domain": "scooter.example" },
"account": { "account_id": "acc_scooter_in" },
"filters": {
"countries": ["IN"],
"channels": ["display", "olv"],
"start_date": "2026-11-16",
"end_date": "2026-11-29",
"budget_range": { "min": 1000000, "max": 1500000, "currency": "INR" }
}
}
Your sales agent returns matching products and, optionally, proposals: a suggested plan with allocations across products. Each proposal carries proposal_status. A draft must be finalized first: the buyer sends buying_mode: "refine" with a proposal entry whose action is "finalize", and you return a committed proposal with firm pricing and an inventory hold until expires_at.
Brief and refine calls may return synchronously or as a submitted task when you need upstream queries or human review. Wholesale reads should be synchronous. You can also decline: 3.2 adds a terminal status: "rejected" response with a reason.
In 3.2: list_products covers published offers, request_proposals returns seller-written plans, refine_proposals revises (revise) or commits (finalize) them, and decline_proposals records the buyer’s no.
Step 3: What does create_media_buy carry?
To book, the buyer calls create_media_buy. In both 3.1 and 3.2 the request must include idempotency_key, account, brand, start_time and end_time, plus either explicit packages or a committed proposal_id with a total_budget. A package names a product_id and pricing_option_id; in 3.1 every package also needs a budget.
{
"adcp_version": "3.1",
"idempotency_key": "scooter-launch-2026-11-0001",
"account": { "account_id": "acc_scooter_in" },
"brand": { "domain": "scooter.example" },
"po_number": "PO-48213",
"start_time": "2026-11-16T00:00:00+05:30",
"end_time": "2026-11-30T00:00:00+05:30",
"packages": [
{
"product_id": "ros_display_in_guaranteed",
"pricing_option_id": "cpm_inr_fixed",
"budget": 900000,
"pacing": "even",
"context": { "buyer_ref": "line-001" }
}
]
}
Your response takes one of three shapes:
- Success with
media_buy_id,confirmed_at,revisionandpackages, usually with acreative_deadline. The buy’s state goes inmedia_buy_status:pending_creatives,pending_start,activeorpaused. - Error with an
errorsarray. - Submitted with
status: "submitted"and atask_id, when the buy cannot be confirmed in the response.
Treat the idempotency key seriously: a retry with the same key and account should return the existing buy, not a second one.
In 3.2: the deprecated body-level status is removed from the success response, so read and write media_buy_status only. New buyers use buy_products for a published offer and accept_proposal for a committed proposal.
Step 4: Where do approvals fit?
AdCP expects some buys to wait for a person. The spec is specific about when:
- Return
submittedwhen the buy includes a guaranteed product and you require IO approval, when a governance or brand-safety review cannot finish in the response, or when the request joins a batch queue. - Return synchronous success when every product is non-guaranteed. A seller that returns
submittedfor every create fails the guaranteed-sales compliance storyboard.
The buyer then polls the task or waits for a webhook, and the completion carries the media_buy_id and packages. If you need more information, the task can move to input-required. A seller may instead return success with confirmed_at: null for a provisional buy; it must not be active until confirmed_at is set.
On Google Ad Manager, the Prebid Sales Agent defaults guaranteed products to manual approval and non-guaranteed products to confirmation_required; we covered those settings in the agent-ready inventory guide.
Step 5: How do creatives reach the sales agent?
Each confirmed package says which creative formats are still needed: format_ids_to_provide in 3.1, and formats_to_provide[] in 3.2. The buyer then calls sync_creatives with the assets and an assignments array mapping each creative_id to a package_id. dry_run: true rehearses the sync without applying it.
Each creative in your response carries a review status: processing, pending_review, approved, suspended, rejected or archived. That status is advisory. The spec tells buyers not to gate spend on it; list_creatives or a signed review webhook is the authoritative record. A buy with no approved creative coverage stays pending_creatives, and a later rejection changes the creative or package state without rolling back the buy.
One design point: create_media_buy with inline creatives is atomic. Any invalid creative fails the whole request and leaves nothing behind. The 3.2 compact path is different: buy_products commits first and sync_creatives follows, so a failed sync leaves the buy in place.
Step 6: How do buyers monitor delivery?
Two tasks, with different jobs:
get_media_buysreturns status, creative approvals and delivery snapshots. From 3.1 it also carrieshealthandimpairments[]when something the buy depends on goes offline, plusavailable_actions[]. The spec calls it operational monitoring.get_media_buy_deliveryis the billing-grade report. Rows carryis_finalandfinalized_at, so the buyer knows when numbers stop moving. Areporting_webhookon the buy can push reports instead of waiting for polls.
In 3.2: delivery dates are calendar dates in each product’s reporting timezone, echoed in reporting_period.timezone, rather than UTC. Currency moves to the media buy or package row.
Step 7: How are live buys changed?
In 3.1 the buyer calls update_media_buy with media_buy_id, account and idempotency_key, plus what changes: paused, canceled, flight dates, package updates or new_packages. Passing the revision from your last response guards against conflicting edits. Use available_actions[] to say which changes are valid now, and return REQUOTE_REQUIRED when a change goes beyond the terms you quoted.
In 3.2: control_media_buy handles changes inside the accepted terms and requires revision. A change to the terms themselves needs a new proposal snapshot and accept_proposal.
Checklist: what your sales agent must get right
- Capabilities list every release, protocol, specialism and publisher domain you actually serve.
- Products carry descriptions a model can match against a brief, plus formats and pricing your ad server can deliver.
- Brief and refine return in time or as a
submittedtask; wholesale reads stay synchronous. - Idempotency on
create_media_buyreturns the original buy on retry. - Approvals follow the rule:
submittedfor guaranteed IO approval, synchronous success for non-guaranteed. - Creative review is reflected in
list_creativesandget_media_buys, not only in the sync response. - Delivery reconciles with your ad server report, same timezone, with
is_finalset when numbers close. - Updates check
revisionand returnREQUOTE_REQUIREDrather than silently repricing.
At BidCliq we build header bidding and agentic tools for publishers, and our sales agent is verified by AgenticAdvertising.org against AdCP 3.1. If you are weighing where agent-booked buys fit next to your IO business, read agents and direct-sold IOs.
Frequently asked questions
What is the first call a buyer agent makes to an AdCP sales agent?
get_adcp_capabilities. It tells the buyer which AdCP releases you support, which protocols and specialisms you claim, which publisher domains you represent, and in 3.2 which compact lifecycle tools you serve.
When should a sales agent return submitted instead of creating the buy immediately?
The spec says to return submitted when a guaranteed product needs IO approval, when a governance review cannot finish in the response, or when the request joins a batch queue. Buys of only non-guaranteed products should get a synchronous success with a media_buy_id.
Is create_media_buy still valid in AdCP 3.2?
Yes. It remains a 3.x compatibility facade, and it is still the only path that creates a buy and its inline creatives in one atomic request. New 3.2 buyers use buy_products or accept_proposal when the seller advertises them.
How does a buyer change a live AdCP media buy?
In 3.1 with update_media_buy, ideally passing the buy's current revision; in 3.2 with control_media_buy, where revision is required. Changes that go beyond the agreed terms need a new quote or proposal, and sellers signal that with REQUOTE_REQUIRED.

About the author
Founder, BidCliq
Sharad Yadav is the founder of BidCliq, a publisher-first ad monetization platform that helps publishers and ad ops teams run header bidding, Prebid and programmatic across display, video, app and CTV. Before BidCliq, he led AdTech and product at GeeksforGeeks, where he built an in-house ads product that doubled programmatic revenue within nine months and an anti-adblock solution that lifted ad yield by 10%. He is a founding member of AdCP.