API di analisi in sola lettura
L’API HTTP api.jonot.io/v1/* consente di leggere i dati su biglietti e code della tua organizzazione. Usa un bearer token al posto di un accesso Admin. Puoi importare i dati in un data warehouse, uno strumento di business intelligence o una dashboard personalizzata.
Ottenere un token
Sezione intitolata “Ottenere un token”- Apri admin.jonot.io/settings/integrations.
- Fai clic sulla scheda API tokens.
- Fai clic su Create token, dagli un nome (es. “Power BI”) e conferma.
- Copia immediatamente il token — viene mostrato una sola volta e non può essere recuperato. Se lo perdi, revocalo e creane uno nuovo.
I token hanno il prefisso jot_ e non scadono mai da soli; revocali dalla stessa scheda quando non sono più necessari.
Autenticazione
Sezione intitolata “Autenticazione”Authorization: Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| Stato | Significato |
|---|---|
401 | Token mancante, malformato, sconosciuto o revocato. |
402 | Token valido, ma l’organizzazione non ha la funzione API abilitata. |
429 | Limite di frequenza superato — vedi Limiti di frequenza sotto. |
400 | Parametri di query non validi, oppure un intervallo di date superiore a 90 giorni. |
Endpoint
Sezione intitolata “Endpoint”GET /v1/queues
Sezione intitolata “GET /v1/queues”Restituisce le sedi e le code della tua organizzazione, non filtrate e non paginate:
curl https://api.jonot.io/v1/queues \ -H "Authorization: Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"{ "locations": [ { "id": "loc_…", "name": "Downtown", "slug": "downtown", "queues": [ { "id": "q_…", "name": "Main Queue", "slug": "main-queue", "status": "ACTIVE" } ] } ]}Usa i valori id restituiti per filtrare /v1/tickets e l’esportazione CSV per queueId / locationId.
GET /v1/tickets
Sezione intitolata “GET /v1/tickets”Lettura paginata dei biglietti, limitata alla tua organizzazione.
| Parametro | Obbligatorio | Ripetibile | Note |
|---|---|---|---|
from | sì | no | ISO-8601, limite inferiore incluso su createdAt. |
to | sì | no | ISO-8601, limite superiore escluso. Intervallo massimo di 90 giorni. |
queueId | no | sì | Ripeti il parametro per filtrare più code. |
locationId | no | sì | Ripeti il parametro per filtrare più sedi. |
status | no | sì | Uno tra WAITING, CALLED, COMPLETED, CANCELED, SKIPPED, NO_SHOW. |
cursor | no | no | Valore opaco da nextCursor della pagina precedente. |
limit | no | no | Predefinito 100, massimo 500. |
curl "https://api.jonot.io/v1/tickets?from=2026-06-01T00:00:00Z&to=2026-06-08T00:00:00Z&status=COMPLETED" \ -H "Authorization: Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"{ "items": [ { "id": "tkt_…", "number": 42, "queueId": "q_…", "locationId": "loc_…", "status": "COMPLETED", "createdAt": "2026-06-01T09:14:02.000Z", "calledAt": "2026-06-01T09:20:11.000Z", "completedAt": "2026-06-01T09:24:47.000Z", "cancelledAt": null, "skippedAt": null, "noShowAt": null, "calledByDeviceSessionId": "dev_…" } ], "nextCursor": "eyJjcmVhdGVkQXQi…"}Le righe non includono mai l’hash bearer del biglietto o dati personali identificabili inseriti dal cliente, come nome, note o numero di persone. Includono solo ID, stato e timestamp del ciclo di vita.
Paginazione: quando nextCursor non è null, passalo come cursor nella richiesta successiva. Mantieni gli stessi valori di from, to e dei filtri. Un nextCursor null indica la fine dell’intervallo.
GET /v1/exports/tickets.csv
Sezione intitolata “GET /v1/exports/tickets.csv”Questo endpoint accetta gli stessi filtri di /v1/tickets: from e to sono obbligatori, mentre queueId, locationId e status sono ripetibili. Non accetta cursor o limit. L’intero intervallo corrispondente viene trasmesso in un’unica risposta CSV, quindi il limite di 500 righe per pagina non si applica.
L’ordine delle colonne è stabile, ma analizza le colonne per nome di intestazione anziché per posizione fissa. La riga di intestazione è sempre presente e corrisponde esattamente a questo elenco:
id,number,queueId,locationId,status,createdAt,calledAt,completedAt,cancelledAt,skippedAt,noShowAt,calledByDeviceSessionIdcurl "https://api.jonot.io/v1/exports/tickets.csv?from=2026-06-01T00:00:00Z&to=2026-07-01T00:00:00Z" \ -H "Authorization: Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \ -o tickets.csvLa risposta usa Transfer-Encoding: chunked. Un’esportazione di 90 giorni con 100.000 righe non deve restare in memoria né sul server né sul client. Inviala direttamente a un file o a un parser.
Limite di intervallo di 90 giorni
Sezione intitolata “Limite di intervallo di 90 giorni”Ogni endpoint che accetta from e to rifiuta con 400 un intervallo superiore a 90 giorni. Per una cronologia più lunga, richiedi intervalli più brevi, ad esempio una settimana alla volta. Usa i timestamp del ciclo di vita, come calledAt e completedAt, per calcolare i tempi di attesa e servizio senza richiedere due volte le stesse righe.
Limiti di frequenza
Sezione intitolata “Limiti di frequenza”Ogni token consente 60 richieste al minuto. Il limite si applica al token, non all’indirizzo IP. Ogni risposta include:
X-RateLimit-Remaining: 42X-RateLimit-Reset: 1751328000000Un 429 porta inoltre Retry-After (in secondi). Attendi quella finestra e riprova; una sincronizzazione pianificata ogni pochi minuti resta comodamente sotto il limite.
Organizzazioni demo
Sezione intitolata “Organizzazioni demo”Un’organizzazione demo ha un limite aggiuntivo di 50 richieste al giorno. Si applica anche il limite al minuto. Puoi usare l’API demo per provare un’integrazione completa: elencare le code, richiedere alcuni biglietti ed esportare un CSV. Il limite giornaliero non basta per l’uso in produzione. Se lo superi, l’API restituisce 429 con un corpo che identifica la causa:
{ "error": "demo_quota_exceeded", "limit": 50, "resetAt": "2026-01-02T09:00:00.000Z"}Anche le esportazioni CSV demo vengono contrassegnate, così un file esportato non può essere confuso con dati di produzione: il nome del file ha il prefisso demo-, la risposta porta l’intestazione X-Jonot-Demo: 1, e viene aggiunta una colonna demo finale al CSV. Le esportazioni a pagamento restano invariate — nessuna colonna né intestazione aggiuntiva. Sottoscrivere un piano a pagamento rimuove la quota giornaliera e i contrassegni.
Python + pandas
Sezione intitolata “Python + pandas”import requestsimport pandas as pd
TOKEN = "jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"BASE = "https://api.jonot.io/v1"HEADERS = {"Authorization": f"Bearer {TOKEN}"}
def fetch_tickets(frm: str, to: str) -> pd.DataFrame: rows = [] cursor = None while True: params = {"from": frm, "to": to, "limit": 500} if cursor: params["cursor"] = cursor res = requests.get(f"{BASE}/tickets", headers=HEADERS, params=params, timeout=30) res.raise_for_status() body = res.json() rows.extend(body["items"]) cursor = body["nextCursor"] if not cursor: break return pd.DataFrame(rows)
df = fetch_tickets("2026-06-01T00:00:00Z", "2026-07-01T00:00:00Z")df["waitSeconds"] = ( pd.to_datetime(df["calledAt"]) - pd.to_datetime(df["createdAt"])).dt.total_seconds()print(df.groupby("queueId")["waitSeconds"].mean())Oppure leggi direttamente l’esportazione CSV — pandas gestisce la risposta in streaming in modo trasparente:
df = pd.read_csv( f"{BASE}/exports/tickets.csv?from=2026-06-01T00:00:00Z&to=2026-07-01T00:00:00Z", storage_options={"Authorization": f"Bearer {TOKEN}"},)Power BI (connettore Web)
Sezione intitolata “Power BI (connettore Web)”- In Power BI Desktop: Get Data → Web.
- Scegli Advanced e costruisci l’URL con il tuo intervallo di date, es.
https://api.jonot.io/v1/exports/tickets.csv?from=2026-06-01T00:00:00Z&to=2026-07-01T00:00:00Z. - Sotto HTTP request header parameters, aggiungi un header chiamato
Authorizationcon il valoreBearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx. - Fai clic su OK — Power BI rileva il CSV e apre l’anteprima della tabella.
- Fai clic su Load (oppure prima su Transform Data se vuoi impostare i tipi di colonna —
createdAt/calledAt/ecc. vengono importati come testo; convertili inDate/Timein Power Query). - Imposta un aggiornamento pianificato nel servizio Power BI se prelevi dati con una cadenza regolare; mantieni l’intervallo comodamente sotto i 90 giorni per aggiornamento.