> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prelude.so/llms.txt
> Use this file to discover all available pages before exploring further.

# Replace a rule

> **Beta.** The request and response shapes may still change.

Overwrite a rule in place. The body is the whole rule, not a patch: what you omit is cleared.

The new expression is compiled before it is stored. It is not re-checked against the recipes already scoring over this rule, so an edit that drops an attribute or parameter reference is accepted here and the rule is reported as unavailable at evaluation time. Re-save the recipe to validate the association.

The body is the whole rule, not a patch. Both `name` and `expression` are required, and the stored rule becomes exactly what you send.

The identifier does not change, so every recipe already scoring over this rule picks up the new condition on its next evaluation. There is no versioning at the rule level.

## Editing a rule a recipe depends on

The new expression is compiled against the latest catalog, on its own - not against the recipes that score over it. An edit that starts reading `attr.cart_total` is accepted here even if no recipe declares that key.

At evaluation time such a rule can't compile in that recipe's environment. It reports `unavailable` and contributes nothing, and the recipe reports `partial_evidence`. Re-saving the recipe is what checks the pair, and it is the fastest way to confirm an edit landed cleanly.

Aiming a replace at a managed rule's identifier answers `403` - `managed_rule_read_only`.


## OpenAPI

````yaml put /v2/watch/management/rules/{rule_id}
openapi: 3.1.0
info:
  title: Prelude API
  version: 2.0.0
  description: The Prelude API allows you to send messages to your users.
  contact:
    email: support@prelude.so
servers:
  - url: https://api.prelude.dev
    description: Production server
security:
  - apiToken: []
tags:
  - name: Notify
    description: Send transactional and marketing messages with compliance enforcement.
  - name: Transactional
    description: Send transactional messages (deprecated - use Notify API instead).
  - name: Verify
    description: Verify phone numbers.
  - name: Watch
    description: Evaluate email addresses and phone numbers for trustworthiness.
  - name: Lookup
    description: >-
      Retrieve detailed information about a phone number including carrier data,
      line type, and portability status.
paths:
  /v2/watch/management/rules/{rule_id}:
    put:
      tags:
        - Watch
      summary: Replace a rule
      description: >-
        **Beta.** The request and response shapes may still change.


        Overwrite a rule in place. The body is the whole rule, not a patch: what
        you omit is cleared.


        The new expression is compiled before it is stored. It is not re-checked
        against the recipes already scoring over this rule, so an edit that
        drops an attribute or parameter reference is accepted here and the rule
        is reported as unavailable at evaluation time. Re-save the recipe to
        validate the association.
      operationId: replaceWatchRule
      parameters:
        - name: rule_id
          in: path
          required: true
          schema:
            type: string
            examples:
              - rul_01jc0t6fwwfgfsq1md24mhyztj
          description: The rule identifier.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WatchRuleRequest'
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/WatchRule'
        '400':
          description: KO
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '403':
          description: Forbidden
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Error'
                example:
                  code: managed_rule_read_only
                  message: >-
                    This rule is managed by Prelude and cannot be edited or
                    deleted.
                  type: forbidden
                  request_id: 3d19215e-2991-4a05-a41a-527314e6ff6a
        '404':
          description: Not Found
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
components:
  schemas:
    WatchRuleRequest:
      type: object
      properties:
        name:
          type: string
          maxLength: 128
          description: >-
            A label for the rule. It is returned in evaluation results, so make
            it say what the rule looks for.
          examples:
            - free_plan_signup
        expression:
          type: string
          description: >
            The condition, written in [CEL](https://cel.dev). It must evaluate
            to a boolean, and it is compiled before it is stored: an expression
            that does not compile is refused.


            It may reference the signals Prelude resolves for an evaluation, a
            recipe's request attributes as `attr.<key>`, and a recipe's
            configured values as `param.<key>`. A rule that references either
            namespace is bound to the recipes declaring those names, and can
            only be used by them. See [Rules, recipes and
            flows](/watch/v2/documentation/rules-recipes-flows#writing-an-expression);
            the signal vocabulary is not published yet, so contact us for the
            names available to your rules.
          examples:
            - attr.plan_tier == "free"
      required:
        - name
        - expression
    WatchRule:
      type: object
      properties:
        id:
          type: string
          examples:
            - rul_01jc0t6fwwfgfsq1md24mhyztj
          description: >-
            The rule identifier. Reference it in a recipe's `rules` to score
            over it.
        name:
          type: string
          examples:
            - free_plan_signup
        expression:
          type: string
          examples:
            - attr.plan_tier == "free"
        type:
          type: string
          enum:
            - CUSTOM
          description: >-
            Always `CUSTOM`. A rule you author is your own; Prelude's are a
            separate, read-only listing.
      required:
        - id
        - name
        - expression
        - type
    Error:
      type: object
      properties:
        code:
          type: string
          description: The error code.
          examples:
            - invalid_phone_number
        message:
          type: string
          examples:
            - >-
              The provided phone number is invalid. Provide a valid E.164 phone
              number.
          description: A human-readable message describing the error.
        type:
          type: string
          examples:
            - bad_request
          description: The error type.
        request_id:
          type: string
          examples:
            - 3d19215e-2991-4a05-a41a-527314e6ff6a
          description: >-
            A string that identifies this specific request. Report it back to us
            to help us diagnose your issues.
        param:
          type: string
          examples:
            - phone_number
          description: The parameter the error refers to, when it applies to a single one.
      required:
        - code
        - message
        - type
  securitySchemes:
    apiToken:
      type: http
      scheme: bearer

````