Entwickler-Dokumentation · API v1

Registrierkasse an TrustNode anbinden

Diese Anleitung zeigt, wie eine Kassensoftware Belege über TrustNode RKSV-konform signieren lässt. Ablionis ist bereits angebunden. Für jede andere Kasse gelten dieselben Schritte.

REST · JSON HTTPS Beträge in Cent Asynchrone Signatur

Überblick

TrustNode ist eine REST-API. Alle Anfragen und Antworten verwenden JSON und laufen über HTTPS. Alle Endpunkte beginnen mit dem Präfix /api/v1.

https://api.trustnode.at/api/v1

Diese Adresse gilt für alle Mandanten. Ihre Zugangsdaten erhalten Sie von uns. In den Beispielen stehen für Adresse und Schlüssel die Umgebungsvariablen TRUSTNODE_URL und TRUSTNODE_API_KEY.

Der Ablauf einer Signatur

Die Signatur läuft asynchron. Ihre Kasse übergibt den Beleg und bekommt sofort eine Job-ID zurück. Mit dieser Job-ID fragt sie ab, bis der signierte Code vorliegt. Auch bei vielen gleichzeitigen Belegen bleibt die Verkettung dadurch in der richtigen Reihenfolge.

Sequenz: Kasse sendet Beleg, erhält Job-ID, TrustNode lässt bei A-Trust signieren, Kasse fragt Status ab und erhält den QR-Code. Registrierkasse TrustNode A-Trust (Signatur) POST /receipts/sign 202 · job_id Signatur anfordern Signatur Beleg gespeichert · Kette fortgeschrieben GET /receipts/jobs/{job_id} COMPLETED · qr_code_string QR-Code drucken

Zugang & Authentifizierung

Jede Anfrage wird mit einem API-Schlüssel im HTTP-Header X-API-Key authentifiziert. Es gibt zwei Arten von Schlüsseln:

SchlüsselFür wenBerechtigt zu
Mandanten-Schlüsselein Unternehmen, also die Betreiberin oder der Betreiber der KasseBelege signieren, Status abfragen, Sonderbelege, DEP-Export – nur für die eigenen Kassen
Partner-SchlüsselKassenhersteller und Softwarepartner wie AblionisKundschaft und Kassen anlegen, eigene Kundschaft auflisten – siehe Partner-API
HTTP-Header
X-API-Key: <Ihr API-Schlüssel>
Content-Type: application/json

Schlüssel werden nur ein einziges Mal angezeigt. TrustNode speichert sie nur als Hash und kann sie später nicht mehr auslesen. Bewahren Sie Schlüssel in einem Secret-Store oder in verschlüsselter Konfiguration auf, niemals im Quellcode, im Browser, in einer App oder in Logdateien.

Die Zugangsdaten erhalten Sie nach Vertragsabschluss von uns. Wenn ein Schlüssel verloren geht oder kompromittiert sein könnte, melden Sie sich sofort. Wir sperren ihn und stellen einen neuen aus.

Inbetriebnahme einer Kasse

Bevor eine Kasse reguläre Belege signiert, sind diese Schritte nötig:

  1. Unternehmen und Kasse anlegen: Das übernimmt entweder TrustNode oder Ihr Kassenhersteller über die Partner-API. Jede Kasse hat eine eindeutige Kassen-ID, zum Beispiel AT1-CAFE-001.
  2. Signaturzertifikat hinterlegen: TrustNode verknüpft das A-Trust-Signaturzertifikat des Unternehmens mit dem Zugang.
  3. Startbeleg erstellen: TrustNode erstellt den Startbeleg der Kasse, einen signierten Nullbeleg.
  4. Registrierung in FinanzOnline: Die Betreiberin oder der Betreiber bzw. die Steuerberatung registriert die Sicherheitseinrichtung und die Kasse. Dafür werden Kassen-ID, Zertifikatsseriennummer, AES-Schlüssel und AES-Prüfwert benötigt. TrustNode stellt diese Daten bereit.
  5. Startbeleg prüfen mit der BMF-Belegcheck-App.

Es gibt zwei Kennungen. Beim Signieren wird die Kasse über die Kassen-ID (kassen_id, Text) angesprochen. Für Sonderbelege und DEP-Export wird die technische Kassen-UUID (cash_register_id) verwendet, die Sie beim Anlegen erhalten.

Beleg signieren

Für jeden Barumsatz übergibt die Kasse einen Beleg. TrustNode prüft die Daten und nimmt den Beleg zur Signatur an.

POST/api/v1/receipts/signMandanten-Schlüssel · 202 Accepted

Felder der Anfrage

FeldTypBeschreibung
kassen_idstringPflichtKassen-ID einer Kasse Ihres Unternehmens
belegnummerstringPflichtFortlaufende Belegnummer, je Kasse eindeutig, max. 50 Zeichen
betrag_normal_centinteger0Bruttobetrag zum Normalsteuersatz (20 %) in Cent
betrag_ermaessigt1_centinteger0Bruttobetrag zum ermäßigten Satz 1 (10 %) in Cent
betrag_ermaessigt2_centinteger0Bruttobetrag zum ermäßigten Satz 2 (13 %) in Cent
betrag_null_centinteger0Steuerfreie bzw. nicht steuerbare Beträge (0 %) in Cent
betrag_besonders_centinteger0Bruttobetrag zum besonderen Steuersatz in Cent
is_trainingbooleanfalseTrainingsbuchung, verändert den Umsatzzähler nicht
storno_of_receipt_numberstring | nullnullBelegnummer des stornierten Belegs. Pflicht, wenn die Summe negativ ist
delivery_typestring | nullnullArt der Belegausgabe: "PAPIER" oder "ELEKTRONISCH"
original_receipt_datetimestring | nullnullNur bei Nacherfassung: Zeitpunkt des ursprünglich ausgegebenen Ausfallbons, ISO 8601 mit Zeitzone (z. B. 2026-09-19T14:32:07+02:00). Wird gespeichert, der signierte Beleg trägt aber den Zeitpunkt der Nacherfassung.
original_receipt_numberstring | nullnullNur bei Nacherfassung: Nummer des ursprünglich ausgegebenen Offline-Belegs (max. 50 Zeichen). Muss sich von belegnummer unterscheiden, denn die Nacherfassung erhält eine neue Belegnummer (siehe Nacherfassung).
Anfrage · JSON
{
  "kassen_id": "AT1-CAFE-001",
  "belegnummer": "2026-004711",
  "betrag_normal_cent": 1250,
  "betrag_ermaessigt1_cent": 480,
  "delivery_type": "PAPIER"
}

Unbekannte Felder werden ignoriert. Ihre Kasse kann also zusätzliche Felder mitsenden, ohne dass die Anfrage abgelehnt wird. Ausgewertet werden nur die oben genannten.

Antwort

Ist der Beleg angenommen, antwortet TrustNode mit 202 Accepted und einer job_id. Die Signatur läuft im Hintergrund.

202 Accepted · JSON
{
  "receipt_id": null,
  "status": "PROCESSING_ASYNC",
  "job_id": "3f9c2a7e5b1d4c8e9a0f6b2d7c1e4a93"
}

Status & QR-Code abrufen

Mit der job_id fragt die Kasse ab, ob der Beleg signiert ist. Sobald der Status COMPLETED ist, enthält die Antwort den fertigen maschinenlesbaren Code.

GET/api/v1/receipts/jobs/{job_id}Mandanten-Schlüssel · 200 OK
FeldTypBeschreibung
job_idstringDie abgefragte Job-ID
statusstringPENDING = in Arbeit, COMPLETED = signiert und gespeichert, FAILED = abgelehnt, nicht signiert. Unbekannte Werte wie PENDING behandeln.
receipt_iduuid | nullKennung des gespeicherten Belegs (bei COMPLETED)
qr_code_stringstring | nullMaschinenlesbarer Code nach RKSV. Diesen Text 1:1 als QR-Code auf den Beleg drucken
is_offline_receiptboolean | nulltrue, wenn der Beleg bei Signaturausfall ausgestellt wurde (siehe Signaturausfall)
error_codestring | nullNur bei FAILED: Grund der Ablehnung (siehe unten)
200 OK · JSON
{
  "job_id": "3f9c2a7e5b1d4c8e9a0f6b2d7c1e4a93",
  "status": "COMPLETED",
  "receipt_id": "b7e41c0a-5d2f-4e8b-9a61-2c3d4e5f6a7b",
  "qr_code_string": "_R1-AT1_AT1-CAFE-001_2026-004711_2026-09-18T14:32:07_12,50_4,80_0,00_0,00_0,00_…",
  "is_offline_receipt": false
}

Aufbau des maschinenlesbaren Codes

Der Code folgt dem RKSV-Format und wird von TrustNode vollständig erzeugt. Die Kasse muss ihn nicht zerlegen, nur drucken:

Format
_R1-AT1_{Kassen-ID}_{Belegnummer}_{Datum-Uhrzeit}_{Normal}_{Ermäßigt1}_{Ermäßigt2}_{Null}_{Besonders}_{Umsatzzähler-verschlüsselt}_{Zertifikat-Seriennummer}_{Verkettungswert}_{Signatur}

Wenn ein Beleg abgelehnt wird

Lehnt TrustNode einen Beleg fachlich ab, lautet der Status FAILED und das Feld error_code nennt den Grund. Es wurde dann nichts signiert, und Umsatzzähler und Kette sind unverändert.

error_codeBedeutung
DUPLICATE_RECEIPT_NUMBERDie Belegnummer ist auf dieser Kasse bereits von einem anderen Beleg belegt.
CASH_REGISTER_INACTIVEDie Kasse wurde deaktiviert oder mit einem Schlussbeleg außer Betrieb genommen.
STORNO_OF_TRAINING_RECEIPTDer Storno verweist auf einen Trainingsbeleg, ist aber selbst nicht als Training gekennzeichnet (siehe Storno & Training).
INTERNAL_ERRORUnerwarteter Fehler bei TrustNode. Bitte mit job_id an uns melden.

Empfohlenes Abfrageverhalten

  • Erste Abfrage nach etwa 200 ms, danach mit wachsendem Abstand bis höchstens 2 Sekunden.
  • Setzen Sie ein Gesamt-Timeout, zum Beispiel 15 Sekunden, und zeigen Sie der Bedienung danach einen Hinweis.
  • Verwerfen Sie die job_id nach dem Timeout nicht. Fragen Sie im Hintergrund weiter ab: Ein Beleg kann auch später noch fertig signiert werden.
  • Signierte Belege sind unter ihrer job_id dauerhaft abrufbar, abgelehnte (FAILED) 8 Tage lang. Ein 404 kommt nur für Jobs, die es nicht gibt oder die einem anderen Unternehmen gehören.

Beleg sicher erneut senden

Ist die Antwort auf POST /receipts/sign verloren gegangen, etwa durch einen Netzwerkfehler oder Timeout, dürfen Sie den Beleg mit derselben Belegnummer und denselben Daten erneut senden. TrustNode erkennt die Wiederholung und liefert die job_id des ursprünglichen Belegs zurück. Es entsteht kein zweiter Beleg.

  • Gleiche Belegnummer, gleiche Daten: 202 mit der ursprünglichen job_id.
  • Gleiche Belegnummer, andere Beträge oder Kennzeichen: 409 Conflict.
  • War der vorherige Versuch abgelehnt (FAILED), wird der neue Versuch normal verarbeitet.

Nie mit einer neuen Belegnummer wiederholen. Das würde einen zweiten, echten Beleg mit demselben Umsatz erzeugen.

Steuersätze & Beträge

Die Kasse teilt den Umsatz jedes Belegs auf die fünf Betragsfelder der RKSV auf. TrustNode addiert sie zum Umsatz, schreibt den Umsatzzähler fort und formatiert die Beträge für den signierten Code.

RKSV-FeldSatzAPI-Feld
Betrag-Satz-Normal20 %betrag_normal_cent
Betrag-Satz-Ermaessigt-110 %betrag_ermaessigt1_cent
Betrag-Satz-Ermaessigt-213 %betrag_ermaessigt2_cent
Betrag-Satz-Null0 %betrag_null_cent
Betrag-Satz-Besondersbesonderer Satzbetrag_besonders_cent

Alle Beträge sind ganze Zahlen in Cent, brutto. 12,50 € wird als 1250 übertragen. Kommazahlen wie 12.5 oder Zahlen als Text wie "1250" werden mit 422 abgelehnt. So entstehen keine Rundungsfehler.

Storno & Training

Stornobeleg

Ein Storno ist ein eigener Beleg mit eigener Belegnummer und negativen Beträgen. Bei negativer Summe ist storno_of_receipt_number Pflicht und verweist auf den ursprünglichen Beleg.

Storno · JSON
{
  "kassen_id": "AT1-CAFE-001",
  "belegnummer": "2026-004712",
  "betrag_normal_cent": -1250,
  "storno_of_receipt_number": "2026-004711"
}

Trainingsbuchung

Mit "is_training": true wird ein Trainingsbeleg erstellt. Er wird signiert und verkettet, der Umsatzzähler bleibt aber unverändert.

Der Storno eines Trainingsbelegs muss ebenfalls mit "is_training": true gesendet werden. Sonst würde ein echter negativer Umsatz entstehen. TrustNode lehnt einen solchen Storno mit STORNO_OF_TRAINING_RECEIPT ab.

Signaturausfall

Ist die Signaturerstellungseinheit vorübergehend nicht erreichbar, stellt TrustNode den Beleg trotzdem aus. Statt der Signatur enthält der Code dann den Hinweis „Sicherheitseinrichtung ausgefallen“, und is_offline_receipt ist true.

  • Drucken Sie den qr_code_string wie gewohnt. Die Kasse kann normal weiterarbeiten.
  • Zeigen Sie der Bedienung einen gut sichtbaren Hinweis, damit ein längerer Ausfall bemerkt wird. Für länger andauernde Ausfälle gelten die gesetzlichen Meldepflichten.
  • Ist die Signatur wieder verfügbar, erstellen Sie einen Sammelbeleg. Er schließt an die Kette an und dokumentiert das Ende des Ausfalls. Die Ausfallbelege selbst bleiben unverändert gespeichert.

Nacherfassung

Anders als beim Signaturausfall erreicht die Kasse TrustNode hier gar nicht, zum Beispiel ohne Internet. Die Kasse gibt dann einen eigenen Offline-Beleg aus und erfasst den Vorgang später in TrustNode nach.

  1. Offline-Belege mit einer eigenen Nummernserie ausgeben (z. B. OFF-2026-00017), getrennt von den Belegnummern, die an TrustNode gehen.
  2. Vor der Nacherfassung prüfen, ob der ursprüngliche Vorgang TrustNode nicht doch erreicht hat, etwa wenn nur die Antwort verloren ging (siehe unten).
  3. Nur wenn TrustNode ausdrücklich NOT_FOUND meldet: den Vorgang mit einer neuen Belegnummer senden, dazu original_receipt_number und original_receipt_datetime des Offline-Belegs.

Belegnummer nachschlagen

GET/api/v1/receipts/by-number?kassen_id=AT1-CAFE-001&belegnummer=2026-004711Mandanten-Schlüssel · 200 OK
statusBedeutungEmpfohlene Reaktion
FOUNDBeleg ist signiert und gespeichert. Die Antwort enthält qr_code_string, receipt_date und job_id.Nicht nacherfassen. Den vorhandenen Beleg verwenden.
PENDINGDer Beleg ist angekommen und wird noch verarbeitet.Mit der job_id den Status abfragen.
FAILEDEin Versuch unter dieser Nummer wurde abgelehnt. error_code nennt den Grund.Grund prüfen, erst dann entscheiden.
NOT_FOUNDUnter dieser Nummer ist bei TrustNode nichts angekommen.Nacherfassung ist sicher.

Nur ein 200 mit "status": "NOT_FOUND" bedeutet „nicht vorhanden“. Ein HTTP-404 bedeutet eine unbekannte Kasse. Er kann auch von einem Proxy während einer Wartung kommen. Timeouts und 5xx sind ebenfalls keine Aussage über den Beleg. In diesen Fällen nicht nacherfassen, sondern später erneut prüfen.

Nacherfassung · JSON
{
  "kassen_id": "AT1-CAFE-001",
  "belegnummer": "2026-004718",
  "betrag_normal_cent": 1250,
  "original_receipt_number": "OFF-2026-00017",
  "original_receipt_datetime": "2026-09-18T14:32:07+02:00"
}

Codebeispiele

Das vollständige Muster: Beleg senden, Status abfragen, QR-Code-Text zurückgeben. API-Adresse und Schlüssel kommen aus Umgebungsvariablen.

cURL
# 1. Beleg zur Signatur übergeben
curl -sS -X POST "$TRUSTNODE_URL/api/v1/receipts/sign" \
  -H "X-API-Key: $TRUSTNODE_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "kassen_id": "AT1-CAFE-001",
        "belegnummer": "2026-004711",
        "betrag_normal_cent": 1250,
        "betrag_ermaessigt1_cent": 480
      }'

# 2. Status abfragen (job_id aus der Antwort von Schritt 1)
curl -sS "$TRUSTNODE_URL/api/v1/receipts/jobs/3f9c2a7e5b1d4c8e9a0f6b2d7c1e4a93" \
  -H "X-API-Key: $TRUSTNODE_API_KEY"
Python 3 · requests
import os
import time

import requests

BASE = os.environ["TRUSTNODE_URL"] + "/api/v1"
HEADERS = {"X-API-Key": os.environ["TRUSTNODE_API_KEY"]}


def sign_receipt(beleg: dict, timeout_s: float = 15.0) -> dict:
    r = requests.post(f"{BASE}/receipts/sign", json=beleg, headers=HEADERS, timeout=10)
    r.raise_for_status()  # 202 Accepted
    job_id = r.json()["job_id"]

    deadline = time.monotonic() + timeout_s
    delay = 0.2
    while time.monotonic() < deadline:
        s = requests.get(f"{BASE}/receipts/jobs/{job_id}", headers=HEADERS, timeout=10)
        if s.status_code == 404:
            raise LookupError(f"Job {job_id} unbekannt oder abgelaufen")
        s.raise_for_status()
        job = s.json()
        if job["status"] == "COMPLETED":
            return job  # job["qr_code_string"] als QR-Code drucken
        if job["status"] == "FAILED":
            raise RuntimeError(f"Beleg abgelehnt: {job['error_code']}")
        time.sleep(delay)
        delay = min(delay * 1.5, 2.0)
    raise TimeoutError(f"Job {job_id} nicht rechtzeitig abgeschlossen")


job = sign_receipt({
    "kassen_id": "AT1-CAFE-001",
    "belegnummer": "2026-004711",
    "betrag_normal_cent": 1250,       # 12,50 € zu 20 %
    "betrag_ermaessigt1_cent": 480,   #  4,80 € zu 10 %
})
print(job["qr_code_string"])
JavaScript · Node.js 18+ (fetch)
const BASE = `${process.env.TRUSTNODE_URL}/api/v1`;
const headers = {
  "X-API-Key": process.env.TRUSTNODE_API_KEY,
  "Content-Type": "application/json",
};
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

export async function signReceipt(beleg, timeoutMs = 15000) {
  const res = await fetch(`${BASE}/receipts/sign`, {
    method: "POST",
    headers,
    body: JSON.stringify(beleg),
  });
  if (res.status !== 202) {
    throw new Error(`Beleg abgelehnt: ${res.status} ${await res.text()}`);
  }
  const { job_id } = await res.json();

  const deadline = Date.now() + timeoutMs;
  for (let delay = 200; Date.now() < deadline; delay = Math.min(delay * 1.5, 2000)) {
    const s = await fetch(`${BASE}/receipts/jobs/${job_id}`, { headers });
    if (s.status === 404) throw new Error(`Job ${job_id} unbekannt oder abgelaufen`);
    const job = await s.json();
    if (job.status === "COMPLETED") return job; // job.qr_code_string drucken
    if (job.status === "FAILED") throw new Error(`Beleg abgelehnt: ${job.error_code}`);
    await sleep(delay);
  }
  throw new Error(`Job ${job_id} nicht rechtzeitig abgeschlossen`);
}

// Nur serverseitig verwenden – der API-Schlüssel gehört nicht in den Browser.
const job = await signReceipt({
  kassen_id: "AT1-CAFE-001",
  belegnummer: "2026-004711",
  betrag_normal_cent: 1250,
  betrag_ermaessigt1_cent: 480,
});
console.log(job.qr_code_string);
C# · .NET 8
using System.Net;
using System.Net.Http.Json;

var http = new HttpClient
{
    BaseAddress = new Uri(Environment.GetEnvironmentVariable("TRUSTNODE_URL") + "/api/v1/"),
    Timeout = TimeSpan.FromSeconds(10),
};
http.DefaultRequestHeaders.Add("X-API-Key", Environment.GetEnvironmentVariable("TRUSTNODE_API_KEY"));

var beleg = new
{
    kassen_id = "AT1-CAFE-001",
    belegnummer = "2026-004711",
    betrag_normal_cent = 1250L,      // 12,50 € zu 20 %
    betrag_ermaessigt1_cent = 480L,  //  4,80 € zu 10 %
};

var res = await http.PostAsJsonAsync("receipts/sign", beleg);
res.EnsureSuccessStatusCode(); // 202 Accepted
var start = await res.Content.ReadFromJsonAsync<JobStart>();

var deadline = DateTime.UtcNow.AddSeconds(15);
var delay = 200;
while (DateTime.UtcNow < deadline)
{
    var s = await http.GetAsync($"receipts/jobs/{start!.job_id}");
    if (s.StatusCode == HttpStatusCode.NotFound)
        throw new InvalidOperationException($"Job {start.job_id} unbekannt oder abgelaufen");
    s.EnsureSuccessStatusCode();

    var job = await s.Content.ReadFromJsonAsync<JobStatus>();
    if (job!.status == "COMPLETED")
    {
        Console.WriteLine(job.qr_code_string); // als QR-Code drucken
        return;
    }
    if (job.status == "FAILED")
        throw new InvalidOperationException($"Beleg abgelehnt: {job.error_code}");
    await Task.Delay(delay);
    delay = Math.Min(delay * 3 / 2, 2000);
}
throw new TimeoutException($"Job {start.job_id} nicht rechtzeitig abgeschlossen");

record JobStart(string job_id, string status);
record JobStatus(string job_id, string status, Guid? receipt_id, string? qr_code_string, bool? is_offline_receipt, string? error_code);

Sonderbelege

Sonderbelege sind signierte Nullbelege, die die RKSV zu bestimmten Anlässen verlangt. Sie werden über die Kassen-UUID angesprochen und antworten mit 202 Accepted. Den Status fragen Sie wie bei normalen Belegen über GET /api/v1/receipts/jobs/{job_id} ab. Nach COMPLETED enthält die Antwort den qr_code_string des Sonderbelegs.

202 Accepted · JSON
{
  "job_id": "8a1d0c5e7f2b4a6c9e3d1b0a7c5e2f48",
  "receipt_type": "SAMMELBELEG"
}
EndpunktBelegWann
POST /api/v1/cash-registers/{cash_register_id}/monthly-receiptMonatsbelegWird von TrustNode am letzten Tag jedes Monats automatisch erstellt. Manuell nur bei Bedarf.
POST /api/v1/cash-registers/{cash_register_id}/annual-receiptJahresbelegAutomatisch Ende Dezember. Danach mit der BMF-Belegcheck-App prüfen.
POST /api/v1/cash-registers/{cash_register_id}/summary-receiptSammelbelegNach Ende eines Signaturausfalls. Schließt signiert an die Kette an.
POST /api/v1/cash-registers/{cash_register_id}/control-receiptKontrollbelegAuf Verlangen der Finanzbehörde.
POST /api/v1/cash-registers/{cash_register_id}/closing-receiptSchlussbelegBei Außerbetriebnahme. Die Kasse ist danach dauerhaft inaktiv.

Sonderbelege können nur für aktive Kassen erstellt werden, sonst antwortet TrustNode mit 409 Conflict und error_code: CASH_REGISTER_INACTIVE. Führen Sie vor einem Schlussbeleg einen DEP-Export durch und lösen Sie den Schlussbeleg in Ihrer Kasse nur nach einer ausdrücklichen Bestätigung aus.

QR-Codes von Sonderbelegen abrufen

Den Jahresbeleg muss die Betreiberin oder der Betreiber bis 15. Februar mit der BMF-Belegcheck-App prüfen, den Startbeleg nach der Registrierung in FinanzOnline. Die Kasse kann dafür den maschinenlesbaren Code aller Sonderbelege abrufen und als QR-Code anzeigen.

GET/api/v1/receipts/special?kassen_id=AT1-CAFE-001&receipt_type=JAHRESBELEGMandanten-Schlüssel · 200 OK
ParameterBeschreibung
kassen_idPflichtKassen-ID
receipt_typealleSTARTBELEG, MONATSBELEG, JAHRESBELEG, SAMMELBELEG, SCHLUSSBELEG oder KONTROLLBELEG
limit20Anzahl, 1 bis 100, neueste zuerst
200 OK · JSON
{
  "kassen_id": "AT1-CAFE-001",
  "receipts": [
    {
      "receipt_number": "JAHRESBELEG-2026-12",
      "receipt_type": "JAHRESBELEG",
      "receipt_date": "2026-12-31T22:50:01Z",
      "qr_code_string": "_R1-AT1_AT1-CAFE-001_JAHRESBELEG-2026-12_2026-12-31T23:50:01_0,00_…",
      "is_offline_receipt": false
    }
  ]
}

Den qr_code_string unverändert als QR-Code darstellen. Sonderbelege bleiben auch nach dem Deaktivieren oder Stilllegen einer Kasse abrufbar. Normale Belege sind über diesen Endpunkt nicht abrufbar.

DEP-Export

Das Datenerfassungsprotokoll enthält alle Belege einer Kasse im RKSV-Exportformat, gruppiert nach Signaturzertifikat.

POST/api/v1/cash-registers/{cash_register_id}/export-depMandanten-Schlüssel · 202 Accepted
202 Accepted · JSON
{
  "job_id": "c2e9b4a17d3f4e0a8b6c5d2e1f0a9b87"
}

Der Export wird im gesicherten Speicher von TrustNode abgelegt. Zusätzlich sichert TrustNode das DEP jedes Quartal automatisch. Für eine Betriebsprüfung stellen wir Ihnen den Export bereit.

Partner-API

Über die Partner-API legen Kassenhersteller und Softwarepartner ihre Kundschaft und deren Kassen direkt aus der eigenen Software an, so wie Ablionis. Alle Aufrufe verwenden den Partner-Schlüssel. Partner sehen ausschließlich die eigene Kundschaft.

Unternehmen und erste Kasse anlegen

POST/api/v1/reseller/provisionPartner-Schlüssel · 201 Created

Legt in einem Schritt ein neues Unternehmen samt erster Kasse an und liefert den Mandanten-Schlüssel dieses Unternehmens.

FeldTypBeschreibung
tenant_namestringPflichtName des Unternehmens
tenant_slugstringPflichtEindeutiges Kürzel, z. B. cafe-mustermann
kassen_idstringPflichtKassen-ID der ersten Kasse
Anfrage · JSON
{
  "tenant_name": "Café Mustermann GmbH",
  "tenant_slug": "cafe-mustermann",
  "kassen_id": "AT1-CAFE-001"
}
201 Created · JSON
{
  "tenant_id": "0e6f1a2b-3c4d-4e5f-8a9b-0c1d2e3f4a5b",
  "api_key": "<Mandanten-Schlüssel – wird nur jetzt angezeigt>",
  "cash_register_id": "5a4b3c2d-1e0f-4a9b-8c7d-6e5f4a3b2c1d",
  "kassen_id": "AT1-CAFE-001"
}

Speichern Sie api_key sofort verschlüsselt und dem Unternehmen zugeordnet ab. Er wird nur in dieser Antwort übertragen und kann nicht erneut abgerufen werden.

Weitere Kasse hinzufügen

POST/api/v1/reseller/tenants/{tenant_id}/cash-registersPartner-Schlüssel · 201 Created
Anfrage · JSON
{
  "kassen_id": "AT1-CAFE-002"
}
AntwortfeldBeschreibung
idKassen-UUID (cash_register_id)
kassen_identifikationsnummerKassen-ID
statusStatus der Kasse, z. B. ACTIVE
tenant_idZugehöriges Unternehmen
aes_256_key_base64AES-256-Schlüssel der Kasse für die FinanzOnline-Registrierung. Vertraulich behandeln.
aes_pruefwertPrüfwert des AES-Schlüssels für die FinanzOnline-Registrierung

Eigene Kundschaft auflisten

GET/api/v1/reseller/tenantsPartner-Schlüssel · 200 OK

Liefert alle Unternehmen, die Ihrem Partnerzugang zugeordnet sind, jeweils mit id, name, slug, status und den Angaben zum hinterlegten Signaturzertifikat.

Statuscodes & Fehler

Fehler werden als JSON mit dem Feld detail zurückgegeben. Bei 409 enthält die Antwort zusätzlich ein maschinenlesbares error_code. Werten Sie dieses aus, nicht den Text in detail.

Fehlerantwort · JSON
{
  "detail": "Kasse 'AT1-CAFE-009' nicht gefunden oder nicht autorisiert"
}
CodeBedeutungWas tun?
200OK–
201Angelegt (Partner-API)Rückgabewerte speichern, insbesondere api_key.
202Angenommen, Verarbeitung läuftStatus über die job_id abfragen.
401API-Schlüssel fehlt, ist ungültig oder der Zugang ist deaktiviertHeader X-API-Key prüfen. Nicht automatisch wiederholen.
404Kasse, Unternehmen oder Job nicht gefunden, oder kein Zugriff darauf. Diese Antworten haben immer einen JSON-Body mit detail.Kassen-ID bzw. UUID prüfen. Bei Jobs: abgelaufen oder unbekannt. Ein 404 ohne JSON-Body kommt nicht von TrustNode, sondern z. B. während einer Wartung vom vorgelagerten Proxy. Behandeln Sie ihn wie einen 5xx.
409Belegnummer bereits mit anderen Daten verwendet (error_code: DUPLICATE_RECEIPT_NUMBER), oder Kasse nicht aktiv (error_code: CASH_REGISTER_INACTIVE)Beleg nicht mit neuer Nummer wiederholen, sondern den Vorgang prüfen. Bei CASH_REGISTER_INACTIVE die Betreiberin oder den Betreiber deutlich warnen: Die Kasse wurde deaktiviert oder stillgelegt.
422Ungültige DatenDie Antwort nennt Feld und Grund. Häufige Ursachen: Kommazahl statt Cent, fehlendes Pflichtfeld, negative Summe ohne Storno-Verweis.
5xxVorübergehender Serverfehler, z. B. 503 für einige Sekunden während einer WartungMit Pause erneut versuchen, bei Signaturanfragen mit derselben Belegnummer (siehe Beleg sicher erneut senden).
422 Unprocessable Entity · JSON
{
  "detail": [
    {
      "type": "int_type",
      "loc": ["body", "betrag_normal_cent"],
      "msg": "Input should be a valid integer",
      "input": 12.5
    }
  ]
}

Best Practices

  • Schlüssel nur serverseitig: Rufen Sie TrustNode aus Ihrem Kassen-Backend oder der Kassenanwendung auf, nie aus einem Browser oder einer öffentlich verteilten App mit eingebettetem Schlüssel.
  • Ein Schlüssel pro Unternehmen: Verwenden Sie für jedes Unternehmen dessen eigenen Mandanten-Schlüssel. Belege nie über einen fremden Zugang signieren.
  • Belegnummern lückenlos und eindeutig: Vergeben Sie die Belegnummer in der Kasse, bevor Sie den Beleg senden, und speichern Sie sie zusammen mit der job_id.
  • Beträge in Cent rechnen: Rechnen Sie auch in Ihrer Kasse durchgehend mit ganzen Cent und wandeln Sie erst für die Anzeige in Euro um.
  • QR-Code unverändert drucken: Den qr_code_string exakt so übernehmen, ohne Kürzen, Trimmen oder Umkodieren.
  • Ausfälle sichtbar machen: is_offline_receipt auswerten und die Bedienung informieren.
  • Übertragung dauerhaft speichern: Legen Sie jeden Beleg vor dem Senden in einer dauerhaften Warteschlange ab und senden Sie ihn bei Verbindungsproblemen später mit denselben Daten erneut. So geht kein Umsatz verloren (siehe Beleg sicher erneut senden und Nacherfassung).
  • Erreichbarkeit prüfen: GET /api/v1/health/live antwortet ohne Schlüssel mit 200 und {"status": "ok"}. Das eignet sich für Monitoring, ersetzt aber nicht die Auswertung der eigentlichen Antworten.
  • Protokollieren ohne Geheimnisse: job_id, Belegnummer und Statuscodes loggen, den API-Schlüssel nie.

Go-live-Checkliste

  • Zugangsdaten sicher hinterlegtMandanten- bzw. Partner-Schlüssel im Secret-Store, nicht im Code
  • Startbeleg erstellt und geprüftKasse und Sicherheitseinrichtung in FinanzOnline registriert, Startbeleg mit der BMF-Belegcheck-App geprüft
  • Steuersätze korrekt zugeordnetJeder Artikel landet im richtigen der fünf Betragsfelder
  • Storno, Training und Ausfall getestetinkl. Hinweis an die Bedienung bei is_offline_receipt
  • QR-Code lesbarGedruckter Code mit der BMF-Belegcheck-App erfolgreich geprüft
  • Verbindungsausfall getestetTrustNode nicht erreichbar → Ersatzbeleg der Kasse → Nachschlagen über by-number → Nacherfassung mit Verweis
  • Timeouts & Fehler behandeltWiederholung nur mit derselben Belegnummer, FAILED wird ausgewertet, job_id wird protokolliert

Fragen zur Integration oder einen Testzugang? Schreiben Sie an office@jln-digital.at.