---
title: "Update Proposal"
method: PATCH
path: "/internal/marketing-preset-proposals/{proposal_id}"
tags: ["internal"]
---

# Update Proposal

`PATCH /internal/marketing-preset-proposals/{proposal_id}`

Save the reviewer's edits and per-product-line approvals.

Validated the same way staging was, so a save that could not be applied is refused while the
reviewer is still looking at the field they broke — rather than at submit time, when they have
already decided they are done.

## Path parameters

- `proposal_id` string, uuid, required

## Request body

- ProposalPatch — A reviewer's save. Each *proposal-level* field is optional; only what is sent is changed. Per *item* the opposite holds — see `ReviewedProductLine`. `expected_revision` is the proposal's revision as the page rendered it; a save against a stale one is refused rather than merged, so two tabs cannot overwrite each other's approvals.
  - `expected_revision` integer, required
  - `title` string, nullable
  - `notes` string, nullable
  - `items` ReviewedProductLine[], nullable
    - `key` string, required
    - `operation` 'create' | 'update' — Whether an item creates a product line or edits one that exists.
    - `preset_id` string, uuid, nullable
    - `name` string, required
    - `description` string, nullable
    - `program_types` MarketingProgramType[]
    - `internal_file_ids` string[]
    - `guideline_notes` string[]
    - `marketing_team_id` string, uuid, nullable
    - `rationale` string, nullable
    - `approved` boolean
    - `applied_preset_id` string, uuid, nullable

## Response `200`

Successful Response

- MarketingPresetProposalDetail — Everything the review page needs, in one response. One call rather than five: the page cannot render a checkbox grid without the regulation list, cannot diff an `update` without the current product lines, and cannot offer a team or a marketing standard without those lists — so fetching them separately only buys four more ways for the page to be half-drawn.
  - `proposal` MarketingPresetProposalSummary, required — A proposal without its items — the listing, and the MCP status read.
    - `proposal_id` string, uuid, required
    - `company_id` string, uuid, required
    - `company_name` string, nullable, required
    - `title` string, required
    - `notes` string, nullable, required
    - `status` 'open' | 'applied' | 'discarded', required — Where a proposal is in its one-way life. `open` is the only state that accepts edits or applies. A proposal reaches `applied` when every item on it has been written, so a reviewer who approves three of five rows leaves it `open` and comes back for the rest rather than stranding them.
    - `revision` integer, required
    - `created_by_email` string, nullable, required
    - `created` string, required
    - `item_count` integer, required
    - `applied_count` integer, required
    - `last_applied_at` string, nullable, required
    - `last_applied_by_email` string, nullable, required
    - `review_url` string, required
  - `items` ProposedProductLine[], required
    - `key` string, required
    - `operation` 'create' | 'update' — Whether an item creates a product line or edits one that exists.
    - `preset_id` string, uuid, nullable
    - `name` string, required
    - `description` string, nullable
    - `program_types` MarketingProgramType[]
    - `internal_file_ids` string[]
    - `guideline_notes` string[]
    - `marketing_team_id` string, uuid, nullable
    - `rationale` string, nullable
    - `approved` boolean
    - `applied_preset_id` string, uuid, nullable
  - `program_types` ProgramTypeRegulations[], required
    - `program_type` 'Consumer UDAAP' | 'UK Financial Promotions' | 'FINRA' | 'Reg E' | 'Reg DD' | 'Card Brand Rules' | 'ECOA (Reg B)' | 'TILA (Reg Z)' | 'CAN-SPAM' | 'FDIC Advertising' | 'Fair Housing Logo' | 'FCRA Consumer Rights' | 'FCRA Prescreened Offers' | 'Kansas UCCC/KMBA' | 'Reg CC' | 'SCRA/MLA' | 'B2B UDAAP' | 'Reg II' | 'TCPA' | 'FTC Endorsement Guides' | 'GLBA / Privacy' | 'Prepaid Rule' | 'Sweepstakes & Giveaways', required
    - `regulations` string[], required
    - `company_override` boolean, required
  - `existing_product_lines` ExistingProductLine[], required
    - `preset_id` string, uuid, required
    - `name` string, required
    - `description` string, nullable, required
    - `program_types` MarketingProgramType[], required
    - `marketing_team_id` string, uuid, nullable, required
    - `marketing_team_name` string, nullable, required
    - `internal_file_ids` string[], required
    - `usage_count` integer, required
  - `files` ProposalFileOption[], required
    - `file_id` string, uuid, required
    - `filename` string, required
  - `teams` ProposalTeamOption[], required
    - `team_id` string, uuid, required
    - `name` string, required

## Other responses

- `422` — Validation Error

---

[API](https://skmtc.dev/kobaltlabs/apis/fastapi.md) · [All operations](https://skmtc.dev/kobaltlabs/apis/fastapi/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/kobaltlabs/fastapi/revisions/f85ef083df64/schema)
