AutomationFlowsData & Sheets › Track Shipments with Dhl/delhivery Apis & Send Google Sheets Updates to…

Track Shipments with Dhl/delhivery Apis & Send Google Sheets Updates to…

Original n8n title: Track Shipments with Dhl/delhivery Apis & Send Google Sheets Updates to Customers via Whatsapp/email

ByOneclick AI Squad @oneclick-ai on n8n.io

This workflow automatically tracks shipments across multiple courier services, updates Google Sheets, and notifies customers via WhatsApp/Email when status changes. Runs daily at 9 AM and only sends notifications when shipment status actually changes API costs may apply for…

Cron / scheduled trigger★★★★☆ complexity13 nodesGoogle SheetsHTTP RequestEmail Send
Data & Sheets Trigger: Cron / scheduled Nodes: 13 Complexity: ★★★★☆ Added:

This workflow corresponds to n8n.io template #6650 — we link there as the canonical source.

This workflow follows the Emailsend → Google Sheets recipe pattern — see all workflows that pair these two integrations.

The workflow JSON

Copy or download the full n8n JSON below. Paste it into a new n8n workflow, add your credentials, activate. Full import guide →

Download .json
{
  "id": "JORMNG6XHP1Akgbo",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Daily Shipment Tracker with Courier API Updates & Customer Alerts",
  "tags": [],
  "nodes": [
    {
      "id": "b2117104-5779-441c-937f-bb09ee7b07f9",
      "name": "Daily Trigger",
      "type": "n8n-nodes-base.cron",
      "position": [
        -660,
        200
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "9b0abc15-5ad5-4585-b755-c30b7193dcff",
      "name": "Get Shipments List",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        -440,
        200
      ],
      "parameters": {
        "options": {},
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "=iuhgt678io"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "jko9876trde456yhn"
        },
        "authentication": "serviceAccount",
        "combineFilters": "AND"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "b4e26387-7f4e-4f5b-846e-36ea97d5cec6",
      "name": "Filter Active Shipments",
      "type": "n8n-nodes-base.filter",
      "position": [
        -220,
        200
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition-1",
              "operator": {
                "type": "string",
                "operation": "notEquals"
              },
              "leftValue": "={{ $json.status }}",
              "rightValue": "delivered"
            },
            {
              "id": "condition-2",
              "operator": {
                "type": "string",
                "operation": "notEmpty"
              },
              "leftValue": "={{ $json.tracking_number }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "a0d9cf87-83c1-4b3f-b844-8913d7b55ef9",
      "name": "Track via Delhivery",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        220,
        100
      ],
      "parameters": {
        "url": "https://track.delhivery.com/api/v1/packages/json/",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "waybill",
              "value": "={{ $json.tracking_number }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "f1853f77-3060-4150-8a35-cefdc20c7ae1",
      "name": "Track via DHL",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        220,
        300
      ],
      "parameters": {
        "url": "https://api-eu.dhl.com/track/shipments",
        "options": {},
        "sendQuery": true,
        "authentication": "genericCredentialType",
        "genericAuthType": "httpHeaderAuth",
        "queryParameters": {
          "parameters": [
            {
              "name": "trackingNumber",
              "value": "={{ $json.tracking_number }}"
            }
          ]
        }
      },
      "credentials": {
        "httpHeaderAuth": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "6b395480-8d71-4492-8b3e-986992b1db3d",
      "name": "Route by Courier",
      "type": "n8n-nodes-base.if",
      "position": [
        0,
        200
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition-1",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.courier }}",
              "rightValue": "delhivery"
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "62185200-0431-449d-9b1b-6b96d63c2893",
      "name": "Parse Tracking Data",
      "type": "n8n-nodes-base.code",
      "position": [
        440,
        200
      ],
      "parameters": {
        "jsCode": "// Parse tracking response and extract relevant information\nconst items = [];\n\nfor (const item of $input.all()) {\n  const trackingData = item.json;\n  \n  let status = 'unknown';\n  let location = '';\n  let lastUpdated = '';\n  let estimatedDelivery = '';\n  \n  // Parse Delhivery response\n  if (trackingData.ShipmentData && trackingData.ShipmentData.length > 0) {\n    const shipment = trackingData.ShipmentData[0];\n    status = shipment.Status?.Status || 'unknown';\n    location = shipment.Status?.StatusLocation || '';\n    lastUpdated = shipment.Status?.StatusDateTime || '';\n    estimatedDelivery = shipment.ExpectedDeliveryDate || '';\n  }\n  \n  // Parse DHL response\n  if (trackingData.shipments && trackingData.shipments.length > 0) {\n    const shipment = trackingData.shipments[0];\n    if (shipment.status) {\n      status = shipment.status.statusCode || 'unknown';\n      location = shipment.status.location || '';\n      lastUpdated = shipment.status.timestamp || '';\n    }\n  }\n  \n  // Normalize status values\n  const normalizedStatus = {\n    'Delivered': 'delivered',\n    'delivered': 'delivered',\n    'In Transit': 'in_transit',\n    'in_transit': 'in_transit',\n    'Out for Delivery': 'out_for_delivery',\n    'Picked up': 'picked_up',\n    'Exception': 'exception'\n  }[status] || 'in_transit';\n  \n  items.push({\n    json: {\n      tracking_number: item.json.tracking_number || '',\n      customer_email: item.json.customer_email || '',\n      customer_phone: item.json.customer_phone || '',\n      order_id: item.json.order_id || '',\n      current_status: normalizedStatus,\n      previous_status: item.json.status || '',\n      location: location,\n      last_updated: lastUpdated,\n      estimated_delivery: estimatedDelivery,\n      status_changed: (item.json.status !== normalizedStatus)\n    }\n  });\n}\n\nreturn items;"
      },
      "typeVersion": 2
    },
    {
      "id": "3a97de9e-ec0e-4628-adab-2758162bfc6c",
      "name": "Check Status Change",
      "type": "n8n-nodes-base.filter",
      "position": [
        660,
        200
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "condition-1",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ $json.status_changed }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2
    },
    {
      "id": "2e53cd9a-9e16-4c9f-87a5-f06ac949596d",
      "name": "Update Google Sheet",
      "type": "n8n-nodes-base.googleSheets",
      "position": [
        880,
        0
      ],
      "parameters": {
        "columns": {
          "value": {},
          "schema": [],
          "mappingMode": "autoMapInputData",
          "matchingColumns": [],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {},
        "operation": "update",
        "sheetName": {
          "__rl": true,
          "mode": "id",
          "value": "=09iuok"
        },
        "documentId": {
          "__rl": true,
          "mode": "id",
          "value": "0iuhgy678o"
        },
        "authentication": "serviceAccount"
      },
      "credentials": {
        "googleApi": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 4
    },
    {
      "id": "dab15a3e-4632-43fa-a5a3-2b39bab593cb",
      "name": "Send WhatsApp Update",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        880,
        200
      ],
      "parameters": {
        "url": "https://api.whatsapp.com/send",
        "options": {},
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "phone",
              "value": "={{ $json.customer_phone }}"
            },
            {
              "name": "text",
              "value": "\ud83d\ude9a Shipment Update for Order #{{ $json.order_id }}\\n\\nTracking: {{ $json.tracking_number }}\\nStatus: {{ $json.current_status }}\\nLocation: {{ $json.location }}\\nLast Updated: {{ $json.last_updated }}\\n\\n{{ $json.estimated_delivery ? 'Estimated Delivery: ' + $json.estimated_delivery : '' }}\\n\\nThank you for choosing us! \ud83d\udce6"
            }
          ]
        }
      },
      "typeVersion": 4.2
    },
    {
      "id": "a23a973c-d76b-4a51-a485-ed65da3da1aa",
      "name": "Send Email Update",
      "type": "n8n-nodes-base.emailSend",
      "position": [
        880,
        400
      ],
      "parameters": {
        "options": {},
        "subject": "Shipment Update - Order #{{ $json.order_id }}",
        "toEmail": "={{ $json.customer_email }}",
        "fromEmail": "user@example.com"
      },
      "credentials": {
        "smtp": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 2
    },
    {
      "id": "9acd8aba-d127-4eec-b276-36dce8ef582c",
      "name": "Execution Summary",
      "type": "n8n-nodes-base.code",
      "position": [
        1100,
        200
      ],
      "parameters": {
        "jsCode": "// Log workflow execution summary\nconst processedItems = $input.all().length;\nconst updatedItems = $input.all().filter(item => item.json.status_changed).length;\n\nconsole.log(`Shipment Tracking Summary:`);\nconsole.log(`- Total shipments processed: ${processedItems}`);\nconsole.log(`- Shipments with status updates: ${updatedItems}`);\nconsole.log(`- Execution completed at: ${new Date().toISOString()}`);\n\nreturn [{\n  json: {\n    summary: {\n      processed: processedItems,\n      updated: updatedItems,\n      timestamp: new Date().toISOString()\n    }\n  }\n}];"
      },
      "typeVersion": 2
    },
    {
      "id": "e959e416-7e2e-4848-a9df-deda76a88204",
      "name": "Sticky Note",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -580,
        -420
      ],
      "parameters": {
        "color": 4,
        "width": 660,
        "height": 320,
        "content": "## How it works\n* **Daily Trigger**: Cron node runs workflow every day at 9 AM\n* **Get Shipments List**: Fetches all shipment data from Google Sheet\n* **Filter Active Shipments**: Excludes delivered orders and empty tracking numbers\n* **Route by Courier**: Directs shipments to appropriate API (Delhivery or DHL)\n* **Track via APIs**: Makes real-time tracking calls to courier services\n* **Parse Tracking Data**: Normalizes different API responses and detects status changes\n* **Check Status Change**: Only processes shipments with actual status updates\n* **Update & Notify**: Simultaneously updates Google Sheet, sends WhatsApp message, and email notification\n* **Execution Summary**: Logs workflow performance metrics"
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "versionId": "d01d33c3-9470-4b29-a8bf-1a0509b18d28",
  "connections": {
    "Daily Trigger": {
      "main": [
        [
          {
            "node": "Get Shipments List",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Track via DHL": {
      "main": [
        [
          {
            "node": "Parse Tracking Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Route by Courier": {
      "main": [
        [
          {
            "node": "Track via Delhivery",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Track via DHL",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send Email Update": {
      "main": [
        [
          {
            "node": "Execution Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Shipments List": {
      "main": [
        [
          {
            "node": "Filter Active Shipments",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Status Change": {
      "main": [
        [
          {
            "node": "Update Google Sheet",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send WhatsApp Update",
            "type": "main",
            "index": 0
          },
          {
            "node": "Send Email Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Tracking Data": {
      "main": [
        [
          {
            "node": "Check Status Change",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Track via Delhivery": {
      "main": [
        [
          {
            "node": "Parse Tracking Data",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Update Google Sheet": {
      "main": [
        [
          {
            "node": "Execution Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send WhatsApp Update": {
      "main": [
        [
          {
            "node": "Execution Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter Active Shipments": {
      "main": [
        [
          {
            "node": "Route by Courier",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  }
}

Credentials you'll need

Each integration node will prompt for credentials when you import. We strip credential IDs before publishing — you'll add your own.

Pro

For the full experience including quality scoring and batch install features for each workflow upgrade to Pro

About this workflow

This workflow automatically tracks shipments across multiple courier services, updates Google Sheets, and notifies customers via WhatsApp/Email when status changes. Runs daily at 9 AM and only sends notifications when shipment status actually changes API costs may apply for…

Source: https://n8n.io/workflows/6650/ — original creator credit. Request a take-down →

More Data & Sheets workflows → · Browse all categories →

Related workflows

Workflows that share integrations, category, or trigger type with this one. All free to copy and import.

Data & Sheets

Security teams, DevOps engineers, vulnerability analysts, and automation builders who want to eliminate repetitive Nessus scan parsing, AI-based risk triage, and manual reporting. Designed for orgs fo

Email Send, HTTP Request, Google Sheets +1
Data & Sheets

This n8n workflow automatically finds apartments for rent in Germany, filters them by your city, rent budget, and number of rooms, and applies to them via email. Each application includes: A personali

HTTP Request, Google Drive, Email Send +1
Data & Sheets

👤 Who it’s for Blue Team leads, CISOs, and SOC managers who want automated visibility into threat metrics, endpoint alerts, and response actions — without needing a full SIEM or BI platform.

HTTP Request, Email Send, Google Sheets
Data & Sheets

Workflow Overview Zoom Attendance Evaluator with Follow-up is an n8n automation workflow that automatically evaluates Zoom meeting attendance and sends follow-up emails to no-shows and early leavers w

Zoom, Item Lists, HTTP Request +3
Data & Sheets

This workflow automatically monitors Amazon product prices, tracks price changes, and sends alerts when significant price fluctuations occur. Built with ScrapeOps' structured data API, it provides a r

Google Sheets, HTTP Request, Email Send