Automating Monday.com workflows often requires more than basic triggers and actions. By using Python snippets within Zapier (or similar automation platforms), you can perform advanced tasks like generating search permutations, querying subitems, and conditionally updating column values all in a single step.
This guide walks you through a practical example: taking a raw property address, finding the matching item in Monday.com, verifying its subitems, and updating a status column if specific conditions are met.
While this example uses specific real estate terms (like "MLS" and "Property Address"), the core concepts—searching by permutations, reading subitems, and executing inline GraphQL mutations—can be adapted to any industry or workflow.
How the workflow operates
Before diving into the code, it helps to understand the logic flow. This script takes a messy input, cleans it up, searches Monday.com, and makes decisions based on the results.
flowchart TD
A["Raw Address Input"] --> B["Generate Permutations (St vs Street)"]
B --> C["Search Monday.com API"]
C --> D{"Item Found?"}
D -- "No" --> E["Return 'No Match'"]
D -- "Yes" --> F["Check Subitems & Stage"]
F --> G{"Is Measurement Job?"}
G -- "Yes, but parent says No" --> H["Mutate: Update Parent to 'Yes'"]
G -- "Already Yes / Not a job" --> I["Skip Update"]
H --> J["Return Item Data to Zapier"]
I --> JImplementing the script in Zapier
To use this script, you will use the Code by Zapier app and select the Run Python action.
- 1
Configure your input data
In your Zapier step, map the data you want to pass into the Python script. For this script, you will need:
api_token: Your Monday.com API Token.raw_address: The address you want to search for.last_modifying_user_name: (Optional) The name of the user triggering the action.
- 2
Customize your configuration variables
At the top of the script, you must replace the placeholder IDs with your actual Monday.com Board ID and Column IDs. You can find Column IDs by enabling "Developer Mode" in your Monday.com profile settings.
- 3
Add the Python code
Copy and paste the following script into the Code field in Zapier.
The Python Script
import requests
import json
import re
# ==========================================
# 1. CONFIGURATION
# ==========================================
API_TOKEN = input_data.get('api_token')
BOARD_ID = "7932413985" # Replace with your Board ID
PROPERTY_ADDR_COL = "text0__1"
STAGE_COL = "deal_stage"
MEASUREMENT_COL = "color_mkv9zkkc"
DELIVERY_COL = "status_mkkac7g6"
PARENT_FOLDER_COL = "text_mktj9wa4"
SUB_ITEM_QBO_COL = "status_mkkaxp21"
SPLIT_STATUS_COL = "color_mm388khb"
HEADERS = {
"Authorization": API_TOKEN,
"Content-Type": "application/json",
"API-Version": "2023-10"
}
# Format user email
raw_modifier = input_data.get('last_modifying_user_name', '').strip()
modifier_email = f"{raw_modifier.split()[0].lower()}@yourdomain.com" if raw_modifier else ""
# ==========================================
# 2. STANDARDIZE & PERMUTATE ADDRESS
# ==========================================
raw_addr = input_data.get('raw_address', '').strip()
clean_addr = re.sub(r'[.]', '', raw_addr).lower()
directions = {"n": "north", "s": "south", "e": "east", "w": "west", "ne": "northeast", "nw": "northwest", "se": "southeast", "sw": "southwest"}
suffixes = {"st": "street", "rd": "road", "ave": "avenue", "dr": "drive", "ln": "lane", "ct": "court", "pl": "place", "blvd": "boulevard", "hwy": "highway"}
def get_variations(addr):
vars = {addr}
# Generate direction variations
for abbr, full in directions.items():
if re.search(rf'\b{abbr}\b', addr): vars.add(re.sub(rf'\b{abbr}\b', full, addr))
if re.search(rf'\b{full}\b', addr): vars.add(re.sub(rf'\b{full}\b', abbr, addr))
final_set = set()
# Generate suffix variations
for v in vars:
final_set.add(v)
for abbr, full in suffixes.items():
if re.search(rf'\b{abbr}\b', v): final_set.add(re.sub(rf'\b{abbr}\b', full, v))
if re.search(rf'\b{full}\b', v): final_set.add(re.sub(rf'\b{full}\b', abbr, v))
return [v.title() for v in final_set]
search_values = get_variations(clean_addr)
# ==========================================
# 3. TARGETED SEARCH
# ==========================================
search_query = """
query ($boardId: ID!, $colId: String!, $values: [String]!) {
items_page_by_column_values (limit: 50, board_id: $boardId, columns: [{column_id: $colId, column_values: $values}]) {
items {
id
name
group { title }
column_values { id text }
}
}
}
"""
res = requests.post("https://api.monday.com/v2",
json={'query': search_query, 'variables': {
'boardId': BOARD_ID,
'colId': PROPERTY_ADDR_COL,
'values': search_values
}}, headers=HEADERS).json()
found_items = res.get('data', {}).get('items_page_by_column_values', {}).get('items', [])
# ==========================================
# 4. VERIFICATION & MUTATION LOOP
# ==========================================
target_id = None
has_mls_subitem = False
current_stage = "No Match"
delivery_status = ""
parent_folder_id = ""
split_status = ""
debug_log = [f"Searched for: {search_values}"]
if found_items:
for item in found_items:
cv_map = {cv['id']: (cv.get('text') or "").strip() for cv in item.get('column_values', [])}
item_stage = cv_map.get(STAGE_COL, "")
measurement_val = cv_map.get(MEASUREMENT_COL, "")
group_title = item.get('group', {}).get('title', "")
# Phase 1: Basic Group & Stage parameters
if item_stage != "SDC" and group_title == "Active Deals":
# Query sub-items
sub_query = "query ($ids: [ID!]) { items (ids: $ids) { subitems { name column_values { id text } } } }"
sub_res = requests.post("https://api.monday.com/v2", json={'query': sub_query, 'variables': {"ids": [item['id']]}}, headers=HEADERS).json()
subitems = sub_res.get('data', {}).get('items', [{}])[0].get('subitems', [])
is_measurement_by_subitem = False
item_has_mls = False
for sub in subitems:
if "MLS Data Collection" in sub.get('name', ''):
item_has_mls = True
sub_cv_map = {cv['id']: (cv.get('text') or "").strip() for cv in sub.get('column_values', [])}
if "measurements" in sub_cv_map.get(SUB_ITEM_QBO_COL, "").lower():
is_measurement_by_subitem = True
# Phase 2: Accept if parent says Yes OR if sub-items prove it
if measurement_val.lower() == "yes" or is_measurement_by_subitem:
target_id = item['id']
current_stage = item_stage
delivery_status = cv_map.get(DELIVERY_COL, "")
parent_folder_id = cv_map.get(PARENT_FOLDER_COL, "")
split_status = cv_map.get(SPLIT_STATUS_COL, "")
has_mls_subitem = item_has_mls
# INLINE MUTATION: Auto-flip parent column if needed
if measurement_val.lower() != "yes" and is_measurement_by_subitem:
update_query = """
mutation ($boardId: ID!, $itemId: ID!, $colId: String!, $value: JSON!) {
change_column_value (board_id: $boardId, item_id: $itemId, column_id: $colId, value: $value) { id }
}
"""
update_vars = {
"boardId": BOARD_ID,
"itemId": target_id,
"colId": MEASUREMENT_COL,
"value": json.dumps({"label": "Yes"})
}
try:
up_res = requests.post("https://api.monday.com/v2", json={'query': update_query, 'variables': update_vars}, headers=HEADERS).json()
debug_log.append(f"Flipped parent item {target_id} to Yes.")
except Exception as e:
debug_log.append(f"Failed to auto-flip parent column: {str(e)}")
break
return {
"target_id": target_id,
"match_found": target_id is not None,
"has_mls_subitem": has_mls_subitem,
"current_stage": current_stage,
"delivery_status": delivery_status,
"parent_folder_id": parent_folder_id,
"split_status": split_status,
"modifier_email": modifier_email,
"debug_info": debug_log
}Never hardcode your API Token directly into the Python script. Always pass it securely via Zapier's input_data to prevent accidental exposure if you share or export your Zap.
Understanding the GraphQL Queries
If you're new to Monday.com's API, the script uses two distinct types of GraphQL operations.
Querying Items by Column Value
The script uses items_page_by_column_values to find items matching the generated address permutations. This is much more efficient than pulling all items on a board and filtering them in Python.
Notice that the query specifically requests the group { title } and column_values { id text } so the script has enough context to verify the item locally.
Mutating (Updating) a Column Value
When the script discovers that a subitem indicates a "measurement" job, but the parent item doesn't reflect this, it executes a change_column_value mutation.
Because Monday.com requires strict JSON formatting for column updates, the Python script uses json.dumps({"label": "Yes"}) and passes it to the GraphQL $value variable typed as JSON!.
Expected Output Variables
Once the script finishes running, it returns a dictionary of values. You can map these variables into subsequent steps in your Zap (for example, sending a Slack message or updating a CRM).
| Output Variable | Description |
|---|---|
target_id | The Monday.com Item ID if a match was successfully found and verified. |
match_found | A boolean (True/False) indicating if the search was successful. |
has_mls_subitem | Boolean indicating if an "MLS Data Collection" subitem exists. |
current_stage | The value of the deal stage column for the matched item. |
split_status | The extracted split status value (e.g., "Parent"). |
debug_info | A list of log messages detailing search parameters and mutation results, useful for troubleshooting in Zapier's history. |