AutomationFlowsWeb Scraping › Create Incoming Invoices in Work4all From Email Attachments with Openai

Create Incoming Invoices in Work4all From Email Attachments with Openai

ByChristoph Baldow @styx0r on n8n.io

This sub-workflow receives an email item with binary attachments, uses an OpenAI-compatible chat completions endpoint to detect and extract invoice fields from PDF/XML/JSON files, and then creates an incoming invoice in work4all with the relevant original attachments. Receives…

Event trigger★★★★☆ complexity22 nodesExecute Workflow TriggerHTTP RequestN8N Nodes Work4All
Web Scraping Trigger: Event Nodes: 22 Complexity: ★★★★☆ Added:

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

This workflow follows the Execute Workflow Trigger → HTTP Request 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": "qqEyPIiXqpshnSKv",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "name": "Create a work4all incoming invoice from email attachments using AI",
  "tags": [],
  "nodes": [
    {
      "id": "e66e1fd3-d063-4ee3-9c6f-62cf8b3e0776",
      "name": "Sticky Note - Description",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        12368,
        7072
      ],
      "parameters": {
        "width": 460,
        "height": 680,
        "content": "## Create a work4all incoming invoice from email attachments using AI\n\nThis **sub-workflow** is called by a parent workflow with one email item whose attachments are passed as binary data. The attachments are read by AI, structured invoice data is extracted, and the **work4all** node books the incoming invoice with the original files attached.\n\n### How it works\n1. Keeps only emails that carry a readable PDF / XML / JSON attachment.\n2. Extracts invoice data in one of two modes (**Extraction config**):\n   - **`backend`** (default) \u2014 work4all AI backend, uses the **work4all** credential.\n   - **`llm`** \u2014 your own **OpenAI-compatible** model (*Call LLM*).\n3. Normalises the result, books the incoming invoice and attaches the files.\n\n### Setup\n1. Add your **work4all** credential.\n2. Call this workflow from a parent that supplies the email + attachments.\n\n### Customization\n- **Extraction mode** \u2014 default is `backend` (work4all AI). For your own model, set **Extraction config** to `llm` and add an **OpenAI-compatible** credential on *Call LLM*.\n- Switch provider/model in *Call LLM* and the `MODEL` constant in *Build LLM messages* (must support **PDF / file input**).\n\nRequires a work4all account and the verified `n8n-nodes-work4all` node."
      },
      "typeVersion": 1
    },
    {
      "id": "78f97643-5f70-480a-b97b-026145b05ebe",
      "name": "Sticky Note - Input",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        12912,
        7680
      ],
      "parameters": {
        "color": 7,
        "width": 704,
        "height": 368,
        "content": "## 1 \u00b7 Input & validation\nReceives the email from the parent workflow and keeps only items that carry a readable PDF / XML / JSON attachment."
      },
      "typeVersion": 1
    },
    {
      "id": "637606f7-39aa-4f71-99eb-988f55e33661",
      "name": "Sticky Note - Extract",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        14304,
        7376
      ],
      "parameters": {
        "color": 7,
        "width": 470,
        "height": 492,
        "content": "## 3 \u00b7 Extract invoice data\nBoth modes read the attachments and return the same structured invoice JSON \u2014 via the work4all AI backend or an OpenAI-compatible LLM (*Build LLM messages* \u2192 *Call LLM*)."
      },
      "typeVersion": 1
    },
    {
      "id": "455c54ab-3f25-4139-a6d0-ae08ce274bf6",
      "name": "Sticky Note - Book",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        15520,
        7488
      ],
      "parameters": {
        "color": 7,
        "width": 736,
        "height": 312,
        "content": "## 5 \u00b7 Book in work4all\nNormalises currency and dates, creates the incoming invoice in work4all and attaches the original files."
      },
      "typeVersion": 1
    },
    {
      "id": "8dac390a-f06a-4a85-bb4f-130559fc4448",
      "name": "When called by parent workflow",
      "type": "n8n-nodes-base.executeWorkflowTrigger",
      "position": [
        12960,
        7872
      ],
      "parameters": {
        "inputSource": "passthrough"
      },
      "typeVersion": 1.1
    },
    {
      "id": "592be2b9-c567-4474-b715-ecbd62727f5a",
      "name": "Has attachments?",
      "type": "n8n-nodes-base.if",
      "position": [
        13184,
        7872
      ],
      "parameters": {
        "options": {
          "ignoreCase": false
        },
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "7ea39fb4-a88f-4f20-85d2-6daea27f1c16",
              "operator": {
                "type": "boolean",
                "operation": "equals"
              },
              "leftValue": "={{ Object.keys($binary ?? {}).length > 0 }}",
              "rightValue": true
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "166ec2d0-b6a8-464c-b876-1ad81472a68c",
      "name": "Build LLM messages",
      "type": "n8n-nodes-base.code",
      "position": [
        14352,
        7696
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "// \u2699\ufe0f CONFIG: set your OpenAI-compatible model here\nconst MODEL = \"policy/EU-Sonnet-4-6\";\n\nconst item = $input.item;\n\nlet content = [\n  {\n    type: \"text\",\n    text: `\nReturn ONLY valid JSON.\nDo not use markdown.\nDo not wrap in triple backticks.\nDo not add explanations before or after the JSON.\n\nUse exactly this shape:\n{\n  \"found_invoice\": true,\n  \"reason\": \"short explanation\",\n  \"relevantAttachmentKeys\": [\"attachment_0\"],\n  \"invoiceData\": {\n    \"supplierCode\": null,\n    \"supplierName\": null,\n    \"supplierCustomerNumberAtSupplier\": null,\n    \"supplierContactMailAddress\": null,\n    \"supplierIban\": null,\n    \"projectCode\": null,\n    \"projectNumber\": null,\n    \"projectName\": null,\n    \"invoiceNumberSupplier\": null,\n    \"note\": null,\n    \"invoiceDate\": null,\n    \"paymentTermDays\": null,\n    \"discount1Rate\": null,\n    \"discount1Days\": null,\n    \"discount2Rate\": null,\n    \"discount2Days\": null,\n    \"currencyCode\": null,\n    \"invoiceItems\": [\n      {\n        \"account\": null,\n        \"costCenter\": null,\n        \"costGroup\": null,\n        \"projectCode\": null,\n        \"taxRate\": null,\n        \"netAmount\": null,\n        \"grossAmount\": null,\n        \"vatAmount\": null,\n        \"note\": null\n      }\n    ]\n  }\n}\n\nRules:\n- found_invoice = true only if at least one attachment is clearly an incoming supplier invoice / Eingangsrechnung / XRechnung / receipt relevant for accounting.\n- relevantAttachmentKeys must contain the original attachment keys like \"attachment_0\".\n- invoiceData field names must match exactly.\n- The note field should hold a short description, e.g. the supplier company name combined with the invoice period.\n- Each invoiceItems note should be a short note, not more than 50 characters.\n- Dates must be ISO-8601 strings if known, otherwise null.\n- Do not invent values.\n- Aggregate invoiceItems by VAT rate (Mehrwertsteuersatz), not by raw line item.\n- Return one invoiceItems entry per VAT bucket.\n- Sum netAmount, vatAmount and grossAmount per VAT bucket.\n- Only fill account, costCenter, costGroup, projectCode, taxCode if explicitly present in the documents.\n- If no invoice is found, return:\n  {\n    \"found_invoice\": false,\n    \"reason\": \"...\",\n    \"relevantAttachmentKeys\": [],\n    \"invoiceData\": {\n      \"supplierCode\": null,\n      \"supplierName\": null,\n      \"supplierCustomerNumberAtSupplier\": null,\n      \"supplierContactMailAddress\": null,\n      \"supplierIban\": null,\n      \"projectCode\": null,\n      \"projectNumber\": null,\n      \"projectName\": null,\n      \"invoiceNumberSupplier\": null,\n      \"note\": null,\n      \"invoiceDate\": null,\n      \"paymentTermDays\": null,\n      \"discount1Rate\": null,\n      \"discount1Days\": null,\n      \"discount2Rate\": null,\n      \"discount2Days\": null,\n      \"currencyCode\": null,\n      \"invoiceItems\": []\n    }\n  }\n`\n  }\n];\n\nlet has_xml_or_json = false;\n\nif (item.binary) {\n  for (const key of Object.keys(item.binary)) {\n    const file = item.binary[key];\n\n    const mimeType = file.mimeType || \"\";\n    const fileName = file.fileName || \"file\";\n\n    const buffer = await this.helpers.getBinaryDataBuffer(0, key);\n    const base64 = buffer.toString(\"base64\");\n\n    const isPdf =\n      mimeType.includes(\"pdf\") ||\n      fileName.toLowerCase().endsWith(\".pdf\");\n\n    if (isPdf) {\n      has_xml_or_json = true;\n      content.push({\n        type: \"input_file\",\n        filename: fileName,\n        file_data: `data:application/pdf;base64,${base64}`\n      });\n    } else if (\n      mimeType.includes(\"xml\") ||\n      mimeType.includes(\"json\") ||\n      fileName.endsWith(\".xml\") ||\n      fileName.endsWith(\".json\")\n    ) {\n      has_xml_or_json = true;\n      const text = buffer.toString(\"utf-8\");\n\n      content.push({\n        type: \"text\",\n        text: `Content of ${fileName}:\\n${text}`\n      });\n    }\n  }\n}\n\nreturn {\n  json: {\n    has_xml_or_json: has_xml_or_json,\n    model: MODEL,\n    messages: [\n      {\n        role: \"user\",\n        content\n      }\n    ]\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "f656a11f-2883-48ac-8b73-3a9151cd4237",
      "name": "Has readable attachment?",
      "type": "n8n-nodes-base.if",
      "position": [
        13424,
        7776
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "a5d662cb-f633-4648-bc88-bcc9362b9630",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ Object.values($binary ?? {}).some(f => /pdf|xml|json/i.test(((f.mimeType || '') + ' ' + (f.fileName || '')))) }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "9fc590c7-a747-4619-9612-df85a34d6bb7",
      "name": "Call LLM",
      "type": "n8n-nodes-base.httpRequest",
      "position": [
        14576,
        7696
      ],
      "parameters": {
        "url": "https://router.eu.requesty.ai/v1/chat/completions",
        "method": "POST",
        "options": {},
        "jsonBody": "={{ $json }}",
        "sendBody": true,
        "sendHeaders": true,
        "specifyBody": "json",
        "authentication": "predefinedCredentialType",
        "headerParameters": {
          "parameters": [
            {
              "name": "Accept",
              "value": "application/json"
            }
          ]
        },
        "nodeCredentialType": "openAiApi"
      },
      "typeVersion": 4.4
    },
    {
      "id": "416e69af-4831-4438-bc55-47645db328b4",
      "name": "Parse extraction result",
      "type": "n8n-nodes-base.code",
      "position": [
        14976,
        7600
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "function removeNullish(value) {\n  if (Array.isArray(value)) {\n    return value.map(removeNullish);\n  }\n  if (value && typeof value === \"object\") {\n    return Object.fromEntries(\n      Object.entries(value)\n        .filter(([, v]) => v !== undefined && v !== null && v !== \"\")\n        .map(([k, v]) => [k, removeNullish(v)])\n    );\n  }\n  return value;\n}\n\n// LLM path returns an OpenAI envelope ($json.choices[0].message.content);\n// the work4all AI backend returns the payload directly (often as a plain JSON string).\nlet raw = $json && $json.choices ? $json.choices[0].message.content : $json;\n\nlet parsed;\nif (typeof raw === \"string\") {\n  raw = raw\n    .replace(/^```json\\s*/i, \"\")\n    .replace(/^```\\s*/i, \"\")\n    .replace(/\\s*```$/, \"\")\n    .trim();\n  parsed = raw ? JSON.parse(raw) : {};\n} else {\n  parsed = raw ?? {};\n}\n\nreturn {\n  json: {\n    found_invoice: parsed.found_invoice === true,\n    reason: parsed.reason ?? \"\",\n    relevantAttachmentKeys: parsed.relevantAttachmentKeys ?? [],\n    invoiceData: removeNullish(parsed.invoiceData ?? {}),\n  },\n  binary: $input.item.binary,\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "6ce97f81-cbb8-4c0d-af82-2f2ee828293c",
      "name": "Has invoice?",
      "type": "n8n-nodes-base.if",
      "position": [
        15200,
        7600
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "6573bc49-61be-476e-95d7-3f9b4e26b1c9",
              "operator": {
                "type": "boolean",
                "operation": "true",
                "singleValue": true
              },
              "leftValue": "={{ $json.found_invoice }}",
              "rightValue": ""
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "a76861d5-716f-48d8-bf94-6174f511f99d",
      "name": "Filter attachments & normalize",
      "type": "n8n-nodes-base.code",
      "position": [
        15568,
        7584
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "const relevantKeys = $json.relevantAttachmentKeys || [];\nconst sourceBinary = $('When called by parent workflow').item.binary || {};\n\nconst keptBinary = Object.fromEntries(\n  relevantKeys\n    .filter((key) => sourceBinary[key])\n    .map((key) => [key, sourceBinary[key]])\n);\n\nconst invoiceData = { ...($json.invoiceData || {}) };\ninvoiceData.currency = \"EUR\";\ndelete invoiceData.currencyCode;\n\nfor (const key of [\"invoiceDate\", \"entryDate\", \"receiptDate\"]) {\n  if (\n    typeof invoiceData[key] === \"string\" &&\n    /^\\d{4}-\\d{2}-\\d{2}$/.test(invoiceData[key])\n  ) {\n    invoiceData[key] = `${invoiceData[key]}T00:00:00Z`;\n  }\n}\n\nconst receiptDate = $('When called by parent workflow').item.json.receivedDateTime;\n\ninvoiceData.receiptDate = receiptDate;\ninvoiceData.entryDate = receiptDate;\n\nreturn {\n  json: {\n    ...$json,\n    invoiceData,\n    relevantAttachmentKeys: relevantKeys,\n  },\n  binary: keptBinary,\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "14556c93-cc8c-41bb-9b00-e2cd136406c0",
      "name": "Create incoming invoice",
      "type": "n8n-nodes-work4all.work4all",
      "position": [
        15792,
        7584
      ],
      "parameters": {
        "dataMode": "json",
        "attachmentsJson": "={{ ($json.relevantAttachmentKeys || []).map(k => ({ binaryPropertyName: k })) }}",
        "attachmentsMode": "json",
        "invoiceDataJson": "={{$json.invoiceData}}"
      },
      "typeVersion": 1
    },
    {
      "id": "b6f276dc-7eb3-4022-a8a2-53267f220c80",
      "name": "Format work4all result",
      "type": "n8n-nodes-base.code",
      "position": [
        16016,
        7584
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "return {\n  json: {\n    messageId: $('When called by parent workflow').item.json.id,\n    errors: $json.errors,\n    invoiceData: $json.data\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "30af0f13-15e8-482a-8209-a000b190baa3",
      "name": "No invoice - skip",
      "type": "n8n-nodes-base.noOp",
      "position": [
        15776,
        7968
      ],
      "parameters": {},
      "typeVersion": 1
    },
    {
      "id": "75dcd732-3065-4e5a-bba9-f87fdda02d50",
      "name": "Build result (no invoice)",
      "type": "n8n-nodes-base.code",
      "position": [
        16016,
        7968
      ],
      "parameters": {
        "mode": "runOnceForEachItem",
        "jsCode": "return {\n  json: {\n    messageId: $('When called by parent workflow').item.json.id,\n    success: true\n  }\n};"
      },
      "typeVersion": 2
    },
    {
      "id": "cc7f976e-5085-42ab-9a8e-7a78155009d3",
      "name": "Extraction config",
      "type": "n8n-nodes-base.set",
      "position": [
        13744,
        7600
      ],
      "parameters": {
        "options": {
          "stripBinary": false
        },
        "assignments": {
          "assignments": [
            {
              "id": "a1b2c3d4-+123456789001",
              "name": "extractionMode",
              "type": "string",
              "value": "backend"
            }
          ]
        },
        "includeOtherFields": true
      },
      "typeVersion": 3.4
    },
    {
      "id": "cc5a7d76-6063-4f73-a15e-3c4382b0bb8e",
      "name": "Use work4all AI backend?",
      "type": "n8n-nodes-base.if",
      "position": [
        13968,
        7600
      ],
      "parameters": {
        "options": {},
        "conditions": {
          "options": {
            "version": 3,
            "leftValue": "",
            "caseSensitive": true,
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "id": "b1b2c3d4-+123456789002",
              "operator": {
                "type": "string",
                "operation": "equals"
              },
              "leftValue": "={{ $json.extractionMode }}",
              "rightValue": "backend"
            }
          ]
        }
      },
      "typeVersion": 2.3
    },
    {
      "id": "2c7e4d91-6af3-458a-9fa7-f4d32917b300",
      "name": "Extract invoice data",
      "type": "n8n-nodes-work4all.work4all",
      "position": [
        14576,
        7504
      ],
      "parameters": {
        "operation": "extractInvoiceData"
      },
      "credentials": {
        "work4allOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "typeVersion": 1
    },
    {
      "id": "147f7d49-6d33-4547-a819-86c90e39ca4a",
      "name": "Sticky Note - Extraction mode",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        13712,
        7472
      ],
      "parameters": {
        "color": 7,
        "width": 446,
        "height": 336,
        "content": "## 2 \u00b7 Choose extraction mode\nSet `extractionMode` in **Extraction config**: `backend` (work4all AI backend) or `llm` (your own OpenAI-compatible model)."
      },
      "typeVersion": 1
    },
    {
      "id": "4e9262e1-c41b-481c-97d4-8678e1cd5810",
      "name": "Sticky Note - Parse",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        14928,
        7488
      ],
      "parameters": {
        "color": 7,
        "width": 420,
        "height": 340,
        "content": "## 4 \u00b7 Parse & check\nNormalises either output into the same shape and checks whether an invoice was found. If not, booking is skipped."
      },
      "typeVersion": 1
    },
    {
      "id": "68c12587-e1d6-4efa-8be4-58b5403e4bb1",
      "name": "Sticky Note - No invoice",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        15728,
        7872
      ],
      "parameters": {
        "color": 7,
        "width": 488,
        "height": 256,
        "content": "## 6 \u00b7 No invoice\nItems without a usable invoice end here and return a simple skipped result."
      },
      "typeVersion": 1
    }
  ],
  "active": false,
  "settings": {
    "binaryMode": "separate",
    "executionOrder": "v1"
  },
  "versionId": "987ac2a4-e699-42e6-ba8b-35ccc0c4fbe7",
  "connections": {
    "Call LLM": {
      "main": [
        [
          {
            "node": "Parse extraction result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has invoice?": {
      "main": [
        [
          {
            "node": "Filter attachments & normalize",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No invoice - skip",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has attachments?": {
      "main": [
        [
          {
            "node": "Has readable attachment?",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No invoice - skip",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extraction config": {
      "main": [
        [
          {
            "node": "Use work4all AI backend?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "No invoice - skip": {
      "main": [
        [
          {
            "node": "Build result (no invoice)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Build LLM messages": {
      "main": [
        [
          {
            "node": "Call LLM",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Extract invoice data": {
      "main": [
        [
          {
            "node": "Parse extraction result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Create incoming invoice": {
      "main": [
        [
          {
            "node": "Format work4all result",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Parse extraction result": {
      "main": [
        [
          {
            "node": "Has invoice?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has readable attachment?": {
      "main": [
        [
          {
            "node": "Extraction config",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "No invoice - skip",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Use work4all AI backend?": {
      "main": [
        [
          {
            "node": "Extract invoice data",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Build LLM messages",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Filter attachments & normalize": {
      "main": [
        [
          {
            "node": "Create incoming invoice",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "When called by parent workflow": {
      "main": [
        [
          {
            "node": "Has attachments?",
            "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 sub-workflow receives an email item with binary attachments, uses an OpenAI-compatible chat completions endpoint to detect and extract invoice fields from PDF/XML/JSON files, and then creates an incoming invoice in work4all with the relevant original attachments. Receives…

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

More Web Scraping workflows → · Browse all categories →

Related workflows

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

Web Scraping

02_LLM_Pipeline v1.0. Uses executeWorkflowTrigger, httpRequest, seaTable. Event-driven trigger; 65 nodes.

Execute Workflow Trigger, HTTP Request, Sea Table
Web Scraping

This template is a powerful, reusable utility for managing stateful, long-running processes. It allows a main workflow to be paused indefinitely at "checkpoints" and then be resumed by external, async

HTTP Request, Execute Workflow Trigger
Web Scraping

Upload files from any source to your account Kommo or AmoCRM with a simple and reusable workflow. It can split a large file into small ones and upload chunks. Works for Kommo and amoCRM There are 3 re

HTTP Request, Execute Workflow Trigger, Stop And Error
Web Scraping

Remixed Backup your workflows to GitHub from Solomon's work. Check out his templates.

HTTP Request, GitHub, Execute Workflow Trigger +1
Web Scraping

Remixed Backup your workflows to GitHub from Solomon's work. Check out his templates.

Execute Workflow Trigger, HTTP Request, GitHub