rechnungsapi.de
    Startseite
    Lösungen
    Steuerberater & KanzleienUnternehmen & MittelstandIT-Teams & SoftwareanbieterE-Invoicing-Berater & PartnerStartups & SaaSInternational & Peppol
    PreiseValidatorBlogKontaktAPI Docs
    🔑Anmelden🚀Loslegen
    Zurück zum Blog
    ShopifyWooCommerceZUGFeRDXRechnungWebhook

    E-Rechnung für Shopify und WooCommerce: So wird jede B2B-Bestellung automatisch konform

    Shopify und WooCommerce erzeugen PDF-Rechnungen — kein strukturiertes XML, keine EN 16931-Konformität. Für B2B-Kunden reicht das ab 2027 nicht mehr. Mit einem Webhook und rechnungsapi.de läuft die E-Rechnungserzeugung vollautomatisch.

    1. September 202611 min LesezeitIntegration

    Was Shopify und WooCommerce nicht können

    Shopify und WooCommerce bieten von Haus aus keine konforme E-Rechnung nach EN 16931. Plugins können helfen — aber oft nur für ZUGFeRD Basic-WL (nicht zugelassen!) oder als manueller Export. Eine vollautomatische Lösung braucht einen Webhook an rechnungsapi.de.

    Welche Shop-Betreiber sind betroffen?

    Die E-Rechnungspflicht gilt nur für B2B (Geschäftskunden), nicht für B2C (Endverbraucher). Das klingt einfach — in der Praxis muss ein gemischter Shop aber zuverlässig zwischen beiden unterscheiden.

    SzenarioE-Rechnungspflicht ab 2027?
    Online-Shop mit Privatkunden (B2C)Nein
    Online-Shop mit Geschäftskunden (B2B)Ja
    Gemischter Shop (B2B + B2C)Ja, für B2B-Bestellungen
    Kleinunternehmer §19 UStGEmpfangen ja, Senden nein

    Praktische Faustregel: Wenn Kunden mit Firmennamen + USt-ID bestellen → B2B → E-Rechnung Pflicht. Das USt-ID-Feld im Checkout ist damit nicht nur ein nettes Feature, sondern die Grundlage für die automatische B2B-Erkennung.

    Was Shopify und WooCommerce können — und was nicht

    S Shopify

    • ~Sendet standardmäßig PDF-Bestellbestätigungen, keine Rechnungen
    • ~Shopify-Apps (z.B. "Order Printer") erzeugen PDFs — kein XML
    • ✗Kein nativer ZUGFeRD/XRechnung Support
    • ✓Shopify empfiehlt selbst externe Services für E-Rechnung

    W WooCommerce

    • ~Plugin "Germanized Pro" kann ZUGFeRD — aber nur Basic-WL Profil
    • ✗Basic-WL ist ab 2027 NICHT für die E-Rechnungspflicht zugelassen
    • ~Plugin "WooRechnung" ähnlich eingeschränkt
    • ✓Für konformes ZUGFeRD COMFORT/EN 16931: externer API-Aufruf nötig

    Lösungsvergleich

    LösungShopifyWooCommerceKonform?
    Standard PDF✓✓✗
    Germanized Pro ZUGFeRD✗Basic-WL✗ (Basic-WL nicht zulässig)
    rechnungsapi.de via Webhook✓✓✓ ZUGFeRD COMFORT/EN 16931

    Der Weg: Shopify Webhook → rechnungsapi.de

    1

    B2B-Bestellung eingeht

    Kunde hat Firmenname + USt-ID hinterlegt.

    2

    Shopify orders/paid Webhook feuert

    Shopify sendet das vollständige Order-Objekt an deine Webhook-URL.

    3

    Server empfängt & validiert Webhook

    HMAC-Prüfung mit dem Shopify Webhook Secret sichert die Authentizität.

    4

    B2B-Erkennung: USt-ID vorhanden?

    Nur Bestellungen mit hinterlegter USt-ID werden als E-Rechnung verarbeitet.

    5

    POST an rechnungsapi.de

    Vollständiger JSON-Payload mit Seller, Buyer und Positionen — Antwort ist ein ZUGFeRD PDF.

    6

    PDF per E-Mail + Archiv

    Rechnung an Kunden versenden und GoBD-konform archivieren (S3, DATEV, Google Drive).

    Shopify Webhook Handler (Node.js)

    // shopify-webhook.js
    const express = require('express')
    const crypto = require('crypto')
    const fetch = require('node-fetch')
    
    const app = express()
    
    app.post('/webhook/shopify/orders-paid', express.raw({ type: 'application/json' }), async (req, res) => {
      // HMAC-Validierung
      const hmac = req.headers['x-shopify-hmac-sha256']
      const hash = crypto.createHmac('sha256', process.env.SHOPIFY_WEBHOOK_SECRET)
        .update(req.body).digest('base64')
      if (hash !== hmac) return res.status(401).send('Unauthorized')
    
      const order = JSON.parse(req.body)
    
      // Nur B2B-Bestellungen (mit USt-ID) als E-Rechnung
      const vatId = order.billing_address?.company &&
        order.note_attributes?.find(a => a.name === 'vat_id')?.value
      if (!vatId) {
        console.log('B2C-Bestellung, keine E-Rechnung noetig:', order.name)
        return res.json({ received: true })
      }
    
      const lineItems = order.line_items.map((item, i) => {
        const netPrice = (item.price * (1 - (item.discount_allocations[0]?.amount || 0) / item.price / 100))
        return {
          invoiceLineIdentifier: String(i + 1),
          invoiceLineNetAmount: (netPrice * item.quantity).toFixed(2),
          itemName: item.name,
          invoicedQuantity: String(item.quantity),
          invoicedQuantityUnitOfMeasureCode: 'C62',
          itemNetPrice: netPrice.toFixed(2),
          invoiceLineVatInformation: { invoiceLineVatCategoryCode: 'S', invoiceLineVatRate: 19 }
        }
      })
    
      const netTotal = lineItems.reduce((s, l) => s + parseFloat(l.invoiceLineNetAmount), 0)
    
      const response = await fetch('https://api.rechnungsapi.de/api/v1/zugferd/createZugferdFromJson', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${process.env.RECHNUNGSAPI_TOKEN}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          invoice: {
            invoiceNumber: order.name.replace('#', 'INV-'),
            invoiceIssueDate: new Date().toISOString().split('T')[0],
            invoiceTypeCode: '380',
            invoiceCurrencyCode: 'EUR',
            seller: {
              sellerName: 'Ihr Shop GmbH',
              sellerVatIdentifier: 'DE123456789',
              sellerElectronicAddress: 'rechnungen@ihrshop.de',
              sellerPostalAddress: {
                sellerAddressLine1: 'Shopstrasse 1',
                sellerCity: 'Hamburg',
                sellerPostCode: '20095',
                sellerCountryCode: 'DE'
              }
            },
            buyer: {
              buyerName: order.billing_address.company || order.billing_address.name,
              buyerVatIdentifier: vatId,
              buyerElectronicAddress: order.email,
              buyerPostalAddress: {
                buyerAddressLine1: order.billing_address.address1,
                buyerCity: order.billing_address.city,
                buyerPostCode: order.billing_address.zip,
                buyerCountryCode: order.billing_address.country_code
              }
            },
            invoiceLine: lineItems,
            documentTotals: {
              sumOfInvoiceLineNetAmount: netTotal.toFixed(2),
              invoiceTotalAmountWithoutVat: netTotal.toFixed(2),
              invoiceTotalVatAmount: (netTotal * 0.19).toFixed(2),
              invoiceTotalAmountWithVat: (netTotal * 1.19).toFixed(2),
              amountDueForPayment: (netTotal * 1.19).toFixed(2)
            },
            vatBreakdown: [{
              vatCategoryTaxableAmount: netTotal.toFixed(2),
              vatCategoryTaxAmount: (netTotal * 0.19).toFixed(2),
              vatCategoryCode: 'S',
              vatCategoryRate: 19
            }]
          }
        })
      })
    
      const pdfBuffer = await response.buffer()
      // E-Mail versenden oder in Archiv speichern
      console.log('ZUGFeRD-Rechnung erzeugt fuer:', order.name)
      res.json({ received: true })
    })

    Den Webhook in Shopify einrichten: Admin → Einstellungen → Benachrichtigungen → Webhooks → "Bestellung bezahlt" → URL deines Servers eintragen.

    WooCommerce Integration (PHP)

    Bei WooCommerce greifst du direkt auf den woocommerce_payment_complete Hook zu. Der Code läuft serverseitig in der functions.php deines Themes oder in einem Custom Plugin — kein separater Server nötig.

    <?php
    // functions.php - WooCommerce Hook nach Zahlung
    add_action('woocommerce_payment_complete', 'generate_e_rechnung', 10, 1);
    
    function generate_e_rechnung($order_id) {
        $order = wc_get_order($order_id);
    
        // Nur B2B (mit USt-ID)
        $vat_id = get_post_meta($order_id, '_billing_vat_id', true);
        if (empty($vat_id)) return;
    
        $line_items = [];
        foreach ($order->get_items() as $i => $item) {
            $net_price = $item->get_subtotal() / $item->get_quantity();
            $line_items[] = [
                'invoiceLineIdentifier' => (string)($i + 1),
                'invoiceLineNetAmount' => number_format($item->get_subtotal(), 2, '.', ''),
                'itemName' => $item->get_name(),
                'invoicedQuantity' => (string)$item->get_quantity(),
                'invoicedQuantityUnitOfMeasureCode' => 'C62',
                'itemNetPrice' => number_format($net_price, 2, '.', ''),
                'invoiceLineVatInformation' => [
                    'invoiceLineVatCategoryCode' => 'S',
                    'invoiceLineVatRate' => 19
                ]
            ];
        }
    
        $net_total = $order->get_subtotal();
        $payload = [
            'invoice' => [
                'invoiceNumber' => 'INV-' . $order->get_order_number(),
                'invoiceIssueDate' => date('Y-m-d'),
                'invoiceTypeCode' => '380',
                'invoiceCurrencyCode' => 'EUR',
                'seller' => [
                    'sellerName' => get_bloginfo('name'),
                    'sellerVatIdentifier' => get_option('woocommerce_vat_id'),
                    'sellerElectronicAddress' => get_option('woocommerce_email'),
                    'sellerPostalAddress' => [
                        'sellerAddressLine1' => get_option('woocommerce_store_address'),
                        'sellerCity' => get_option('woocommerce_store_city'),
                        'sellerPostCode' => get_option('woocommerce_store_postcode'),
                        'sellerCountryCode' => 'DE'
                    ]
                ],
                'buyer' => [
                    'buyerName' => $order->get_billing_company() ?: $order->get_formatted_billing_full_name(),
                    'buyerVatIdentifier' => $vat_id,
                    'buyerElectronicAddress' => $order->get_billing_email(),
                    'buyerPostalAddress' => [
                        'buyerAddressLine1' => $order->get_billing_address_1(),
                        'buyerCity' => $order->get_billing_city(),
                        'buyerPostCode' => $order->get_billing_postcode(),
                        'buyerCountryCode' => $order->get_billing_country()
                    ]
                ],
                'invoiceLine' => $line_items,
                'documentTotals' => [
                    'sumOfInvoiceLineNetAmount' => number_format($net_total, 2, '.', ''),
                    'invoiceTotalAmountWithoutVat' => number_format($net_total, 2, '.', ''),
                    'invoiceTotalVatAmount' => number_format($net_total * 0.19, 2, '.', ''),
                    'invoiceTotalAmountWithVat' => number_format($net_total * 1.19, 2, '.', ''),
                    'amountDueForPayment' => number_format($net_total * 1.19, 2, '.', '')
                ],
                'vatBreakdown' => [[
                    'vatCategoryTaxableAmount' => number_format($net_total, 2, '.', ''),
                    'vatCategoryTaxAmount' => number_format($net_total * 0.19, 2, '.', ''),
                    'vatCategoryCode' => 'S',
                    'vatCategoryRate' => 19
                ]]
            ]
        ];
    
        $response = wp_remote_post('https://api.rechnungsapi.de/api/v1/zugferd/createZugferdFromJson', [
            'headers' => [
                'Authorization' => 'Bearer ' . get_option('rechnungsapi_token'),
                'Content-Type' => 'application/json'
            ],
            'body' => json_encode($payload),
            'timeout' => 30
        ]);
    
        if (!is_wp_error($response)) {
            $pdf = wp_remote_retrieve_body($response);
            $upload_dir = wp_upload_dir();
            file_put_contents($upload_dir['path'] . '/rechnung-' . $order_id . '.pdf', $pdf);
        }
    }

    Die USt-ID musst du im WooCommerce Checkout als Custom Field erfassen. Mit Germanized Pro oder dem WooCommerce EU VAT Plugin wird _billing_vat_id automatisch als Order Meta gespeichert.

    Alternative: n8n oder Make.com — kein eigener Server nötig

    Wer keinen eigenen Server betreiben möchte, kann n8n oder Make.com als Middleware einsetzen. Die Daten fließen dann per Webhook direkt vom Shop in das No-Code-Tool und von dort an rechnungsapi.de. Du willst dich nicht selbst darum kümmern? Wir richten den n8n-Workflow für dich ein — oder übernehmen die individuelle Implementierung komplett. Sprich uns einfach an.

    1

    Shopify Webhook

    orders/paid Webhook triggert n8n HTTP Trigger Node in Echtzeit.

    2

    n8n verarbeitet

    Daten werden gemappt, B2B-Erkennung per IF-Node, JSON-Payload zusammengebaut.

    3

    rechnungsapi.de

    HTTP Request Node POST → ZUGFeRD PDF zurück → E-Mail oder Archiv.

    Dauert ca. 30 Minuten, kein Code nötig. Die vollständige Anleitung für n8n, Make.com und Zapier findest du im Artikel XRechnung & ZUGFeRD per n8n, Make oder Zapier automatisieren.

    Häufige Fehler — und wie ihr sie vermeidet

    B2B-Erkennung fehlt

    Problem: Nicht alle Bestellungen brauchen eine E-Rechnung — nur B2B-Kunden. Ohne Prüfung werden auch Privatkunden als B2B behandelt.

    Lösung: USt-ID als Pflichtfeld für Firmenkunden im Checkout einrichten. Der Webhook prüft dann nur Bestellungen mit vorhandener USt-ID.

    Falsches ZUGFeRD-Profil

    Problem: Germanized Pro erzeugt ZUGFeRD Basic-WL. Dieses Profil ist ab 2027 NICHT als E-Rechnung im Sinne des §14 UStG anerkannt — trotz "ZUGFeRD"-Label.

    Lösung: rechnungsapi.de erzeugt immer ZUGFeRD COMFORT/EN 16931 — das einzige Profil, das die gesetzlichen Anforderungen erfüllt.

    Kein Archiv

    Problem: E-Rechnungen müssen 10 Jahre GoBD-konform aufbewahrt werden. Ein einfaches Verzeichnis auf dem Server genügt nicht.

    Lösung: PDF direkt nach Erzeugung in S3, Google Drive oder DATEV Unternehmen Online speichern — unveränderbar und revisionssicher.

    Häufige Fragen

    Muss ich alle Shopify-Bestellungen als E-Rechnung versenden?

    +

    Nein. Die E-Rechnungspflicht gilt nur für B2B-Transaktionen zwischen deutschen Unternehmen. Bestellungen von Privatpersonen (B2C) sind ausgenommen. Erkennungsmerkmal: Hat die Bestellung eine USt-ID hinterlegt? Dann ist es B2B.

    Funktioniert das mit Shopify Plus?

    +

    Ja. Webhooks sind auf allen Shopify-Plänen verfügbar — Basic, Shopify, Advanced und Plus. Der orders/paid Webhook ist auf jedem Plan nutzbar. Shopify Plus bietet zusätzlich erweiterte Webhook-Verwaltung über die Admin API.

    Was kostet die rechnungsapi.de API?

    +

    Die API ist nutzungsbasiert abgerechnet. Es gibt einen kostenlosen Test-Account ohne Kreditkarte. Details und aktuelle Preise findest du unter rechnungsapi.de/pricing.

    Gibt es eine Shopify-App dafür?

    +

    Derzeit gibt es keine native Shopify-App für konforme E-Rechnungen nach EN 16931. Die Webhook-Integration ist schneller einzurichten als eine App-Installation und gibt dir volle Kontrolle über die Rechnungslogik.

    Was ist mit internationalen B2B-Kunden (EU, nicht Deutschland)?

    +

    Die E-Rechnungspflicht gilt aktuell für B2B-Transaktionen zwischen deutschen Unternehmen (inländische Leistungen). Bei EU-Kunden aus anderen Ländern: ZUGFeRD schadet nicht und bereitet auf kommende EU-weite Pflichten (ViDA ab 2030) vor, ist aber noch keine gesetzliche Pflicht.

    E-Rechnung-API für deinen Shop kostenlos testen

    Kostenlosen Account anlegen, API-Key holen, Webhook konfigurieren — fertig. Keine Kreditkarte, keine Mindestlaufzeit. Dein Shop erzeugt innerhalb von Minuten konforme ZUGFeRD-Rechnungen für B2B-Bestellungen.

    Kostenlos startenAPI-Dokumentation

    Verwandte Artikel

    Integration

    XRechnung & ZUGFeRD per n8n, Make oder Zapier automatisieren – in 30 Minuten live

    Artikel lesen
    Integration

    Stripe + E-Rechnung: ZUGFeRD und XRechnung automatisch nach Zahlung erzeugen

    Artikel lesen
    Formate & Standards

    XRechnung oder ZUGFeRD? Der ehrliche Vergleich – wann was und warum

    Artikel lesen
    rechnungsapi.de

    Professionelle E-Rechnungs-APIs für KMUs. Transformieren Sie Ihr ERP-System mit ZUGFeRD-konformen Lösungen und DSGVO-konformer KI-Technologie.

    DSGVO-konform & sicher

    Produkt

    • Preise

    Lösungen

    • Steuerberater & Kanzleien
    • Unternehmen & Mittelstand
    • IT-Teams & Softwareanbieter
    • E-Invoicing-Berater & Partner
    • Startups & SaaS
    • International & Peppol

    Rechtliches

    • Impressum
    • Datenschutzerklärung
    • Nutzungsbedingungen
    • Kontakt
    • DSGVO-Konformität

    Server in Deutschland · DSGVO-konform · Auftragsverarbeiter ISO/IEC 27001-zertifiziert (Open Telekom Cloud)

    © 2026 rechnungsapi.de

    support@rechnungsapi.de