iiziticket
Come funzionaPer chiFunzioniPrezziFAQ
AccediScarica gratis
  • ItalianoIT
  • EnglishEN

Ricevere le stampe sul tuo server

Ultimo aggiornamento: 9 novembre 2026

Con l'abbonamento mensile o annuale, iiziticket può inviare ogni stampa a un indirizzo web scelto da te: il tuo gestionale, uno script, Zapier, Make, n8n, Google Apps Script. Ricevi un elemento per ogni copia stampata, con i valori del modulo e i numeri dei contatori. I totali, i riepiloghi e tutto il resto li calcoli tu con i tuoi servizi.

L'invio parte dal telefono o dal tablet che stampa: i dati non passano dai server di iiziticket.

In breve

  • Una richiesta POST in JSON per ogni stampa, con un elemento per copia.
  • Firmata con HMAC-SHA256: il tuo server verifica che arrivi dal tuo dispositivo.
  • Se il server non risponde, la stampa resta in coda e riparte; la stampa non aspetta mai l'invio.
  • Si configura nell'app: Impostazioni → Integrazioni.

Configurazione

  • Indirizzo (URL): dove ricevere le stampe. Deve iniziare con https://. Per un server nella rete del negozio è consentito http:// con indirizzi locali (192.168.x.x, 10.x.x.x, 172.16–31.x.x, *.local).
  • Invio continuo: acceso, ogni stampa parte subito dopo essere uscita; spento, le stampe restano in coda finché premi Invia ora.
  • Nome del dispositivo: arriva con ogni stampa (es. "Cassa 1"), utile se stampi da più dispositivi.
  • Segreto per la firma: serve a verificare che le richieste arrivino davvero dal tuo dispositivo. Si copia dal menu ⋮; "Rigenera" lo cambia.
  • Intestazione aggiuntiva (facoltativa): per i servizi che chiedono un token fisso, per esempio Authorization: Bearer ….
  • Invia prova: manda una richiesta di tipo test per controllare indirizzo e firma.

La configurazione vale per il dispositivo su cui la fai: con più casse va ripetuta su ognuna.

Quando arrivano le stampe

  • Con l'invio continuo: subito dopo ogni stampa e quando l'app viene aperta.
  • Sempre: con Invia ora.
  • Le stampe partono una alla volta, in ordine. Se il tuo server non risponde o risponde con un errore, quella stampa e le successive restano in coda e si riprova alla stampa successiva, all'apertura dell'app o con Invia ora.
  • Con l'app chiusa non parte niente.
  • La stessa stampa può arrivare più di una volta (per esempio se la risposta del server si perde): riconoscila dal campo id.

In Integrazioni trovi, giorno per giorno, i biglietti stampati e quanti sono stati inviati, sono in coda o hanno dato errore. Una stampa che il tuo server rifiuta sempre si può scartare.

La richiesta

POST con corpo JSON, una richiesta per stampa:

JSON
{
  "id": "0b6c2f0e-6a1d-4c39-9d0e-0a4f1f1d2b7c",
  "type": "print.completed",
  "version": 1,
  "createdAt": "2026-11-09T20:15:03.120+01:00",
  "device": { "id": "d7a1…", "name": "Cassa 1", "counterPrefix": "A" },
  "data": {
    "printId": "0b6c2f0e-6a1d-4c39-9d0e-0a4f1f1d2b7c",
    "reprint": false,
    "reprintOf": null,
    "template": { "id": "3f2c…", "name": "Biglietto ingresso" },
    "fields": [
      { "key": "tipo", "label": "Tipo", "type": "select", "value": "Intero", "text": "Intero" },
      { "key": "prezzo", "label": "Prezzo", "type": "price", "value": 5, "text": "5,00 €" }
    ],
    "copies": [
      { "id": "0b6c…-1", "n": 1, "counters": { "numero": { "value": 12, "text": "A-0012" } } },
      { "id": "0b6c…-2", "n": 2, "counters": { "numero": { "value": 13, "text": "A-0013" } } }
    ]
  }
}
  • fields: i campi del modulo, uguali per tutte le copie. value è il dato grezzo (numeri come numeri, date in ISO 8601: 2026-11-09 per una data, con il fuso orario per data e ora), text è com'è stampato. type è uno tra text, number, price, select, date, datetime.
  • copies: un elemento per copia stampata, con un id proprio e i numeri dei campi contatore (con il prefisso del dispositivo, se c'è). Per una riga per biglietto, usa un elemento di copies per riga.
  • Ristampe: reprint: true e reprintOf con l'id della stampa originale; le copie hanno gli stessi numeri dell'originale. Non sono biglietti nuovi: escludile dai totali se serve.
  • Arrivano solo le copie uscite davvero dalla stampante.
  • type: "test": la richiesta di Invia prova, con lo stesso formato e dati di esempio.

Il tuo server deve rispondere con un codice 2xx (il corpo della risposta non viene letto) entro 15 secondi. Un 302 o 303 dopo la richiesta viene seguito con un GET senza dati (come fa Google Apps Script); 301, 307 e 308 sono errori: aggiorna l'indirizzo.

Intestazioni e firma

HTTP
Content-Type: application/json; charset=utf-8
User-Agent: iiziticket/1.0.0
X-Iiziticket-Event: print.completed
X-Iiziticket-Delivery: <id>
X-Iiziticket-Timestamp: 1794251703
X-Iiziticket-Signature: sha256=<hex>

La firma è l'HMAC-SHA256, in esadecimale, di timestamp + "." + corpo, con il segreto come chiave. Per verificarla:

  1. leggi il corpo così com'è, prima di convertirlo in JSON;
  2. calcola la firma e confrontala con X-Iiziticket-Signature con un confronto a tempo costante;
  3. rifiuta le richieste con un X-Iiziticket-Timestamp più vecchio di qualche minuto.
Node.js (Express)
import crypto from 'node:crypto';
import express from 'express';

const app = express();
app.post('/iiziticket', express.raw({ type: 'application/json' }), (req, res) => {
  const timestamp = req.get('X-Iiziticket-Timestamp');
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.IIZITICKET_SECRET)
    .update(`${timestamp}.${req.body}`)
    .digest('hex');
  const signature = req.get('X-Iiziticket-Signature') ?? '';
  const fresh = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300;
  if (!fresh || signature.length !== expected.length ||
      !crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
    return res.sendStatus(401);
  }
  const event = JSON.parse(req.body);
  // event.data.copies: one item per printed ticket
  res.sendStatus(204);
});
PHP
$body = file_get_contents('php://input');
$timestamp = $_SERVER['HTTP_X_IIZITICKET_TIMESTAMP'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $timestamp . '.' . $body, getenv('IIZITICKET_SECRET'));
$signature = $_SERVER['HTTP_X_IIZITICKET_SIGNATURE'] ?? '';
if (abs(time() - (int) $timestamp) > 300 || !hash_equals($expected, $signature)) {
    http_response_code(401);
    exit;
}
$event = json_decode($body, true);
http_response_code(204);
Python (Flask)
import hashlib, hmac, os, time
from flask import Flask, request

app = Flask(__name__)

@app.post("/iiziticket")
def iiziticket():
    body = request.get_data()
    timestamp = request.headers.get("X-Iiziticket-Timestamp", "")
    expected = "sha256=" + hmac.new(
        os.environ["IIZITICKET_SECRET"].encode(),
        f"{timestamp}.".encode() + body,
        hashlib.sha256,
    ).hexdigest()
    signature = request.headers.get("X-Iiziticket-Signature", "")
    if abs(time.time() - int(timestamp or 0)) > 300 or not hmac.compare_digest(expected, signature):
        return "", 401
    event = request.get_json()
    return "", 204

Servizi come Zapier o Make non verificano la firma: in quel caso usa un indirizzo difficile da indovinare (quello che ti danno loro) o l'intestazione aggiuntiva, se il servizio la supporta.

Esempio: un foglio Google

  1. Crea un foglio con le colonne che ti servono (es. data, cassa, template, tipo, prezzo, numero, ristampa).
  2. Estensioni → Apps Script, incolla:
Apps Script
function doPost(e) {
  const event = JSON.parse(e.postData.contents);
  if (event.type !== 'print.completed') return ContentService.createTextOutput('ok');
  const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0];
  const field = (key) => (event.data.fields.find((f) => f.key === key) || {}).value;
  for (const copy of event.data.copies) {
    const counter = Object.values(copy.counters)[0];
    sheet.appendRow([
      event.createdAt, event.device.name, event.data.template.name,
      field('tipo'), field('prezzo'), counter ? counter.text : '', event.data.reprint,
    ]);
  }
  return ContentService.createTextOutput('ok');
}
  1. Esegui il deployment → Nuovo deployment → App web, accesso "Chiunque", e incolla l'URL in iiziticket.

Apps Script non legge le intestazioni, quindi non può verificare la firma: tieni privato l'URL.

Privacy

Le stampe partono dal tuo dispositivo verso l'indirizzo che indichi tu: iiziticket non le riceve e non le conserva. Di quei dati, e di dove li mandi, sei responsabile tu. Il resto è nell'Informativa privacy.

© 2026 iiziticket · Biglietti e ricevute con stampante termica
PrivacyTerminiIntegrazioniContatti