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 →
{
"id": "TrackingMorePolling01",
"name": "HFD TrackingMore Polling \u2192 JONI WhatsApp",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 2
}
]
}
},
"id": "node-schedule",
"name": "Every 2 Hours",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.2,
"position": [
240,
300
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.monday.com/v2",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Authorization",
"value": "eyJhbGciOiJIUzI1NiJ9.eyJ0aWQiOjU1OTAyMjM2MiwiYWFpIjoxMSwidWlkIjo2Mzc3NjA5NywiaWFkIjoiMjAyNS0wOS0wN1QxNTowMToxNy4wMDBaIiwicGVyIjoibWU6d3JpdGUiLCJhY3RpZCI6MjQ1MzIyMjcsInJnbiI6ImV1YzEifQ.d86GOnxc-RhtZND7Q7LIoIg3ShFUW0xImLCVjRlzXHQ"
},
{
"name": "Content-Type",
"value": "application/json"
},
{
"name": "API-Version",
"value": "2023-10"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify({ query: '{ boards(ids: [2131896795]) { items_page(limit: 200) { items { id name column_values { id text } } } } }' }) }}",
"options": {}
},
"id": "node-get-monday",
"name": "Get Monday Orders",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
460,
300
]
},
{
"parameters": {
"jsCode": "// Parse Monday board items \u2014 extract tracking, phone, postal code\nconst data = $input.first().json.data || {};\nconst items = data.boards?.[0]?.items_page?.items || [];\n\nconst orders = [];\n\nfor (const item of items) {\n const cols = {};\n (item.column_values || []).forEach(c => { cols[c.id] = (c.text || '').trim(); });\n\n const trackingNumber = cols['text__1'];\n if (!trackingNumber) continue;\n\n const rawPhone = cols['phone__1'];\n if (!rawPhone) continue;\n const phone = rawPhone.replace(/[^0-9]/g, '');\n if (phone.length < 9) continue;\n\n // Extract 7-digit Israeli postal code from any column\n let postalCode = '';\n for (const text of Object.values(cols)) {\n const m = text.match(/\\b\\d{7}\\b/);\n if (m) { postalCode = m[0]; break; }\n }\n\n orders.push({\n item_id: item.id,\n customer_name: item.name,\n tracking_number: trackingNumber,\n phone,\n postal_code: postalCode\n });\n}\n\nreturn orders.map(o => ({ json: o }));"
},
"id": "node-parse-orders",
"name": "Parse Orders",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
680,
300
]
},
{
"parameters": {
"method": "POST",
"url": "https://api.trackingmore.com/v4/trackings/create",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Tracking-Api-Key",
"value": "yocbwatn-q6cl-f3o2-gpdi-5n7qdsd2xh5b"
},
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify({ tracking_number: $json.tracking_number, courier_code: 'hfd', tracking_postal_code: $json.postal_code || undefined }) }}",
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"id": "node-register-tracking",
"name": "Register on TrackingMore",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
900,
300
]
},
{
"parameters": {
"url": "=https://api.trackingmore.com/v4/trackings/hfd/{{ $('Parse Orders').item.json.tracking_number }}",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Tracking-Api-Key",
"value": "yocbwatn-q6cl-f3o2-gpdi-5n7qdsd2xh5b"
}
]
},
"options": {
"response": {
"response": {
"neverError": true
}
}
}
},
"id": "node-get-status",
"name": "Get TrackingMore Status",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1120,
300
]
},
{
"parameters": {
"jsCode": "// Check if status changed; update static data\nconst staticData = $getWorkflowStaticData('global');\nconst order = $('Parse Orders').item.json;\nconst tracking = order.tracking_number;\n\nconst tmResponse = $input.first().json;\nconst trackInfo = tmResponse.data?.[0]?.track_info || {};\nconst currentStatus = trackInfo.latest_status?.status || '';\n\n// Only act on meaningful statuses\nconst KEY_STATUSES = ['InTransit', 'OutForDelivery', 'Delivered', 'Exception', 'AvailableForPickup', 'Undelivered'];\nif (!currentStatus || !KEY_STATUSES.includes(currentStatus)) return [];\n\nconst lastKnown = staticData[tracking] || null;\nif (currentStatus === lastKnown) return []; // No change\n\n// Save new status\nstaticData[tracking] = currentStatus;\n\nconst lastEvent = trackInfo.latest_event || {};\nconst eta = trackInfo.time_metrics?.estimated_delivery_date || {};\n\nreturn [{ json: {\n phone: order.phone,\n customer_name: order.customer_name,\n tracking_number: tracking,\n status: currentStatus,\n sub_status: trackInfo.latest_status?.sub_status || '',\n last_message: lastEvent.description || '',\n last_location: lastEvent.location || '',\n eta_from: eta.from || '',\n eta_to: eta.to || ''\n}}];"
},
"id": "node-check-status",
"name": "Status Changed?",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1340,
300
]
},
{
"parameters": {
"jsCode": "const { status, last_message, last_location, eta_from, eta_to, phone, tracking_number, customer_name } = $input.first().json;\n\nconst warNotice = '\u05d1\u05e2\u05e7\u05d1\u05d5\u05ea \u05de\u05d1\u05e6\u05e2 \u05e9\u05d0\u05d2\u05ea \u05d4\u05d0\u05e8\u05d9 \u05e6\u05e4\u05d5\u05d9\u05d9\u05dd \u05e2\u05d9\u05db\u05d5\u05d1\u05d9\u05dd \u05e7\u05dc\u05d9\u05dd \u05d1\u05de\u05e9\u05dc\u05d5\u05d7\u05d9\u05dd, \u05d0\u05e0\u05d7\u05e0\u05d5 \u05e2\u05dd \u05d9\u05d3 \u05e2\u05dc \u05d4\u05d3\u05d5\u05e4\u05e7 \u05d5\u05d1\u05d5\u05d3\u05e7\u05d9\u05dd \u05de\u05d4 \u05e2\u05dd \u05d4\u05de\u05e9\u05dc\u05d5\u05d7 \u05e9\u05dc\u05da \u05d1\u05db\u05dc \u05d9\u05d5\u05dd \u05d5\u05d9\u05d5\u05dd.\\n\u05e0\u05d0 \u05dc\u05d4\u05d9\u05d5\u05ea \u05e1\u05d1\u05dc\u05e0\u05d9\u05d9\u05dd \ud83d\ude4f';\n\nconst statusMap = {\n InTransit: { headline: '\u05d1\u05d3\u05e8\u05db\u05d4 \u05dc\u05d0\u05e8\u05e5! \u2708\ufe0f', detail: '\u05d6\u05de\u05e0\u05d9 \u05d4\u05d0\u05e1\u05e4\u05e7\u05d4 \u05d4\u05dd 7-21 \u05d9\u05de\u05d9 \u05e2\u05e1\u05e7\u05d9\u05dd, \u05d0\u05e0\u05d5 \u05e0\u05e2\u05d3\u05db\u05df \u05d0\u05d5\u05ea\u05db\u05dd \u05d1\u05db\u05dc \u05e9\u05dc\u05d1 \u05d5\u05e9\u05dc\u05d1.' },\n OutForDelivery: { headline: '\u05d9\u05d5\u05e6\u05d0\u05ea \u05dc\u05de\u05e1\u05d9\u05e8\u05d4 \u05e2\u05db\u05e9\u05d9\u05d5! \ud83d\ude9a', detail: '\u05d4\u05e9\u05dc\u05d9\u05d7 \u05d1\u05d3\u05e8\u05db\u05d5 \u05d0\u05dc\u05d9\u05da \u05d4\u05d9\u05d5\u05dd \u2014 \u05e9\u05de\u05d5\u05e8 \u05e2\u05dc \u05d4\u05d8\u05dc\u05e4\u05d5\u05df \u05e4\u05ea\u05d5\u05d7!' },\n Delivered: { headline: '\u05e0\u05de\u05e1\u05e8\u05d4! \ud83c\udf89', detail: '\u05d4\u05d4\u05d6\u05de\u05e0\u05d4 \u05e9\u05dc\u05da \u05e0\u05de\u05e1\u05e8\u05d4 \u05d1\u05d4\u05e6\u05dc\u05d7\u05d4!\\n\u05e0\u05e9\u05de\u05d7 \u05dc\u05e9\u05de\u05d5\u05e2 \u05e9\u05d4\u05d2\u05d9\u05e2\u05d4 \u2014 \u05ea\u05d4\u05e0\u05d4 \u05de\u05d4\u05de\u05d5\u05e6\u05e8! \u26bd' },\n Exception: { headline: '\u05d1\u05e2\u05d9\u05d4 \u05d1\u05de\u05e9\u05dc\u05d5\u05d7 \u26a0\ufe0f', detail: '\u05d0\u05e0\u05d7\u05e0\u05d5 \u05d1\u05d5\u05d3\u05e7\u05d9\u05dd \u05de\u05d4 \u05e7\u05d5\u05e8\u05d4 \u05d5\u05e0\u05d7\u05d6\u05d5\u05e8 \u05d0\u05dc\u05d9\u05da \u05d1\u05d4\u05e7\u05d3\u05dd.' },\n AvailableForPickup: { headline: '\u05de\u05d7\u05db\u05d4 \u05dc\u05da \u05d1\u05e0\u05e7\u05d5\u05d3\u05ea \u05d7\u05dc\u05d5\u05e7\u05d4 \ud83d\udccd', detail: '\u05d4\u05d7\u05d1\u05d9\u05dc\u05d4 \u05e9\u05dc\u05da \u05de\u05d7\u05db\u05d4 \u05dc\u05d0\u05d9\u05e1\u05d5\u05e3 \u05d1\u05e0\u05e7\u05d5\u05d3\u05ea \u05d4\u05d7\u05dc\u05d5\u05e7\u05d4 \u05d4\u05e7\u05e8\u05d5\u05d1\u05d4 \u05d0\u05dc\u05d9\u05da.' },\n Undelivered: { headline: '\u05e0\u05d9\u05e1\u05d9\u05d5\u05df \u05de\u05e1\u05d9\u05e8\u05d4 \u05e0\u05db\u05e9\u05dc \u26a0\ufe0f', detail: '\u05dc\u05d0 \u05d4\u05e6\u05dc\u05d7\u05e0\u05d5 \u05dc\u05de\u05e1\u05d5\u05e8 \u05d0\u05ea \u05d4\u05d7\u05d1\u05d9\u05dc\u05d4. \u05e0\u05e0\u05e1\u05d4 \u05e9\u05d5\u05d1 \u05d1\u05d4\u05e7\u05d3\u05dd.' }\n};\n\nconst info = statusMap[status];\nif (!info) return [];\n\nlet etaLine = '';\nif (eta_from) {\n try {\n const d = new Date(eta_from);\n const formatted = d.toLocaleDateString('he-IL', { weekday: 'long', day: 'numeric', month: 'long' });\n etaLine = `\\n\u05e6\u05e4\u05d9 \u05d4\u05d2\u05e2\u05d4: ${formatted}`;\n } catch(e) {\n etaLine = `\\n\u05e6\u05e4\u05d9 \u05d4\u05d2\u05e2\u05d4: ${eta_from}`;\n }\n}\n\nconst firstName = (customer_name || '').split(' ')[0];\nconst greeting = firstName ? `\u05e9\u05dc\u05d5\u05dd ${firstName}! \ud83d\udc4b\\n\\n` : '';\nconst war = (status !== 'Delivered') ? `\\n\\n${warNotice}` : '';\nconst trackingLink = `\\n\\n\ud83d\udd0d *\u05dc\u05de\u05e2\u05e7\u05d1 \u05e2\u05e6\u05de\u05d0\u05d9 \u05d1\u05db\u05dc \u05e8\u05d2\u05e2:* https://www.hfd.co.il/\u05d0\u05d9\u05ea\u05d5\u05e8-\u05d7\u05d1\u05d9\u05dc\u05d4/\\n_(\u05d9\u05e9 \u05dc\u05d4\u05e7\u05dc\u05d9\u05d3 \u05d0\u05ea \u05de\u05e1\u05e4\u05e8 \u05d4\u05de\u05e2\u05e7\u05d1 \u05d9\u05d3\u05e0\u05d9\u05ea)_`;\n\nconst message = `*\u05e2\u05d3\u05db\u05d5\u05df \u05de\u05e9\u05dc\u05d5\u05d7 | OneZone* \ud83c\udfc6\\n\\n${greeting}*\u05e1\u05d8\u05d8\u05d5\u05e1:* ${info.headline}\\n\\n${info.detail}${etaLine}${war}\\n\\n*\u05de\u05e1\u05f3 \u05de\u05e2\u05e7\u05d1:* ${tracking_number}${trackingLink}\\n\\n_\u05dc\u05d4\u05e4\u05e1\u05e7\u05ea \u05e2\u05d3\u05db\u05d5\u05e0\u05d9\u05dd \u05e9\u05dc\u05d7 STOP_`;\n\nreturn [{ json: { phone, message } }];"
},
"id": "node-format-message",
"name": "Format Hebrew Message",
"type": "n8n-nodes-base.code",
"typeVersion": 2,
"position": [
1560,
300
]
},
{
"parameters": {
"method": "POST",
"url": "https://joni-e746b-default-rtdb.europe-west1.firebasedatabase.app//joni/send.json",
"sendHeaders": true,
"headerParameters": {
"parameters": [
{
"name": "Content-Type",
"value": "application/json"
}
]
},
"sendBody": true,
"contentType": "raw",
"rawContentType": "application/json",
"body": "={{ JSON.stringify({ to: $json.phone, text: $json.message }) }}",
"options": {}
},
"id": "node-send-joni",
"name": "Send via JONI",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 4.2,
"position": [
1780,
300
]
}
],
"connections": {
"Every 2 Hours": {
"main": [
[
{
"node": "Get Monday Orders",
"type": "main",
"index": 0
}
]
]
},
"Get Monday Orders": {
"main": [
[
{
"node": "Parse Orders",
"type": "main",
"index": 0
}
]
]
},
"Parse Orders": {
"main": [
[
{
"node": "Register on TrackingMore",
"type": "main",
"index": 0
}
]
]
},
"Register on TrackingMore": {
"main": [
[
{
"node": "Get TrackingMore Status",
"type": "main",
"index": 0
}
]
]
},
"Get TrackingMore Status": {
"main": [
[
{
"node": "Status Changed?",
"type": "main",
"index": 0
}
]
]
},
"Status Changed?": {
"main": [
[
{
"node": "Format Hebrew Message",
"type": "main",
"index": 0
}
]
]
},
"Format Hebrew Message": {
"main": [
[
{
"node": "Send via JONI",
"type": "main",
"index": 0
}
]
]
}
},
"settings": {
"executionOrder": "v1",
"saveStaticData": true
},
"staticData": null,
"meta": {
"templateCredsSetupCompleted": true
},
"versionId": "1",
"triggerCount": 0,
"active": false
}
For the full experience including quality scoring and batch install features for each workflow upgrade to Pro
About this workflow
HFD TrackingMore Polling → JONI WhatsApp. Uses httpRequest. Scheduled trigger; 8 nodes.
Source: https://github.com/mirrorframestudio/amit-projects/blob/caed3818fa157d3059c4a053cd67b8caa8fb90d2/n8n/trackingmore-polling.json — original creator credit. Request a take-down →
Related workflows
Workflows that share integrations, category, or trigger type with this one. All free to copy and import.
Auto Hunt. Uses httpRequest, googleSheets, rssFeedRead, telegram. Scheduled trigger; 78 nodes.
Auto-Hunt. Uses httpRequest, googleSheets, rssFeedRead, telegram. Scheduled trigger; 78 nodes.
debug. Uses httpRequest, slack, redis, mailgun. Scheduled trigger; 60 nodes.
Seller Follow-Up Engine (Enhanced). Uses httpRequest, slack. Scheduled trigger; 44 nodes.
This workflow runs daily at 9 AM, uses Perplexity to compile vaping industry news, optionally captures article screenshots via Browserless, and generates a HeyGen avatar video from a template. It then