Automating subitem creation allows you to sync complex order data—like line items from an external system—directly into Monday.com. By parsing input data, applying custom business rules, and batching GraphQL mutations, you can create multiple subitems in a single API call.
This guide walks you through the developer workflow for transforming raw order arrays into structured Monday.com subitems.
flowchart TD
A[Receive Order Data] --> B[Parse & Map to DB Items]
B --> C{Check Bundle Status}
C -->|Bundle Match| D[Flag as Bundle Item]
C -->|No Match| E[Standard Item]
D --> F[Apply Business Rules]
E --> F
F --> G[Construct GraphQL Batch]
G --> H[Send to Monday.com API]Prerequisites
Before building your automation, ensure you have:
A valid Monday API Token with write access to the target board.
The Parent Item ID (
parentPulseId) where the subitems will be created.Your source data provided as comma-separated lists (e.g., from a Zapier trigger or webhook).
Implementation Workflow
Follow these steps to parse your inputs, apply logic, and send the data to Monday.com.
- 1
Parse and map your data
Incoming data often arrives as parallel comma-separated lists (e.g., a list of product IDs and a corresponding list of prices). First, split these strings into arrays and map them into a structured dictionary so you can easily look up item details by Product ID.
- 2
Apply business rules
Iterate through your order items and apply your specific business logic. Common examples include:
Quantity Extraction: Checking if the first character of a product name is a number (2-9) to automatically set the quantity.
Bundle Detection: Comparing product IDs against a known set of bundle IDs to flag items appropriately.
Conditional Overrides: Suppressing certain fields (like title codes) if a specific threshold is met (e.g.,
titleOrder > 900).
- 3
Construct column values
Monday.com requires column values to be passed as a JSON string. Map your calculated values to their specific Monday.com column IDs (e.g.,
text_Mjj2AaAS,status_mkkaxp21). - 4
Batch the GraphQL mutations
Instead of making a separate API call for every subitem, use GraphQL aliases (e.g.,
item_0:,item_1:) to bundle multiplecreate_subitemmutations into a single request. This dramatically improves performance and helps you avoid rate limits.
Code Example
Here is a complete Node.js example demonstrating how to implement this workflow. This script is designed to run in environments like Zapier's "Run Javascript" action or a custom Node.js microservice.
const MONDAY_API_TOKEN = "your_api_token_here";
const parentPulseId = "1234567890";
// 1. Helper to parse comma-separated inputs
const split = (str) => str ? str.split(",").map(x => x.trim()).filter(Boolean) : [];
// Example Inputs
const orderProductIds = split("PROD-01, PROD-02");
const orderProductNames = split("1x Widget, 3x Gadget");
const dbQboIds = split("QBO-991, QBO-992");
const dbTitleOrders = split("100, 950"); // 950 will trigger our suppression rule
const mutationParts = [];
const preview = [];
// 2. Process each item
orderProductIds.forEach((productId, i) => {
const productName = orderProductNames[i] || "";
const rawTitleOrder = parseFloat(dbTitleOrders[i]) || 0;
// Business Rule: Extract quantity if the first char is 2-9
const firstChar = productName.charAt(0);
const quantity = /^[2-9]$/.test(firstChar) ? firstChar : "1";
// Business Rule: Suppress title order if > 900
const titleOrder = rawTitleOrder > 900 ? "" : rawTitleOrder;
// 3. Map to Monday.com Column IDs
const cols = {};
if (productId) cols["text_Mjj2AaAS"] = productId;
if (quantity) cols["text_mkkcefge"] = quantity;
if (dbQboIds[i]) cols["text_mkkq88hk"] = dbQboIds[i];
if (titleOrder) cols["numbers_mkkw8n33"] = titleOrder;
// Double stringify is required when interpolating directly into a GraphQL query string
const colStr = JSON.stringify(JSON.stringify(cols));
const alias = "item_" + i;
// 4. Construct the aliased mutation
mutationParts.push(
`${alias}: create_subitem(
parent_item_id: ${parentPulseId},
item_name: ${JSON.stringify(productName)},
column_values: ${colStr}
) { id }`
);
preview.push({ productId, quantity, titleOrder });
});
// 5. Execute the batch mutation
async function createSubitems() {
if (mutationParts.length === 0) return { status: "Nothing to create" };
const batchMutation = `mutation { ${mutationParts.join("\n")} }`;
const response = await fetch("https://api.monday.com/v2", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": MONDAY_API_TOKEN,
"API-Version": "2025-01",
},
body: JSON.stringify({ query: batchMutation }),
});
const data = await response.json();
if (data.errors) throw new Error("Monday API error: " + JSON.stringify(data.errors));
return data.data;
}Notice the JSON.stringify(JSON.stringify(cols)) syntax in the code above. When embedding JSON directly into a GraphQL query string (rather than using GraphQL variables), Monday.com requires the column_values argument to be a properly escaped JSON string.
Common Column Mappings
When mapping your database fields to Monday.com, you will need to use the specific column IDs generated by your board. Here are common examples of how different data types are formatted:
| Field Type | Example Column ID | Expected Format |
|---|---|---|
| Text | text_Mjj2AaAS | "String value" |
| Numbers | numbers_mkkw8n33 | 123.45 (Integer or Float) |
| Status | status_mkkaxp21 | { "label": "Done" } |
| Color/Dropdown | color_mkx2z43z | { "label": "Special Action" } |
Always verify your column IDs by querying the board's schema first, as these IDs (e.g., text_Mjj2AaAS) are unique to the specific board where they were created.
Advanced Features
Implementing a Dry Run Mode
When testing complex logic, it's highly recommended to implement a DRY_RUN toggle.
Wrap your fetch call in an if (!DRY_RUN) block. Instead of sending the API request, log the preview array to your console. This allows you to verify your business rules (like quantity extraction and bundle scoring) without creating dummy data in your live Monday.com workspace.
Handling Locked Team Members
If your workflow assigns team members dynamically, you can implement a "lock" override. For example, check if a database item has a lockTeamMember status set to "locked". If it does, force the assignment to a defaultMember rather than the dynamically passed team member.