Getting Started with Order Intake Handling New Order Webhooks

When integrating HD Photo Hub (HDPH) with your order management system, you need to ensure that new orders are processed cleanly and accurately. This guide walks you through configuring a webhook to catch new orders, match them against existing sites and orders in Monday.com, and filter out manual entries to prevent duplicates.

Workflow Overview

The order intake process follows a strict sequence to ensure data integrity. Before any new records are created, the system checks for manual stops, existing bundles, and duplicate orders.

flowchart TD
    A[Webhook catches HDPH Order] --> B[(Fetch Zapier Tables)]
    B --> C[Run Unified Filtering Code]
    C --> D{Is manual order?}
    D -- Yes --> E[Filter / Stop]
    D -- No --> F{Order/Site Exists?}
    F -- Yes --> G[Filter / Stop]
    F -- No --> H[Process Subitems & Create Records]

Configuration Steps

Follow these steps to set up your order intake and filtering logic.

  1. 1

    Configure the Webhook Trigger

    Set up your webhook to catch the incoming payload from HD Photo Hub. This payload will contain essential data like the orderNumber, siteId, and an array of orderProductIds.

  2. 2

    Fetch Bundle and Manual Items

    Before processing the order, look up your reference data. You will need to query your Zapier Tables (or equivalent database) to fetch:

    • Manual Stop Items: Products that require manual intervention.

    • Bundle Items: Products that are part of a larger package.

  3. 3

    Execute Unified Filtering Logic

    Use a code step to compare the incoming order against your manual items list and query the Monday.com API to check for existing records.

    Here is the JavaScript snippet to handle the matching and API querying:

    const apiToken = inputData.apiToken;
    const boardId = "7932413985";
    const orderNumber = inputData.orderNumber;
    const siteId = inputData.siteId;
    
    const toArray = (v) => (Array.isArray(v) ? v : String(v || "").split(",")).map((x) => String(x).trim()).filter(Boolean);
    
    const orderIds = toArray(inputData.orderProductIds);
    const stopItems = toArray(inputData.manualStopItems);
    const bundleIdList = toArray(inputData.tableBundleIds);
    
    // Check if any product in the order is flagged for manual processing
    const manualOrder = orderIds.some((id) => stopItems.includes(id)) ? "Yes" : "No";
    
    const bundleId = orderIds.find((id) => bundleIdList.includes(id)) || "0";
    const bundleOrder = bundleId !== "0" ? "Yes" : "No";
    
    // Query Monday.com to see if the order or site already exists
    const query = `
      query {
        orderMatch: items_page_by_column_values(
          board_id: ${boardId},
          columns: [{ column_id: "text__1", column_values: ["${orderNumber}"] }]
        ) { items { id } }
        siteMatch: items_page_by_column_values(
          board_id: ${boardId},
          columns: [{ column_id: "text_mkkbfs64", column_values: ["${siteId}"] }]
        ) { items { id } }
      }
    `;
    
    const response = await fetch("https://api.monday.com/v2", {
      method: "POST",
      headers: {
        "Content-Type": "application/json",
        "Authorization": apiToken,
        "API-Version": "2025-01",
      },
      body: JSON.stringify({ query }),
    });
    const result = await response.json();
    
    const orderFound = result.data.orderMatch.items.length > 0;
    const siteFound = result.data.siteMatch.items.length > 0;
    
    output = {
      manual_order: manualOrder,
      bundle_id: bundleId,
      order_match_found: orderFound,
      site_match_found: siteFound
    };

    Notice the bundleId || "0" fallback in the code above. Never output an empty string ("") for table lookups. Exact-match lookups will throw an error on a blank input instead of returning "not found". Using "0" is a safe non-match value.

  4. 4

    Apply Clearance Filters

    Add filter steps immediately after your code block to halt the workflow if the order shouldn't be processed automatically:

    1. Manual Order Filter: Only continue if manual_order does NOT contain "Yes" (or "true").

    2. Existing Order Filter: Only continue if order_match_found is "false". This prevents duplicate entries if HDPH sends the webhook multiple times.

  5. 5

    Process Subitems

    Once the order passes all filters, run your subitem creation script. This script maps the incoming orderProductIds to your database of services to generate the correct line items.

Testing Subitem Creation

When setting up or modifying your subitem logic, you can use the built-in DRY_RUN toggle. This allows you to verify the output shape without actually firing the Monday.com API calls.

// Flip this to false when you're ready to actually create subitems.
// Output shape is identical either way — only whether the Monday
// API call fires, and whether subitemId gets a real value, changes.
const DRY_RUN = true;

// ... subitem processing logic ...

Always run a few test payloads from HDPH with DRY_RUN = true to ensure your bundle scoring (isInBundle) and quantity calculations are working as expected before pushing to production.

Output Variables Reference

The unified filtering code outputs several variables that you can use in subsequent steps. Here is a breakdown of what they mean:

VariableTypeDescription
manual_orderStringReturns "Yes" if any product ID matches the manual stop list.
bundle_orderStringReturns "Yes" if the order contains a recognized bundle ID.
bundle_idStringThe specific ID of the bundle found, or "0" if none exist.
order_match_foundBooleantrue if the orderNumber already exists in Monday.com.
site_match_foundBooleantrue if the siteId already exists in Monday.com.