Deutschland Schnellstart
Dieser Schnellstart führt Sie durch die Authentifizierung mit der SIGN-DE-API, das Erstellen einer TSS (Technische Sicherheitseinrichtung) und das Signieren Ihrer ersten Transaktion. Am Ende verfügen Sie über einen funktionierenden Fiskalsignierungsablauf.
Voraussetzungen
Abschnitt betitelt „Voraussetzungen“- Ein fiskaly-Konto mit einer deutschen Organisation (Registrierung unter hub.fiskaly.com)
- Ein API-Schlüssel und -Secret, erstellt in der TEST-Umgebung
- Ein Tool für HTTP-Anfragen (cURL, Postman oder Ihr Anwendungscode)
Ihr API-Secret wird nur einmal angezeigt. Speichern Sie es sofort an einem sicheren Ort.
Schritte
Abschnitt betitelt „Schritte“Authentifizieren
Verwenden Sie Ihren API-Schlüssel und Ihr Secret, um ein Zugriffstoken zu erhalten:
curl -X POST https://kassensichv-middleware.fiskaly.com/api/v2/auth \ -H "Content-Type: application/json" \ -d '{ "api_key": "YOUR_API_KEY", "api_secret": "YOUR_API_SECRET" }'const response = await fetch( "https://kassensichv-middleware.fiskaly.com/api/v2/auth", { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ api_key: "YOUR_API_KEY", api_secret: "YOUR_API_SECRET", }), } ); const { access_token } = await response.json();import requests response = requests.post( "https://kassensichv-middleware.fiskaly.com/api/v2/auth", json={ "api_key": "YOUR_API_KEY", "api_secret": "YOUR_API_SECRET", }, ) access_token = response.json()["access_token"]HttpClient client = HttpClient.newHttpClient(); String body = """ {"api_key":"YOUR_API_KEY","api_secret":"YOUR_API_SECRET"} """; HttpRequest request = HttpRequest.newBuilder() .uri(URI.create("https://kassensichv-middleware.fiskaly.com/api/v2/auth")) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(body)) .build(); HttpResponse<String> response = client.send( request, HttpResponse.BodyHandlers.ofString()); // Parse response.body() for access_tokenusing var client = new HttpClient(); var payload = new { api_key = "YOUR_API_KEY", api_secret = "YOUR_API_SECRET" }; var response = await client.PostAsJsonAsync( "https://kassensichv-middleware.fiskaly.com/api/v2/auth", payload); var result = await response.Content .ReadFromJsonAsync<JsonElement>(); var accessToken = result .GetProperty("access_token").GetString();Die Antwort enthält ein
access_token(gültig 24h) und einrefresh_token(gültig 48h).TSS erstellen und initialisieren
TSS erstellen, Admin-PIN setzen, als Admin authentifizieren und initialisieren:
# TSS erstellen TSS_ID=$(uuidgen) curl -X PUT "https://kassensichv-middleware.fiskaly.com/api/v2/tss/${TSS_ID}" \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"description": "Quickstart TSS"}' # Admin-PIN ändern curl -X PATCH "https://kassensichv-middleware.fiskaly.com/api/v2/tss/${TSS_ID}/admin" \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"admin_puk": "ADMIN_PUK_FROM_RESPONSE", "new_admin_pin": "my-secure-pin"}' # Als Admin authentifizieren curl -X POST "https://kassensichv-middleware.fiskaly.com/api/v2/tss/${TSS_ID}/admin/auth" \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"admin_pin": "my-secure-pin"}' # TSS initialisieren curl -X PATCH "https://kassensichv-middleware.fiskaly.com/api/v2/tss/${TSS_ID}" \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"state": "INITIALIZED"}'const tssId = crypto.randomUUID(); const BASE = "https://kassensichv-middleware.fiskaly.com/api/v2"; const headers = { "Authorization": `Bearer ${accessToken}`, "Content-Type": "application/json", }; // TSS erstellen const tss = await fetch(`${BASE}/tss/${tssId}`, { method: "PUT", headers, body: JSON.stringify({ description: "Quickstart TSS" }), }).then(r => r.json()); // Admin-PIN ändern await fetch(`${BASE}/tss/${tssId}/admin`, { method: "PATCH", headers, body: JSON.stringify({ admin_puk: tss.admin_puk, new_admin_pin: "my-secure-pin", }), }); // Als Admin authentifizieren await fetch(`${BASE}/tss/${tssId}/admin/auth`, { method: "POST", headers, body: JSON.stringify({ admin_pin: "my-secure-pin" }), }); // TSS initialisieren await fetch(`${BASE}/tss/${tssId}`, { method: "PATCH", headers, body: JSON.stringify({ state: "INITIALIZED" }), });import uuid, requests tss_id = str(uuid.uuid4()) BASE = "https://kassensichv-middleware.fiskaly.com/api/v2" headers = {"Authorization": f"Bearer {access_token}"} # TSS erstellen tss = requests.put(f"{BASE}/tss/{tss_id}", headers=headers, json={"description": "Quickstart TSS"}).json() # Admin-PIN ändern requests.patch(f"{BASE}/tss/{tss_id}/admin", headers=headers, json={"admin_puk": tss["admin_puk"], "new_admin_pin": "my-secure-pin"}) # Als Admin authentifizieren requests.post(f"{BASE}/tss/{tss_id}/admin/auth", headers=headers, json={"admin_pin": "my-secure-pin"}) # TSS initialisieren requests.patch(f"{BASE}/tss/{tss_id}", headers=headers, json={"state": "INITIALIZED"})String tssId = UUID.randomUUID().toString(); String BASE = "https://kassensichv-middleware.fiskaly.com/api/v2"; // TSS erstellen HttpRequest createTss = HttpRequest.newBuilder() .uri(URI.create(BASE + "/tss/" + tssId)) .header("Authorization", "Bearer " + accessToken) .header("Content-Type", "application/json") .PUT(HttpRequest.BodyPublishers.ofString( "{\"description\":\"Quickstart TSS\"}")) .build(); String tssBody = client.send(createTss, HttpResponse.BodyHandlers.ofString()).body(); // admin_puk aus tssBody parsen, dann PIN ändern, Auth, Initialisierung...var tssId = Guid.NewGuid().ToString(); var BASE = "https://kassensichv-middleware.fiskaly.com/api/v2"; client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); // TSS erstellen var tss = await client.PutAsJsonAsync( $"{BASE}/tss/{tssId}", new { description = "Quickstart TSS" }); var tssData = await tss.Content.ReadFromJsonAsync<JsonElement>(); var adminPuk = tssData.GetProperty("admin_puk").GetString(); // Admin-PIN ändern, Auth, Initialisierung folgen dem gleichen Muster...Client erstellen
CLIENT_ID=$(uuidgen) curl -X PUT "https://kassensichv-middleware.fiskaly.com/api/v2/tss/${TSS_ID}/client/${CLIENT_ID}" \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"serial_number": "POS-001"}'const clientId = crypto.randomUUID(); const clientResp = await fetch( `${BASE}/tss/${tssId}/client/${clientId}`, { method: "PUT", headers, body: JSON.stringify({ serial_number: "POS-001" }), } );client_id = str(uuid.uuid4()) requests.put(f"{BASE}/tss/{tss_id}/client/{client_id}", headers=headers, json={"serial_number": "POS-001"})String clientId = UUID.randomUUID().toString(); HttpRequest createClient = HttpRequest.newBuilder() .uri(URI.create(BASE + "/tss/" + tssId + "/client/" + clientId)) .header("Authorization", "Bearer " + accessToken) .header("Content-Type", "application/json") .PUT(HttpRequest.BodyPublishers.ofString( "{\"serial_number\":\"POS-001\"}")) .build(); client.send(createClient, HttpResponse.BodyHandlers.ofString());var clientId = Guid.NewGuid().ToString(); await client.PutAsJsonAsync( $"{BASE}/tss/{tssId}/client/{clientId}", new { serial_number = "POS-001" });Erste Transaktion signieren
Transaktion starten, dann mit Bondaten abschließen:
TX_ID=$(uuidgen) # Transaktion starten curl -X PUT "https://kassensichv-middleware.fiskaly.com/api/v2/tss/${TSS_ID}/tx/${TX_ID}?tx_revision=1" \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -d '{"state": "ACTIVE", "client_id": "'${CLIENT_ID}'"}' # Transaktion mit Bon abschließen curl -X PUT "https://kassensichv-middleware.fiskaly.com/api/v2/tss/${TSS_ID}/tx/${TX_ID}?tx_revision=2" \ -H "Authorization: Bearer ${ACCESS_TOKEN}" \ -H "Content-Type: application/json" \ -d '{ "state": "FINISHED", "client_id": "'${CLIENT_ID}'", "schema": { "standard_v1": { "receipt": { "receipt_type": "RECEIPT", "amounts_per_vat_rate": [{"vat_rate": "NORMAL", "amount": "10.00"}], "amounts_per_payment_type": [{"payment_type": "CASH", "amount": "10.00"}] } } } }'const txId = crypto.randomUUID(); // Transaktion starten await fetch( `${BASE}/tss/${tssId}/tx/${txId}?tx_revision=1`, { method: "PUT", headers, body: JSON.stringify({ state: "ACTIVE", client_id: clientId }), } ); // Mit Bondaten abschließen const tx = await fetch( `${BASE}/tss/${tssId}/tx/${txId}?tx_revision=2`, { method: "PUT", headers, body: JSON.stringify({ state: "FINISHED", client_id: clientId, schema: { standard_v1: { receipt: { receipt_type: "RECEIPT", amounts_per_vat_rate: [ { vat_rate: "NORMAL", amount: "10.00" }, ], amounts_per_payment_type: [ { payment_type: "CASH", amount: "10.00" }, ], }, }, }, }), } ).then(r => r.json()); console.log("Signierte Transaktion:", tx.signature);tx_id = str(uuid.uuid4()) # Transaktion starten requests.put(f"{BASE}/tss/{tss_id}/tx/{tx_id}?tx_revision=1", headers=headers, json={"state": "ACTIVE", "client_id": client_id}) # Mit Bondaten abschließen tx = requests.put(f"{BASE}/tss/{tss_id}/tx/{tx_id}?tx_revision=2", headers=headers, json={ "state": "FINISHED", "client_id": client_id, "schema": { "standard_v1": { "receipt": { "receipt_type": "RECEIPT", "amounts_per_vat_rate": [ {"vat_rate": "NORMAL", "amount": "10.00"} ], "amounts_per_payment_type": [ {"payment_type": "CASH", "amount": "10.00"} ], } } }, }).json() print("Signiert:", tx["signature"])String txId = UUID.randomUUID().toString(); // Transaktion starten: PUT /tss/{tssId}/tx/{txId}?tx_revision=1 // Body: {"state":"ACTIVE","client_id":"<clientId>"} // Transaktion abschließen: PUT /tss/{tssId}/tx/{txId}?tx_revision=2 // Body: {"state":"FINISHED","client_id":"<clientId>","schema":{...}} // Antwort enthält die kryptografische Signatur der TSSvar txId = Guid.NewGuid().ToString(); // Starten: PUT /tss/{tssId}/tx/{txId}?tx_revision=1 // Body: { state = "ACTIVE", client_id = clientId } // Abschließen: PUT /tss/{tssId}/tx/{txId}?tx_revision=2 // Body: { state = "FINISHED", client_id = clientId, schema = {...} } // Antwort enthält die kryptografische Signatur der TSSDie Antwort enthält eine kryptografische
signatureder TSS, densignature_counterund alle für einen KassenSichV-konformen Beleg benötigten Daten.
Nächste Schritte
Abschnitt betitelt „Nächste Schritte“Was this page helpful?