Validation Rules

Learn how to create, update, and manage validation rules on monday.com boards to enforce data quality through the API

🚧

Only available in API versions 2026-07 and later

Validation rules let you enforce data quality on monday.com boards by defining constraints on column values. Unlike required columns which simply mark a column as mandatory, validation rules support comparison operators, value ranges, and conditional logic. For an overview of the feature in the monday.com UI, see Data validations.

This guide walks you through the validation rules API from basic constraints to conditional rules. By the end, you'll be able to programmatically enforce business rules like "amounts must be at least 5" or "if the status is Done, the description must be filled in."

Key concepts

How validation rules work

A validation rule has two parts:

PartRequiredDescription
thenYesThe constraint that must be satisfied. Defines what the column value should look like.
ifNoA condition that triggers the rule. When provided, the then constraint only applies when the if condition is met.

Rules without an if clause are validation rules — they always apply. Rules with an if clause are conditional rules — they only apply when the condition is met.

Enforcement

Validation rules are enforced both in the monday.com interface and through the API. When you create or update items via mutations like create_item, change_simple_column_value, or change_column_values, the API checks active validation rules and rejects requests that violate them with a DATA_VALIDATIONS_ERROR error (422 status code).

The error response includes details about which columns failed validation:

{
  "errors": [
    {
      "message": "data_validation_error",
      "extensions": {
        "code": "DATA_VALIDATIONS_ERROR",
        "status_code": 422,
        "error_data": [
          {
            "itemId": null,
            "columnIds": ["numeric_mm1pddwd"],
            "message": "'Amount' must be at least [5]"
          }
        ]
      }
    }
  ]
}

Relationship to required columns

Validation rules and required columns are separate features that coexist on the same board:

  • Required columns (add_required_column / remove_required_column) mark a column as mandatory. The column must have a value, but there's no constraint on what that value is.
  • Validation rules (create_validation_rule / update_validation_rule / delete_validation_rule) define constraints on what values are acceptable.

Both appear in the validations query response — required columns in required_column_ids and rules in rules.

Prerequisites

  • API authentication token
  • A board ID (find it in the URL: monday.com/boards/{board_id})
  • Familiarity with the column IDs on your board (query boardscolumnsid)
  • Requests must include the API-Version: 2026-07 header
  • Pro or Enterprise monday.com account

Creating your first rule

Validation rule

Let's create a rule that requires a status column to be one of two specific values (label indices 1 and 2):

mutation {
  create_validation_rule(
    id: 1234567890,
    type: board,
    rule: {
      then: {
        operator: AND,
        groups: [{
          operator: ANY_OF,
          column_id: "status",
          compare_value: [1, 2]
        }]
      }
    }
  ) {
    id
    if
    then
  }
}

The response includes the generated rule ID:

{
  "data": {
    "create_validation_rule": {
      "id": "cd7f1b7b-452e-40d3-886c-346184ffee7e",
      "if": null,
      "then": {
        "operator": "AND",
        "groups": [
          {
            "operator": "ANY_OF",
            "column_id": "status",
            "compare_value": [1, 2]
          }
        ]
      }
    }
  }
}

Key things to note:

  • The then clause requires an operator (AND or OR) and a groups array of constraints
  • Each constraint targets a column_id with a comparison operator and optional compare_value
  • Validation rules (without an if clause) return null for the if field
  • The returned id is a UUID you'll use for updates and deletes

Numeric constraint

Require a numbers column to be at least 5:

mutation {
  create_validation_rule(
    id: 1234567890,
    type: board,
    rule: {
      then: {
        operator: AND,
        groups: [{
          operator: GREATER_THAN_OR_EQUALS,
          column_id: "numbers0",
          compare_value: [5]
        }]
      }
    }
  ) {
    id
    then
  }
}

Date range constraint

Require a date column to fall within a specific range:

mutation {
  create_validation_rule(
    id: 1234567890,
    type: board,
    rule: {
      then: {
        operator: AND,
        groups: [{
          operator: BETWEEN,
          column_id: "date0",
          compare_value: ["2026-01-01", "2026-12-31"]
        }]
      }
    }
  ) {
    id
    then
  }
}

Text constraint

Require a text column to contain a specific substring:

mutation {
  create_validation_rule(
    id: 1234567890,
    type: board,
    rule: {
      then: {
        operator: AND,
        groups: [{
          operator: CONTAINS_TEXT,
          column_id: "text0",
          compare_value: ["REQ-"]
        }]
      }
    }
  ) {
    id
    then
  }
}

Conditional rules

Conditional rules use an if clause to gate when the then constraint applies. This lets you build logic like "if the status is Done, then the description must be filled in."

Basic conditional rule

mutation {
  create_validation_rule(
    id: 1234567890,
    type: board,
    rule: {
      if: {
        operator: AND,
        groups: [{
          operator: ANY_OF,
          column_id: "status",
          compare_value: [1]
        }]
      },
      then: {
        operator: AND,
        groups: [{
          operator: IS_NOT_EMPTY,
          column_id: "text0"
        }]
      }
    }
  ) {
    id
    if
    then
  }
}
👍

IS_NOT_EMPTY in conditional rules

The IS_NOT_EMPTY operator is only available inside conditional rules (rules with an if clause). It cannot be used in standalone validation rules. You can use it in both the if and then clauses — for example, to trigger a rule when one column is not empty, or to require a column to have a value when a condition is met.

Multiple then constraints

Conditional rules can enforce multiple constraints at once. If a condition is met, require both a numbers column and a date column to be filled:

mutation {
  create_validation_rule(
    id: 1234567890,
    type: board,
    rule: {
      if: {
        operator: AND,
        groups: [{
          operator: ANY_OF,
          column_id: "priority",
          compare_value: [1]
        }]
      },
      then: {
        operator: AND,
        groups: [
          {
            operator: IS_NOT_EMPTY,
            column_id: "numbers0"
          },
          {
            operator: IS_NOT_EMPTY,
            column_id: "date0"
          }
        ]
      }
    }
  ) {
    id
    if
    then
  }
}

Updating and deleting rules

Update a rule

Use update_validation_rule with the rule's ID. You must provide the full rule definition — partial updates are not supported:

mutation {
  update_validation_rule(
    id: 1234567890,
    type: board,
    rule_id: "cd7f1b7b-452e-40d3-886c-346184ffee7e",
    rule: {
      then: {
        operator: AND,
        groups: [{
          operator: GREATER_THAN_OR_EQUALS,
          column_id: "numbers0",
          compare_value: [10]
        }]
      }
    }
  ) {
    id
    if
    then
  }
}

Delete a rule

mutation {
  delete_validation_rule(
    id: 1234567890,
    type: board,
    rule_id: "cd7f1b7b-452e-40d3-886c-346184ffee7e"
  ) {
    id
  }
}

The mutation returns the deleted rule's data.

Reading validation rules

Query the validations endpoint to see all validation rules and required columns on a board:

query {
  validations(id: 1234567890) {
    required_column_ids
    rules
  }
}

The rules field returns a JSON object where each key is a rule ID and each value is the rule definition:

{
  "data": {
    "validations": {
      "required_column_ids": null,
      "rules": {
        "80d2c9d3-c93d-40be-9d34-b611241345b5": {
          "then": {
            "operator": "AND",
            "groups": [{
              "operator": "GREATER_THAN_OR_EQUALS",
              "column_id": "numbers0",
              "compare_value": [5]
            }]
          }
        },
        "31933592-171a-47ae-93a5-7a1c214fc9a3": {
          "if": {
            "operator": "AND",
            "groups": [{
              "operator": "ANY_OF",
              "column_id": "status",
              "compare_value": [1]
            }]
          },
          "then": {
            "operator": "AND",
            "groups": [{
              "operator": "IS_NOT_EMPTY",
              "column_id": "text0",
              "compare_value": []
            }]
          }
        }
      }
    }
  }
}
📘

NOTE

In the query response, conditional rules include both if and then keys. Validation rules (without a condition) only have a then key (the if key is absent, not null). This differs from the mutation response where if is explicitly null.

Supported operators by column type

Operator support varies significantly by clause type (plain rules vs. conditional IF vs. conditional THEN). Not all operators work with all column types. Review the tables below for your specific use case.

Plain validation rules (no if clause)

Plain rules support the most limited operator set. A column can have only ONE plain rule with ONE constraint:

Column TypeSupported Operators
statusANY_OF, NOT_ANY_OF
dropdownANY_OF, NOT_ANY_OF
ratingANY_OF, NOT_ANY_OF
numbersNOT_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUALS, LOWER_THAN, LOWER_THAN_OR_EQUAL
dateNOT_EQUALS, GREATER_THAN, GREATER_THAN_OR_EQUALS, LOWER_THAN, LOWER_THAN_OR_EQUAL, BETWEEN
textCONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
long_textCONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
emailCONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
phoneCONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
linkCONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
countryCONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
checkbox, people, timeline, location, week, hour, tags, file, world_clock, vote, color_picker, time_tracking, dependency(no operators supported)

Conditional rules: IF clause

The if clause triggers the rule. It supports a subset of operators:

Column TypeSupported Operators
statusANY_OF, NOT_ANY_OF, IS_NOT_EMPTY
dropdownANY_OF, NOT_ANY_OF, IS_NOT_EMPTY
ratingANY_OF, NOT_ANY_OF, IS_NOT_EMPTY
numbersEQUALS, NOT_EQUALS, IS_NOT_EMPTY, GREATER_THAN, GREATER_THAN_OR_EQUALS, LOWER_THAN, LOWER_THAN_OR_EQUAL
dateEQUALS, NOT_EQUALS, IS_NOT_EMPTY, GREATER_THAN, GREATER_THAN_OR_EQUALS, LOWER_THAN, LOWER_THAN_OR_EQUAL, BETWEEN
textIS_NOT_EMPTY, CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
long_textIS_NOT_EMPTY, CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
emailIS_NOT_EMPTY, CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
phoneIS_NOT_EMPTY, CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
linkIS_NOT_EMPTY, CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
countryIS_NOT_EMPTY, CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
checkboxIS_NOT_EMPTY
peopleIS_NOT_EMPTY
timelineIS_NOT_EMPTY
locationIS_NOT_EMPTY
week, hour, tags, file, world_clock, vote, color_picker, time_tracking, dependency(no operators supported)

Conditional rules: THEN clause

The then clause enforces the constraint when the condition is met. It has broader operator support:

Column TypeSupported Operators
statusANY_OF, NOT_ANY_OF, IS_EMPTY, IS_NOT_EMPTY
dropdownANY_OF, NOT_ANY_OF, IS_EMPTY, IS_NOT_EMPTY
ratingANY_OF, NOT_ANY_OF, IS_NOT_EMPTY
numbersEQUALS, NOT_EQUALS, IS_NOT_EMPTY, GREATER_THAN, GREATER_THAN_OR_EQUALS, LOWER_THAN, LOWER_THAN_OR_EQUAL
dateNOT_EQUALS, IS_NOT_EMPTY, GREATER_THAN, GREATER_THAN_OR_EQUALS, LOWER_THAN, LOWER_THAN_OR_EQUAL, BETWEEN
textIS_NOT_EMPTY, CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
long_textIS_NOT_EMPTY, CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
emailIS_NOT_EMPTY, CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
phoneIS_NOT_EMPTY, CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
linkIS_NOT_EMPTY, CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
countryIS_NOT_EMPTY, CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT
checkboxIS_EMPTY, IS_NOT_EMPTY
peopleIS_EMPTY, IS_NOT_EMPTY
timelineIS_NOT_EMPTY
locationIS_NOT_EMPTY
week, hour, tags, file, world_clock, vote, color_picker, time_tracking, dependency(no operators supported)
📘

BETWEEN on numbers

The BETWEEN operator is NOT supported on numbers columns in any clause. It is only supported on date columns.

Constraints and limitations

ConstraintDescription
One plain rule per columnA column can have at most one validation rule without an if clause. Attempting to add a second plain rule fails with "A column can have only one non-conditional rule".
One constraint per plain ruleValidation rules (without an if clause) must have exactly one constraint in the then clause. Multiple constraints are not allowed.
Multiple constraints per conditionalConditional rules (with an if clause) can have multiple constraints in the then clause, combined with AND or OR. The if clause must have exactly one constraint.
No mixing rule typesA column cannot have both a plain validation rule AND a conditional rule. Attempting to add both fails with "A column cannot have both conditional and non-conditional rules".
Pro/Enterprise onlyValidation rules require a Pro or Enterprise plan. Free/Standard accounts get UserUnauthorizedException with failure reason mentioning "data_validation_rules" or "required_columns".
Enforced in UI and APIRules are enforced in both the monday.com UI and via the API. API requests that violate rules return a DATA_VALIDATIONS_ERROR (422 status code) with details about which columns failed.
Required-capable vs rule-capableA column can be marked required but may not support any validation rules (e.g., timeline, location). See Required columns and Operator support.

Compare value formats

The compare_value array format varies by column type and operator. Follow these rules precisely — the API is strict about format:

Label-based operators (status, dropdown, rating)

Use label indices (integers), not label names:

# ✅ DO: Use label index
compare_value: [1, 2]

# ❌ DON'T: Use label name
compare_value: ["Done", "In Progress"]

Numeric values

Use a single number for comparison, two numbers for BETWEEN (not supported on numbers):

Operatorcompare_valueNotes
GREATER_THAN, GREATER_THAN_OR_EQUALS, LOWER_THAN, LOWER_THAN_OR_EQUAL, EQUALS, NOT_EQUALS[5]Single numeric value

Date and timeline values

Critical: Date comparisons require a specific format depending on the operator:

Operatorcompare_valueNotes
BETWEEN["2026-01-01", "2026-12-31"]Two date strings in YYYY-MM-DD, no EXACT prefix
GREATER_THAN, GREATER_THAN_OR_EQUALS, LOWER_THAN, LOWER_THAN_OR_EQUAL, NOT_EQUALS["EXACT", "2026-01-01"]Required: Prefix with "EXACT", then the date in YYYY-MM-DD
EQUALS["EXACT", "2026-01-01"]Same as other comparisons — prefix with "EXACT"

Timeline columns follow the same format as date columns.

Text-based operators

Use a single string value:

Operatorcompare_valueNotes
CONTAINS_TEXT, NOT_CONTAINS_TEXT, STARTS_WITH_TEXT["search term"]Single string value

Empty/non-empty operators

Omit compare_value or pass an empty array:

Operatorcompare_value
IS_EMPTY, IS_NOT_EMPTY(omit) or []

Required columns

Required columns mark a field as mandatory but do not enforce constraints on the column value. A column can be marked required but still allow any value.

Column types that support required

The following 14 column types can be marked as required using add_required_column:

  • status, dropdown, numbers, date, timeline, people, text, long_text, email, phone, link, rating, country, location

Column types that DO NOT support required

The following column types cannot be marked as required (API returns "Column ids are unsupported due to their types"):

  • checkbox, week, hour, tags, file, world_clock, vote, color_picker, time_tracking, dependency, button, formula, mirror, lookup, auto_number, integration, doc, progress, subtasks, vote

Required-capable but rule-incapable columns

Some columns can be marked required but do not support any validation rules:

  • timeline — can be required, but rejects all operators in plain, IF, and THEN clauses
  • location — can be required, but rejects all operators in plain, IF, and THEN clauses

Error handling

Data validation errors

When an API mutation violates a validation rule, the response includes a 422 status code and a DATA_VALIDATIONS_ERROR code:

{
  "errors": [
    {
      "message": "data_validation_error",
      "extensions": {
        "code": "DATA_VALIDATIONS_ERROR",
        "status_code": 422,
        "error_data": [
          {
            "itemId": null,
            "columnIds": ["numeric_mm1pddwd"],
            "message": "'Amount' must be at least [5]"
          },
          {
            "itemId": null,
            "columnIds": ["text_mm1pecmq"],
            "message": "'Description' must not be empty"
          }
        ]
      }
    }
  ]
}

Important: The error_data field is an array, not a single object. Multiple columns can fail validation in a single request — iterate through the array to handle all failures.

Plan gating errors

Accounts without Pro/Enterprise plan receive UserUnauthorizedException:

{
  "errors": [
    {
      "message": "UserUnauthorizedException",
      "extensions": {
        "error_data": {
          "failure_reason": "ms-authorization.permissions.data_validation_rules.not_available"
        }
      }
    }
  ]
}

Null validations query

The validations query returns null for rules in two scenarios:

  1. No rules configured on the board
  2. Feature unavailable (Free/Standard tier, feature restricted to Pro/Enterprise)

Since these are indistinguishable, your code cannot determine if null means "no rules" or "account lacks access". You may need to check the account plan separately.

Next steps

If you have questions, post them in the monday developer community.


Did this page help you?