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

# Create a rule

> Creates a data rule on the project. A rule either flags matching records with an alert, or corrects the matching value by working through a chain of substitution methods.

Evaluation over the rule's historical range is queued as soon as the rule is saved, so results and corrections land shortly after this call returns rather than during it.

Creating a substitute rule requires corrections to be enabled on the account.



## OpenAPI

````yaml POST /projects/{project_id}/rules
openapi: 3.1.0
info:
  title: Mangrove - API
  version: 1.1.0
servers:
  - url: https://app.gomangrove.com/api/v1
security:
  - sec0: []
paths:
  /projects/{project_id}/rules:
    post:
      summary: Create a rule
      description: >-
        Creates a data rule on the project. A rule either flags matching records
        with an alert, or corrects the matching value by working through a chain
        of substitution methods.


        Evaluation over the rule's historical range is queued as soon as the
        rule is saved, so results and corrections land shortly after this call
        returns rather than during it.


        Creating a substitute rule requires corrections to be enabled on the
        account.
      operationId: create-project-rule
      parameters:
        - name: project_id
          in: path
          schema:
            type: string
          required: true
      requestBody:
        content:
          application/json:
            schema:
              type: object
              required:
                - rule
              properties:
                rule:
                  $ref: '#/components/schemas/RuleInput'
            examples:
              Alert rule:
                value:
                  rule:
                    name: Negative Temp Alert
                    target_type: data_point
                    rule_text: '{{data-point.ambient-temperature-c}} < 0'
                    alert_message: Ambient temperature below zero
              Substitute rule:
                value:
                  rule:
                    name: Fill ambient temperature dropouts
                    target_type: data_point
                    action: substitute
                    rule_text: '{{data-point.ambient-temperature-c}} = 0'
                    subject_slugs:
                      - ambient-temperature-c
                    method_chain:
                      - method: trailing_average
                        params:
                          window:
                            kind: rolling
                            value: 7
                            unit: day
                      - method: forward_fill
      responses:
        '201':
          description: '201'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Rule'
        '400':
          description: '400'
          content:
            application/json:
              examples:
                Result:
                  value:
                    errors:
                      - message: >-
                          param is missing or the value is empty or invalid:
                          rule
        '422':
          description: >-
            A duplicate rule repeats its detail as a `duplicate_rule` sibling of
            `errors` as well as inside the entry. Its `message` ends with the
            existing rule's effective period in parentheses, which the example
            below leaves off: read the period from `duplicate_rule` rather than
            parsing the text.
          content:
            application/json:
              examples:
                Missing method chain:
                  value:
                    errors:
                      - message: >-
                          Method chain must list at least one method for
                          substitute rules
                        field: method_chain
                        code: must list at least one method for substitute rules
                Duplicate rule:
                  value:
                    errors:
                      - message: >-
                          A rule with the same expression already exists: 'Fill
                          ambient temperature dropouts'
                        field: rule_text
                        code: duplicate_rule
                        duplicate_rule:
                          friendly_id: rule_Qb3k9TzdL0pWnXyz
                          name: Fill ambient temperature dropouts
                          effective_from: '2026-01-01'
                          effective_to: null
                    duplicate_rule:
                      friendly_id: rule_Qb3k9TzdL0pWnXyz
                      name: Fill ambient temperature dropouts
                      effective_from: '2026-01-01'
                      effective_to: null
      deprecated: false
components:
  schemas:
    RuleInput:
      type: object
      description: >-
        The rule body on a create or update. On an update, send only the fields
        you are changing.
      properties:
        name:
          type: string
        target_type:
          type: string
          enum:
            - data_point
            - model
        rule_text:
          type: string
        action:
          type: string
          enum:
            - alert
            - substitute
          default: alert
        alert_message:
          type: string
        subject_slugs:
          type: array
          items:
            type: string
          description: >-
            A substitute rule takes exactly one slug. It has to appear in
            `rule_text`, and its data point type has to be numeric.
        method_chain:
          type: array
          description: >-
            Required on a substitute rule. Mangrove rejects a chain that repeats
            a method with the same parameters, or that places a method after a
            `constant`.
          items:
            $ref: '#/components/schemas/SubstitutionMethod'
        modeling_model_id:
          type: string
          description: Required on a model rule. Pass the model's friendly ID.
        effective_from:
          type: string
          format: date
          nullable: true
        effective_to:
          type: string
          format: date
          nullable: true
    Rule:
      type: object
      description: >-
        A data rule on a project. The rule's identity is stable across edits;
        the condition lives on its latest version.
      properties:
        id:
          type: string
          description: Rule friendly ID.
          example: rule_Qb3k9TzdL0pWnXyz
        name:
          type: string
        rule_type:
          type: string
          enum:
            - alert
            - substitution
          description: Derived from `action`. Read-only.
        action:
          type: string
          enum:
            - alert
            - substitute
          description: >-
            `alert` flags the matching record and changes nothing. `substitute`
            replaces the matching value with one derived from `method_chain`.
            Only data point rules may substitute.
        method_chain:
          type: array
          description: >-
            Ordered substitution candidates. The first method that resolves
            wins. Empty on alert rules.
          items:
            $ref: '#/components/schemas/SubstitutionMethod'
        target_type:
          type: string
          enum:
            - data_point
            - model
          description: >-
            `data_point` evaluates event data as it arrives. `model` evaluates
            model outputs after a batch calculation.
        status:
          type: string
          enum:
            - active
        enabled:
          type: boolean
        rule_text:
          type: string
          description: The condition, in the rule expression language.
          example: '{{data-point.ambient-temperature-c}} < 0'
        subject_slugs:
          type: array
          items:
            type: string
          description: >-
            On an alert rule, narrows which of the values the condition reads
            may be flagged. On a substitute rule, names the single value the
            rule corrects.
        alert_message:
          type: string
          nullable: true
          description: >-
            Shown on the records this rule flags. Required on an alert rule.
            Optional on a substitute rule, where it covers the records whose
            method chain resolved nothing, and Mangrove supplies a default.
        version:
          type: integer
        effective_from:
          type: string
          format: date
          nullable: true
        effective_to:
          type: string
          format: date
          nullable: true
        model_id:
          type: string
          nullable: true
          description: Model rules only.
        model_name:
          type: string
          nullable: true
        created_by:
          type: string
        created_at:
          type: string
          format: date-time
        updated_at:
          type: string
          format: date-time
    SubstitutionMethod:
      type: object
      description: One candidate in a substitute rule's method chain.
      properties:
        method:
          type: string
          enum:
            - constant
            - fallback_to_dpt
            - forward_fill
            - backward_fill
            - trailing_average
            - trailing_min
            - trailing_max
          description: >-
            `constant` uses a fixed number and always resolves, so no method may
            follow it. `fallback_to_dpt` copies another data point type on the
            same event. `forward_fill` and `backward_fill` borrow the nearest
            earlier or later valid reading. The three trailing methods take the
            average, lowest or highest reading across a window.
        params:
          type: object
          description: >-
            `constant` takes `value`. `fallback_to_dpt` takes `slug`. The
            trailing methods take `window`. The two fills take no parameters.
          properties:
            value:
              type: number
              description: >-
                `constant` only. Rejected when the value would itself match the
                rule's condition.
            slug:
              type: string
              description: >-
                `fallback_to_dpt` only. A data point type slug on the same
                event.
            window:
              type: object
              description: Trailing methods only.
              properties:
                kind:
                  type: string
                  enum:
                    - rolling
                    - calendar
                value:
                  type: integer
                  description: Required on a rolling window. Not used on a calendar window.
                unit:
                  type: string
                  description: >-
                    Rolling windows take `second`, `minute`, `hour`, `day`,
                    `week`, `month` or `year`. Calendar windows take `day`,
                    `week`, `month`, `quarter` or `year`.
  securitySchemes:
    sec0:
      type: apiKey
      in: header
      name: Authorization
      x-bearer-format: ''

````