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

# Media buys & pending operations

> See every buy on your storefront, trace one buy end to end, and work everything that is waiting on someone

Three read-only surfaces answer the operating questions "what buys do I have, where is this one stuck, and what needs attention" — without a ticket and without platform support looking at a database. Each is available as a REST endpoint and as an in-chat surface (ask Murph, or open it from the rail's **Operate** section).

All examples use the storefront base URL:

```
https://api.interchange.io/api/v2/storefront
```

Authenticate every request with `Authorization: Bearer $SCOPE3_API_KEY`.

## Recover a failed GAM order safely

If GAM created an order but line-item trafficking failed, Pending Operations shows a separate cleanup task. Interchange uses ESA's structured cleanup result; it never interprets vendor exception text or exposes GAM credentials.

* If `ArchiveOrders` is missing, grant it in GAM and re-check, or archive the order manually.
* If authentication expired, reconnect the ad-server connection before re-checking.
* Review and archive appears when cleanup is verified retryable. Permission and authentication failures instead offer a confirmation-gated re-check, and archive proceeds only if the repeated safety check passes.
* Unknown or unsafe orders require GAM review and cannot be archived from Interchange.

Only storefront account admins can resolve these tasks. Archiving requires explicit confirmation naming the GAM order, and ESA repeats every safety check immediately before archiving. An already-archived response completes the task. Marking an order manually cleaned requires the matching order ID and an audit note; it is recorded distinctly and never claims ESA archived it.

## Media buys — every buy on the storefront

`GET /media-buys` returns every buy forwarded across connected sources plus buys
managed directly by an ad-server source. The API retains `kind: routed | esa` as
legacy wire values; those values describe implementation provenance, not
campaign mode or settlement. Filter by `status`, `buyerCustomerId`, `sourceId`,
or flight-start window.

The default sort is **urgency**: buys still waiting on someone whose flight starts within 48 hours (or has already started) come first, ordered by flight start; everything else follows newest-first.

Each row carries:

| Field            | Meaning                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| ---------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `status`         | A coarse seller lifecycle view derived from persisted state: `pending_approval`, `forwarding`, `forward_failed`, `awaiting_source`, `rejected`, `canceled`, `booked`, `delivering`, `paused`, `completed`. This is a platform list-view convenience, never an AdCP status.                                                                                                                                                                                                                                                                                                                   |
| `sourceStatus`   | The raw upstream status as persisted, for transparency.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `pendingReason`  | Why the buy is not delivering yet — the **same shared vocabulary buyers see** (`awaiting_storefront_approval`, `awaiting_source_moderation`, `no_creatives_attached`, `source_rejected_creatives`, `creative_processing_at_source`, `awaiting_creative_approval`, `forward_failed_retrying`, `forward_failed_needs_correction`, `accepted_awaiting_trafficking`, `scheduled_not_started`), rolled up to the most-blocking source leg. It is an annotation, never a status. `no_creatives_attached` and `source_rejected_creatives` are buyer-owned (the buyer must attach or fix creatives). |
| `errorCode`      | The structured error code of the latest failed exchange (the platform's ledger vocabulary, e.g. `unknown_product_ids`).                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| `forwardOutcome` | How far dispatch got: `not_forwarded`, `all_completed`, `all_submitted`, `partial`, `failed`.                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                |

## Per-buy timeline — what was sent, when, and where it is stuck

`GET /media-buys/{mediaBuyId}/timeline` is the seller-scoped projection of the buy's exchange record. Stages follow the exchange lifecycle, failure branches included:

```
received → screened → decided → forwarded / forward-failed → submitted
        → source moderation (pending since T) → accepted / rejected → delivering
```

Update exchanges reuse the same stages. Inbound source webhooks appear as **evidence inside stages**, never as a stage of their own — many sources never send webhooks, so their absence means nothing. The `screened` stage is reserved for the acceptance-policy pre-screen record and is not emitted today; do not wait for it.

**What you can see, and what you cannot.** The forwarded payload is yours to inspect — you are the counterparty to that message — *minus platform-internal fields*: webhook/push-notification configuration and any signing or credential material are removed server-side. Platform-internal diagnostics (resolution cache internals, worker polling state, cross-tenant audit entries) never appear; failures surface as structured error codes with a recovery class instead. A payload shown as `{"pruned": true}` means retention removed the stored bytes (payload bodies are kept for 90 days; the slim event record is kept indefinitely).

Each source leg carries a trafficker-grade summary of the request (flight, budget, packages, targeting dimensions) with the raw JSON behind a disclosure.

### Whose reference to quote to whom

Every leg carries two references, and they are for different counterparties:

| Reference                                           | Field                                                                                                             | Quote it to                                                                                                                                                                                                                        |
| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Their reference** — the source's own ids          | `theirReference.mediaBuyId` / `theirReference.taskId`                                                             | The inventory source. These are ids minted in *their* system; their support can look them up directly. For adapter sources (e.g. Google Ad Manager) the platform order id plays this role.                                         |
| **Platform reference** — the create idempotency key | `platformReference.idempotencyKey` (`sf:<storefront>:<buy>:<source>`) paired with `platformReference.requestedAt` | The source (for pre-acceptance exchanges — it is the deduplication key they received) and Scope3 support. Always quote the key **together with the request timestamp**: the key is stable across the buy's life, requests are not. |

While a source is still moderating (no upstream buy exists yet), their task id is the handle; once accepted, their media-buy id is.

## Pending operations — everything waiting on someone

`GET /pending-operations` returns the union of work in flight, grouped; a group appears **only when it is non-empty**:

* **`approvals`** — media buys (creates and updates) waiting on your review.
* **`creativeReviews`** — creatives waiting on your review.
* **`failedForwards`** — approved buys that could not be sent to their source, **grouped by structured error code** so a source outage reads as one row, not N. Each group and item carries its gated action (below).
* **`awaitingSource`** — buys a source accepted asynchronously and is still moderating, each with "waiting since" and the source's task id.
* **`sourceDegradations`** — seller-owned source-health diagnoses: an ad-server or sales-agent source you operate that is degraded, each with its severity (`blocking`, `attention`, or `advisory`) and a one-line summary. Only diagnoses **you** own appear — an issue Scope3 or a vendor must fix never shows up as your task. Each row links to the [source diagnostics surface](/v2/storefront/inventory-sources/diagnostics) scoped to that source.
* **`gamCleanups`** — failed GAM order cleanups that require an operator decision. The Page offers automatic archive only when the server marks the cleanup safe; recording a manual cleanup requires a note.

The same Page works in Interchange, Claude, ChatGPT, and other MCP-app hosts. Its buttons open the exact portable Approvals, timeline, retry, or source-diagnostics surface directly—there is no generated chat prompt or second assistant turn. GAM cleanup is a two-step human confirmation inside the Page and uses an app-only commit that is not exposed to the model.

### Recovery classes: why some failures have no retry

Every forwarding failure carries a recovery class, and the class — not the operator's optimism — decides which action is offered:

| Recovery class | Meaning                                                                                                                                          | Action offered                                                                                                                                                        |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `transient`    | The send can succeed if repeated (source outage, timeout). The platform retries these itself for up to 6 hours after approval.                   | **Retry** — a one-decision confirmation that re-fires the forward. The create idempotency key makes a duplicate booking impossible if the source already received it. |
| `correctable`  | The request needs a change before any send can succeed (e.g. an expired cross-currency quote).                                                   | **Review correction** — opens the exact buy timeline and evidence; retrying the same payload would fail identically.                                                  |
| `structural`   | No retry can ever succeed (e.g. the selected product no longer resolves). The platform terminalizes these — it stops retrying and marks the buy. | **Review escalation** — opens the exact buy timeline and references. A retry button is never shown, because a retry would silently do nothing.                        |

A `transient` failure whose retry window has lapsed is treated as terminalized and also becomes escalate-only.

<Tip>
  **If your source consistently produces `transient` timeout failures** on `create_media_buy` or `update_media_buy` — visible in source diagnostics and as persistent `failedForwards` here — the long-term fix is to implement AdCP asynchronous acceptance on your sales agent. Return a `submitted` response (with a stable `task_id`) immediately when the platform's request arrives, complete the work out-of-band, then POST the result to the `push_notification_config` webhook URL included in the original request. This decouples your processing time from the platform's call timeout and eliminates the failure class entirely.

  See the [AdCP async operations reference](https://docs.adcontextprotocol.org/docs/media-buy/task-reference/update_media_buy#asynchronous-operations) for the protocol and payload details. Contact your operator or Scope3 support to discuss implementation.
</Tip>

### Transition notifications

You do not have to keep this surface open: a **forward failure** on an approved buy and a **source-moderation wait that ages past its deadline** each push one notification to your storefront's notification stream (in-app, email, Slack — per your delivery settings). These fire on the transition only, never repeatedly, and carry the error code and recovery class.

## Task reference

<CardGroup cols={2}>
  <Card title="List media buys" href="/v2/storefront/media-buys/overview" icon="list">
    `GET /media-buys` — every buy across the storefront and connected sources,
    urgency-sorted
  </Card>

  <Card title="Get a buy's timeline" href="/v2/storefront/media-buys/overview" icon="timeline">
    `GET /media-buys/{mediaBuyId}/timeline` — the seller-scoped exchange record
  </Card>

  <Card title="List pending operations" href="/v2/storefront/media-buys/overview" icon="hourglass">
    `GET /pending-operations` — everything waiting on someone
  </Card>

  <Card title="Retry a failed forward" href="/v2/storefront/media-buy-approvals/overview" icon="rotate-right">
    `POST /media-buy-approvals/{mediaBuyId}/retry-forward` — transient, non-terminalized failures only
  </Card>
</CardGroup>
