AutomationFlowsWeb Scraping › Woocommerce → Faktury Ksef

Woocommerce → Faktury Ksef

WooCommerce → Faktury KSeF. Uses httpRequest. Webhook trigger; 15 nodes.

Webhook trigger★★★★☆ complexity15 nodesHTTP Request
Web Scraping Trigger: Webhook Nodes: 15 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
{
  "name": "WooCommerce \u2192 Faktury KSeF",
  "nodes": [
    {
      "parameters": {
        "content": "## Automatycznie wysy\u0142aj zam\u00f3wienia WooCommerce do KSeF\n\n### Jak to dzia\u0142a\nTen workflow nas\u0142uchuje podpisanego webhooka zam\u00f3wienia z WooCommerce, weryfikuje jego nag\u0142\u00f3wek `X-WC-Webhook-Signature`, pobiera NIP kupuj\u0105cego z metadanych zam\u00f3wienia i przekazuje zam\u00f3wienie do Twojego self-hostowanego [KSeF Gateway](https://github.com/jurczykpawel/ksef-gateway) - niewielkiej nak\u0142adki HTTP na oficjalne API polskiego e-fakturowania. Zam\u00f3wienia bez NIP-u s\u0105 traktowane jako zakupy konsumenckie i pomijane, bo KSeF wymagany jest tylko dla sprzeda\u017cy B2B. Stawka VAT jest wykrywana automatycznie dla ka\u017cdej pozycji na podstawie sum podatkowych WooCommerce.\n\n### Konfiguracja\n1. Wdr\u00f3\u017c instancj\u0119 KSeF Gateway (Docker, Render albo StackPilot - patrz README projektu) i zanotuj jej adres URL. Nowy w KSeF albo potrzebujesz certyfikatu (tokeny KSeF b\u0119d\u0105 wycofywane)? Zobacz [g\u0142\u00f3wny README](https://github.com/jurczykpawel/ksef-gateway#certificate-based-auth-alternative-to-tokens).\n2. Otw\u00f3rz **Configuration (EDIT ME)** i uzupe\u0142nij URL bramki, klucz API bramki, dane sprzedawcy oraz sekret webhooka WooCommerce.\n3. W WooCommerce dodaj niestandardowe pole checkoutu zapisuj\u0105ce NIP kupuj\u0105cego jako metadane zam\u00f3wienia `_billing_nip` (albo `billing_nip`), a potem utw\u00f3rz webhook (Ustawienia \u2192 Zaawansowane \u2192 Webhooks) wskazuj\u0105cy na Production URL tego workflowa z tym samym sekretem.\n4. Zobacz czerwon\u0105 notatk\u0119 przy **Verify Signature** - jedno wymagane ustawienie \u015brodowiska n8n.\n\n### Wskaz\u00f3wki dotycz\u0105ce personalizacji\nDodaj node Slack albo email po **Respond Skipped**, je\u015bli chcesz dostawa\u0107 powiadomienie za ka\u017cdym razem, gdy zam\u00f3wieniu brakuje NIP-u.",
        "height": 720,
        "width": 700,
        "color": 1
      },
      "id": "sticky-overview",
      "name": "Overview",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -760,
        -380
      ]
    },
    {
      "parameters": {
        "content": "## Odbi\u00f3r i weryfikacja\nPrzyjmuje webhook WooCommerce i sprawdza jego podpis HMAC, zanim zaufa danym.",
        "height": 510,
        "width": 1120,
        "color": 7
      },
      "id": "sticky-section-a",
      "name": "Section: Receive & Verify",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -760,
        360
      ]
    },
    {
      "parameters": {
        "content": "## Budowa i sprawdzenie\nMapuje zam\u00f3wienie na payload faktury KSeF i sprawdza NIP kupuj\u0105cego.",
        "height": 510,
        "width": 520,
        "color": 7
      },
      "id": "sticky-section-b",
      "name": "Section: Build & Check",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        440,
        360
      ]
    },
    {
      "parameters": {
        "content": "## Wysy\u0142ka i odpowied\u017a\nWysy\u0142a faktur\u0119 do Twojego KSeF Gateway i zwraca wynik do WooCommerce.",
        "height": 350,
        "width": 520,
        "color": 7
      },
      "id": "sticky-section-c",
      "name": "Section: Send & Respond",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        1040,
        360
      ]
    },
    {
      "parameters": {
        "content": "## Wymagane ustawienie node'a\nTen node Code potrzebuje `require('crypto')`. Self-hostowany n8n: ustaw `NODE_FUNCTION_ALLOW_BUILTIN=crypto` w \u015brodowisku n8n i zrestartuj.",
        "height": 220,
        "width": 300,
        "color": 3
      },
      "id": "sticky-warning",
      "name": "Warning: crypto module",
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -130,
        710
      ]
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "woo-ksef",
        "responseMode": "responseNode",
        "options": {
          "rawBody": true
        }
      },
      "id": "webhook",
      "name": "WooCommerce Webhook",
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2,
      "position": [
        -700,
        550
      ],
      "notes": "Raw Body is required so the signature check below sees the exact bytes WooCommerce signed.",
      "onError": "continueRegularOutput"
    },
    {
      "parameters": {
        "assignments": {
          "assignments": [
            {
              "id": "a1",
              "name": "ksefGatewayUrl",
              "value": "https://your-ksef-gateway.example.com",
              "type": "string"
            },
            {
              "id": "a2",
              "name": "sellerNip",
              "value": "0000000000",
              "type": "string"
            },
            {
              "id": "a3",
              "name": "sellerName",
              "value": "Your Company sp. z o.o.",
              "type": "string"
            },
            {
              "id": "a4",
              "name": "sellerStreet",
              "value": "ul. Example 1",
              "type": "string"
            },
            {
              "id": "a5",
              "name": "sellerCity",
              "value": "00-001 Warszawa",
              "type": "string"
            },
            {
              "id": "a6",
              "name": "webhookSecret",
              "value": "change-me-webhook-secret",
              "type": "string"
            },
            {
              "id": "a7",
              "name": "gatewayApiKey",
              "value": "your-gateway-api-key",
              "type": "string"
            }
          ]
        },
        "includeOtherFields": true,
        "options": {
          "stripBinary": false
        }
      },
      "id": "config-1",
      "name": "Configuration (EDIT ME)",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        -400,
        550
      ],
      "notes": "Fill in your KSeF Gateway URL, seller details, and the WooCommerce webhook secret before activating this workflow."
    },
    {
      "parameters": {
        "jsCode": "const crypto = require('crypto');\nconst config = $('Configuration (EDIT ME)').first().json;\nconst item = $input.first();\n\nconst signatureHeader = (item.json.headers && item.json.headers['x-wc-webhook-signature']) || '';\nconst rawBody = item.binary && item.binary.data\n  ? Buffer.from(item.binary.data.data, 'base64').toString('utf8')\n  : JSON.stringify(item.json.body || {});\n\nconst expected = crypto.createHmac('sha256', config.webhookSecret).update(rawBody).digest('base64');\n\nlet valid = false;\nif (signatureHeader && expected.length === signatureHeader.length) {\n  valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signatureHeader));\n}\n\nreturn [{ json: { valid, body: JSON.parse(rawBody) } }];"
      },
      "id": "code-verify",
      "name": "Verify Signature",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        -100,
        550
      ],
      "notes": "Verifies WooCommerce's base64 HMAC-SHA256 X-WC-Webhook-Signature header and re-parses the raw body for downstream nodes."
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "leftValue": "={{ $json.valid }}",
              "rightValue": true,
              "operator": {
                "type": "boolean",
                "operation": "true"
              }
            }
          ]
        },
        "options": {}
      },
      "id": "if-sig",
      "name": "Signature Valid?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        200,
        550
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "{\"success\":false,\"error\":\"invalid signature\"}",
        "options": {
          "responseCode": 401
        }
      },
      "id": "res-unauth",
      "name": "Respond Unauthorized",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        200,
        710
      ],
      "notes": "Dead end: bad or missing signature. Nothing downstream trusts this payload."
    },
    {
      "parameters": {
        "jsCode": "// Transform WooCommerce order to KSeF invoice format\nconst order = $input.first().json.body;\nconst config = $('Configuration (EDIT ME)').first().json;\n\n// Extract NIP from billing fields or meta_data\nconst nipField = (order.meta_data || []).find(m => m.key === '_billing_nip' || m.key === 'billing_nip');\nconst buyerNip = nipField?.value || '';\n\nif (!buyerNip) {\n  // No NIP = consumer (osoba fizyczna), skip KSeF\n  return [{ json: { skip: true, reason: 'No buyer NIP - consumer purchase, KSeF not required' } }];\n}\n\n// Map WooCommerce line items to KSeF items\nconst items = (order.line_items || []).map(item => {\n  const netTotal = parseFloat(item.total) || 0;\n  const taxTotal = parseFloat(item.total_tax) || 0;\n  const quantity = item.quantity || 1;\n  const unitPrice = Math.round((netTotal / quantity) * 100) / 100;\n\n  // Detect VAT rate from tax amount\n  let vatRate = 23; // default\n  if (netTotal > 0) {\n    const rate = Math.round((taxTotal / netTotal) * 100);\n    if ([23, 8, 5, 0].includes(rate)) vatRate = rate;\n  }\n\n  return {\n    name: item.name,\n    quantity: quantity,\n    unitPrice: unitPrice,\n    vatRate: vatRate\n  };\n});\n\nconst today = new Date().toISOString().split('T')[0];\n\nconst invoice = {\n  invoiceNumber: `WOO/${order.number || order.id}`,\n  issueDate: today,\n  saleDate: order.date_created?.split('T')[0] || today,\n  issuePlace: order.billing?.city || 'Warszawa',\n  currency: order.currency || 'PLN',\n  type: 'VAT',\n  seller: {\n    nip: config.sellerNip,\n    name: config.sellerName,\n    address: {\n      street: config.sellerStreet,\n      city: config.sellerCity\n    }\n  },\n  buyer: {\n    nip: buyerNip,\n    name: order.billing?.company || `${order.billing?.first_name} ${order.billing?.last_name}`,\n    address: {\n      street: order.billing?.address_1 || '',\n      city: `${order.billing?.postcode || ''} ${order.billing?.city || ''}`\n    }\n  },\n  items: items,\n  payment: {\n    paid: order.status === 'completed' || order.date_paid != null,\n    date: order.date_paid?.split('T')[0] || today,\n    method: order.payment_method === 'cod' ? 'cash' : 'transfer'\n  }\n};\n\nreturn [{ json: { skip: false, invoice } }];"
      },
      "id": "transform",
      "name": "Transform to KSeF",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        500,
        550
      ]
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict"
          },
          "combinator": "and",
          "conditions": [
            {
              "leftValue": "={{ $json.skip }}",
              "rightValue": "",
              "operator": {
                "type": "boolean",
                "operation": "false"
              }
            }
          ]
        },
        "options": {}
      },
      "id": "has-nip",
      "name": "Has NIP?",
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.2,
      "position": [
        800,
        550
      ],
      "notes": "IF, not Filter - a Filter node only has one output and silently drops non-matching items, which broke the 'skipped' response path."
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: true, skipped: true, reason: $json.reason }) }}",
        "options": {
          "responseCode": 200
        }
      },
      "id": "respond-skip",
      "name": "Respond Skipped",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        800,
        710
      ]
    },
    {
      "parameters": {
        "method": "POST",
        "url": "={{ $('Configuration (EDIT ME)').item.json.ksefGatewayUrl }}/ksef/invoice",
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify($json.invoice) }}",
        "options": {
          "timeout": 120000
        },
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-Api-Key",
              "value": "={{ $('Configuration (EDIT ME)').item.json.gatewayApiKey }}"
            }
          ]
        }
      },
      "id": "send-invoice",
      "name": "Send to KSeF Gateway",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1100,
        550
      ]
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "={{ JSON.stringify({ success: $json.data?.ksefNumber ? true : false, ksefNumber: $json.data?.ksefNumber || null, error: $json.error || null }) }}"
      },
      "id": "respond-ok",
      "name": "Respond OK",
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.1,
      "position": [
        1400,
        550
      ]
    }
  ],
  "connections": {
    "WooCommerce Webhook": {
      "main": [
        [
          {
            "node": "Configuration (EDIT ME)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configuration (EDIT ME)": {
      "main": [
        [
          {
            "node": "Verify Signature",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Verify Signature": {
      "main": [
        [
          {
            "node": "Signature Valid?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Signature Valid?": {
      "main": [
        [
          {
            "node": "Transform to KSeF",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond Unauthorized",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Transform to KSeF": {
      "main": [
        [
          {
            "node": "Has NIP?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Has NIP?": {
      "main": [
        [
          {
            "node": "Send to KSeF Gateway",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "Respond Skipped",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Send to KSeF Gateway": {
      "main": [
        [
          {
            "node": "Respond OK",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "settings": {
    "executionOrder": "v1"
  },
  "staticData": null,
  "tags": [],
  "triggerCount": 0
}
Pro

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

About this workflow

WooCommerce → Faktury KSeF. Uses httpRequest. Webhook trigger; 15 nodes.

Source: https://github.com/jurczykpawel/ksef-gateway/blob/afca51b445f6b89255b326b4f3bae52aa79cb682/examples/n8n/woocommerce-ksef-PL.json — 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

This n8n template provides enterprise-level version control for your workflows using GitHub integration. Stop losing hours to broken workflows and manual exports – get proper commit history, visual di

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

This flow creates dummy files for every item added in your *Arrs (Radarr/Sonarr) with the tag .

HTTP Request, Ssh
Web Scraping

eek-Go v2 (Batch-Then-Review). Uses httpRequest. Webhook trigger; 75 nodes.

HTTP Request
Web Scraping

This workflow receives webhook requests from a content calendar and uses the X API v2 to publish text posts, threads, image/video posts, and polls, as well as delete existing posts and run a credentia

HTTP Request
Web Scraping

This workflow acts as a central API gateway for all technical indicator agents in the Binance Spot Market Quant AI system. It listens for incoming webhook requests and dynamically routes them to the c

HTTP Request