---
title: "Update Requirement"
method: PATCH
path: "/marketing/guidelines/requirements/{requirement_id}"
tags: ["marketing-guidelines"]
---

# Update Requirement

`PATCH /marketing/guidelines/requirements/{requirement_id}`

Change a requirement's wording, guidance or scope by recording a new revision.

Nothing already written is altered. The previous wording stays readable in the history.

## Path parameters

- `requirement_id` string, uuid, required

## Request body

- UpdateRequirementRequest — An edit to a requirement's wording, guidance or scope. Only fields the client actually sends are applied, so an omitted field is carried forward from the current revision. `collateral_types` and `marketing_team_ids` accept an explicit `null`, which clears the scope back to "applies to everything" — the same convention as `CompanyMarketingRule`. An empty list is refused: see `_validate_scope_not_empty`. `base_revision_number` is the revision the form was filled in against. It is optional only so an older client is not broken by adding it; when it is sent and no longer current, the edit is refused. Without it two people editing the same requirement minutes apart both succeed and the second silently discards the first — the append-only history records the loss faithfully, which is not the same as preventing it.
  - `base_revision_number` integer, nullable
  - `requirement_text` string, nullable
  - `judging_guidance` string, nullable
  - `collateral_types` MarketingCollateralType[], nullable
  - `marketing_team_ids` string[], nullable
  - `trigger_terms` string[], nullable
  - `change_note` string, nullable

## Response `200`

Successful Response

- GuidelineRequirementResponse
  - `requirement_id` string, uuid, required
  - `file_id` string, uuid, required
  - `filename` string, nullable, required
  - `decomposition_id` string, uuid, required
  - `ordinal` integer, required
  - `revision_number` integer, required
  - `state` 'active' | 'disabled' | 'archived' | 'superseded', required — Whether a requirement is in the working library, and if not, why not. All four are recorded as revisions, so every one of them is reversible and readable. ARCHIVED and SUPERSEDED are deliberately distinct: ARCHIVED is a person deciding this obligation does not apply to them, SUPERSEDED is a newer decomposition of the same guideline taking over. A regeneration must never overwrite the first with the second — that would erase a human decision.
  - `requirement_text` string, required
  - `judging_guidance` string, nullable, required
  - `collateral_types` MarketingCollateralType[], nullable, required
  - `marketing_team_ids` string[], nullable, required
  - `source_collateral_terms` string[], nullable, required
  - `trigger_terms` string[], required
  - `unresolved_collateral_terms` string[], required
  - `section_label` string, nullable, required
  - `title` string, nullable, required
  - `source_page` integer, nullable, required
  - `citation` GroundedSpan, required — Where a requirement appears to have come from, and how much to trust it.
    - `page_number` integer, required
    - `boxes` BoundingBox[]
      - `x0` number, required
      - `y0` number, required
      - `x1` number, required
      - `y1` number, required
    - `source_text` string, nullable
    - `matched_terms` string[]
    - `score` number
    - `basis` string
    - `cited_page` integer, nullable
    - `refusal` string, nullable
  - `change_kind` 'extracted' | 'edited' | 'disabled' | 'enabled' | 'archived' | 'restored' | 'superseded', required — What a revision was for. Redundant with comparing a revision to its predecessor, and that is the point: the reason a change was made is the part a diff cannot recover.
  - `change_note` string, nullable, required
  - `updated_at` string, date-time, required
  - `updated_by_email` string, nullable, required
  - `has_human_edits` boolean, required
  - `signal` RequirementSignal — One requirement's track record, as a ranked read reports it. Present only when the list was asked for an `order`; `None` otherwise, so an ordinary library read pays neither the aggregate nor the payload. A row whose requirement has never been checked is absent from a ranked read entirely rather than carrying zeros — there is nothing to rank. **The two halves are in different units and must not be added or compared.** `collateral_checked` and the three `checks_*` count *checks* — one per (evaluation, requirement), which `uq_marketing_requirement_check_once_per_evaluation` guarantees. The `risks_*` count *risks*, and one check can produce several, so `risks_flagged + risks_over_flagged` is not bounded by `checks_failed`. The rates come from the server because the server ordered by them. A client re-deriving them would be a second definition of the number the ranking was built on. `None` means no evidence, which is a different claim from `0.0`.
    - `collateral_checked` integer, required
    - `checks_failed` integer, required
    - `checks_passed` integer, required
    - `checks_not_determined` integer, required
    - `checks_current_revision` integer, required
    - `verdicts` object, required
    - `risks_superseded` integer, required
    - `false_positive_rate` number, nullable, required
    - `dismissal_rate` number, nullable, required
    - `fire_rate` number, nullable, required
  - `downvotes` integer, nullable

## 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/3ff4c0bd276b/schema)
