Die Umsatz-API liefert alle umsatzrelevanten Transaktionen eines Zeitraums — samt Positionen, Zahlungen und Steueraufteilung — in einer einzigen Abfrage. Ideal für Buchhaltungsexporte, Umsatzabstimmung, BI-Warehouses oder Ad-hoc-Reports.
Tipp: Umsatz API oder SQL Views?
Die Umsatz-API und die SQL Views liefern
dieselben Daten in unterschiedlicher Form für unterschiedliche
Laufzeiten:
- Umsatz API — über den öffentlichen Cloud-Endpunkt
(my.apro.at). Pro Beleg ein hierarchisches JSON-Objekt mit
Positionen, Zahlungen, Steuersätzen, Bediener und Tisch bereits
verschachtelt. Ideal für Off-Premise-Systeme, SaaS-Integrationen,
Mobile Clients — überall, wo ein fertiger Objektbaum gewünscht ist.
- SQL Views — lesende Views direkt auf der
On-Premise-Kassendatenbank. Flach, relational, mit jedem
SQL-Server-fähigen Tool abfragbar. Ideal für On-Premise-
Integrationen, ETL-Pipelines und **bestehende BI-Workflows
(Power BI, Tableau, Qlik, Metabase)**.
Cloud-API für Realtime-System-zu-System-Integration, SQL-Views für
Bulk-Analytics und Dashboards.
- Host:
my.apro.at - Auth: API-Key im
x-api-key - Content type:
application/json
Endpunkte
Variante | Endpunkt | Standort aus |
|---|---|---|
Pfad + Key |
|
|
Nur Key |
| dem API-Key selbst. |
Beide Varianten erfordern einen standortgebundenen API-Key. Der Key selbst bestimmt, welche Standortdaten geliefert werden — einen mandantenweiten Endpunkt gibt es nicht. Wähle, was im Client-Code klarer ist — beide liefern dieselben Daten und benötigen denselben Key.
Request-Body
Feld | Typ | Pflicht | Beschreibung |
|---|---|---|---|
| ISO 8601 Timestamp | ✅ | Nur Belege nach diesem Zeitpunkt. |
| ISO 8601 Timestamp | ✅ | Nur Belege vor diesem Zeitpunkt. |
| integer | — | Anzahl zurückgelieferter Belege begrenzen. |
| GUID | — | Cursor — Transaktionen nach dieser ID liefern. Für Paging zusammen mit |
Beispielanfrage
POST /api/v1/reports/receipts
{
"after": "2026-01-01T00:00:00Z",
"before": "2026-02-01T00:00:00Z",
"limit": 100,
"afterTransactionID": "f03e11de-6330-4a03-a8a8-b6e5fd4e32a5"
}Download: revenue-request.json
Antwort
Ein Array von Belegen. Jedes Element ist eine Transaktion mit Positionen, Zahlungen und Metadaten.
Top-Level-Felder
Feld | Typ | Beschreibung |
|---|---|---|
| GUID | Eindeutige Transaktions-ID. |
| string | Siehe Transaktionstypen. |
| string |
|
| decimal | Bruttogesamtbetrag. |
| decimal | Im |
| decimal | Abgezogener Rabatt. |
| ISO 8601 | Zeitpunkt der Transaktion. |
| Unternehmen / Mandant. | |
| Der APRO-Standort, für den abgefragt wurde. | |
| Bediener / Kellner. | |
| Tisch oder Bestellziel (z. B. | |
| Bereich / Zone des Tisches (z. B. Garten, Bar). | |
| Customer · nullable | Rechnungsempfänger. Auf diesem Endpunkt immer |
| Gruppierung, in die die Zahlungsarten zusammenlaufen. | |
| [Payment] | Zahlungen zum Beleg. |
| [Item] | Belegpositionen. |
| integer | Gästeanzahl, summiert über die Positionen des Belegs. |
Item
Feld | Typ | Beschreibung |
|---|---|---|
| string | Eindeutige Artikel-ID. |
| integer | Artikelnummer (in APRO). |
| string | Artikelname. |
| string · nullable | Stabiler Identifier je Position. Zum Deduplizieren bzw. Abgleichen über wiederholte Abfragen hinweg. |
| string · nullable | Referenz aus einem Fremdsystem. |
| ISO 8601 | Buchungszeitpunkt. |
| decimal | Bruttopreis. |
| decimal | Nettopreis. |
| decimal | Einkaufspreis der Position, für Deckungsbeitrags-Auswertungen. |
| decimal | Stückzahl. |
| integer · nullable | Gang bei mehrgängigem Service. |
| Angewendeter Steuersatz. | |
| Sparte. | |
| [Side dish] · nullable | Unterartikel / Beilagen zu dieser Position. |
Side dish
Unterartikel sind die Beilagen und Modifikatoren, die unter einer Position gebucht werden — die Pommes zum Schnitzel, das ohne Zwiebel zum Burger. Sie werden verschachtelt in der übergeordneten Position zurückgegeben, nie als eigene Positionen.
Ein Unterartikel nutzt dieselbe Item-Struktur, befüllt aber nur die folgenden Felder. Alle übrigen — bookDate, externalId, purchasePrice, course, tax, category, sideDishes — sind null bzw. ihr Default-Wert; Unterartikel verschachteln sich nicht rekursiv.
Feld | Typ | Beschreibung |
|---|---|---|
| string | Eindeutige Unterartikel-ID. |
| integer | Artikelnummer des Unterartikels. |
| string | Bezeichnung des Unterartikels. |
| string | Stabiler Identifier je Unterartikel. Zugleich der Schlüssel, über den dedupliziert wird. |
| decimal | Bruttopreis des Unterartikels. |
| decimal | Nettopreis des Unterartikels. |
| decimal | Stückzahl des Unterartikels. |
Achtung: Unterartikel nicht zu den Summen addieren
Ein Unterartikel mit Aufpreis ist **bereits imgrossAmount/netAmountder übergeordneten Position** und imtotalAmountdes
Belegs enthalten. WersideDishes[].grossAmountzusätzlich aufaddiert,
zählt Umsatz doppelt. Die Beträge sind eine Aufschlüsselung für die
Anzeige, keine eigenständigen Positionen.
sideDishes ist null — nicht [] — wenn eine Position keine Unterartikel hat, ebenso bei älteren Query-Konfigurationen aus der Zeit vor diesem Feature. Daher auf null-oder-leer prüfen, statt ein Array vorauszusetzen.
Tax
Feld | Typ | Beschreibung |
|---|---|---|
| string | Eindeutige ID des Steuersatzes. |
| decimal | Höhe, z. B. |
| string | Bezeichnung, z. B. |
Category
Feld | Typ | Beschreibung |
|---|---|---|
| string | Eindeutige Sparten-ID. |
| integer | Sparten-Nummer. |
| string | Bezeichnung. |
Payment
Feld | Typ | Beschreibung |
|---|---|---|
| string | Eindeutige Zahlungs-ID. Zahlungen werden über diesen Wert dedupliziert. |
| decimal | Gezahlter Betrag. |
| Verwendetes Zahlungsmittel. | |
| string · nullable | Fibu-Kontonummer, auf die die Zahlung gebucht wird. Für die Zuordnung auf Sachkonten im Export. |
Payment type
Feld | Typ | Beschreibung |
|---|---|---|
| integer · nullable | Eindeutige Zahlungsmittel-ID. |
| integer · nullable | Zahlungsmittel-Nummer. Der Schlüssel heißt |
| string | Bezeichnung, z. B. |
Business
Feld | Typ | Beschreibung |
|---|---|---|
| string | Mandanten-ID aus der Kassendatenbank. |
| string | Firmenname. |
Staff
Feld | Typ | Beschreibung |
|---|---|---|
| string | Eindeutige Mitarbeiter-ID. |
| integer | Personalnummer. |
| string | Mitarbeitername. |
Table
Feld | Typ | Beschreibung |
|---|---|---|
| string | Eindeutige Tisch-ID. |
| integer | Tischnummer. |
| string | Tischbezeichnung, z. B. |
Location
Feld | Typ | Beschreibung |
|---|---|---|
| string | APRO-Standort-ID — die |
| string · nullable | Standortname. |
Area
Der Bereich bzw. die Zone, in der ein Tisch steht.
Feld | Typ | Beschreibung |
|---|---|---|
| string | Eindeutige Bereichs-ID. |
| integer | Bereichsnummer. |
| string | Bezeichnung, z. B. |
Payment group
Die Gruppierung, in der die Zahlungsarten zusammenlaufen — für Kassabuch- und Abschluss-Auswertungen.
Feld | Typ | Beschreibung |
|---|---|---|
| integer | Zahlungsgruppen-ID. |
| string | Bezeichnung der Gruppe. |
Customer
Feld | Typ | Beschreibung |
|---|---|---|
| string | Eindeutige Kunden-ID. |
| integer | Kundennummer. |
| string | Kundenname. |
Hinweis: Aktuell immer null
Der Receipts-Endpunkt befülltcustomernicht — das Feld ist im
Response-Contract reserviert, wird von der Abfrage aber nicht gesetzt.
Keine Rechnungsempfänger-Logik darauf aufbauen; Kunden stattdessen über
die eigenen Endpunkte auflösen.
Beispielantwort
Response · zwei direkt aufeinanderfolgende Abrechnungen
[
{
"transactionId": "f03e11de-6330-4a03-a8a8-b6e5fd4e32a5",
"transactionType": "Abrechnen",
"receiptType": "Beleg",
"totalAmount": 3.2,
"tip": 0.0,
"discount": 0.0,
"dateTime": "03.10.2021 21:59:57",
"business": { "id": "1", "name": "APRO Kassensysteme" },
"location": { "id": "7236", "name": "Wien Haupthaus" },
"staff": { "id": "8", "number": 9500, "name": "Onlinekellner" },
"table": { "id": "76", "number": 76, "name": "Daniel Z" },
"area": { "id": "3", "number": 3, "name": "Garten" },
"customer": null,
"paymentGroup": { "id": 2, "name": "Kartenzahlung" },
"payments": [
{
"id": "04b2d2f5-8765-41b5-ad5c-aed802dc23bc",
"amount": 3.2,
"paymentType": { "id": 26, "nr": 200, "name": "Smorder Kreditkarte" },
"fibuAccountNr": "2751"
}
],
"items": [
{
"id": "38",
"number": 216,
"name": "Wiener Schnitzel",
"uniqueId": "0f6c2c14-3f8a-4f0b-9a1e-2b7d5c8e4411",
"externalId": null,
"bookDate": "03.10.2021 21:59:55",
"grossAmount": 3.2,
"netAmount": 3.2,
"purchasePrice": 1.1,
"quantity": 1.0,
"course": 2,
"tax": { "id": "5", "value": 5.0, "name": "Mwst 5 %" },
"category": { "id": "12", "number": 12, "name": "Hauptspeisen" },
"sideDishes": [
{
"id": "512",
"number": 9001,
"name": "Pommes",
"uniqueId": "b41d9a77-55c2-4e3d-8f10-6cc0a2b93d88",
"grossAmount": 1.5,
"netAmount": 1.36,
"quantity": 1.0
},
{
"id": "518",
"number": 9007,
"name": "ohne Zwiebel",
"uniqueId": "c9a70e31-1d44-4a92-b7e5-30f8c1d6a204",
"grossAmount": 0.0,
"netAmount": 0.0,
"quantity": 1.0
}
]
}
],
"guestCount": 2
},
{
"transactionId": "db2b90d1-ab37-4557-b169-2289c3004a0a",
"transactionType": "Abrechnen",
"receiptType": "Beleg",
"totalAmount": 3.2,
"tip": 0.0,
"discount": 0.0,
"dateTime": "03.10.2021 22:00:12",
"business": { "id": "1", "name": "APRO Kassensysteme" },
"location": { "id": "7236", "name": "Wien Haupthaus" },
"staff": { "id": "8", "number": 9500, "name": "Onlinekellner" },
"table": { "id": "76", "number": 76, "name": "Daniel Z" },
"area": { "id": "3", "number": 3, "name": "Garten" },
"customer": null,
"paymentGroup": { "id": 2, "name": "Kartenzahlung" },
"payments": [
{
"id": "bb3e6300-0cc3-4922-80c4-a8a4c3530d3c",
"amount": 3.2,
"paymentType": { "id": 26, "nr": 200, "name": "Smorder Kreditkarte" },
"fibuAccountNr": "2751"
}
],
"items": [
{
"id": "38",
"number": 216,
"name": "Cola 0,5",
"uniqueId": "7d2f3b90-6c11-4c8e-93aa-5e4419c7f0d3",
"externalId": null,
"bookDate": "03.10.2021 22:00:11",
"grossAmount": 3.2,
"netAmount": 3.2,
"purchasePrice": 0.7,
"quantity": 1.0,
"course": null,
"tax": { "id": "5", "value": 5.0, "name": "Mwst 5 %" },
"category": { "id": "20", "number": 20, "name": "Alkoholfreie Getränke" },
"sideDishes": null
}
],
"guestCount": 1
}
]Dieselbe Payload als eigenständige Datei herunterladen: revenue-response.json
Transaktionstypen
Der transactionType unterscheidet, was eine Zeile repräsentiert. Für umsatzrelevante Reports auf Abrechnen filtern (und RechnungZurückholen für Rückholungen).
Typ | Bedeutung |
|---|---|
| Artikel auf offenen Tisch boniert. |
| Tischwechsel. |
| Abschluss — bezahlter Beleg. |
| Stornierung einer Buchung. |
| Rücknahme einer Abrechnung. |
| Debit-Buchung. |
| Ausgangsrechnungs-Lifecycle. |
| Tagesabschluss / Vorschau. |
| Kellnerübergabe / Abschlag. |
| Gesetzliche Fiskalbelege (RKSV). |
| Tisch-Lifecycle. |
| Bestellmanager-Events. |
| Warenkorb-Lifecycle. |
| Datenexport-Markierungen. |
| Weitere operative Ereignisse. |
Umsatzberechnung
Um den umsatzrelevanten Umsatz einer Antwort zu berechnen, behält man bezahlte Abrechnungen samt Rückholungen und summiert die Netto-Positionen:
response
.filter(x =>
x.paymentGroup.name === "Umsatzwirksam" &&
["Abrechnen", "RechnungZurückholen"].includes(x.transactionType)
)
.map(x =>
x.items.reduce((sum, item) => sum + item.netAmount * item.quantity, 0)
)
.reduce((sum, val) => sum + val, 0);Paging
Es gibt keinen Cursor in der Antwort — nutzen Sie die deterministische transactionId der zuletzt gesehenen Zeile als afterTransactionID der nächsten Anfrage, after/before bleiben unverändert. So lange iterieren, bis die Antwort weniger Zeilen liefert als Ihr limit.
