bexio API aus Make und Zapier: was die fertigen Module nicht können

Make und Zapier bieten bexio als fertige App an: ein paar Felder ausfüllen, und die Rechnung steht in der Buchhaltung. In den Community-Foren beider Dienste stehen seit 2023 aber Fragen zu bexio, die ohne Lösung blieben, weil dem Modul ein Feld oder ein Endpunkt fehlt. Ich habe diese Fäden durchgesehen und mit der offiziellen bexio-API-Dokumentation verglichen. Dieser Ratgeber zeigt je Fall, woran es im Forum scheiterte und welches Feld der bexio API den Fall löst. Er beschreibt die Module so, wie die Fragenden sie beschreiben; eigene Erfahrung mit Make oder Zapier steckt nicht darin.

Ablauf: Shop, Formular oder Zahlungsanbieter liefern die Daten, ein eigener Dienst spricht die bexio API mit allen Feldern an, api.bexio.com legt Rechnung, Offerte oder Zeiteintrag anShop, Formular,ZahlungsanbieterBestellung, Anfrageoder ZahlungEigener DienstAlle Felder der API,Fehler werdenwiederholtapi.bexio.comRechnung mitPositionen, Offerte,Zeiteintrag, PDFAblauf: Shop, Formular oder Zahlungsanbieter liefern die Daten, ein eigener Dienst spricht die bexio API mit allen Feldern an, api.bexio.com legt Rechnung, Offerte oder Zeiteintrag anShop, Formular, ZahlungsanbieterBestellung, Anfrage oder ZahlungEigener DienstAlle Felder der API, Fehler werdenwiederholtapi.bexio.comRechnung mit Positionen, Offerte,Zeiteintrag, PDF

Woher die acht Fälle stammen

Die Fälle kommen aus den öffentlichen Foren community.make.com und community.zapier.com, Fragen von 2023 bis 2025. Jeder Fall ist unten verlinkt. «Ohne Lösung» heisst: Im Faden steht keine Antwort, die der Fragende bestätigt hat, oder die Antwort verweist an den Support. Mehrere Fragende melden dasselbe Muster, teils mit Monaten Abstand. Die Lösung über die API ist jeweils an der Dokumentation belegt; die Pfade stehen so in der Referenz.

Fall 1: Mehrere Positionen in einer Rechnung

Das häufigste Problem. Ein Fragender will in Make mehrere Positionen in eine bexio-Rechnung schreiben; das Modul lehnt die Liste ab, und «Update Invoice» bietet gar keine Position an. In Zapier scheitert dasselbe bei einer Shopify-Bestellung mit mehreren Produkten, bei einer WooCommerce-Bestellung über einen Umweg mit Schleife und Zwischenspeicher, und bei einer Payrexx-Zahlung mit der Meldung, dass die Liste der Beträge nicht gleich lang sei wie die Liste der Artikel; am Ende steht ein Entwurf ohne Positionen mit Summe 0.

In der API ist das kein Sonderfall. POST /2.0/kb_invoice nimmt ein Array positions entgegen, und die Dokumentation sagt ausdrücklich, dass sich Positionstypen mischen lassen: KbPositionCustom für freie Zeilen, KbPositionArticle für Artikel aus dem Stamm, dazu Text-, Zwischensummen-, Rabatt- und Seitenumbruch-Positionen. Eine Rechnung mit zwei Zeilen sieht so aus:

{
  "contact_id": 14,
  "user_id": 1,
  "mwst_type": 0,
  "mwst_is_net": true,
  "positions": [
    { "type": "KbPositionArticle", "article_id": 3, "amount": "2", "unit_price": "45.00", "tax_id": 4 },
    { "type": "KbPositionCustom", "text": "Versand", "amount": "1", "unit_price": "9.00", "tax_id": 4 }
  ]
}

bexio empfiehlt höchstens 150 Positionen beim Anlegen; weitere Zeilen hängt man danach mit POST /2.0/kb_invoice/{document_id}/kb_position_article oder …/kb_position_custom an. Versand und Rabatt sind damit gewöhnliche Zeilen, kein Sonderweg.

Fall 2: Dokumentnummer bei Offerten

Ein Zapier-Nutzer kann keine Offerte anlegen: bexio verlangt document_nr, die Aktion hat kein Feld dafür; ein zweiter Betroffener meldet sich im selben Faden. Ein anderer findet eine Offerte über ihre Nummer nicht, obwohl dieselbe Nummer in einem anderen Werkzeug Treffer liefert.

Die Dokumentation zu POST /2.0/kb_offer erklärt die Regel: document_nr darf nicht gesetzt werden, wenn in bexio die automatische Nummerierung aktiv ist, und ist Pflicht, wenn sie abgeschaltet ist. Ein Modul ohne dieses Feld funktioniert also nur bei automatischer Nummerierung. Wer eigene Nummern führt, setzt sie über die API. Die Suche läuft über POST /2.0/kb_offer/search mit document_nr als Suchfeld:

[{ "field": "document_nr", "value": "AN-00001", "criteria": "=" }]

Ohne criteria sucht bexio mit «like», also nach Teiltreffern; für eine Nummer ist = der sichere Weg. Dieselben Suchfelder gibt es für Rechnungen unter POST /2.0/kb_invoice/search.

Fall 3: Steuersatz je Position

Eine Rechnung kommt mit 7.7 % statt 8.1 % in bexio an, und der Steuersatz lässt sich im Modul nicht wählen. Zapier bestätigt im Faden einen Fehlerbericht; der Workaround lautet, den Satz am Produkt in bexio zu hinterlegen.

In der API trägt jede Position ihr Feld tax_id. Die gültigen Werte liefert GET /3.0/taxes?types=sales_tax&scope=active; genau diesen Aufruf empfiehlt die Dokumentation, weil auf Offerten, Aufträgen und Rechnungen nur aktive Umsatzsteuern zulässig sind. Die Antwort nennt je Satz id, code, value und die Jahre, in denen er gilt. Ein Dienst liest diese Liste einmal und wählt die tax_id nach Prozentsatz, statt eine Nummer fest einzubauen, die beim nächsten Satzwechsel falsch wird.

Fall 4: Referenz für den Zahlungsabgleich

Ein Fragender legt Rechnungen aus einem Google Sheet an und will die 27-stellige Referenznummer in das Referenzfeld schreiben, damit bexio Zahlungen von der Bank automatisch zuordnet. Zapier legt einen Funktionswunsch an; ein Termin wird nicht genannt.

Die Rechnung in der API hat zwei Referenzfelder. reference ist ein Freitext auf dem Dokument. api_reference ist laut Dokumentation nur über die API lesbar und änderbar und dafür gedacht, Verweise auf andere Systeme abzulegen, etwa die Bestellnummer des Shops oder die Zahlungs-ID des Anbieters; es ist auch ein Suchfeld von POST /2.0/kb_invoice/search. Die Antwort einer Rechnung enthält zudem qr_invoice_id. Ein Feld, über das man die Referenz des QR-Zahlteils selbst setzt, beschreibt die Dokumentation nicht.

Wer die Zahlung ohnehin von einem Zahlungsanbieter gemeldet bekommt, braucht den Bankabgleich dafür nicht: POST /2.0/kb_invoice/{invoice_id}/payment bucht die Zahlung mit date, value und bank_account_id direkt auf die Rechnung. Die Zahlung steht dann in bexio auf der Rechnung, und niemand mahnt Kunden, die längst bezahlt haben.

Fall 5: Benutzer bei der Zeiterfassung

Zeiteinträge aus einem Google Sheet sollen in bexio dem richtigen Mitarbeiter gehören. Im Zapier-Modul lässt sich die Benutzer-ID nicht setzen; das Feld wird mit einem Kontakt gefüllt, der Fragende findet keinen Weg.

POST /2.0/timesheet verlangt user_id als Pflichtfeld, dazu client_service_id für die Leistung, allowable_bill für «verrechenbar» und ein Objekt tracking, entweder als Dauer (type: duration mit date und duration) oder als Zeitspanne (type: range). Die Benutzer liefert GET /3.0/users, die Leistungen GET /2.0/client_service. Kontakt und Projekt sind optional (contact_id, pr_project_id). Ein Eintrag von einer Stunde und vierzig Minuten:

{
  "user_id": 1,
  "client_service_id": 1,
  "allowable_bill": true,
  "contact_id": 2,
  "tracking": { "type": "duration", "date": "2026-11-04", "duration": "01:40" }
}

Fall 6: PDF einer Offerte

Ein Make-Nutzer will Offerten als PDF in DocuWare ablegen. Für Rechnungen gibt es ein Modul, für Offerten nicht; der Versuch mit einem HTTP-Aufruf liefert ein PDF, das sich nicht öffnen lässt. Die einzige Antwort verweist auf HTTP-Grundlagen.

GET /2.0/kb_offer/{quote_id}/pdf liefert das Dokument, wahlweise mit oder ohne Briefpapier (logopaper). Der Punkt, an dem der Fragende scheiterte: Die Antwort ist kein PDF, sondern JSON mit den Feldern name, size, mime und content, und content enthält die Datei Base64-kodiert. Erst nach dem Dekodieren liegt eine gültige PDF-Datei vor. Dasselbe gilt für Rechnungen (/2.0/kb_invoice/{invoice_id}/pdf) und Aufträge (/2.0/kb_order/{order_id}/pdf).

Fall 7: Geänderte Rechnungen erkennen

Der Make-Trigger «Watch Invoices» liefert nach Angabe eines Fragenden keine Datensätze, wenn eine Rechnung nur geändert wird. Ein Antwortender vermutet einen Fehler im Modul, ein zweiter schlägt vor, stattdessen zu suchen.

Die API bietet dafür das Suchfeld updated_at mit Vergleichskriterien. Ein Dienst merkt sich den Zeitstempel seines letzten Laufs und fragt:

[{ "field": "updated_at", "value": "2026-11-04 06:00:00", "criteria": ">" }]

an POST /2.0/kb_invoice/search?order_by=updated_at_desc. Das Zeitformat entspricht dem, das bexio in updated_at zurückgibt. So erscheinen neue und geänderte Rechnungen gleich, etwa ein Statuswechsel auf «bezahlt».

Fall 8: Rechnung aus einer Bestellung

Eine Shopify-Bestellung wird in Make zur bexio-Bestellung; die Rechnung daraus soll ein HTTP-Aufruf erzeugen, weil es kein Modul dafür gibt. Der Aufruf scheitert mit Status 415, während derselbe Aufruf in Postman funktioniert. Der Make-Support bestätigt im Faden ein bekanntes Problem («known issue») und gibt es an die Entwicklung weiter, ohne Termin.

Der Endpunkt ist POST /2.0/kb_order/{order_id}/invoice. Der Body ist optional: Fehlt er, übernimmt bexio alle Positionen der Bestellung; sonst nennt positions die gewünschten Zeilen mit id, type und amount. Status 415 bedeutet, dass der Server den Inhaltstyp der Anfrage nicht annimmt; die Dokumentation verlangt Accept: application/json und JSON als Body. Ein eigener Dienst setzt die Header selbst und ist nicht davon abhängig, wie ein Zwischendienst sie weitergibt.

Die acht Fälle im Überblick

FallIm ForumIn der bexio API
Mehrere PositionenListe wird abgelehnt, Entwurf mit Summe 0positions in POST /2.0/kb_invoice, gemischte Typen
DokumentnummerPflichtfeld fehlt, Suche ohne Trefferdocument_nr, Suche mit criteria: "="
Steuersatznicht wählbar, falscher Satztax_id je Position, Liste aus /3.0/taxes
ReferenzFeld fehlt, Funktionswunsch offenreference, api_reference, Zahlung per …/payment
ZeiterfassungBenutzer nicht setzbaruser_id in POST /2.0/timesheet
Offerten-PDFkein Modul, Datei unlesbar/2.0/kb_offer/{id}/pdf, content Base64 dekodieren
Geänderte RechnungenTrigger reagiert nichtSuche nach updated_at mit >
Rechnung aus Bestellungkein Modul, Status 415POST /2.0/kb_order/{id}/invoice

Dazu kommt ein Risiko, das keinem Feld zuzuordnen ist: Ein Zapier-Nutzer meldet, dass bexio die Client-ID der Zapier-App gesperrt hat und seine Verbindung damit stand. Wer über eine fremde App verbindet, hängt an deren Zulassung; eine eigene App im Developer Portal hängt nur an der eigenen. Wie man sie anlegt, steht im Ratgeber bexio API Token erstellen, die Anmeldung per OAuth 2 im Ratgeber bexio API mit WordPress verbinden.

Wann sich die direkte Anbindung lohnt

Für einen Kontakt aus einem Formular reichen die fertigen Module meist. Sobald Rechnungen mit mehreren Zeilen, eigene Nummern, Steuersätze, Zeiteinträge je Mitarbeiter oder PDFs im Spiel sind, kostet der Umweg über die Zwischenplattform mehr Zeit, als er spart: Jedes fehlende Feld wird zu einem Forenfaden ohne Ende.

Eine Schnittstelle, die direkt mit der bexio API spricht, baue ich zum Festpreis: Sie nennen mir Quellsystem und Ablauf, ich lege den Umfang an Ihren echten Belegen fest, die Anbindung läuft auf eigener Infrastruktur ohne Abo bei einem Dritten, mit Wiederholung bei Fehlern und einem Protokoll, das zeigt, was übertragen wurde. Für HubSpot gibt es die Anbindung fertig: bexio ↔ HubSpot macht aus einem gewonnenen Deal eine Offerte oder Rechnung mit Positionen und meldet den Zahlungsstand zurück. Für alles andere: Kontakt, mit Quellsystem und dem, was heute von Hand läuft.

Alle Ratgeber