> ## 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.

# Update media buy

> Partially update a single media buy by its mediaBuyId

`PATCH /api/v2/buyer/media-buys/:mediaBuyId`

Also available as the `update_media_buy` MCP tool on the buyer server.

Updates one media buy directly, addressed by `mediaBuyId` — the owning campaign is resolved server-side, the same way [Get media buy](/v2/buyer/campaigns/tasks/get-media-buy-status) reads work. Use it when you already know which buy to change and don't want to route the edit through [Update campaign](/v2/buyer/campaigns/tasks/update-campaign)'s `mediaBuys[]` array.

All fields are optional; send only what you want to change. Fields you omit are left as they are.

To create media buys, use [Create media buys](/v2/buyer/discovery/tasks/create-media-buys) — this task edits an existing buy and never adds a brand-new product selection.

## Request

```bash theme={null}
curl -X PATCH https://api.interchange.io/api/v2/buyer/media-buys/mb_ETBn4gJ9Wu \
  -H "Authorization: Bearer $SCOPE3_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "end_time": "2026-09-30T23:59:59Z",
    "packages": [
      { "packageId": "sf_pkg_sf_mb_1783618937177_43ycbp7b_1", "budget": 6000 }
    ],
    "updated_reason": "Extended flight with additional Week 1 budget"
  }'
```

## Parameters

| Field                | Type   | Required | Notes                                                                                                                                                                                                                                                                   |
| -------------------- | ------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `mediaBuyId`         | string | Yes      | Media buy ID (path parameter; top-level field on the MCP tool).                                                                                                                                                                                                         |
| `name`               | string | No       | New display name.                                                                                                                                                                                                                                                       |
| `start_time`         | string | No       | `"asap"` or ISO 8601. A start earlier than the campaign's flight start does not fail — see [flight dates](#flight-dates-outside-the-campaign-window).                                                                                                                   |
| `end_time`           | string | No       | ISO 8601. An end later than the campaign's flight end does not fail — see [flight dates](#flight-dates-outside-the-campaign-window).                                                                                                                                    |
| `packages[]`         | array  | No       | Per-package updates: `packageId` (required), `budget`, `pacing`, `bidPrice`, `startTime`, `endTime`. Package flight dates must fall within the media buy's own date range. Resolve IDs with [Get media buy packages](/v2/buyer/campaigns/tasks/get-media-buy-packages). |
| `products[]`         | array  | No       | Per-product updates: `productId` (required), `budget`, `pacing`, `bidPrice`, `pricingOptionId`, `remove`. Additive — products you don't list are untouched; `remove: true` deletes one.                                                                                 |
| `optimization_goals` | array  | No       | Replaces the buy's optimization goals; applied to every package at execution. Empty array clears.                                                                                                                                                                       |
| `creative_ids`       | array  | No       | Explicit creative assignments for this buy. Empty array clears; omit to keep auto-sync.                                                                                                                                                                                 |
| `updated_reason`     | string | No       | Stored with the new version for audit history.                                                                                                                                                                                                                          |

## What is validated

The update is rejected — never silently adjusted — when it would violate a campaign invariant:

| Invariant          | Error                     | When                                                                                                                                                                                                                                                                                          |
| ------------------ | ------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Currency           | `CURRENCY_MISMATCH` (400) | A `products[].pricingOptionId` resolves to a pricing option that settles in a different currency than this buy. A media buy settles in exactly one currency; to buy the product in another currency, re-discover it and use [Create media buys](/v2/buyer/discovery/tasks/create-media-buys). |
| Budget headroom    | `VALIDATION_ERROR` (400)  | A budget increase would push the campaign's allocated total past its all-in budget ceiling. Raise the campaign budget or reduce other buys first.                                                                                                                                             |
| Mode compatibility | `VALIDATION_ERROR` (400)  | The owning campaign is directed (mirrored from a connected seller account). The mirrored buy is the campaign itself and has no platform-managed update path.                                                                                                                                  |
| Campaign state     | `VALIDATION_ERROR` (400)  | The owning campaign is completed, archived, or cancelled.                                                                                                                                                                                                                                     |
| Buy state          | `CONFLICT` (409)          | The media buy itself is in a terminal status (cancelled, failed, rejected) and can no longer be updated.                                                                                                                                                                                      |
| Spend floor        | `VALIDATION_ERROR` (400)  | A package budget would be set below what that package has already delivered.                                                                                                                                                                                                                  |

## Flight dates outside the campaign window

Flight dates that fall outside the campaign's current window are a **warning, not a failure**: the campaign flight is widened to cover the requested dates and the response tells you it happened. This matches how campaign dates already auto-extend during execute.

This warn-and-widen behavior applies to the media buy's own `start_time`/`end_time`. Per-package `packages[].startTime`/`endTime` are intentionally validated against the **media buy's** date range, not the campaign's — a package can never outrun its buy, so an out-of-range package date is a validation error, not a warning. Widen the buy's own dates first if a package needs to run longer.

```json theme={null}
{
  "mediaBuy": { "...": "..." },
  "warnings": [
    "Requested end_time (2026-10-15T00:00:00Z) is later than campaign camp_1's current flight end (2026-09-30T23:59:59.000Z); the campaign flight was widened to cover it."
  ]
}
```

## Response

`200` with the updated buy in the same shape as `GET /media-buys/:mediaBuyId` — identity, status, and the why-visibility fields — plus `warnings[]` when a flight date widened the campaign window:

```json theme={null}
{
  "mediaBuy": {
    "mediaBuyId": "mb_ETBn4gJ9Wu",
    "name": "Q3 Display — extended",
    "status": "PENDING_APPROVAL",
    "pendingChange": {
      "status": "PENDING_APPROVAL",
      "differences": {
        "endTime": { "live": "2026-08-31T23:59:59Z", "proposed": "2026-09-30T23:59:59Z" }
      }
    },
    "startTime": "2026-08-01T00:00:00Z",
    "endTime": "2026-08-31T23:59:59Z",
    "createdAt": "2026-07-01T09:00:00Z",
    "updatedAt": "2026-07-26T14:00:00Z"
  }
}
```

<Note>
  Updating an ACTIVE or PAUSED buy stages a new version for seller confirmation rather than mutating the live buy: the response's top-level fields keep describing what is delivering now, and the queued change appears under `pendingChange` until the seller confirms it. DRAFT buys update in place.
</Note>

## Errors

| Code                | When                                                                        |
| ------------------- | --------------------------------------------------------------------------- |
| `NOT_FOUND`         | Media buy ID does not exist for the authenticated account.                  |
| `VALIDATION_ERROR`  | A campaign invariant above was violated, or a field failed validation.      |
| `CURRENCY_MISMATCH` | A replacement pricing option settles in a different currency than this buy. |
| `CONFLICT`          | The buy is terminal and can no longer be updated.                           |

See [Errors](/v2/reference/errors) for the full error shape and recovery semantics.

## Related

<CardGroup cols={2}>
  <Card title="Get media buy packages" href="/v2/buyer/campaigns/tasks/get-media-buy-packages" icon="boxes-stacked">
    Resolve a package description to the packageId to update
  </Card>

  <Card title="Update campaign" href="/v2/buyer/campaigns/tasks/update-campaign" icon="pen">
    Campaign-addressed updates, cancels, and multi-buy edits in one request
  </Card>

  <Card title="Create media buys" href="/v2/buyer/discovery/tasks/create-media-buys" icon="cart-shopping">
    Stage and execute new product selections through the campaign cart
  </Card>

  <Card title="Media buys" href="/v2/buyer/campaigns/media-buys" icon="diagram-project">
    How media buys relate to campaigns, packages, and sellers
  </Card>
</CardGroup>
