Inicio rápido de Alemania
Este inicio rápido te guía a través de la autenticación con la API de SIGN DE, la creación de un TSS (Sistema de Seguridad Técnica) y la firma de tu primera transacción. Al final tendrás un flujo de firma fiscal funcional.
Requisitos previos
Sección titulada «Requisitos previos»- Una cuenta fiskaly con una organización alemana (regístrate en hub.fiskaly.com)
- Una clave de API y un secreto generados en el entorno de PRUEBA
- Una herramienta para realizar solicitudes HTTP (cURL, Postman o el código de tu aplicación)
Tu secreto de API se muestra solo una vez. Guárdalo inmediatamente en un lugar seguro.
Autenticar
Usa tu clave de API y secreto para obtener un token de acceso:
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();La respuesta contiene un
access_token(válido 24h) y unrefresh_token(válido 48h).Crear e inicializar un TSS
Crea un TSS, establece el PIN de administrador, autentícate como administrador e inicializa:
# Crear 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"}' # Cambiar PIN de administrador 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"}' # Autenticarse como administrador 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"}' # Inicializar 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", }; // Crear TSS const tss = await fetch(`${BASE}/tss/${tssId}`, { method: "PUT", headers, body: JSON.stringify({ description: "Quickstart TSS" }), }).then(r => r.json()); // Cambiar PIN de administrador await fetch(`${BASE}/tss/${tssId}/admin`, { method: "PATCH", headers, body: JSON.stringify({ admin_puk: tss.admin_puk, new_admin_pin: "my-secure-pin", }), }); // Autenticarse como administrador await fetch(`${BASE}/tss/${tssId}/admin/auth`, { method: "POST", headers, body: JSON.stringify({ admin_pin: "my-secure-pin" }), }); // Inicializar 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}"} # Crear TSS tss = requests.put(f"{BASE}/tss/{tss_id}", headers=headers, json={"description": "Quickstart TSS"}).json() # Cambiar PIN de administrador requests.patch(f"{BASE}/tss/{tss_id}/admin", headers=headers, json={"admin_puk": tss["admin_puk"], "new_admin_pin": "my-secure-pin"}) # Autenticarse como administrador requests.post(f"{BASE}/tss/{tss_id}/admin/auth", headers=headers, json={"admin_pin": "my-secure-pin"}) # Inicializar 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"; // Crear 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); // Crear 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(); // Cambiar PIN de administrador, Auth, Inicializar siguen el mismo patrón...Crear un cliente
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" });Firmar tu primera transacción
Inicia una transacción y luego finalízala con los datos del recibo:
TX_ID=$(uuidgen) # Iniciar transacción 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}'"}' # Finalizar transacción con recibo 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(); // Iniciar transacción await fetch( `${BASE}/tss/${tssId}/tx/${txId}?tx_revision=1`, { method: "PUT", headers, body: JSON.stringify({ state: "ACTIVE", client_id: clientId }), } ); // Finalizar con datos del recibo 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("Transacción firmada:", tx.signature);tx_id = str(uuid.uuid4()) # Iniciar transacción requests.put(f"{BASE}/tss/{tss_id}/tx/{tx_id}?tx_revision=1", headers=headers, json={"state": "ACTIVE", "client_id": client_id}) # Finalizar con datos del recibo 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("Firmado:", tx["signature"])String txId = UUID.randomUUID().toString(); // Iniciar transacción: PUT /tss/{tssId}/tx/{txId}?tx_revision=1 // Body: {"state":"ACTIVE","client_id":"<clientId>"} // Finalizar transacción: PUT /tss/{tssId}/tx/{txId}?tx_revision=2 // Body: {"state":"FINISHED","client_id":"<clientId>","schema":{...}} // La respuesta contiene la firma criptográfica del TSSvar txId = Guid.NewGuid().ToString(); // Iniciar: PUT /tss/{tssId}/tx/{txId}?tx_revision=1 // Body: { state = "ACTIVE", client_id = clientId } // Finalizar: PUT /tss/{tssId}/tx/{txId}?tx_revision=2 // Body: { state = "FINISHED", client_id = clientId, schema = {...} } // La respuesta contiene la firma criptográfica del TSSLa respuesta incluye una
signaturecriptográfica del TSS, elsignature_countery todos los datos necesarios para un recibo conforme a KassenSichV.
Próximos pasos
Sección titulada «Próximos pasos»Was this page helpful?