> ## Documentation Index
> Fetch the complete documentation index at: https://docs.adcontextprotocol.org/llms.txt
> Use this file to discover all available pages before exploring further.

# list_proposals

> Read a seller's current proposals and their lifecycle state for an account or opportunity.

> [!WARNING]
>
> `list_proposals` is **experimental** (feature id `media_buy.open_opportunities`). Sellers that implement it list the feature id in `experimental_features` and set `media_buy.open_opportunities.list_proposals: true` on [`get_adcp_capabilities`](/dist/docs/3.3.0-beta.0/protocol/get_adcp_capabilities). See [Experimental status](/dist/docs/3.3.0-beta.0/reference/experimental-status).

`list_proposals` returns the seller's current proposals for one account, narrowed to opportunities, media buys, or proposal IDs when the buyer supplies them. It is a synchronous read that never changes proposal or opportunity state. It is the repair read for [`proposal.created`](/dist/docs/3.3.0-beta.0/media-buy/product-discovery/proposal-negotiation#open-opportunities-and-later-proposals) notifications, for `proposal.offered` (the buy-scoped sibling for seller offers against accepted media buys, defined under `media_buy.seller_offers`), and for `proposal` records in [`list_account_changes`](/dist/docs/3.3.0-beta.0/accounts/tasks/list_account_changes). Buyers learn that something changed from those signals and use `list_proposals` for current state, not for routine polling.

**Request schema:** [`/schemas/3.3.0-beta.0/media-buy/list-proposals-request.json`](https://adcontextprotocol.org/schemas/3.3.0-beta.0/media-buy/list-proposals-request.json)

```json theme={null}
{
  "account": { "account_id": "acc_nova_za" },
  "opportunity_ids": ["opp_nova_za_q4"],
  "dispositions": ["available"]
}
```

To repair after a `proposal.offered` notification, read the proposal named in it with `proposal_ids`. To catch up on a buy after missed notifications, filter by buy:

```json theme={null}
{
  "account": { "account_id": "acc_nova_za" },
  "media_buy_ids": ["mb_nova_za_0412"],
  "dispositions": ["available"]
}
```

| Field | Notes |
| - | - |
| `account` | Required. Results never cross accounts. |
| `opportunity_ids` | Optional. Proposals created without an opportunity appear only when this filter is absent. |
| `media_buy_ids` | Optional. Returns proposals whose snapshot `media_buy_id` is one of these buys: seller offers and other amendments against them, plus the accepted snapshots that created them. Proposals with no `media_buy_id` appear only when this filter is absent. Unknown or inaccessible IDs are omitted. Filters combine as an AND, so `media_buy_ids` with `dispositions: ["available"]` is the repair scan for live offers on a buy. |
| `proposal_ids` | Optional. Unknown or inaccessible IDs are omitted, not errors. |
| `dispositions` | Optional. Defaults to every disposition the seller still retains. |
| `cursor`, `max_results` | Paging, as on [`list_products`](/dist/docs/3.3.0-beta.0/media-buy/task-reference/list_products). |

**Response schema:** [`/schemas/3.3.0-beta.0/media-buy/list-proposals-response.json`](https://adcontextprotocol.org/schemas/3.3.0-beta.0/media-buy/list-proposals-response.json)

```json theme={null}
{
  "outcome": "listed",
  "proposals": [
    {
      "proposal": { "proposal_id": "prop_nova_za_evt_07", "proposal_status": "draft", "opportunity_id": "opp_nova_za_q4", "...": "unchanged snapshot" },
      "disposition": "available",
      "disposition_changed_at": "2026-10-23T09:14:04Z",
      "origin": "later",
      "later_reason": "event_package"
    }
  ],
  "opportunities": [
    {
      "opportunity_id": "opp_nova_za_q4",
      "status": "open",
      "later_proposals": {
        "accepted": true,
        "window_ends_at": "2026-12-31T23:59:59Z",
        "max_count": 5,
        "min_interval": { "interval": 1, "unit": "days" },
        "created_count": 1,
        "updated_at": "2026-10-09T15:02:11Z"
      }
    }
  ]
}
```

## Snapshot and disposition

Each `proposal` is the snapshot exactly as the seller issued it, so its `terms_digest` still verifies. Lifecycle state sits beside it in `disposition`, because a snapshot's `proposal_status` (`draft`, `committed`, `accepted`) never changes after issue.

| Disposition | Meaning |
| - | - |
| `available` | Can still be refined, declined, or, when committed and before `expires_at`, accepted. A refined source stays `available`; refinement creates new snapshots and does not retire the source. |
| `accepted` | Executed through [`accept_proposal`](/dist/docs/3.3.0-beta.0/media-buy/task-reference/accept_proposal) or [`create_media_buy`](/dist/docs/3.3.0-beta.0/media-buy/task-reference/create_media_buy). |
| `declined` | Declined through [`decline_proposals`](/dist/docs/3.3.0-beta.0/media-buy/task-reference/decline_proposals). Terminal. |
| `expired` | `expires_at` passed before acceptance. Terminal. |
| `withdrawn` | The seller retracted a draft before expiry. Terminal. A seller must not withdraw a committed proposal before its `expires_at`, except an outstanding seller offer made stale by a revision of its media buy (see [Seller offers](#seller-offers)). |

Sellers keep a snapshot readable while it is `available` and for at least 30 days after it becomes `accepted`, `declined`, `expired`, or `withdrawn`. After that the snapshot may be gone; [`get_media_buys`](/dist/docs/3.3.0-beta.0/media-buy/task-reference/get_media_buys) remains the record of accepted terms, and an older change-feed record repairs as unavailable. Refining or accepting a `withdrawn` snapshot fails with [`INVALID_STATE`](/dist/docs/3.3.0-beta.0/building/verification/compliance-catalog#error-code-invalid-state), as for a declined one. There is no withdrawal notification.

`origin` says how the snapshot was created:

| Origin | Snapshot rules |
| - | - |
| `request` | Returned by [`request_proposals`](/dist/docs/3.3.0-beta.0/media-buy/task-reference/request_proposals). |
| `refinement` | Created by [`refine_proposals`](/dist/docs/3.3.0-beta.0/media-buy/task-reference/refine_proposals). |
| `later` | Created by the seller after the creating task completed, under `later_proposals` consent. Always a `draft` `new_media_buy` with `opportunity_id` and `expires_at`, and carries `later_reason`. |
| `seller_offer` | A seller offer against an accepted media buy, defined under `media_buy.seller_offers`. Requires `proposal_initiator: "seller"` on the snapshot, a `media_buy_update` or `media_buy_cancellation` kind, and `proposal_status` `committed` (`accepted` once the buyer accepts it). Never carries `later_reason`. |

A snapshot with `proposal_initiator: "seller"` is always listed with `origin: "seller_offer"`.

## Seller offers

Seller offers are distinct from later proposals. A later proposal is a `draft` `new_media_buy` the seller creates under the buyer's `later_proposals` consent and announces with `proposal.created`. A seller offer is a committed change to a live buy, announced with `proposal.offered`; it needs no `later_proposals` consent. Post-purchase `media_buy_update` proposals are out of scope for later proposals, so `media_buy_update` appears here only as a seller offer. Both notifications are identifiers-only and repair through `list_proposals`.

An outstanding offer (committed, not yet accepted, declined, or expired) is stale when a revision of its media buy leaves its `base_media_buy_revision` behind the buy's current revision, whoever made the revision. A revision made by accepting the offer itself is not a staleness event, and terminal dispositions never change. A stale offer stays readable but cannot be accepted:

* The seller derives the state from the buy's current revision at read time, so it never lists a stale offer as `available`. It reports `withdrawn`, with `disposition_changed_at` set to the revision time. This is the one exception to the rule that a committed proposal is not withdrawn before `expires_at`: the buyer could not act on the offer anyway, and the seller may release the replacement inventory it held.
* [`accept_proposal`](/dist/docs/3.3.0-beta.0/media-buy/task-reference/accept_proposal) and [`refine_proposals`](/dist/docs/3.3.0-beta.0/media-buy/task-reference/refine_proposals) for it fail with [`INVALID_STATE`](/dist/docs/3.3.0-beta.0/building/verification/compliance-catalog#error-code-invalid-state), like any withdrawn snapshot, and the existing base-revision check still guards acceptance. Once `expires_at` has passed, [`PROPOSAL_EXPIRED`](/dist/docs/3.3.0-beta.0/building/verification/compliance-catalog#error-code-proposal-expired) takes precedence.
* It stays readable for at least 30 days after the revision, the same as any terminal disposition. No `withdrawn` notification is sent, so buyers must not cache `available` for an offer; read it with `proposal_ids` before acting.

Because stale offers are never `available`, `media_buy_ids` with `dispositions: ["available"]` returns only offers the buyer can still accept. A buyer that finds a notified offer missing from that scan reads it by `proposal_ids`, which distinguishes `withdrawn` (stale) from a snapshot past retention.

## Opportunities

`opportunities[]` has one entry for each opportunity referenced by a returned proposal or named in `opportunity_ids`; unknown or inaccessible opportunity IDs are omitted. `later_proposals` is the consent the seller recorded and will enforce, including the computed `window_ends_at` and `created_count`. If `updated_at` shows a change the buyer did not make, another principal on the same account updated the opportunity.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.