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

# Decide an approval

> Approve or reject a pending media buy

`POST /api/v2/storefront/media-buy-approvals/{mediaBuyId}/decide`

Records your decision on a pending media buy. Only valid on entries still in `pending` state — a double-decide is rejected. Approved entries are forwarded upstream to the underlying sales agent by the storefront's MCP layer; watch `forwardedAt` on a subsequent read to confirm the forward landed.

## Request

<CodeGroup>
  ```bash Approve theme={null}
  curl -X POST \
    "https://api.interchange.io/api/v2/storefront/media-buy-approvals/mb_2026_q2_ctv/decide" \
    -H "Authorization: Bearer $SCOPE3_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "status": "approved"
    }'
  ```

  ```bash Reject theme={null}
  curl -X POST \
    "https://api.interchange.io/api/v2/storefront/media-buy-approvals/mb_2026_q2_ctv/decide" \
    -H "Authorization: Bearer $SCOPE3_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "status": "rejected",
      "reviewerNotes": "Targeting outside coverage area"
    }'
  ```
</CodeGroup>

## Parameters

| Field           | Type   | Required | Notes                                                                                                   |
| --------------- | ------ | -------- | ------------------------------------------------------------------------------------------------------- |
| `mediaBuyId`    | string | Yes      | Path param — buyer-supplied media buy identifier (AdCP `media_buy_id`)                                  |
| `status`        | enum   | Yes      | Decision to record. `approved` or `rejected`                                                            |
| `reviewerNotes` | string | No       | Note surfaced back to the buyer alongside the status. Keep it actionable when rejecting. Max 2000 chars |

## Response

<CodeGroup>
  ```json Approved theme={null}
  {
    "id": "42",
    "storefrontId": "1234",
    "mediaBuyId": "mb_2026_q2_ctv",
    "buyerCustomerId": 8801,
    "submittedPayload": {
      "media_buy_id": "mb_2026_q2_ctv",
      "total_budget": 50000,
      "currency": "USD"
    },
    "status": "approved",
    "reviewedBy": "5567",
    "reviewedAt": "2026-06-02T12:30:00Z",
    "reviewerNotes": null,
    "forwardedAt": "2026-06-02T12:30:05Z",
    "createdAt": "2026-06-02T10:00:00Z",
    "updatedAt": "2026-06-02T12:30:05Z",
    "forwardOutcome": "all_completed",
    "forwardResult": [
      {
        "sourceId": "src_001",
        "upstreamMediaBuyId": "upstream_mb_xyz",
        "status": "completed"
      }
    ]
  }
  ```

  ```json Rejected theme={null}
  {
    "id": "42",
    "storefrontId": "1234",
    "mediaBuyId": "mb_2026_q2_ctv",
    "buyerCustomerId": 8801,
    "submittedPayload": {
      "media_buy_id": "mb_2026_q2_ctv",
      "total_budget": 50000,
      "currency": "USD"
    },
    "status": "rejected",
    "reviewedBy": "5567",
    "reviewedAt": "2026-06-02T12:30:00Z",
    "reviewerNotes": "Targeting outside coverage area",
    "forwardedAt": null,
    "createdAt": "2026-06-02T10:00:00Z",
    "updatedAt": "2026-06-02T12:30:00Z"
  }
  ```
</CodeGroup>

Returns the decided `PendingMediaBuyResponse`. `reviewedBy`, `reviewedAt`, and `updatedAt` are stamped at decision time.

**Approval** responses include two extra fields stamped by the forwarder:

| Field            | Type   | Notes                                                                                             |
| ---------------- | ------ | ------------------------------------------------------------------------------------------------- |
| `forwardOutcome` | enum   | `all_completed`, `partial`, `all_failed`, or `precondition_failed`                                |
| `forwardResult`  | array  | Per-source forwarding result (`sourceId`, `status`, `upstreamMediaBuyId?`, `packages?`, `error?`) |
| `forwardError`   | object | Present only on non-`all_completed` outcomes: `{ code, message, productIds?, productId? }`        |

`forwardedAt` is `null` when `forwardOutcome` is not `all_completed`; populated once every source accepts. **Rejection** responses contain only the base `PendingMediaBuyResponse` fields.

## Errors

* `400 VALIDATION_ERROR` — missing `status`, invalid `status`, or the entry is no longer `pending` (double-decide).
* `404 NOT_FOUND` — no approval entry with that media buy id exists for your storefront.

See [Errors](/v2/reference/errors) for the full error contract.

## Related

<CardGroup cols={2}>
  <Card title="Get an approval" href="/v2/storefront/media-buy-approvals/tasks/get-approval" icon="magnifying-glass">
    Inspect the entry before deciding
  </Card>

  <Card title="List approvals" href="/v2/storefront/media-buy-approvals/tasks/list-approvals" icon="list">
    See the pending queue
  </Card>

  <Card title="Media-buy approval tasks" href="/v2/storefront/media-buy-approvals/tasks" icon="list-check">
    All media-buy approval operations
  </Card>

  <Card title="Media-buy approvals overview" href="/v2/storefront/media-buy-approvals/overview" icon="clipboard-check">
    Queue lifecycle and concepts
  </Card>
</CardGroup>
