Kassenbuch
Die Bewegungen der Kasse.
GET/api/invoice/cash_transaction
Query parameters
idinteger | |
deletedboolean | This property is used to mark an entity as deleted / archived | Default value: false |
namestring | |
cashRegisterstring | Die Kasse, zu der diese Bewegung gehört. Pflichtangabe: eine Kassenbewegung ohne Kasse hätte keinen Bestand, an dem sie sich fortschreiben könnte. |
sequenceNumberinteger | Fortlaufende Nummer im Kassenbuch der jeweiligen Kasse, lückenlos ab 1. Die Lückenlosigkeit ist der Grund für die Nummer: fehlt eine, ist eine Bewegung entfernt worden. Sie wird deshalb von `CashBookService` vergeben und nicht vom Aufrufer gesetzt. |
transactionDatestring | Tag der Bewegung. |
typestring | |
grossAmountnumber | Der Betrag, der tatsächlich die Kasse wechselt - immer brutto und immer positiv. Die Richtung steckt in `type`, nicht im Vorzeichen. Ein Vorzeichen zusätzlich zur Richtung wäre eine zweite Wahrheit über dieselbe Sache; bei einer Ausgabe von -50 mit type=expense wüsste niemand, ob das nun eine Einnahme ist. |
taxRatenumber | Steuersatz in Prozent, wie er auf dem Beleg steht. |
taxAmountnumber | Der Steueranteil des Bruttobetrags, aus Satz und Betrag gerechnet. |
balanceAfternumber | Bestand der Kasse nach dieser Bewegung. |
documentNumberstring | Belegnummer - die Nummer des Kassenbelegs, nicht die laufende Nummer. |
expenseCategorystring | Die EÜR-Kategorie - dieselbe Brücke wie am Sachkonto und am Anlagegut. |
contraLedgerAccountstring | Das Gegenkonto für die Bilanzierung - die Kasse selbst ist die andere Seite und steht im Kontenrahmen fest. |
costCenterstring | Die steuerliche Sphäre beim gemeinnützigen Verein. |
incomingInvoicestring | Die bar bezahlte Eingangsrechnung, falls es eine gibt. |
invoicestring | Die bar kassierte Ausgangsrechnung, falls es eine gibt. |
journalEntrystring | Der Buchungssatz, sofern die Bewegung verbucht wurde. Nur bei Bilanzierung gesetzt. Bei der EÜR bleibt er leer, weil es dort keine Buchungssätze gibt - die Bewegung zählt trotzdem. |
reversalOfstring | Die Bewegung, die diese hier storniert. Ein echter Verweis und nicht der Buchungstext: der Text ist frei editierbar, und eine Stornoprüfung, die auf "Storno zu Nr. 4" sucht, ließe sich durch Umbenennen aushebeln - und träfe nebenbei auch "Storno zu Nr. 41". |
lockedboolean | Festgeschrieben - die Bewegung ist unveränderlich (GoBD). Korrigiert wird wie im Journal über eine Gegenbewegung, nicht durch Ändern der ursprünglichen Zeile. |
createdstring | |
updatedstring | |
searchStringstring | text to search for in the list |
orderFieldNamestring | name of the order field |
orderFieldSortstring | sorting modeAllowed: DESCASC |
pageinteger | page of the list |
pageSizeinteger | number of entries for each page |
withMaxPageNumberstring | returns the number of pages available as a header if this is set |
Responses
200Kassenbewegungenarray<CashTransaction>
Show fields (22)
idintegerPrimary key of the cash transaction. Internal ID.
cash_registerCashRegisterDie Kasse, zu der diese Bewegung gehört. Pflichtangabe: eine Kassenbewegung ohne Kasse hätte keinen Bestand, an dem sie sich fortschreiben könnte.
Show fields (10)
idintegerPrimary key of the cash register. Internal ID.
codestringKurzzeichen für die Belegnummer, etwa "VH" für Vereinsheim.
ledger_accountLedgerAccountDas Bestandskonto dieser Kasse für die Bilanzierung. Je Kasse ein eigenes Konto, sonst stünden in der Bilanz beide Bestände auf einer Zeile und ließen sich nicht mehr trennen.
cost_centerCostCenterDie steuerliche Sphäre beim gemeinnützigen Verein. Eine Kasse gehört meist zu einem Bereich - die Kasse am Getränkestand zum wirtschaftlichen Geschäftsbetrieb, die Kasse der Geschäftsstelle zum ideellen Bereich.
is_activebooleanStillgelegte Kassen nehmen keine Buchungen mehr an, bleiben aber mit ihrem Buch bestehen - die Aufzeichnungen sind aufzubewahren.
locked_throughstring (date-time)Bis zu welchem Tag das Kassenbuch abgeschlossen ist. Der Kassenabschluss schiebt dieses Datum vor. Bis hierhin nimmt die Kasse keine Bewegung mehr an - auch nicht am selben Tag: die Chronologieprüfung allein ließ nach dem Monatsabschluss noch eine Bewegung mit dem letzten Tag des Monats zu, und der abgeschlossene Monat wäre hinterher ein anderer gewesen als der abgeschlossene.
deletedbooleanThis property is used to mark an entity as deleted / archived
namestringName of the entity.
createdstring (date-time)Point in time the entity was created.
updatedstring (date-time)Point in time the entity was last updated.
sequence_numberintegerFortlaufende Nummer im Kassenbuch der jeweiligen Kasse, lückenlos ab 1. Die Lückenlosigkeit ist der Grund für die Nummer: fehlt eine, ist eine Bewegung entfernt worden. Sie wird deshalb von `CashBookService` vergeben und nicht vom Aufrufer gesetzt.
transaction_datestring (date-time)Tag der Bewegung.
typestringType of the cash transaction, for example income or expense.
gross_amountnumber (float)Der Betrag, der tatsächlich die Kasse wechselt - immer brutto und immer positiv. Die Richtung steckt in `type`, nicht im Vorzeichen. Ein Vorzeichen zusätzlich zur Richtung wäre eine zweite Wahrheit über dieselbe Sache; bei einer Ausgabe von -50 mit type=expense wüsste niemand, ob das nun eine Einnahme ist.
tax_ratenumber (float)Steuersatz in Prozent, wie er auf dem Beleg steht.
tax_amountnumber (float)Der Steueranteil des Bruttobetrags, aus Satz und Betrag gerechnet.
balance_afternumber (float)Bestand der Kasse nach dieser Bewegung.
document_numberstringBelegnummer - die Nummer des Kassenbelegs, nicht die laufende Nummer.
expense_categoryExpenseCategory10Die EÜR-Kategorie - dieselbe Brücke wie am Sachkonto und am Anlagegut.
Show fields (19)
idintegerPrimary key of the expense category. Internal ID.
codestringKurzbezeichnung/Code (z.B. "WAREN", "PERSONAL", "MIETE")
eur_line_numberintegerZeile in der Anlage EÜR (z.B. 23 für Wareneinkauf)
eur_line_namestringBezeichnung der EÜR-Zeile (z.B. "Waren, Rohstoffe und Hilfsstoffe")
category_typestringTyp der Kategorie (expense, income, neutral, asset, private)
default_taxTaxStandard-Steuersatz für diese Kategorie
cost_centerCostCenterKostenstelle der Kategorie - bei Vereinen die steuerliche Sphäre. Ein Beleg trägt keine eigene Sphäre; über seine Kategorie bekommt er eine. Die EÜR des wirtschaftlichen Geschäftsbetriebs liest sie (billing_euer_commercial_sphere_only), die automatische Buchung setzt sie auf die Buchungszeilen (billing_accounting_cost_center_from_category).
is_vat_deductiblebooleanIst Vorsteuerabzug möglich?
is_immediate_deductionbooleanIst die Kategorie sofort abzugsfähig? (vs. Abschreibung über mehrere Jahre)
depreciation_yearsintegerAbschreibungsdauer in Jahren (für Anlagevermögen)
sort_orderintegerSortierreihenfolge
is_activebooleanIst die Kategorie aktiv/sichtbar?
colorstringFarbe für UI-Darstellung (Hex-Code)
iconstringIcon-Name für UI-Darstellung
is_systembooleanIst dies eine System-Kategorie? (nicht löschbar)
deletedbooleanThis property is used to mark an entity as deleted / archived
namestringName of the entity.
createdstring (date-time)Point in time the entity was created.
updatedstring (date-time)Point in time the entity was last updated.
contra_ledger_accountLedgerAccountDas Gegenkonto für die Bilanzierung - die Kasse selbst ist die andere Seite und steht im Kontenrahmen fest.
Show fields (15)
display_namestringidintegerPrimary key of the ledger account. Internal ID.
numberstringKontonummer im Kontenrahmen, z.B. "1200" (SKR03 Bank) oder "40000" (SKR42). Als String geführt, weil SKR42 fünfstellig ist und führende Nullen bedeutungstragend sein können.
chart_of_accountsstringChart of accounts the account belongs to, for example SKR03.
account_typestringType of the account, for example asset or revenue.
default_taxTaxSteuersatz, der beim Buchen auf dieses Konto vorgeschlagen wird. Bei Erlös- und Aufwandskonten ist der Satz durch die Kontonummer vorgegeben (etwa "Erlöse 19% USt"), deshalb hängt er am Konto und nicht an der einzelnen Buchung.
tax_accountLedgerAccountGegenkonto für die Steuer, die beim Buchen auf dieses Konto entsteht. Bei Erlöskonten das Umsatzsteuerkonto, bei Aufwandskonten das Vorsteuerkonto. Damit lässt sich aus einem Bruttobetrag automatisch der dreizeilige Buchungssatz erzeugen.
expense_categoryExpenseCategory10Brücke zur EÜR: auf welcher Zeile der Anlage EÜR dieses Konto zählt. Erlaubt es, beide Gewinnermittlungsarten aus denselben Belegen zu bedienen - etwa im Wechseljahr oder wenn ein Verein den wirtschaftlichen Geschäftsbetrieb per EÜR und den Rest bilanziell führt.
cost_center_requiredbooleanOb auf diesem Konto eine Kostenstelle angegeben werden muss. Der SKR42 bildet die vier steuerlichen Sphären eines gemeinnützigen Vereins über Kostenstellen ab, nicht über getrennte Konten. Für die Erfolgskonten ist die Angabe dort deshalb Pflicht.
is_systembooleanVom Kontenrahmen-Initialisierer angelegt. Nummer und Art sind dann durch den Rahmen vorgegeben und sollten nicht geändert werden.
is_activebooleanKonten lassen sich stilllegen, statt sie zu löschen - bebuchte Konten dürfen nicht verschwinden.
deletedbooleanThis property is used to mark an entity as deleted / archived
namestringName of the entity.
createdstring (date-time)Point in time the entity was created.
updatedstring (date-time)Point in time the entity was last updated.
cost_centerCostCenterDie steuerliche Sphäre beim gemeinnützigen Verein.
Show fields (10)
display_namestringidintegerPrimary key of the cost center. Internal ID.
numberstringNumber of the cost center.
spherestringSteuerliche Sphäre, null bei rein betriebswirtschaftlicher Gliederung.
is_systembooleanThe cost center is created by the system and cannot be deleted.
is_activebooleanThe cost center is active.
deletedbooleanThis property is used to mark an entity as deleted / archived
namestringName of the entity.
createdstring (date-time)Point in time the entity was created.
updatedstring (date-time)Point in time the entity was last updated.
incoming_invoiceIncomingInvoice3Die bar bezahlte Eingangsrechnung, falls es eine gibt.
Show fields (43)
idintegerPrimary key of the invoice document. Internal ID.
tokenstringToken that identifies the document for public access.
numberintegerRunning document number.
manual_number_prefixstringPrefix of a manually entered document number.
manual_numberintegerManually entered document number.
number_stringstringDocument number as displayed to users.
generation_datestring (date-time)Date the document was generated.
number_datestring (date-time)Date used for the document number.
messagestringMessage printed on the document.
currencystringCurrency of the document.
namestringName of the document.
due_datestring (date-time)Due date of the document.
netto_valuenumber (float)Net total of the document.
brutto_valuenumber (float)Gross total of the document.
tax_valuenumber (float)Total tax amount of the document.
taxTaxrequiredTax rate applied to the document.
linked_number_titlestringTitle of the linked document number.
linked_numberstringNumber of the linked document.
statusstringStatus of the document.
previous_statusstringStatus before the last change.
status_updatedstring (date-time)Point in time the status was last changed.
archivedbooleanWhether the document is archived.
last_pdf_exportstring (date-time)Point in time the PDF was last exported.
last_status_exportstringStatus at the last export.
search_stringstringText that the entity can be searched by.
external_invoice_numberstringExterne Rechnungsnummer des Lieferanten
received_datestring (date-time)Eingangsdatum (wann wurde die Rechnung empfangen)
payment_datestring (date-time)Zahlungsdatum
service_date_startstring (date-time)Leistungszeitraum Start
service_date_endstring (date-time)Leistungszeitraum Ende
vat_categorystringDer umsatzsteuerliche Sachverhalt. Auf der Eingangsseite entscheidet er darüber, ob die Vorsteuer unter Kennzahl 66 steht (Rechnung eines anderen Unternehmers), unter 61 (innergemeinschaftlicher Erwerb), unter 62 (Einfuhrumsatzsteuer) oder unter 67 (§ 13b UStG). Beim Erwerb und bei § 13b kommt eine zweite Zeile hinzu: die Steuer schulden wir selbst, obwohl sie uns niemand berechnet hat, und sie steht deshalb zugleich als Umsatzsteuer im Vordruck. Wer nur eine der beiden bucht, zahlt zu viel oder zu wenig. Ohne Angabe der Regelfall.
vat_self_assessed_ratenumber (float)Der Steuersatz, mit dem die selbst geschuldete Steuer zu rechnen ist. Beim innergemeinschaftlichen Erwerb und bei § 13b UStG berechnet der Lieferant keine Steuer - die Rechnung ist netto, und die Steuer schulden wir. Womit sie zu rechnen ist, steht deshalb auf keinem Beleg: es ist der Satz, der im Inland auf diese Leistung anzuwenden wäre. Ohne Angabe rechnet die Voranmeldung mit dem Regelsatz und sagt in den Hinweisen, bei wie vielen Belegen sie das getan hat. Stillschweigend zu raten wäre in einer Steueranmeldung das Falsche.
import_vat_amountstringDie Einfuhrumsatzsteuer aus dem Zollbescheid. Sie steht NICHT auf der Rechnung des Lieferanten - die ist bei einer Einfuhr ohne deutsche Steuer. Entrichtet wird sie an den Zoll, und nur der entrichtete Betrag ist als Vorsteuer abziehbar (§ 15 Abs. 1 Satz 1 Nr. 2 UStG, Kennzahl 62 der Voranmeldung). Den Steuerbetrag der Lieferantenrechnung dafür zu nehmen war schlicht der falsche Beleg.
paid_valuenumber (float)Bereits bezahlter Betrag (für Teilzahlungen)
sellerIncomingInvoiceSellerVerkäufer/Lieferant Informationen (Snapshot)
expense_categoryExpenseCategory10Hauptkategorie für EÜR
document_pathstringPfad zur gespeicherten Rechnungsdatei (PDF/Bild)
document_filenamestringOriginal Dateiname
document_mime_typestringMIME Type des Dokuments
notesstringNotizen/Bemerkungen
is_deductiblebooleanIst die Rechnung für den Vorsteuerabzug relevant?
is_approvedbooleanWurde die Rechnung geprüft/freigegeben?
approved_atstring (date-time)Time the incoming invoice was approved.
invoiceInvoiceDie bar kassierte Ausgangsrechnung, falls es eine gibt.
Show fields (38)
idintegerPrimary key of the invoice document. Internal ID.
tokenstringToken that identifies the document for public access.
numberintegerRunning document number.
manual_number_prefixstringPrefix of a manually entered document number.
manual_numberintegerManually entered document number.
number_stringstringDocument number as displayed to users.
generation_datestring (date-time)Date the document was generated.
number_datestring (date-time)Date used for the document number.
messagestringMessage printed on the document.
currencystringCurrency of the document.
namestringName of the document.
due_datestring (date-time)Due date of the document.
netto_valuenumber (float)Net total of the document.
brutto_valuenumber (float)Gross total of the document.
tax_valuenumber (float)Total tax amount of the document.
taxTaxrequiredTax rate applied to the document.
linked_number_titlestringTitle of the linked document number.
linked_numberstringNumber of the linked document.
statusstringStatus of the document.
previous_statusstringStatus before the last change.
status_updatedstring (date-time)Point in time the status was last changed.
archivedbooleanWhether the document is archived.
last_pdf_exportstring (date-time)Point in time the PDF was last exported.
last_status_exportstringStatus at the last export.
search_stringstringText that the entity can be searched by.
accounting_typeAccountingTyperequiredAccounting type of the invoice.
payment_typePaymentTypePayment type of the invoice.
payment_goalPaymentGoalPayment term of the invoice.
expense_categoryExpenseCategory10EÜR-Kategorie für diese Rechnung (Einnahmen-Zuordnung) Wenn nicht gesetzt, wird die Default-Kategorie des AccountingTypes verwendet
buyerInvoiceBuyerBuyer of the invoice.
payment_datestring (date-time)Date the invoice was paid.
vat_categorystringDer umsatzsteuerliche Sachverhalt. Der Steuersatz sagt nicht, in welche Zeile der Voranmeldung ein Umsatz gehört. Null Prozent stehen an einer innergemeinschaftlichen Lieferung (Kennzahl 41), an einer Ausfuhr (43), an einer Leistung nach § 13b UStG (60) und an einem steuerfreien Umsatz nach § 4 UStG (48) - vier verschiedene Zeilen, derselbe Steuersatz. Hier ist die einzige Stelle, an der jemand das weiss: beim Schreiben der Rechnung ist bekannt, ob der Kunde eine USt-IdNr. hat und wohin die Ware geht. Später ist es nicht mehr rekonstruierbar. Ohne Angabe der Regelfall - alles andere war bisher nicht erfassbar.
is_payment_date_from_ext_servicebooleanThe payment date comes from an external service.
direct_debit_exportedbooleanThe invoice was exported for direct debit.
cancel_datestring (date-time)Date the invoice was canceled.
cancel_textstringText of the cancellation.
start_datestring (date-time)Start of the billed period.
end_datestring (date-time)End of the billed period.
journal_entryJournalEntryDer Buchungssatz, sofern die Bewegung verbucht wurde. Nur bei Bilanzierung gesetzt. Bei der EÜR bleibt er leer, weil es dort keine Buchungssätze gibt - die Bewegung zählt trotzdem.
Show fields (21)
debit_totalnumber (float)Summe der Sollbeträge.
credit_totalnumber (float)Summe der Habenbeträge.
is_balancedbooleanSoll gleich Haben - die Grundregel der doppelten Buchführung.
idintegerPrimary key of the journal entry. Internal ID.
entry_numberstringFortlaufende Buchungsnummer, vergeben beim Festschreiben. Erst dann, weil die GoBD eine lückenlose Nummerierung der festgeschriebenen Buchungen verlangt - eine verworfene Erfassung darf keine Lücke hinterlassen.
entry_datestring (date-time)Buchungsdatum - bestimmt, in welche Periode die Buchung fällt.
document_datestring (date-time)Belegdatum - das Datum auf dem Papier. Kann vom Buchungsdatum abweichen.
document_numberstringBelegnummer - die Brücke zwischen Buchung und Beleg. Ohne sie ist die Buchung nicht nachvollziehbar ("keine Buchung ohne Beleg").
fiscal_yearFiscalYearFiscal year the entry belongs to.
periodintegerBuchungsperiode innerhalb des Geschäftsjahres. 1 bis 12 für die laufenden Monate, 13 für die Abschlussperiode. Die Zahl wird aus dem Buchungsdatum abgeleitet, sobald sie nicht ausdrücklich gesetzt ist - nur der Abschluss setzt sie selbst. Die Spalte heisst `accounting_period` und nicht `period`: MariaDB hält PERIOD seit der System-Versionierung (`PERIOD FOR SYSTEM_TIME`) als Schlüsselwort frei, und die Migration scheitert daran. Das Feld in PHP bleibt `period` - DQL und die JSON-Ausgabe ändern sich damit nicht.
statusstringStatus of the entry, for example draft or posted.
source_typestringSource of the entry, for example invoice or payment.
source_idintegerId des auslösenden Belegs, damit sich Buchung und Beleg gegenseitig finden - und damit derselbe Beleg nicht zweimal gebucht wird.
reversal_ofJournalEntryDie Buchung, die durch diese hier storniert wird.
posted_atstring (date-time)Time the entry was posted.
posted_byUser14Login user who posted the entry.
linesarray<JournalEntryLine>Lines of the entry.
deletedbooleanThis property is used to mark an entity as deleted / archived
namestringName of the entity.
createdstring (date-time)Point in time the entity was created.
updatedstring (date-time)Point in time the entity was last updated.
reversal_ofCashTransactionDie Bewegung, die diese hier storniert. Ein echter Verweis und nicht der Buchungstext: der Text ist frei editierbar, und eine Stornoprüfung, die auf "Storno zu Nr. 4" sucht, ließe sich durch Umbenennen aushebeln - und träfe nebenbei auch "Storno zu Nr. 41".
lockedbooleanFestgeschrieben - die Bewegung ist unveränderlich (GoBD). Korrigiert wird wie im Journal über eine Gegenbewegung, nicht durch Ändern der ursprünglichen Zeile.
deletedbooleanThis property is used to mark an entity as deleted / archived
namestringName of the entity.
createdstring (date-time)Point in time the entity was created.
updatedstring (date-time)Point in time the entity was last updated.
curl --request GET \
--url https://your-instance.iw-erp.de/api/invoice/cash_transaction \
--header 'x-iw-jwt-token: <TOKEN>'const options = {method: 'GET', headers: {'x-iw-jwt-token': '<TOKEN>'}};
fetch('https://your-instance.iw-erp.de/api/invoice/cash_transaction', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/invoice/cash_transaction"
headers = {"x-iw-jwt-token": "<TOKEN>"}
response = requests.get(url, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://your-instance.iw-erp.de/api/invoice/cash_transaction', [
'headers' => [
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/invoice/cash_transaction"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/invoice/cash_transaction")
.get()
.addHeader("x-iw-jwt-token", "<TOKEN>")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/invoice/cash_transaction"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with package:http (no controller in the iw_erp_api package)
import 'package:http/http.dart' as http;
final response = await http.get(
Uri.parse('https://your-instance.iw-erp.de/api/invoice/cash_transaction'),
headers: {'x-iw-jwt-token': '<TOKEN>'},
);
print(response.body);[
{
"id": 42,
"name": "Beispiel",
"cash_register": {
"id": 42,
"name": "Beispiel",
"code": "string",
"is_active": true,
"locked_through": "2026-10-15T09:30:00+02:00",
"deleted": true,
"created": "2026-10-15T09:30:00+02:00",
"updated": "2026-10-15T09:30:00+02:00"
},
"sequence_number": 1,
"transaction_date": "2026-10-15T09:30:00+02:00",
"type": "string",
"gross_amount": 49.9,
"tax_rate": 1.5,
"tax_amount": 49.9,
"balance_after": 1.5
}
]Trägt eine Bewegung ins Kassenbuch ein.
POST/api/invoice/cash_transaction
Laufende Nummer und Bestand vergibt der Dienst; was daran übergeben wird, wird ignoriert.
Request body application/json
transaction_datestring (date)typestringAllowed:
incomeexpensegross_amountnumbertax_ratenumbertax_amountnumbernamestringdocument_numberstringexpense_categoryintegercash_registerintegerPflicht, sobald es mehr als eine Kasse gibt
Responses
201Die eingetragene Bewegung samt neuem Bestand
409Der Bestand würde negativ, oder die Bewegung läge vor der letzten
curl --request POST \
--url https://your-instance.iw-erp.de/api/invoice/cash_transaction \
--header 'content-type: application/json' \
--header 'x-iw-jwt-token: <TOKEN>' \
--data '
{
"name": "Büromaterial",
"transaction_date": "2026-07-31",
"type": "expense",
"gross_amount": 23.8,
"tax_rate": 19,
"tax_amount": 3.8
}
'const options = {
method: 'POST',
headers: {'x-iw-jwt-token': '<TOKEN>', 'content-type': 'application/json'},
body: JSON.stringify({
name: 'Büromaterial',
transaction_date: '2026-07-31',
type: 'expense',
gross_amount: 23.8,
tax_rate: 19,
tax_amount: 3.8
})
};
fetch('https://your-instance.iw-erp.de/api/invoice/cash_transaction', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/invoice/cash_transaction"
payload = {
"name": "Büromaterial",
"transaction_date": "2026-07-31",
"type": "expense",
"gross_amount": 23.8,
"tax_rate": 19,
"tax_amount": 3.8
}
headers = {
"x-iw-jwt-token": "<TOKEN>",
"content-type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://your-instance.iw-erp.de/api/invoice/cash_transaction', [
'body' => '{"name":"Büromaterial","transaction_date":"2026-07-31","type":"expense","gross_amount":23.8,"tax_rate":19,"tax_amount":3.8}',
'headers' => [
'content-type' => 'application/json',
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/invoice/cash_transaction"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
Content = new StringContent("{\"name\":\"Büromaterial\",\"transaction_date\":\"2026-07-31\",\"type\":\"expense\",\"gross_amount\":23.8,\"tax_rate\":19,\"tax_amount\":3.8}")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"name\":\"Büromaterial\",\"transaction_date\":\"2026-07-31\",\"type\":\"expense\",\"gross_amount\":23.8,\"tax_rate\":19,\"tax_amount\":3.8}");
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/invoice/cash_transaction")
.post(body)
.addHeader("x-iw-jwt-token", "<TOKEN>")
.addHeader("content-type", "application/json")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/invoice/cash_transaction"
payload := strings.NewReader("{\"name\":\"Büromaterial\",\"transaction_date\":\"2026-07-31\",\"type\":\"expense\",\"gross_amount\":23.8,\"tax_rate\":19,\"tax_amount\":3.8}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
req.Header.Add("content-type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with the iw_erp_api package
import 'package:iw_erp_api/clients/cash_book_controller.dart';
import 'package:iw_erp_api/logic/iw_api_state.dart';
IwApiState().host = 'your-instance.iw-erp.de';
IwApiState().currentJwtApiToken = '<TOKEN>';
final result = await CashBookController.book(transactionDate: DateTime.fromJson({
"name": "Büromaterial",
"transaction_date": "2026-07-31",
"type": "expense",
"gross_amount": 23.8,
"tax_rate": 19,
"tax_amount": 3.8
}), type: '…', grossAmount: 42, name: '…');
if (result.success) {
print(result.data);
}Das Kassenbuch eines Zeitraums samt Anfangs- und Endbestand.
GET/api/invoice/cash_transaction/book
Query parameters
fromstring (date) | |
tostring (date) |
Responses
200Die Bewegungen des Zeitraums mit fortlaufendem Bestand
curl --request GET \
--url https://your-instance.iw-erp.de/api/invoice/cash_transaction/book \
--header 'x-iw-jwt-token: <TOKEN>'const options = {method: 'GET', headers: {'x-iw-jwt-token': '<TOKEN>'}};
fetch('https://your-instance.iw-erp.de/api/invoice/cash_transaction/book', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/invoice/cash_transaction/book"
headers = {"x-iw-jwt-token": "<TOKEN>"}
response = requests.get(url, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://your-instance.iw-erp.de/api/invoice/cash_transaction/book', [
'headers' => [
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/invoice/cash_transaction/book"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/invoice/cash_transaction/book")
.get()
.addHeader("x-iw-jwt-token", "<TOKEN>")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/invoice/cash_transaction/book"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with the iw_erp_api package
import 'package:iw_erp_api/clients/cash_book_controller.dart';
import 'package:iw_erp_api/logic/iw_api_state.dart';
IwApiState().host = 'your-instance.iw-erp.de';
IwApiState().currentJwtApiToken = '<TOKEN>';
final result = await CashBookController.getBook();
if (result.success) {
print(result.data);
}Der aktuelle Kassenbestand - was in der Schublade liegen müsste.
GET/api/invoice/cash_transaction/balance
Responses
200Der Bestand nach der letzten Bewegung
curl --request GET \
--url https://your-instance.iw-erp.de/api/invoice/cash_transaction/balance \
--header 'x-iw-jwt-token: <TOKEN>'const options = {method: 'GET', headers: {'x-iw-jwt-token': '<TOKEN>'}};
fetch('https://your-instance.iw-erp.de/api/invoice/cash_transaction/balance', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/invoice/cash_transaction/balance"
headers = {"x-iw-jwt-token": "<TOKEN>"}
response = requests.get(url, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('GET', 'https://your-instance.iw-erp.de/api/invoice/cash_transaction/balance', [
'headers' => [
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/invoice/cash_transaction/balance"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/invoice/cash_transaction/balance")
.get()
.addHeader("x-iw-jwt-token", "<TOKEN>")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/invoice/cash_transaction/balance"
req, _ := http.NewRequest("GET", url, nil)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with the iw_erp_api package
import 'package:iw_erp_api/clients/cash_book_controller.dart';
import 'package:iw_erp_api/logic/iw_api_state.dart';
IwApiState().host = 'your-instance.iw-erp.de';
IwApiState().currentJwtApiToken = '<TOKEN>';
final result = await CashBookController.getBalance();
if (result.success) {
print(result.data);
}Schreibt die Bewegungen eines Zeitraums fest (Kassenabschluss).
POST/api/invoice/cash_transaction/lock
Request body application/json
fromstring (date)tostring (date)
Responses
200Wie viele Bewegungen festgeschrieben wurden
curl --request POST \
--url https://your-instance.iw-erp.de/api/invoice/cash_transaction/lock \
--header 'content-type: application/json' \
--header 'x-iw-jwt-token: <TOKEN>' \
--data '
{
"from": "2026-10-15",
"to": "2026-10-15"
}
'const options = {
method: 'POST',
headers: {'x-iw-jwt-token': '<TOKEN>', 'content-type': 'application/json'},
body: JSON.stringify({from: '2026-10-15', to: '2026-10-15'})
};
fetch('https://your-instance.iw-erp.de/api/invoice/cash_transaction/lock', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/invoice/cash_transaction/lock"
payload = {
"from": "2026-10-15",
"to": "2026-10-15"
}
headers = {
"x-iw-jwt-token": "<TOKEN>",
"content-type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://your-instance.iw-erp.de/api/invoice/cash_transaction/lock', [
'body' => '{"from":"2026-10-15","to":"2026-10-15"}',
'headers' => [
'content-type' => 'application/json',
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/invoice/cash_transaction/lock"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
Content = new StringContent("{\"from\":\"2026-10-15\",\"to\":\"2026-10-15\"}")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"from\":\"2026-10-15\",\"to\":\"2026-10-15\"}");
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/invoice/cash_transaction/lock")
.post(body)
.addHeader("x-iw-jwt-token", "<TOKEN>")
.addHeader("content-type", "application/json")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/invoice/cash_transaction/lock"
payload := strings.NewReader("{\"from\":\"2026-10-15\",\"to\":\"2026-10-15\"}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
req.Header.Add("content-type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with the iw_erp_api package
import 'package:iw_erp_api/clients/cash_book_controller.dart';
import 'package:iw_erp_api/logic/iw_api_state.dart';
IwApiState().host = 'your-instance.iw-erp.de';
IwApiState().currentJwtApiToken = '<TOKEN>';
final result = await CashBookController.lock(from: DateTime.fromJson({
"from": "2026-10-15",
"to": "2026-10-15"
}), to: DateTime.fromJson({
"from": "2026-10-15",
"to": "2026-10-15"
}));
if (result.success) {
print(result.data);
}Storniert eine Bewegung durch eine Gegenbewegung.
POST/api/invoice/cash_transaction/{identifier}/reversal
Die ursprüngliche Zeile bleibt stehen. Sie zu entfernen widerspräche der Unveränderbarkeit und risse eine Lücke in die laufende Nummer.
Path parameters
identifierrequiredstring |
Request body application/json
reasonstring
Responses
201Die Gegenbewegung
curl --request POST \
--url https://your-instance.iw-erp.de/api/invoice/cash_transaction/42/reversal \
--header 'content-type: application/json' \
--header 'x-iw-jwt-token: <TOKEN>' \
--data '
{
"reason": "Betrag falsch erfasst"
}
'const options = {
method: 'POST',
headers: {'x-iw-jwt-token': '<TOKEN>', 'content-type': 'application/json'},
body: JSON.stringify({reason: 'Betrag falsch erfasst'})
};
fetch('https://your-instance.iw-erp.de/api/invoice/cash_transaction/42/reversal', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://your-instance.iw-erp.de/api/invoice/cash_transaction/42/reversal"
payload = { "reason": "Betrag falsch erfasst" }
headers = {
"x-iw-jwt-token": "<TOKEN>",
"content-type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)<?php
require_once('vendor/autoload.php');
$client = new \GuzzleHttp\Client();
$response = $client->request('POST', 'https://your-instance.iw-erp.de/api/invoice/cash_transaction/42/reversal', [
'body' => '{"reason":"Betrag falsch erfasst"}',
'headers' => [
'content-type' => 'application/json',
'x-iw-jwt-token' => '<TOKEN>',
],
]);
echo $response->getBody();using System.Net.Http.Headers;
var client = new HttpClient();
var request = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri("https://your-instance.iw-erp.de/api/invoice/cash_transaction/42/reversal"),
Headers =
{
{ "x-iw-jwt-token", "<TOKEN>" },
},
Content = new StringContent("{\"reason\":\"Betrag falsch erfasst\"}")
{
Headers =
{
ContentType = new MediaTypeHeaderValue("application/json")
}
}
};
using (var response = await client.SendAsync(request))
{
response.EnsureSuccessStatusCode();
var body = await response.Content.ReadAsStringAsync();
Console.WriteLine(body);
}OkHttpClient client = new OkHttpClient();
MediaType mediaType = MediaType.parse("application/json");
RequestBody body = RequestBody.create(mediaType, "{\"reason\":\"Betrag falsch erfasst\"}");
Request request = new Request.Builder()
.url("https://your-instance.iw-erp.de/api/invoice/cash_transaction/42/reversal")
.post(body)
.addHeader("x-iw-jwt-token", "<TOKEN>")
.addHeader("content-type", "application/json")
.build();
Response response = client.newCall(request).execute();package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://your-instance.iw-erp.de/api/invoice/cash_transaction/42/reversal"
payload := strings.NewReader("{\"reason\":\"Betrag falsch erfasst\"}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-iw-jwt-token", "<TOKEN>")
req.Header.Add("content-type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}Dart with the iw_erp_api package
import 'package:iw_erp_api/clients/cash_book_controller.dart';
import 'package:iw_erp_api/logic/iw_api_state.dart';
IwApiState().host = 'your-instance.iw-erp.de';
IwApiState().currentJwtApiToken = '<TOKEN>';
final result = await CashBookController.reverse('42');
if (result.success) {
print(result.data);
}