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

> Edit the label, notes, or expiry of a storefront proposal

`PATCH /api/v2/storefront/proposals/{id}`

Updates the editable fields of a proposal — `label`, `notes`, or `expiresAt`. The frozen `snapshot`, `operatorId`, and `proposalCode` are immutable; this operation only changes seller-side metadata and the expiry window. Send only the fields you want to change.

## Request

<CodeGroup>
  ```bash curl theme={null}
  curl -X PATCH https://api.interchange.io/api/v2/storefront/proposals/318 \
    -H "Authorization: Bearer $SCOPE3_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "label": "Acme Q3 RFP — CTV (extended)",
      "expiresAt": "2026-10-31T23:59:59Z"
    }'
  ```

  ```json Notes only theme={null}
  {
    "notes": "Buyer confirmed the rate on 2026-06-09; holding through Q3."
  }
  ```
</CodeGroup>

## Parameters

| Field       | Type    | Required | Notes                            |
| ----------- | ------- | -------- | -------------------------------- |
| `id`        | integer | Yes      | Proposal row ID (path parameter) |
| `label`     | string  | No       | Updated label (1..255 chars)     |
| `notes`     | string  | No       | Updated notes (max 4000 chars)   |
| `expiresAt` | string  | No       | Updated expiry (ISO 8601)        |

## Response

```json theme={null}
{
  "id": 318,
  "proposalCode": "PRP-XK4A29",
  "operatorId": "acme",
  "label": "Acme Q3 RFP — CTV (extended)",
  "notes": "Offline RFP follow-up; honors the upfront rate.",
  "status": "active",
  "expiresAt": "2026-10-31T23:59:59Z",
  "proposalId": "proposal_abc123",
  "discoverySessionId": "disc_a1b2c3",
  "snapshot": { "products": [], "proposals": [] },
  "createdAt": "2026-06-07T15:00:00Z",
  "createdBy": "seller@acme-media.example.com",
  "firstViewedAt": null,
  "lastViewedAt": null,
  "redeemedAt": null,
  "redeemedInMediaBuyId": null
}
```

The full updated proposal is returned, including its frozen `snapshot`.

## Errors

* `400 VALIDATION_ERROR` — empty `label`, `notes` over the length limit, or malformed `expiresAt`.
* `404 NOT_FOUND` — no proposal with that `id` is visible to the authenticated seller.

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

## Related

<CardGroup cols={2}>
  <Card title="Proposal tasks" href="/v2/storefront/proposals/tasks" icon="list-check">
    All proposal operations
  </Card>

  <Card title="Get proposal" href="/v2/storefront/proposals/tasks/get-proposal" icon="magnifying-glass">
    Read back the current state
  </Card>

  <Card title="Revoke proposal" href="/v2/storefront/proposals/tasks/revoke-proposal" icon="ban">
    Withdraw a code before redemption
  </Card>

  <Card title="Proposals overview" href="/v2/storefront/proposals/overview" icon="file-signature">
    Lifecycle and concepts
  </Card>
</CardGroup>
