AutomationFlowsData & Sheets › Vendors

Vendors

Vendors. Uses postgres, readWriteFile. Webhook trigger; 25 nodes.

Webhook trigger★★★★☆ complexity25 nodesPostgresRead Write File
Data & Sheets Trigger: Webhook Nodes: 25 Complexity: ★★★★☆ Added:

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
{
  "createdAt": "2025-10-11T19:27:07.787Z",
  "updatedAt": "2025-10-25T07:25:06.000Z",
  "id": "J9fS2IqweuJi5M9j",
  "name": "Vendors",
  "active": true,
  "isArchived": false,
  "nodes": [
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "UPDATE vendors SET\n  vendor_name = '{{ $json.body.vendor_name }}',\n  website = '{{ $json.body.website }}',\n  contact_email = '{{ $json.body.contact_email }}',\n  phone_number = '{{ $json.body.phone_number }}',\n  vendor_icon_name = '{{ $json.body.vendor_icon_name }}',\n  vendor_icon_type = '{{ $json.body.vendor_icon_type }}',\n  vendor_icon_content = decode('{{ $json.body.vendor_icon_content }}', 'base64')\nWHERE vendor_id = {{ $json.body.vendor_id }}\nRETURNING *;\n",
        "options": {}
      },
      "name": "Execute Vendor Update",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        160,
        608
      ],
      "id": "51063782-6a83-4a76-8018-dad13196eecc",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json;\nreturn [{ json: { success: true, message: 'Vendor updated', data } }];"
      },
      "name": "Format Vendor Update Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        384,
        608
      ],
      "id": "2f1ea46c-efe9-4e1f-bb7a-3a36a30c84d8"
    },
    {
      "parameters": {
        "respondWith": "allIncomingItems",
        "options": {}
      },
      "name": "Respond Vendor Update",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        608,
        608
      ],
      "id": "4fe4cd5f-0332-47d8-85a9-bb81a105d888"
    },
    {
      "parameters": {
        "jsCode": "// Get all incoming items\nconst items = $input.all();\n\n// Extract query from the first item, or use an empty object\nconst q = (items[0] && items[0].json && items[0].json.query) ? items[0].json.query : {};\n\n// Safely parse and default parameters\nconst search = (q.search || \" \").trim(); // Ensure it's always a string\nconst limit = Number.isInteger(parseInt(q.pageSize)) ? parseInt(q.pageSize) : 100000;\nconst pageNo = Number.isInteger(parseInt(q.pageNo)) ? parseInt(q.pageNo) : 1;\nconst offset = (pageNo - 1) * limit;\n\n// Return a single item with params for the next node\nreturn [\n  {\n    json: {\n      params: {\n        search,\n        limit,\n        offset\n      }\n    }\n  }\n];\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        160,
        928
      ],
      "id": "eba15563-b8fe-4dda-b2cb-02e8fe474ee8",
      "name": "Parse Params4"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "SELECT \n  *\nFROM public.vendors\nWHERE \n  vendor_name ILIKE '%{{ $json.params.search }}%'\n  OR contact_email ILIKE '%{{ $json.params.search }}%'\n  OR website ILIKE '%{{ $json.params.search }}%'\nORDER BY vendor_name ASC \nLIMIT {{ $json.params.limit }} \nOFFSET {{ $json.params.offset }}\n",
        "options": {}
      },
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2.6,
      "position": [
        384,
        928
      ],
      "id": "bf08b130-6525-41b5-be5c-0830b3d2c027",
      "name": "Execute a SQL query4",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "respondWith": "allIncomingItems",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.4,
      "position": [
        832,
        832
      ],
      "id": "eaec72b9-b865-413c-a254-487138a04fd2",
      "name": "Respond to Webhook4"
    },
    {
      "parameters": {
        "jsCode": "return $input.all().map(item => {\n  const data = item.json;\n  const imageBuffer = Buffer.from(data.vendor_icon_content.data);\n  const imageType = data.vendor_icon_type || 'jpeg';\n  const base64Image = imageBuffer.toString('base64');\n\n  // Generate filename\n  const filename = `vendor_${data.vendor_id}.${imageType}`;\n\n  return {\n    json:  {  // 'data' is the standard expected binary property name\n        data: base64Image,\n        mimeType: `image/${imageType}`,\n        fileName: filename\n      }\n  };\n});\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        608,
        1024
      ],
      "id": "d567fe1c-c251-4c4c-8a79-5070b267e2d8",
      "name": "Image2"
    },
    {
      "parameters": {
        "operation": "toBinary",
        "sourceProperty": "data",
        "options": {
          "fileName": "={{ $json.fileName }}",
          "mimeType": "={{ $json.mimeType }}"
        }
      },
      "type": "n8n-nodes-base.convertToFile",
      "typeVersion": 1.1,
      "position": [
        832,
        1024
      ],
      "id": "0a1a27a7-49ba-4bc2-a579-38224eba4832",
      "name": "Convert to File2"
    },
    {
      "parameters": {
        "operation": "write",
        "fileName": "=/images/vendors/{{ $('Image2').item.json.fileName }}",
        "options": {}
      },
      "type": "n8n-nodes-base.readWriteFile",
      "typeVersion": 1,
      "position": [
        1056,
        1024
      ],
      "id": "b6a2180e-bb4d-4c71-ab3a-035f29681f2d",
      "name": "Read/Write Files from Disk2"
    },
    {
      "parameters": {
        "jsCode": "const keysToRemove = ['vendor_icon_content', 'vendor_icon_type'];\n\nreturn $input.all().map(item => {\n  const json = {...item.json};\n  keysToRemove.forEach(k => delete json[k]);\n  \n  json.filename = `http://192.168.0.7:5678/webhook/image?filename=vendor_${item.json.vendor_id}.${item.json.vendor_icon_type || 'jpeg'}`;\n\n  return { json };\n});\n"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        608,
        832
      ],
      "id": "8560ed4e-bc10-4f3b-935a-d9c0ea523ea6",
      "name": "Image3"
    },
    {
      "parameters": {
        "path": "api/components/vendors",
        "responseMode": "responseNode",
        "options": {}
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -64,
        928
      ],
      "id": "002f2181-c7b2-446b-a100-bbb9415ddd15",
      "name": "api/components/vendors"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "api/components/vendors/update",
        "responseMode": "responseNode",
        "options": {}
      },
      "name": "UPDATE api/components/vendors/:id",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -64,
        608
      ],
      "id": "ceaf0646-5243-49f2-b688-dc7328a10cad"
    },
    {
      "parameters": {
        "jsCode": "// Get incoming data from POST body\nconst items = $input.all();\nconst body = (items[0] && items[0].json && items[0].json.body) ? items[0].json.body : {};\n\n// Extract vendor ID from body\nconst vendorId = parseInt(body.vendor_id || body.vendorId || body.id) || 0;\n\n// Validate\nif (!vendorId) {\n  throw new Error('Vendor ID is required in request body');\n}\n\nreturn [\n  {\n    json: {\n      params: {\n        id: vendorId\n      }\n    }\n  }\n];"
      },
      "name": "Parse Vendor Delete Params",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        160,
        384
      ],
      "id": "ef82a62c-0ef6-4525-a546-482f4f6b9f72"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "DELETE FROM vendors WHERE vendor_id = {{ $json.params.id }} RETURNING *;",
        "options": {}
      },
      "name": "Execute Vendor Delete",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        384,
        384
      ],
      "id": "c9acc4c5-f08d-4cef-a25d-a9559cdedb5f",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const result = $input.first().json;\nif (result && result.vendor_id) {\n  return [{ json: { success: true, message: 'Vendor deleted successfully' } }];\n}\nreturn [{ json: { success: false, message: 'Vendor not found or could not be deleted' } }];"
      },
      "name": "Format Vendor Delete Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        608,
        384
      ],
      "id": "efa66b1f-ee25-4ab6-801b-f618532a709b"
    },
    {
      "parameters": {
        "respondWith": "allIncomingItems",
        "options": {}
      },
      "name": "Respond Vendor Delete",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        832,
        384
      ],
      "id": "a64fdca3-84ad-49e8-8d2d-03613b349fc7"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "api/components/vendors/delete",
        "responseMode": "responseNode",
        "options": {}
      },
      "name": "DELETE api/components/vendors/delete",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -64,
        384
      ],
      "id": "a7b9ecd0-6b26-43d5-901d-4785a6991422"
    },
    {
      "parameters": {
        "path": "api/components/vendors/meta",
        "responseMode": "responseNode",
        "options": {}
      },
      "name": "api/components/vendors/meta",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -64,
        160
      ],
      "id": "e8a5121c-2b17-4019-b30c-fb9ec9d55d7d"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "WITH vendor_stats AS (\n  SELECT \n    COUNT(DISTINCT v.vendor_id) as total_vendors,\n    COUNT(CASE WHEN v.vendor_icon_name IS NOT NULL THEN 1 END) as vendors_with_icon,\n    COUNT(CASE WHEN v.website IS NOT NULL AND v.website != '' THEN 1 END) as vendors_with_website,\n    COUNT(CASE WHEN v.contact_email IS NOT NULL AND v.contact_email != '' THEN 1 END) as vendors_with_email\n  FROM vendors v\n),\norder_stats AS (\n  SELECT\n    COUNT(*) as total_orders,\n    SUM(total_cost) as total_spent,\n    MAX(order_date) as last_order_date\n  FROM orders\n),\ntop_vendor AS (\n  SELECT\n    v.vendor_id,\n    v.vendor_name,\n    COUNT(o.order_id) as order_count,\n    SUM(o.total_cost) as total_spent,\n    CASE \n      WHEN v.vendor_icon_name IS NOT NULL \n      THEN CONCAT('http://192.168.0.7:5678/webhook/image?filename=', v.vendor_icon_name)\n      ELSE NULL\n    END as vendor_icon\n  FROM vendors v\n  LEFT JOIN orders o ON v.vendor_id = o.vendor_id\n  GROUP BY v.vendor_id, v.vendor_name, v.vendor_icon_name\n  ORDER BY order_count DESC, total_spent DESC\n  LIMIT 1\n),\nrecent_purchase AS (\n  SELECT\n    v.vendor_name,\n    o.order_date,\n    o.total_cost,\n    CASE \n      WHEN v.vendor_icon_name IS NOT NULL \n      THEN CONCAT('http://192.168.0.7:5678/webhook/image?filename=', v.vendor_icon_name)\n      ELSE NULL\n    END as vendor_icon\n  FROM orders o\n  JOIN vendors v ON o.vendor_id = v.vendor_id\n  ORDER BY o.order_date DESC\n  LIMIT 1\n)\nSELECT \n  (SELECT row_to_json(vendor_stats.*) FROM vendor_stats) as vendor_stats,\n  (SELECT row_to_json(order_stats.*) FROM order_stats) as order_stats,\n  (SELECT row_to_json(top_vendor.*) FROM top_vendor) as top_vendor,\n  (SELECT row_to_json(recent_purchase.*) FROM recent_purchase) as recent_purchase;",
        "options": {}
      },
      "name": "Execute Vendors Meta Query",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        160,
        160
      ],
      "id": "26ab9533-7fa1-4200-b064-aa336005aa41",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json;\nconst vendorStats = data.vendor_stats || {};\nconst orderStats = data.order_stats || {};\nconst topVendor = data.top_vendor || {};\nconst recentPurchase = data.recent_purchase || {};\n\nconst total = parseInt(vendorStats.total_vendors || 0);\nconst withIcon = parseInt(vendorStats.vendors_with_icon || 0);\nconst withWebsite = parseInt(vendorStats.vendors_with_website || 0);\nconst withEmail = parseInt(vendorStats.vendors_with_email || 0);\n\nreturn [{\n  json: {\n    summary: {\n      totalVendors: total,\n      vendorsWithIcon: withIcon,\n      vendorsWithWebsite: withWebsite,\n      vendorsWithEmail: withEmail\n    },\n    completeness: {\n      iconCompletion: total > 0 ? Math.round((withIcon / total) * 100) : 0,\n      websiteCompletion: total > 0 ? Math.round((withWebsite / total) * 100) : 0,\n      emailCompletion: total > 0 ? Math.round((withEmail / total) * 100) : 0\n    },\n    purchases: {\n      totalOrders: parseInt(orderStats.total_orders || 0),\n      totalSpent: parseFloat(orderStats.total_spent || 0),\n      lastOrderDate: orderStats.last_order_date || null\n    },\n    topVendor: {\n      vendorId: topVendor.vendor_id || null,\n      vendorName: topVendor.vendor_name || null,\n      orderCount: parseInt(topVendor.order_count || 0),\n      totalSpent: parseFloat(topVendor.total_spent || 0),\n      vendorIcon: topVendor.vendor_icon || null\n    },\n    recentPurchase: {\n      vendorName: recentPurchase.vendor_name || null,\n      orderDate: recentPurchase.order_date || null,\n      totalCost: parseFloat(recentPurchase.total_cost || 0),\n      vendorIcon: recentPurchase.vendor_icon || null\n    }\n  }\n}];"
      },
      "name": "Format Vendors Meta",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        384,
        160
      ],
      "id": "41afe7f2-af4f-4d80-97c1-3792d9534f2f"
    },
    {
      "parameters": {
        "respondWith": "allIncomingItems",
        "options": {}
      },
      "name": "Respond Vendors Meta",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        608,
        160
      ],
      "id": "b7052ab5-3e04-4b01-82c3-749f1484df13"
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "api/components/vendors",
        "responseMode": "responseNode",
        "options": {}
      },
      "name": "ADD api/components/vendors",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -64,
        -32
      ],
      "id": "de48b8f8-70fd-4981-b814-db7341a84816"
    },
    {
      "parameters": {
        "operation": "executeQuery",
        "query": "INSERT INTO public.vendors (\n  vendor_name,\n  website,\n  contact_email,\n  phone_number,\n  vendor_icon_name,\n  vendor_icon_type,\n  vendor_icon_content\n)\nVALUES (\n  '{{ $json.body.vendor_name }}',\n  '{{ $json.body.website }}',\n  '{{ $json.body.contact_email }}',\n  '{{ $json.body.phone_number }}',\n  '{{ $json.body.vendor_icon_name }}',\n  '{{ $json.body.vendor_icon_type }}',\n  decode('{{ $json.body.vendor_icon_content }}', 'base64')\n)\nRETURNING \n  vendor_id,\n  vendor_name,\n  website,\n  contact_email,\n  phone_number,\n  vendor_icon_name,\n  vendor_icon_type,\n  vendor_icon_content,\n  CASE \n    WHEN vendor_icon_name IS NOT NULL \n    THEN CONCAT('http://192.168.0.7:5678/webhook/image?filename=', vendor_icon_name)\n    ELSE NULL\n  END as filename;",
        "options": {}
      },
      "name": "Execute Vendor Insert",
      "type": "n8n-nodes-base.postgres",
      "typeVersion": 2,
      "position": [
        160,
        -32
      ],
      "id": "241e4c02-7411-4797-85d9-0ccfb4a46fec",
      "credentials": {
        "postgres": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "jsCode": "const data = $input.first().json;\nreturn [{ \n  json: { \n    success: true, \n    message: 'Vendor created successfully', \n    vendor: data \n  } \n}];"
      },
      "name": "Format Vendor Insert Response",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        384,
        -32
      ],
      "id": "0b31d9bc-6ad8-475d-a3a3-550a4280e043"
    },
    {
      "parameters": {
        "respondWith": "allIncomingItems",
        "options": {}
      },
      "name": "Respond Vendor Create",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1,
      "position": [
        608,
        -32
      ],
      "id": "8c19a118-6f3b-4948-8cb0-149dcf1d0c02"
    }
  ],
  "connections": {
    "Execute Vendor Update": {
      "main": [
        [
          {
            "node": "Format Vendor Update Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Vendor Update Response": {
      "main": [
        [
          {
            "node": "Respond Vendor Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Params4": {
      "main": [
        [
          {
            "node": "Execute a SQL query4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute a SQL query4": {
      "main": [
        [
          {
            "node": "Image3",
            "type": "main",
            "index": 0
          },
          {
            "node": "Image2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Image2": {
      "main": [
        [
          {
            "node": "Convert to File2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Convert to File2": {
      "main": [
        [
          {
            "node": "Read/Write Files from Disk2",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Image3": {
      "main": [
        [
          {
            "node": "Respond to Webhook4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "api/components/vendors": {
      "main": [
        [
          {
            "node": "Parse Params4",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "UPDATE api/components/vendors/:id": {
      "main": [
        [
          {
            "node": "Execute Vendor Update",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse Vendor Delete Params": {
      "main": [
        [
          {
            "node": "Execute Vendor Delete",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Vendor Delete": {
      "main": [
        [
          {
            "node": "Format Vendor Delete Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Vendor Delete Response": {
      "main": [
        [
          {
            "node": "Respond Vendor Delete",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "DELETE api/components/vendors/delete": {
      "main": [
        [
          {
            "node": "Parse Vendor Delete Params",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "api/components/vendors/meta": {
      "main": [
        [
          {
            "node": "Execute Vendors Meta Query",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Vendors Meta Query": {
      "main": [
        [
          {
            "node": "Format Vendors Meta",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Vendors Meta": {
      "main": [
        [
          {
            "node": "Respond Vendors Meta",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "ADD api/components/vendors": {
      "main": [
        [
          {
            "node": "Execute Vendor Insert",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Execute Vendor Insert": {
      "main": [
        [
          {
            "node": "Format Vendor Insert Response",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Format Vendor Insert Response": {
      "main": [
        [
          {
            "node": "Respond Vendor Create",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "meta": null,
  "versionId": "df784ab9-5e77-463e-b40c-15c668cfd57a",
  "triggerCount": 5,
  "tags": [],
  "shared": [
    {
      "createdAt": "2025-10-11T19:27:07.794Z",
      "updatedAt": "2025-10-11T19:27:07.794Z",
      "role": "workflow:owner",
      "workflowId": "J9fS2IqweuJi5M9j",
      "projectId": "0tBJbgcFWwxEMKPn",
      "project": {
        "createdAt": "2025-10-05T16:55:31.619Z",
        "updatedAt": "2025-10-05T16:55:58.616Z",
        "id": "0tBJbgcFWwxEMKPn",
        "name": "Bikash Panda <oksbwn@gmail.com>",
        "type": "personal",
        "icon": null,
        "description": null
      }
    }
  ]
}

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

Vendors. Uses postgres, readWriteFile. Webhook trigger; 25 nodes.

Source: https://github.com/oksbwn/Inventory-Management-System/blob/7f26462a83a574049df178775808226e970cd4f8/n8n/J9fS2IqweuJi5M9j.json — 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

Boxes APIs. Uses postgres, readWriteFile. Webhook trigger; 28 nodes.

Postgres, Read Write File
Data & Sheets

n8n-supabase-ai-pipeline. Uses supabase, httpRequest, postgres, readWriteFile. Webhook trigger; 25 nodes.

Supabase, HTTP Request, Postgres +1
Data & Sheets

CMM. Uses httpRequest, postgres, redis. Webhook trigger; 90 nodes.

HTTP Request, Postgres, Redis
Data & Sheets

Scraping. Uses httpRequest, postgres, @apify/n8n-nodes-apify, respondToWebhook. Webhook trigger; 61 nodes.

HTTP Request, Postgres, @Apify/N8N Nodes Apify
Data & Sheets

Projects. Uses postgres. Webhook trigger; 58 nodes.

Postgres