maesn
Für Entwickler

BuchhaltungsButler anbinden: Vier Ratenbegrenzungen auf 48 POST-Pfaden

BuchhaltungsButler hat eine kleine Oberfläche und einen ungewöhnlichen Zuschnitt: 48 Operationen, jede davon ein POST, und die Bedeutung trägt der Pfad statt der Methode. Nichts davon begrenzt Ihren Bau. Vier veröffentlichte Grenzen tun das, drei davon liegen auf den Schreibpfaden, für die es dieses Produkt gibt, und nichts hier sendet ein Event, das Ihnen die Aufrufe erspart.

Lennart Svensson, CTO und Mitgründer bei Maesn
Lennart Svensson
CTO und Mitgründer · · Aktualisiert
Illustration zu BuchhaltungsButler anbinden: Jeden Aufruf einplanen
Der Kontext

Zwei Werte authentifizieren Sie, der dritte wählt den Kunden

Für die Anbindung braucht es drei Werte aus dem Konto Ihres Kunden: einen API Client, ein API Secret und einen API Key. Fast jede Beschreibung dieses Systems, unsere eingeschlossen, nennt sie drei Zugangsdaten und geht weiter. Die Referenz gruppiert sie anders, und der Unterschied entscheidet, wie Ihr Code für viele Konten geschnitten ist.

Unter der Überschrift Authentication wird die Referenz bei zweien davon konkret: „Die Authentifizierung erfolgt über HTTP Basic Auth nach RFC 2617. Das ist so umzusetzen, dass daraus der Request-Header ‚Authorization‘ entsteht, der den folgenden Wert enthält: ‚<Api Client>:<Api Secret>‘.“ Das ist das Paar aus Zugangsdaten, und es reist bei jeder Anfrage im Header mit.

Der dritte Wert bekommt eine eigene Überschrift, Customer Selection, und eine andere Aufgabe: „Um die API-Methoden zu nutzen, müssen Sie das BB-Kundenkonto angeben, das Sie verwalten wollen. Das geschieht über das Formularfeld ‚api_key‘, das den API-Schlüssel des Zielkunden enthält.“

Der API Key wählt das Konto aus. Er benennt, wessen Bücher Sie anfassen, und er reist im Rumpf der Anfrage mit, als Formularfeld.

Für ein Skript, das ein einziges Kundenkonto bedient, ist diese Unterscheidung Nebensache. Für ein Produkt mit tausend angebundenen Unternehmen entscheidet sie den Zuschnitt Ihres Codes: Die Auswahl gehört zur Nutzlast statt zu den Zugangsdaten im Header und muss bei jeder einzelnen Anfrage stimmen. Wer sie falsch setzt, bekommt keine 401, sondern die Bücher eines anderen.

Die zwei Ebenen in einer AnfrageHTTP
POST /api/v1/receipts/get HTTP/1.1
Host: app.buchhaltungsbutler.de
Authorization: Basic BASE64(api_client:api_secret)
Content-Type: application/json
 
{ "api_key": "<the customer's key>" }

Der Header trägt das Paar aus Zugangsdaten, der Rumpf die Auswahl. Der api_key benennt das Kundenkonto und wechselt bei jeder Anfrage, die ein anderes bedient.

Beide Zitate aus der veröffentlichten Referenz von BuchhaltungsButler, Abschnitte Authentication und Customer Selection, geprüft am 19. August 2026. Die Referenz sagt auch, woher der Wert kommt: Der API-Schlüssel „ist in den Firmendaten-Einstellungen des Kunden zu finden, wenn der Kunde sich für den API-Zugang registriert hat“.

Es gibt hier keine OAuth-Weiterleitung, also auch keine gehostete Seite, auf die Sie jemanden schicken. Ihr Kunde schaltet den Zugang in seinen eigenen Einstellungen frei, alle drei Werte erscheinen gemeinsam, und sie lassen sich aus Ihrer eigenen Oberfläche heraus übergeben.

Unified Authentication verhindert, dass daraus ein Zweig je System wird: Eine Weiterleitung beim nächsten System und ein Datenbankzugang beim übernächsten kommen am selben Account-Key an, und Ihr Code sieht immer nur den Schlüssel.

Der eine Schritt, den Sie Ihrem Kunden nicht abnehmen können
Solange niemand im eigenen Konto auf API-Zugang aktivieren klickt, gibt es nichts anzubinden und keine Werte zu kopieren. Das gehört als Anweisung in Ihren Onboarding-Schritt.
Das Problem

Jede der 48 Operationen ist ein POST

Aus der veröffentlichten Referenz gezählt: 48 verschiedene Operationen, und alle 48 sind POST. Darunter die zwölf, deren Pfad ein get-Segment trägt, die zwei, die löschen, und die vier, die aktualisieren. Was der Aufruf tut, steht im Pfad.

Es liegt nahe, das unter Kosmetik abzulegen, und es wäre ein Fehler. Ein gewöhnlicher HTTP-Client leitet drei Dinge aus der Methode ab, ohne dass man es ihm sagt: ob ein Aufruf gefahrlos zu wiederholen ist, ob eine Antwort zwischengespeichert werden darf und ob eine fehlgeschlagene Anfrage blind erneut gesendet werden kann.

Auf einer Schnittstelle, auf der Lesen und Löschen beide POST sind, trägt keine dieser Ableitungen, und jede davon ist hier je Pfad zu entscheiden.

Was Ihr Client erwartet48 von 48 sind POST
GET /receipts
POST /receipts/get

Zwölf der 48 Pfade tragen ein get-Segment, und jeder davon wird mit einem POST erreicht.

DELETE /receipts/:id
POST /receipts/delete/id_by_customer

Zwei Pfade löschen. Beide sind POST, und beide markieren den Beleg, ohne ihn zu entfernen.

PATCH /debtors/:id
POST /settings/update/debtor

Vier Pfade aktualisieren, alle POST, und die Geschäftspartner liegen hinter den Einstellungen.

Die Methode hört auf, ein Signal zu sein. Sicherheit, Zwischenspeicherung und Wiederholbarkeit lassen sich hier nicht an der Methode ablesen, sie sind also je Pfad zu entscheiden statt je Anfrage.

Links, was ein Client erwartet, rechts, was die Referenz veröffentlicht. Gezählt am 13. August 2026.

Auch die Operationen verteilen sich ungleich, und die Verteilung sagt, wofür das Produkt da ist. Zwei Tags tragen je elf Operationen, und eines davon ist die Einstellungsoberfläche, auf der die Geschäftspartner liegen.

Die 48 Operationen nach Tag, so wie die Referenz sie gruppiert
TagOpsWas es abdeckt
Postings11Anlegen, Stapel, Freigabe zurücknehmen
Settings11Debitoren, Kreditoren, Konten
Receipts8Hochladen, zuordnen, löschen, wiederherstellen
Transactions8Lesen und Belegen zuordnen
Cost locations4Der einzige vollständige Umlauf
Invoices3Anlegen, Entwurf, E-Rechnung
Accounts2Lesen und anlegen
Comments1Anlegen

Tags und Anzahlen aus der Operationsliste in der Herstellerreferenz, geprüft am 19. August 2026. Cost locations ist das einzige Tag, das add, get, update und delete zusammen trägt.

Das Problem

Vier Grenzen, und die engsten liegen auf den Schreibpfaden

Das ist der Teil, der Ihre Architektur entscheidet, und es ist der Teil, den weder unsere eigene Systemseite noch der Artikel nennt, den sie ersetzt. Die Referenz veröffentlicht eine Obergrenze in einem Satz: „Es ist nur erlaubt, maximal 100 Anfragen je Kunde und Minute an die API zu stellen.“ Die Obergrenze gilt je Kunde, und das ist die gute Nachricht: Ihr hundertstes Kundenkonto bremst Ihr erstes nicht.

Die anderen drei sind leichter zu übersehen, weil sie gar nicht im Abschnitt zu den Grenzen stehen. Sie liegen als Implementierungshinweise an einzelnen Operationen, und über die Referenz gezählt sind es genau drei von 48: /receipts/upload trägt „Hinweis: maximal 10 Anfragen pro Minute“, während /receipts/addBatch und /transactions/addBatch je „Hinweis: eine Anfrage ist nur alle 5 Sekunden erlaubt“ tragen.

Hält man diese Fakten neben das, was dieses Produkt tut, zeigt sich die Form der Einschränkung. BuchhaltungsButler gibt es, um Belege aufzunehmen und daraus Buchungen zu machen, und jede Operation, die in Menge schreibt, ist unterhalb der globalen Obergrenze gedeckelt: der einzelne Upload bei einem Zehntel davon, die zwei Batch-Pfade bei je einer Anfrage alle fünf Sekunden. Die 100 pro Minute sind das Budget für das Lesen, das Schreiben hat ein eigenes und deutlich niedrigeres.

Die Migration des Altbestands eines Kunden ist deshalb nicht durch Ihre Zahl an Workern oder seinen Tarif begrenzt. Sie ist durch zehn Uploads pro Minute begrenzt, oder durch einen Stapel alle fünf Sekunden, wenn Sie diesen Weg gehen, und keine Parallelität bewegt eine der beiden Zahlen.

Ein Kunde, eine MinuteVier eigene Obergrenzen
Jede Operation, je Kunde
100 / Minute
Die Obergrenze, die die Referenz für die Schnittstelle als Ganzes nennt.
Beleg-Upload, pro Minute
10 / Minute
Ein eigener Hinweis an /receipts/upload.
Belege, Batch-Endpunkt
1 / 5 Sekunden
Ein eigener Hinweis an /receipts/addBatch.
Transaktionen, Batch-Endpunkt
1 / 5 Sekunden
Ein eigener Hinweis an /transactions/addBatch.

Der Abruf geht aus demselben Kontingent ab. Kein Objekt hier kündigt seine eigenen Änderungen an, jede Prüfung auf Bewegung ist also eine Anfrage, die Sie ausgeben, und die drei Schreibendpunkte haben dabei je einen eigenen Boden, unter dem Sie bleiben.

Ein Kunde, eine Minute. Die Endpunkt-Obergrenzen sind eigene Grenzen und kein Anteil an der globalen. Alle vier veröffentlicht, geprüft am 19. August 2026.

Globale Obergrenze aus dem Abschnitt zu den API-Grenzen der Herstellerreferenz; die drei Endpunkt-Hinweise aus den Implementierungshinweisen dieser Operationen, geprüft am 19. August 2026. Die Referenz dokumentiert für keine davon einen Statuscode bei Überschreitung, lesen Sie also die Antwort aus.

Planen Sie das Nachladen, bevor Sie es zusagen
Zehn Uploads pro Minute sind 600 pro Stunde. Ein Kunde, der mit zwei Jahren Belegen ankommt, ist ein geplanter Lauf, der in Tagen gemessen wird, und das ist eine Zahl, die Sie beim Onboarding aussprechen, bevor sie in Woche drei auffällt.
Wie es funktioniert

Kunden und Lieferanten sind Debitoren und Kreditoren in den Einstellungen

Es gibt hier kein Kontaktobjekt und kein Kundenobjekt. Die Geschäftspartner existieren als Debitoren und Kreditoren, und sie liegen nicht bei den Belegen, die auf sie verweisen. Alle acht Operationen, die einen Geschäftspartner lesen, anlegen und aktualisieren, liegen hinter einem settings-Pfad.

Das ist eine buchhalterische Sicht statt einer Produktsicht, und sie ist in sich stimmig: In einem System, dessen Aufgabe das Zuordnen von Belegen ist, ist ein Debitor ein Stück Konfiguration, das entscheidet, wo ein Beleg landet. Ihr Produkt hat eine andere Sicht, in der ein Kunde ein eigenständiges Objekt mit Namen und Anschrift ist.

Es ist zugleich der klarste Fall auf diesem System für das Lesen über eine normalisierte Schicht. Das Common Data Model gibt Ihnen Kunden und Lieferanten als Objekte mit denselben Feldern, die Sie auf jedem anderen angebundenen System benutzen, und dass ein Hersteller sie unter den Einstellungen führt und ein anderer unter den Kontakten, hört auf, etwas zu sein, das Ihr Code weiß.

Einen Geschäftspartner anlegen, so wie die Referenz es benenntHTTP
POST /api/v1/settings/add/debtor
POST /api/v1/settings/add/creditor
POST /api/v1/settings/add-batch/debtors
POST /api/v1/settings/update/debtor

Vier der acht Operationen für Geschäftspartner. Die anderen vier lesen sie zurück und aktualisieren Kreditoren, und jede davon behält das Präfix settings.

Pfade aus dem Tag Settings der Herstellerreferenz, geprüft am 19. August 2026. Über maesn lesen sich dieselben Datensätze als Kunden und Lieferanten, und das sind hier die zwei Objekte, die den vollen Umlauf aus Lesen, Anlegen und Aktualisieren machen.

Wie es funktioniert

Ein gelöschter Beleg ist ein Zustand, und ein festgeschriebener Buchungssatz bleibt liegen

Zwei Verhaltensweisen arbeiten hier anders als in einem Dokumentenspeicher. Beide stehen in den Hinweisen zu den Operationen, und beide ändern, was Ihr Code aushalten muss.

Die erste: Löschen löscht nicht. Die Referenz beschreibt die Operation als „einen Beleg für ein angegebenes Kundenkonto als gelöscht markieren“, und es gibt eine passende Operation, um „einen als gelöscht markierten Beleg wiederherzustellen“. Ein entfernter Beleg ist ein Zustand, und alles, was Sie schreiben und das liest, ohne diesen Zustand zu berücksichtigen, sieht ihn weiter.

Die zweite: Buchungen können unbeweglich werden. Alle drei unconfirm-Operationen, für freie Buchungen, Belegbuchungen und Transaktionsbuchungen, tragen denselben Satz: „Das funktioniert nur, wenn die Buchungssätze nicht festgeschrieben sind.“ Ist ein Buchungssatz einmal festgeschrieben, ist der Weg zurück ein neuer Buchungssatz, und das ist gewöhnliches Verhalten in der Buchhaltung und ungewöhnliches Verhalten in einer API.

Es gibt eine dritte Gewohnheit, die eine Planung wert ist, weil sie eine Anfrage kostet. Sechs Operationen identifizieren ihr Ziel über id_by_customer, und die Referenz sagt, woher man sie bekommt: „Die ‚id_by_customer‘ erhalten Sie, indem Sie zuerst die Methode ‚/receipts/get‘ benutzen.“ Ein Löschen sind deshalb zwei Aufrufe, und beide gehen von denselben hundert ab.

Ein Löschen ist erst ein Lesen und dann ein SchreibenHTTP
POST /api/v1/receipts/get
-> id_by_customer
 
POST /api/v1/receipts/delete/id_by_customer
-> als gelöscht markiert, wiederherstellbar

Zwei Anfragen gegen das Kontingent je Kunde für eine logische Operation, und die zweite ist von Haus aus umkehrbar.

Zitate aus den Implementierungshinweisen der Beleg- und Buchungsoperationen in der Herstellerreferenz, geprüft am 19. August 2026. Die Referenz definiert nicht, wann ein Buchungssatz festgeschrieben wird, prüfen Sie die Bedingung also, bevor Sie darauf bauen.

Wie es funktioniert

Ein geplanter Abruf, und er teilt sich Ihr Anfragebudget

BuchhaltungsButler kündigt seine eigenen Änderungen nicht an, es gibt also kein Abonnement einzurichten und keinen Callback zu prüfen. Aktuell zu bleiben ist ein geplanter Abruf. Das ist eine Eigenschaft des Systems und gehört deshalb von Anfang an in die Planung.

An seine Stelle tritt ein Delta-Abruf über dieselben Filter und dasselbe Paging, die Sie überall sonst benutzen: Sie fragen, was sich seit Ihrem letzten Lauf geändert hat, und bekommen es im gemeinsamen Modell zurück. Was hier arbeitet, ist die Pull-Hälfte, die das Event-Modell ohnehin vorsieht, und auf diesem System hat die Push-Hälfte nichts, was sie füllt.

Ein Abruf hat eine Eigenschaft, die ein Push nicht hat, und auf diesem System ist sie die wichtige: Er holt auf. Fällt Ihr Worker eine Stunde aus, liefert der nächste Lauf trotzdem alles, was sich in dieser Stunde bewegt hat, und auf einer Plattform, auf der Belege stapelweise aus einer Scan-App ankommen, zählt das mehr als Latenz.

Was er kostet, sind Anfragen, und Anfragen sind das, was gedeckelt ist. Jeder Abruf wird aus denselben hundert je Kunde und Minute bezahlt wie Ihre Schreibzugriffe, das Intervall ist damit eine Budgetentscheidung. Selten lesen und ein weites Fenster abfragen ist günstiger als oft lesen und ein enges.

Wo unser Teil endet

Was maesn übernimmt, und was bei Ihnen bleibt

Die Anbindung ist hier schnell erledigt, und genau deshalb verdient der Rest Aufmerksamkeit. Was wir von der Liste nehmen:

  • Die Übersetzung der Methoden. Ihr Client benutzt die gewöhnlichen REST-Methoden, und die Abbildung auf 48 POST-Pfade liegt bei uns, die drei Ableitungen, die ein HTTP-Client sonst trifft, bleiben Ihnen also erhalten.
  • Die zwei Ebenen der Zugangsdaten. Das Basic-Auth-Paar und der Schlüssel je Kunde liegen bei der Verbindung, die Kontoauswahl hört also auf, etwas zu sein, das Ihr Code beim Bauen einer Anfrage falsch setzen kann. Wie das Modell der Geschäftspartner abgebildet wird, steht auf der Seite zur BuchhaltungsButler-Schnittstelle.
  • Das Modell der Geschäftspartner. Debitoren und Kreditoren unter den Einstellungen kommen als Kunden und Lieferanten an, mit den Feldern, die sie auf jedem anderen System haben.

Was bei Ihnen bleibt, und das erste davon ist eine Entscheidung statt einer Aufgabe:

  • Wie Sie die hundert ausgeben. Wie aktuell Ihr Produkt sein muss und was das gegen eine Obergrenze je Kunde kostet, ist eine Produktentscheidung, zu der wir beitragen können.
  • Das Tempo beim Nachladen. Zehn Uploads pro Minute ist die Zahl des Herstellers, und keine Schnittstelle davor lässt den elften Upload gelingen.
  • Der Nettobetrag, falls Sie einen brauchen. Das Betragsfeld eines Belegs ist hier brutto, Netto und Steuer kommen leer zurück. Eine Nettobasis abzuleiten ist Rechnen auf Ihrer Seite oder eine Frage an eine andere Quelle.
  • Der Klick im Konto Ihres Kunden. Den Zugang freizuschalten und drei Werte zu kopieren ist seine Aufgabe, und das in Ihrer eigenen Oberfläche klar zu sagen, ist der Unterschied zwischen einer Verbindung und einem Support-Ticket.
FAQ

Häufige Fragen

Welche Ratenbegrenzungen hat BuchhaltungsButler?

Vier. Die Referenz setzt eine globale Obergrenze von 100 Anfragen je Kunde und Minute, und drei der 48 Operationen tragen einen eigenen Hinweis: der Beleg-Upload zehn pro Minute und beide Batch-Endpunkte je eine Anfrage alle fünf Sekunden. Die Endpunktgrenzen gelten zusätzlich zur globalen und liegen auf den Schreibpfaden, Massenimporte brauchen also Taktung statt Parallelität.

Warum muss eine Leseanfrage ein POST sein?

Weil die Operation nicht in der Methode steht. Alle 48 veröffentlichten Operationen sind POST, und zwölf davon tragen ein Pfadsegment, das get lautet. Die Bedeutung sitzt im Pfad, Ihre HTTP-Schicht kann Sicherheit, Zwischenspeicherung und Wiederholbarkeit also nicht aus der Methode ableiten, wie sie es sonst tut.

Was ist der Unterschied zwischen API Client, API Secret und API Key?

Die ersten beiden sind das Paar aus Zugangsdaten für HTTP Basic Auth. Der dritte authentifiziert nichts: Er benennt das Kundenkonto, auf dem Sie arbeiten wollen, und reist als Formularfeld der Anfrage mit. Über viele angebundene Kundenkonten hinweg sind das Daten je Aufruf.

Entfernt das Löschen eines Belegs ihn wirklich?

Nein. Die Operation markiert den Beleg als gelöscht, und eine eigene Operation zum Wiederherstellen holt ihn über denselben Bezeichner zurück. Behandeln Sie es als Zustandswechsel statt als Entfernung, und rechnen Sie damit, dass ein gelöschter Datensatz überall dort weiter auftaucht, wo ohne Filter auf diesen Zustand gelesen wird.

Warum kann ich die Freigabe eines Buchungssatzes nicht zurücknehmen?

Weil er festgeschrieben ist. Die Referenz wiederholt dieselbe Bedingung bei allen drei unconfirm-Operationen, für freie Buchungen, Belegbuchungen und Transaktionsbuchungen: Es funktioniert nur, wenn die Buchungssätze nicht festgeschrieben sind. Ist dieser Zustand gesetzt, führt der Weg zur Korrektur über einen neuen Buchungssatz.

Wo liegen Kunden und Lieferanten in BuchhaltungsButler?

Unter den Einstellungen. Es gibt kein zusammengefasstes Kontaktobjekt, und die acht Operationen, die Geschäftspartner lesen, anlegen und aktualisieren, liegen alle hinter einem settings-Pfad als Debitoren und Kreditoren. Über maesn kommen sie als Kunden und Lieferanten an, mit den Feldern, die Sie auf jedem anderen angebundenen System benutzen.

Bekomme ich aus einer BuchhaltungsButler-Rechnung einen Nettobetrag?

Aus dem Beleg selbst nicht. Der Beleg trägt ein einzelnes Betragsfeld, und dieses Feld ist brutto. Netto und Steuer kommen leer zurück, alles, was auf einer Nettobasis abrechnen muss, braucht also eine eigene Berechnung oder eine andere Quelle für die Steueraufteilung.

Einmal bauen, auf der Unified API.

BuchhaltungsButler misst zehn Uploads pro Minute, sevdesk veröffentlicht überhaupt keine Grenze und Xero misst, was Sie lesen. Bauen Sie gegen eine Schnittstelle, und jedes davon wird eine Zeile in einer Tabelle statt eines Projekts.