Dieses Tutorial zeigt, wie man bei jeder bezahlten Shopify-Bestellung automatisch eine offene Debitoren-Rechnung in CashCTRL erstellen lässt, ganz ohne eigenen Server/VPS, komplett kostenlos gehostet, und auch für absolute Einsteiger ohne Programmiervorkenntnisse nachvollziehbar.
Die Zahlung selbst (z.B. der Zahlungseingang aus der Shopify-Auszahlung) wird bewusst NICHT automatisch verbucht, sondern bleibt wie gewohnt manueller Abgleich – so bleibt die Kontrolle über die Buchhaltung erhalten, während der lästige manuelle Teil (Rechnung erfassen, Kunde anlegen, Positionen eintippen) wegfällt.
Kunde bezahlt im Shopify-Shop
↓ (Webhook)
Kleiner Node.js-Server (kostenlos gehostet auf Render.com)
↓ (API-Aufruf)
CashCTRL: neue offene Debitoren-Rechnung mit Kunde und allen Positionen
Kein eigener VPS nötig, keine laufenden Kosten (solange man beim kostenlosen Render-Tier bleibt), keine Serverwartung.
Wichtiger Hinweis zu Artikeln/Positionen
Der Sync legt keine "echten" Artikel-Stammdaten in CashCTRL an. Jede Rechnungsposition wird als freie Textzeile direkt aus den Shopify-Bestelldaten erzeugt (Name, Menge, Preis, SKU als Text) – genau so, wie wenn man in CashCTRL von Hand eine Position ohne hinterlegten Artikel eintippt. Das funktioniert auch dann, wenn die Produkte in CashCTRL nicht als Artikel gepflegt sind.
Voraussetzungen
- Ein Shopify-Shop mit Adminzugriff
- Ein CashCTRL-Konto mit PRO-Abo (für API-Zugriff nötig, 30 Tage kostenlos testbar)
- Ein kostenloses GitHub-Konto
- Ein kostenloses Render.com-Konto
- Keine Programmiererfahrung nötig, aber etwas Geduld beim ersten Mal mit dem Terminal
Schritt 1: API-User in CashCTRL anlegen
In CashCTRL einloggen.
Settings (Zahnrad oben rechts) → Users & Roles → Add → Add API benutzer.
Den angezeigten API-Key kopieren und sicher aufbewahren.
Schritt 2: Drei IDs aus CashCTRL herausfinden
Man braucht die IDs von: der Rechnungs-Kategorie, dem Ertragskonto und optional dem Steuercode. Diese liest man über einfache API-Aufrufe ab.
Unter Windows (PowerShell) curl.exe verwenden (nicht curl, das ist in PowerShell nur ein Alias für Invoke-WebRequest und funktioniert anders):
curl.exe "https://DEIN_ORG.cashctrl.com/api/v1/order/category/list.json" -u DEIN_API_KEY:
curl.exe "https://DEIN_ORG.cashctrl.com/api/v1/account/list.json" -u DEIN_API_KEY:
curl.exe "https://DEIN_ORG.cashctrl.com/api/v1/tax/list.json" -u DEIN_API_KEY:
DEIN_ORG ist die Sub-Domain deiner Organisation (bei https://firma.cashctrl.com ist es firma). Der Doppelpunkt nach dem API-Key ist wichtig (curl erwartet dort ein leeres Passwort).
In der Antwort auf den ersten Befehl sucht man die Kategorie mit "type": "SALES" und nameSingular gleich "Rechnung"/"Invoice" – deren id ist die CASHCTRL_INVOICE_CATEGORY_ID.
In der Antwort auf den zweiten Befehl sucht man ein Konto mit "accountClass": "REVENUE", das für Verkäufe genutzt werden soll – deren id ist die CASHCTRL_REVENUE_ACCOUNT_ID. Falls dieses Konto schon eine taxId hinterlegt hat, kann man diese direkt für CASHCTRL_TAX_ID übernehmen, ohne den dritten Befehl separat auszuwerten.
-> Die Beispiel Datei ist ebenfalls als DOWNLOAD verfügbar.
Schritt 3: Shopify Custom App erstellen
Shopify-Adminbereich → Einstellungen → Apps und Vertriebskanäle → App-Entwicklung.
"App erstellen" → Namen vergeben (z.B. "CashCTRL Sync").
Bei der Konfiguration/Version: App-URL kann als Platzhalter https://example.com bleiben, Häkchen "App in den Shopify-Adminbereich einbetten" kann entfernt werden.
Bei "API-Zugriff" → "Bereiche": read_orders eintragen.
Version veröffentlichen.
App installieren (Button auf der App-Übersichtsseite).
Wichtiger Punkt, der leicht zu Verwirrung führt: Für den eigentlichen Webhook wird NICHT der API-Secret-Key dieser Custom App gebraucht. Stattdessen registriert man den Webhook direkt über die normale Shopify-Benachrichtigungsseite (siehe Schritt 7) – dort zeigt Shopify einen eigenen, account-weiten Signatur-Schlüssel an, der ins Projekt eingetragen wird. Die Custom App wird in diesem einfachen Setup nur für die Berechtigungsstruktur gebraucht, nicht für einen aktiven API-Aufruf.
Schritt 4: Projektcode
Ordnerstruktur:
shopify-cashctrl-sync/
├── lib/
│ ├── cashctrl.js
│ ├── mapping.js
│ └── shopify.js
├── .env.example
├── package.json
├── README.md
└── server.js
Könnt ihr alles hier herunterladen: HIER
Schritt 5: Code auf GitHub hochladen
Auf github.com registrieren/einloggen.
Neues Repository erstellen, Sichtbarkeit "Private".
Über "uploading an existing file" alle Dateien hochladen (inkl. lib-Ordner und .env.example).
Wichtig: die tatsächliche .env-Datei mit den echten Zugangsdaten NIEMALS mit hochladen – nur lokal behalten.
"Commit changes" klicken.
Schritt 6: Auf Render.com deployen
Auf render.com registrieren (am einfachsten "Sign up with GitHub").
"New" → "Web Service" → das eigene Repository auswählen/verbinden.
Einstellungen:
Region: möglichst nah am eigenen Standort (z.B. Frankfurt für die Schweiz)
Branch: main
Build Command: npm install
Start Command: npm start (oder node server.js)
Instance Type: "Free"
Bei "Environment Variables" auf "Add from .env" klicken und den kompletten Inhalt der lokalen .env-Datei einfügen – Render übernimmt automatisch alle Variablen einzeln.
"Deploy Web Service" klicken.
Nach ein bis zwei Minuten zeigt Render den Status "Live" und eine öffentliche URL wie:
https://dein-projektname.onrender.com.
Schritt 7: Webhook in Shopify registrieren
Shopify-Adminbereich → Einstellungen → Benachrichtigungen.
Ganz nach unten scrollen zu "Webhooks" → "Webhook erstellen".
Ereignis: "Bestellungszahlung" (orders/paid)
Format: JSON
URL: https://dein-projektname.onrender.com/webhooks/shopify/orders-paid
Webhook-API-Version: die neueste stabile Version wählen (nicht "unstable")
Speichern.
Nach dem Speichern zeigt Shopify auf derselben Seite einen Signatur-Schlüssel an ("Deine Webhooks werden mit ... signiert"). Diesen Wert in die .env-Datei (lokal) UND bei Render unter "Environment" als SHOPIFY_WEBHOOK_SECRET eintragen. Nach dem Speichern bei Render deployt der Service automatisch neu.
Schritt 8: Testen
Man muss nicht auf eine echte Bestellung warten:
In Shopify beim eigenen Webhook-Eintrag auf "..." klicken → "Senden" (Testversand).
Im Render-Dashboard unter "Logs" nachsehen, ob eine Zeile erscheint wie:
Bestellung #9999 -> CashCTRL-Rechnung erstellt (ID ..., offen).
In CashCTRL unter Bestellungen die neue, offene Rechnung kontrollieren (Kunde, Positionen, Steuersatz, Betrag).
Häufige Stolpersteine
"curl: -u nicht erkannt" in PowerShell
curl ist in PowerShell nur ein Alias für Invoke-WebRequest, das den Parameter -u nicht kennt. Lösung: curl.exe statt curl verwenden.
"fetch failed" im Render-Log
Meist ein falscher Wert bei CASHCTRL_ORG. Dort darf NUR der reine Sub-Domain-Name stehen (z.B. firma), nicht die volle URL mit https:// und .cashctrl.com.
Webhook kommt nicht an / "Invalid signature"
Meist ein falscher Wert bei SHOPIFY_WEBHOOK_SECRET. Wichtig: Der Signatur-Schlüssel, der auf der Shopify-Benachrichtigungsseite direkt bei den Webhooks angezeigt wird ("signiert mit ..."), ist nicht dasselbe wie der API-Secret-Key der Custom App.
Render-Service reagiert manchmal verzögert
Der kostenlose Render-Plan schläft nach ca. 15 Minuten Inaktivität ein und braucht beim Aufwecken 30-60 Sekunden. Shopify liefert Webhooks bei Verzögerung automatisch erneut aus (Retry-Logik), daher geht dabei nichts verloren – nur etwas später. Bei Bedarf lässt sich auf einen kostenpflichtigen Render-Plan wechseln, der durchgehend läuft.
Hoffe, konnte damit unterstützen. Bei Fragen, einfach fragen.