Germany Quickstart
This quickstart walks you through authenticating with the SIGN DE API, creating a TSS (Technical Security System), and signing your first transaction. By the end you will have a working fiscal signing flow.
Prerequisites
Section titled “Prerequisites”- A fiskaly account with a German organization (sign up at hub.fiskaly.com)
- An API Key and Secret generated in the TEST environment
- A tool to make HTTP requests (cURL, Postman, or your application code)
⚠️Store credentials securely
Your API Secret is shown only once. Store it immediately in a secure location.
Authenticate
Use your API Key and Secret to obtain an access token:
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();The response contains an
access_token(valid 24h) and arefresh_token(valid 48h).Create and initialize a TSS
Create a TSS, set the Admin PIN, authenticate as admin, and initialize:
# Create TSS 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"}' # Change Admin PIN 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"}' # Authenticate as Admin 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"}' # Initialize TSS 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", }; // Create TSS const tss = await fetch(`${BASE}/tss/${tssId}`, { method: "PUT", headers, body: JSON.stringify({ description: "Quickstart TSS" }), }).then(r => r.json()); // Change Admin PIN await fetch(`${BASE}/tss/${tssId}/admin`, { method: "PATCH", headers, body: JSON.stringify({ admin_puk: tss.admin_puk, new_admin_pin: "my-secure-pin", }), }); // Authenticate as Admin await fetch(`${BASE}/tss/${tssId}/admin/auth`, { method: "POST", headers, body: JSON.stringify({ admin_pin: "my-secure-pin" }), }); // Initialize TSS 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}"} # Create TSS tss = requests.put(f"{BASE}/tss/{tss_id}", headers=headers, json={"description": "Quickstart TSS"}).json() # Change Admin PIN requests.patch(f"{BASE}/tss/{tss_id}/admin", headers=headers, json={"admin_puk": tss["admin_puk"], "new_admin_pin": "my-secure-pin"}) # Authenticate as Admin requests.post(f"{BASE}/tss/{tss_id}/admin/auth", headers=headers, json={"admin_pin": "my-secure-pin"}) # Initialize TSS 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"; // Create TSS 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(); // Parse admin_puk from tssBody, then change PIN, auth, initialize...var tssId = Guid.NewGuid().ToString(); var BASE = "https://kassensichv-middleware.fiskaly.com/api/v2"; client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); // Create TSS 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(); // Change Admin PIN, Auth, Initialize follow the same pattern...Create a Client
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" });Sign your first transaction
Start a transaction, then finish it with receipt data:
TX_ID=$(uuidgen) # Start transaction 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}'"}' # Finish transaction with receipt 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(); // Start transaction await fetch( `${BASE}/tss/${tssId}/tx/${txId}?tx_revision=1`, { method: "PUT", headers, body: JSON.stringify({ state: "ACTIVE", client_id: clientId }), } ); // Finish with receipt data 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("Signed transaction:", tx.signature);tx_id = str(uuid.uuid4()) # Start transaction requests.put(f"{BASE}/tss/{tss_id}/tx/{tx_id}?tx_revision=1", headers=headers, json={"state": "ACTIVE", "client_id": client_id}) # Finish with receipt data 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("Signed:", tx["signature"])String txId = UUID.randomUUID().toString(); // Start transaction: PUT /tss/{tssId}/tx/{txId}?tx_revision=1 // Body: {"state":"ACTIVE","client_id":"<clientId>"} // Finish transaction: PUT /tss/{tssId}/tx/{txId}?tx_revision=2 // Body: {"state":"FINISHED","client_id":"<clientId>","schema":{...}} // Response contains the cryptographic signature from the TSSvar txId = Guid.NewGuid().ToString(); // Start: PUT /tss/{tssId}/tx/{txId}?tx_revision=1 // Body: { state = "ACTIVE", client_id = clientId } // Finish: PUT /tss/{tssId}/tx/{txId}?tx_revision=2 // Body: { state = "FINISHED", client_id = clientId, schema = {...} } // Response contains the cryptographic signature from the TSSThe response includes a cryptographic
signaturefrom the TSS, thesignature_counter, and all data needed for a KassenSichV-compliant receipt.
Next Steps
Section titled “Next Steps”Was this page helpful?