{
  "id": "qhFZ5grN9fdPR5Nw",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Automate Multi-Carrier Shipping Quotes with AI",
  "tags": [],
  "nodes": [
    {
      "id": "95f1536e-a443-4b4b-9a3b-219d96f5bdcf",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        3792,
        2128
      ],
      "parameters": {
        "width": 480,
        "height": 896,
        "content": "## Automate Multi-Carrier Shipping Quotes with AI\n\n### How it works\n\n1. The workflow triggers on incoming WhatsApp messages and validates contact status in HighLevel.\n2. An AI agent processes the message context to extract lead details and syncs them to HighLevel.\n3. The workflow evaluates if lead data collection was successful.\n4. If data is collected, it retrieves shipping rates from ShipEngine and adds a commission percentage.\n5. Finally, it cleans the data and sends the best rate options back via WhatsApp.\n\n### Setup steps\n\n- [ ] Connect your WhatsApp Business API credentials.\n- [ ] Configure the HighLevel integration with valid API keys.\n- [ ] Set up a Google Gemini API key for the AI agent.\n- [ ] Configure the Redis instance for chat memory.\n- [ ] Provide valid credentials for the ShipEngine API in the HTTP request node.\n\n### Customization\n\nYou can adjust the commission percentage in the final processing node or swap the AI model provider by updating the system prompt node."
      },
      "typeVersion": 1
    },
    {
      "id": "7c6476af-75fb-4318-b734-5572bb013435",
      "name": "Sticky Note4",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6096,
        2128
      ],
      "parameters": {
        "color": 7,
        "width": 1172,
        "height": 272,
        "content": "## Shipping rate processing pipeline\n\nCalculates shipping rates and sends quotes."
      },
      "typeVersion": 1
    },
    {
      "id": "d22bad62-40ec-433a-bbfd-62614b9ce70a",
      "name": "Redis Chat Memory",
      "type": "@n8n/n8n-nodes-langchain.memoryRedisChat",
      "position": [
        5472,
        2880
      ],
      "parameters": {
        "sessionKey": "={{ $('When WhatsApp Message Received').item.json.messages[0].from }}",
        "sessionTTL": 55000,
        "sessionIdType": "customKey"
      },
      "typeVersion": 1.6
    },
    {
      "id": "037fc852-efb3-463d-9c63-ad79cb4e85cf",
      "name": "Send Shipping Quote Message",
      "type": "n8n-nodes-base.whatsApp",
      "position": [
        7152,
        2240
      ],
      "parameters": {
        "textBody": "={{ $json.quote }}",
        "operation": "send",
        "phoneNumberId": "1083481144853090",
        "additionalFields": {},
        "recipientPhoneNumber": "={{ $('When WhatsApp Message Received').item.json.contacts[0].wa_id }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "e551042b-813f-497c-8149-377ff1e6e5ca",
      "name": "Set Commission Rate",
      "type": "n8n-nodes-base.set",
      "position": [
        6144,
        2240
      ],
      "parameters": {
        "options": {},
        "assignments": {
          "assignments": [
            {
              "id": "57703348-579f-4da1-a5c9-1b234b1038eb",
              "name": "commission_percentage",
              "type": "number",
              "value": 10
            }
          ]
        }
      },
      "typeVersion": 3.4
    },
    {
      "id": "d7bf68d9-c4dd-4eb6-83da-f396b0b8ecec",
      "name": "Fetch Shipping Rates",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        6432,
        2240
      ],
      "parameters": {
        "url": "https://api.shipengine.com/v1/rates",
        "method": "POST",
        "options": {},
        "jsonBody": "={\n  \"shipment\": {\n    \"ship_from\": {\n      \"name\": \"Test Sender\",\n      \"phone\": \"5551234567\",\n      \"address_line1\": \"123 Main St\",\n      \"city_locality\": \"{{ $('Lead Processing Agent').item.json.output.shipment.ship_from.city_locality }}\",\n      \"state_province\": \"{{ $('Lead Processing Agent').item.json.output.shipment.ship_from.state_province }}\",\n      \"postal_code\": \"{{ $('Lead Processing Agent').item.json.output.shipment.ship_from.postal_code }}\",\n      \"country_code\": \"US\"\n    },\n    \"ship_to\": {\n      \"name\": \"{{ $('When WhatsApp Message Received').item.json.contacts[0].profile.name }}\",\n      \"phone\": \"{{ $('When WhatsApp Message Received').item.json.contacts[0].wa_id }}\",\n      \"address_line1\": \"123 Placeholder Ave\",\n      \"city_locality\": \"{{ $('Lead Processing Agent').item.json.output.shipment.ship_to.city_locality }}\",\n      \"state_province\": \"{{ $('Lead Processing Agent').item.json.output.shipment.ship_to.state_province }}\",\n      \"postal_code\": \"{{ $('Lead Processing Agent').item.json.output.shipment.ship_to.postal_code }}\",\n      \"country_code\": \"US\",\n      \"address_residential_indicator\": \"{{ $('Lead Processing Agent').item.json.output.shipment.ship_to.address_residential_indicator === true || $('Lead Processing Agent').item.json.output.shipment.ship_to.address_residential_indicator === 'yes' ? 'yes' : 'no' }}\"\n    },\n    \"packages\": [\n      {\n        \"weight\": {\n          \"value\": {{ $('Lead Processing Agent').item.json.output.shipment.packages[0].weight.value }},\n          \"unit\": \"pound\"\n        },\n        \"dimensions\": {\n          \"length\": {{ $('Lead Processing Agent').item.json.output.shipment.packages[0].dimensions.length }},\n          \"width\": {{ $('Lead Processing Agent').item.json.output.shipment.packages[0].dimensions.width }},\n          \"height\": {{ $('Lead Processing Agent').item.json.output.shipment.packages[0].dimensions.height }},\n          \"unit\": \"inch\"\n        }\n      }\n    ]\n  },\n  \"rate_options\": {\n    \"carrier_ids\": [\"enter-UPS-carrier-id-here\", \"enter-Fedex-carrier-id-here\", \"enter-DHL-carrier-id-here\"]\n  }\n}",
        "sendBody": true,
        "specifyBody": "json",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth"
      },
      "typeVersion": 4.4
    },
    {
      "id": "7ac3fc81-dc2a-4740-b110-d50385d161a0",
      "name": "Process and Rank Shipping Quotes",
      "type": "n8n-nodes-base.code",
      "position": [
        6672,
        2240
      ],
      "parameters": {
        "jsCode": "const data = $input.first().json;\nconst rates = data.rate_response.rates;\nconst commissionPct = $('Set Commission Rate').first().json.commission_percentage;\n\n// Filter valid rates only and sort by total cost\nconst validRates = rates\n  .filter(r => r.validation_status === 'valid' && r.shipping_amount.amount > 0)\n  .map(r => {\n    const baseTotal = parseFloat((r.shipping_amount.amount + r.other_amount.amount).toFixed(2));\n    const markedUpTotal = parseFloat((baseTotal * (1 + commissionPct / 100)).toFixed(2));\n    return {\n      carrier: r.carrier_friendly_name,\n      service: r.service_type,\n      base_total: baseTotal,\n      total: markedUpTotal,\n      delivery: r.carrier_delivery_days,\n      guaranteed: r.guaranteed_service,\n      rate_id: r.rate_id\n    };\n  })\n  .sort((a, b) => a.total - b.total);\n\nconst cheapest = validRates[0];\nconst fastest = validRates.find(r => r !== cheapest && r.delivery !== cheapest.delivery) || validRates[1];\n\nconst formatOption = (label, r) =>\n  `*${label}*\\n` +\n  `\ud83d\udce6 ${r.carrier} \u2014 ${r.service}\\n` +\n  `\ud83d\udcb0 $${r.total.toFixed(2)}\\n` +\n  `\ud83d\udd50 ${r.delivery}${r.guaranteed ? ' \u2705 Guaranteed' : ''}`;\n\nconst message =\n  `Here are your best shipping options! \ud83d\ude9a\\n\\n` +\n  `${formatOption('\ud83d\udc9a Cheapest', cheapest)}\\n\\n` +\n  `${formatOption('\u26a1 Fastest', fastest)}\\n\\n` +\n  `Call us directly to book this quote!`;\n\nreturn [{\n  json: {\n    whatsapp_message: message,\n    cheapest_rate: cheapest,\n    fastest_rate: fastest,\n    all_valid_rates: validRates\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "3cf5ce8b-ab83-48fc-b80a-3122f85d14d9",
      "name": "Sticky Note5",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        4352,
        2544
      ],
      "parameters": {
        "color": 7,
        "width": 864,
        "height": 288,
        "content": "## Trigger and contact validation\n\nReceives WhatsApp messages and verifies contacts."
      },
      "typeVersion": 1
    },
    {
      "id": "01f5a9e9-e121-4b4a-9aa2-23e58ccfed16",
      "name": "Sticky Note6",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        5248,
        2528
      ],
      "parameters": {
        "color": 7,
        "width": 816,
        "height": 496,
        "content": "## AI lead processing agent\n\nUses AI to process lead information."
      },
      "typeVersion": 1
    },
    {
      "id": "676090e2-e10f-4e34-adaa-26065070dd8b",
      "name": "Sticky Note7",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        6096,
        2528
      ],
      "parameters": {
        "color": 7,
        "width": 416,
        "height": 384,
        "content": "## Lead data collection routing\n\nRoutes based on successful data collection."
      },
      "typeVersion": 1
    },
    {
      "id": "de3d94cf-476d-4740-888c-d548d0272272",
      "name": "When WhatsApp Message Received",
      "type": "n8n-nodes-base.whatsAppTrigger",
      "position": [
        4400,
        2672
      ],
      "parameters": {
        "options": {
          "messageStatusUpdates": [
            "all"
          ]
        },
        "updates": [
          "messages"
        ]
      },
      "typeVersion": 1
    },
    {
      "id": "24374d92-f5b8-4ee1-8504-7a9217fcc385",
      "name": "Check Message Content",
      "type": "n8n-nodes-base.if",
      "position": [
        4624,
        2672
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "eb417180-cf35-4c4f-a0e2-55d37bd65c70",
              "operator": {
                "type": "string",
                "operation": "notEmpty",
                "singleValue": true
              },
              "leftValue": "={{ $json.messages[0].text.body }}",
              "rightValue": ""
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.3
    },
    {
      "id": "9e88a71e-3e4f-4470-bb59-9854d652741b",
      "name": "Fetch HighLevel Contacts",
      "type": "n8n-nodes-base.highLevel",
      "position": [
        4848,
        2656
      ],
      "parameters": {
        "filters": {
          "query": "=+{{ $('When WhatsApp Message Received').item.json.contacts[0].wa_id }}"
        },
        "options": {},
        "operation": "getAll",
        "requestOptions": {}
      },
      "typeVersion": 2,
      "alwaysOutputData": true
    },
    {
      "id": "9eb56047-4946-4dd2-a68a-9a30d6a99844",
      "name": "If Not Do Not Disturb",
      "type": "n8n-nodes-base.if",
      "position": [
        5072,
        2656
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "0a871a82-0677-40d2-b476-6c9ff6a54d31",
              "operator": {
                "type": "boolean",
                "operation": "false",
                "singleValue": true
              },
              "leftValue": "={{ $json.dnd }}",
              "rightValue": false
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "0043f55d-55fa-4b77-bd61-2f4925a4fae2",
      "name": "Google Gemini Model",
      "type": "@n8n/n8n-nodes-langchain.lmChatGoogleGemini",
      "position": [
        5296,
        2880
      ],
      "parameters": {
        "options": {}
      },
      "typeVersion": 1.1
    },
    {
      "id": "aca59006-ce66-474f-84b7-43ea5a218f30",
      "name": "Lead Processing Agent",
      "type": "@n8n/n8n-nodes-langchain.agent",
      "position": [
        5600,
        2640
      ],
      "parameters": {
        "text": "=Contact:\n{{ $json.id ? `Contact Status: The contact is already in our CRM. Their name is ${$json.firstName || 'User'}. We are good to go. Move directly to asking about pending gaps in the Freight Quote query.` : `Contact Status: The contact is NOT created. Simply ask the user for their full name and email address, and use the 'Create Contact' tool once provided. Do not proceed to freight questions until this is done.` }}\n\nUser Message:\n{{ $('When WhatsApp Message Received').item.json.messages[0].text.body }}\n\nTime Now:\n{{ $now }}\nUse the current time below to correctly interpret relative dates the user mentions, such as \"5 days from now\" or \"the 20th of this month.\"",
        "options": {
          "systemMessage": "You are a Parcel Rate Shopping Assistant powered by Blankarray. Your job is to collect shipment details from the user via WhatsApp, then trigger a rate fetch automatically.\n\nFollow these rules in exact order.\n\n---\n\n**Rule 0 \u2014 Contact check**\nRead the \"Contact Status\" in your context. If the contact does not exist, your ONLY task is to ask for their Full Name and Email so you can use the \"Create Contact\" tool. Do not proceed to shipping questions until the contact is created.\n\n**Rule 1 \u2014 The offload condition**\nIf the user says they do not need the service, are testing, or explicitly opts out, immediately call the \"Offload Lead\" tool and end the conversation.\n\n**Rule 2 \u2014 The gathering protocol (strict order)**\nCollect shipment details in exactly this sequence. Do not move to the next phase until the current phase is complete.\n\nPhase A \u2014 Origin & Destination (ask all at once in one message):\n- Origin: city, state, and ZIP code\n- Destination: city, state, and ZIP code\n- Is the destination a residential address? (yes or no)\n\nPhase B \u2014 Package details (ask all at once in one message):\n- Package weight in pounds\n- Package dimensions: length \u00d7 width \u00d7 height in inches\n- Number of packages (if more than 1, ask if all packages are the same size and weight)\n\nPhase C \u2014 Confirmation:\nSummarize all collected details back to the user in a clean, readable format and ask them to confirm. Once confirmed, set is_data_collection_complete to true. Do NOT ask the user about carrier IDs \u2014 those are fixed on your end.\n\n---\n\n**Rule 3 \u2014 Output format**\nEvery response MUST use the exact JSON structure defined by the output parser. Your message to the user always goes inside the user_reply field. Populate shipment fields as you collect them. Leave unknown fields as empty strings or 0. The carrier_ids array is always [\"se-111111\", \"se-222222\"] \u2014 never change it.\n\n**Rule 4 \u2014 Completion flag**\nKeep is_data_collection_complete as false until the user explicitly confirms their shipment details in Phase C. Only then set it to true.\n\n**Rule 5 \u2014 Tone**\nBe friendly, conversational, and concise. Use simple language. Avoid freight jargon. If the user gives a city and state but no ZIP, ask for the ZIP \u2014 it is required for rate calculation."
        },
        "promptType": "define",
        "hasOutputParser": true
      },
      "retryOnFail": true,
      "typeVersion": 3.1
    },
    {
      "id": "8b662f8e-fa37-4d09-93e4-1365acb8175a",
      "name": "Offload Lead",
      "type": "n8n-nodes-base.highLevelTool",
      "position": [
        5632,
        2880
      ],
      "parameters": {
        "contactId": "={{ $json.id }}",
        "operation": "update",
        "updateFields": {
          "dnd": true
        },
        "requestOptions": {}
      },
      "typeVersion": 2
    },
    {
      "id": "056b5e87-1ae2-464a-813b-2a9df6e87f1d",
      "name": "Create Contact",
      "type": "n8n-nodes-base.highLevelTool",
      "position": [
        5776,
        2880
      ],
      "parameters": {
        "email": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Email', ``, 'string') }}",
        "phone": "={{ $('When WhatsApp Message Received').item.json.contacts[0].wa_id }}",
        "requestOptions": {},
        "additionalFields": {
          "lastName": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('Last_Name', ``, 'string') }}",
          "firstName": "={{ /*n8n-auto-generated-fromAI-override*/ $fromAI('First_Name', ``, 'string') }}"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "d7baa945-3a14-4c47-91c6-f240abdcd1b4",
      "name": "Parse Structured Output",
      "type": "@n8n/n8n-nodes-langchain.outputParserStructured",
      "position": [
        5936,
        2880
      ],
      "parameters": {
        "jsonSchemaExample": "{ \"user_reply\": \"Got it! Fetching rates now \ud83d\udce6\", \"is_data_collection_complete\": false, \"shipment\": { \"ship_from\": { \"city_locality\": \"\", \"state_province\": \"\", \"postal_code\": \"\", \"country_code\": \"US\" }, \"ship_to\": { \"city_locality\": \"\", \"state_province\": \"\", \"postal_code\": \"\", \"country_code\": \"US\", \"address_residential_indicator\": \"no\" }, \"packages\": [ { \"weight\": { \"value\": 0, \"unit\": \"pound\" }, \"dimensions\": { \"length\": 0, \"width\": 0, \"height\": 0, \"unit\": \"inch\" } } ] }, \"rate_options\": { \"carrier_ids\": [ \"se-111111\", \"se-222222\" ] } }"
      },
      "retryOnFail": true,
      "typeVersion": 1.3
    },
    {
      "id": "bf28b863-b2dc-400e-b482-baa46096b6dd",
      "name": "If Data Collected",
      "type": "n8n-nodes-base.if",
      "position": [
        6144,
        2640
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "loose"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "3ed59445-7f07-4161-8f73-3656b1dbf8e6",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.output.is_data_collection_complete }}",
              "rightValue": ""
            }
          ]
        },
        "looseTypeValidation": true
      },
      "typeVersion": 2.3
    },
    {
      "id": "5f6f625f-9011-42f7-ad60-6b94d45063b4",
      "name": "Send WhatsApp Message",
      "type": "n8n-nodes-base.whatsApp",
      "position": [
        6368,
        2752
      ],
      "parameters": {
        "textBody": "={{ $json.output.user_reply }}",
        "operation": "send",
        "phoneNumberId": "1083481144853090",
        "additionalFields": {},
        "recipientPhoneNumber": "={{ $('When WhatsApp Message Received').item.json.contacts[0].wa_id }}"
      },
      "typeVersion": 1.1
    },
    {
      "id": "b428bda0-b519-4441-b9fe-508ad003fce0",
      "name": "Append or update row in sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        6880,
        2240
      ],
      "parameters": {
        "columns": {
          "value": {
            "time": "={{$now}}",
            "quote": "={{ $json.whatsapp_message }}",
            "number": "={{ $('When WhatsApp Message Received').item.json.contacts[0].wa_id }}",
            "quoteid": "={{ 'q' + $now.valueOf() + Math.random().toString(36).substring(2, 6) }}"
          },
          "schema": [
            {
              "id": "quoteid",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "quoteid",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "number",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "number",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "quote",
              "type": "string",
              "display": true,
              "required": false,
              "displayName": "quote",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            },
            {
              "id": "time",
              "type": "string",
              "display": true,
              "removed": false,
              "required": false,
              "displayName": "time",
              "defaultMatch": false,
              "canBeUsedToMatch": true
            }
          ],
          "mappingMode": "defineBelow",
          "matchingColumns": [
            "quoteid"
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "appendOrUpdate",
        "sheetName": {
          "__rl": true,
          "mode": "list",
          "value": "gid=0",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1q-hdg-wv_sVrSN7ozzdQi4_Gs9ROgYeezNtxyNhTmvQ/edit#gid=0",
          "cachedResultName": "Sheet1"
        },
        "documentId": {
          "__rl": true,
          "mode": "list",
          "value": "1q-hdg-wv_sVrSN7ozzdQi4_Gs9ROgYeezNtxyNhTmvQ",
          "cachedResultUrl": "https://docs.google.com/spreadsheets/d/1q-hdg-wv_sVrSN7ozzdQi4_Gs9ROgYeezNtxyNhTmvQ/edit?usp=drivesdk",
          "cachedResultName": "Quotes"
        },
        "authentication": "serviceAccount"
      },
      "typeVersion": 4.7
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "availableInMCP": false,
    "executionOrder": "v1"
  },
  "versionId": "2bc37873-d81d-4046-a7e9-8ed8dd90fbf1",
  "nodeGroups": [],
  "connections": {
    "Offload Lead": {
      "ai_tool": [
        [
          {
            "node": "Lead Processing Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Create Contact": {
      "ai_tool": [
        [
          {
            "node": "Lead Processing Agent",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "If Data Collected": {
      "main": [
        [
          {
            "node": "Set Commission Rate",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Send WhatsApp Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Redis Chat Memory": {
      "ai_memory": [
        [
          {
            "node": "Lead Processing Agent",
            "type": "ai_memory",
            "index": 0
          }
        ]
      ]
    },
    "Google Gemini Model": {
      "ai_languageModel": [
        [
          {
            "node": "Lead Processing Agent",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "Set Commission Rate": {
      "main": [
        [
          {
            "node": "Fetch Shipping Rates",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Fetch Shipping Rates": {
      "main": [
        [
          {
            "node": "Process and Rank Shipping Quotes",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Message Content": {
      "main": [
        [
          {
            "node": "Fetch HighLevel Contacts",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "If Not Do Not Disturb": {
      "main": [
        [
          {
            "node": "Lead Processing Agent",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Lead Processing Agent": {
      "main": [
        [
          {
            "node": "If Data Collected",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Structured Output": {
      "ai_outputParser": [
        [
          {
            "node": "Lead Processing Agent",
            "type": "ai_outputParser",
            "index": 0
          }
        ]
      ]
    },
    "Fetch HighLevel Contacts": {
      "main": [
        [
          {
            "node": "If Not Do Not Disturb",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Append or update row in sheet": {
      "main": [
        [
          {
            "node": "Send Shipping Quote Message",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When WhatsApp Message Received": {
      "main": [
        [
          {
            "node": "Check Message Content",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Process and Rank Shipping Quotes": {
      "main": [
        [
          {
            "node": "Append or update row in sheet",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}