Schreibgeschützte Analytics-API
Die HTTP-API api.jonot.io/v1/* bietet schreibgeschützten Zugriff auf die Ticket- und Warteschlangendaten Ihrer Organisation — keine Admin-Anmeldung erforderlich, nur ein Bearer-Token. Nutzen Sie sie, um Daten in ein Data Warehouse, ein BI-Tool oder ein eigenes Dashboard zu übertragen.
Ein Token erhalten
Abschnitt betitelt „Ein Token erhalten“- Öffnen Sie admin.jonot.io/settings/integrations.
- Klicken Sie auf den Tab API tokens.
- Klicken Sie auf Create token, geben Sie ihm einen Namen (z. B. „Power BI“) und bestätigen Sie.
- Kopieren Sie das Token sofort — es wird nur einmal angezeigt und kann nicht wiederhergestellt werden. Verlieren Sie es, widerrufen Sie es und erstellen Sie ein neues.
Tokens beginnen mit dem Präfix jot_ und laufen von selbst nie ab; widerrufen Sie sie im selben Tab, sobald sie nicht mehr benötigt werden.
Authentifizierung
Abschnitt betitelt „Authentifizierung“Authorization: Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx| Status | Bedeutung |
|---|---|
401 | Token fehlt, ist fehlerhaft, unbekannt oder wurde widerrufen. |
402 | Gültiges Token, aber die Organisation hat die API-Funktion nicht aktiviert. |
429 | Ratenlimit überschritten — siehe Ratenlimits unten. |
400 | Ungültige Abfrageparameter oder ein Zeitraum von über 90 Tagen. |
Endpunkte
Abschnitt betitelt „Endpunkte“GET /v1/queues
Abschnitt betitelt „GET /v1/queues“Gibt die Standorte und Warteschlangen Ihrer Organisation ungefiltert und unpaginiert zurück:
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" } ] } ]}Verwenden Sie die zurückgegebenen id-Werte, um /v1/tickets und den CSV-Export nach queueId / locationId zu filtern.
GET /v1/tickets
Abschnitt betitelt „GET /v1/tickets“Paginiertes Ticket-Lesen, beschränkt auf Ihre Organisation.
| Parameter | Erforderlich | Wiederholbar | Hinweise |
|---|---|---|---|
from | ja | nein | ISO-8601, untere Grenze für createdAt, inklusive. |
to | ja | nein | ISO-8601, obere Grenze, exklusive. Maximal 90 Tage Zeitspanne. |
queueId | nein | ja | Parameter wiederholen, um mehrere Warteschlangen zu filtern. |
locationId | nein | ja | Parameter wiederholen, um mehrere Standorte zu filtern. |
status | nein | ja | Einer von WAITING, CALLED, COMPLETED, CANCELED, SKIPPED, NO_SHOW. |
cursor | nein | nein | Undurchsichtiger Wert aus nextCursor der vorherigen Seite. |
limit | nein | nein | Standard 100, maximal 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…"}Die Zeilen enthalten niemals den Bearer-Hash des Tickets oder vom Kunden eingegebene personenbezogene Daten (Name, Notizen, Personenzahl) — nur IDs, Status und die Lebenszyklus-Zeitstempel.
Paginierung: Ist nextCursor nicht null, übergeben Sie ihn als cursor in der nächsten Anfrage, um dort fortzufahren, wo Sie aufgehört haben (gleiche from/to/Filter). Ein nextCursor-Wert von null bedeutet, dass Sie das Ende des Zeitraums erreicht haben.
GET /v1/exports/tickets.csv
Abschnitt betitelt „GET /v1/exports/tickets.csv“Dieselben Filter wie bei /v1/tickets (from/to erforderlich, queueId/locationId/status wiederholbar) ohne cursor/limit — der gesamte übereinstimmende Zeitraum wird als eine einzige CSV-Antwort gestreamt, sodass bei einem Massenabruf kein 500-Zeilen-Seitenlimit umgangen werden muss.
Die Spaltenreihenfolge ist stabil, aber lesen Sie Spalten anhand des Spaltennamens statt einer festen Position aus. Die Kopfzeile ist immer vorhanden und entspricht exakt dieser Liste:
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.csvDie Antwort wird gestreamt (Transfer-Encoding: chunked), sodass ein Export über 90 Tage / 100.000 Zeilen auf keiner Seite im Speicher gepuffert werden muss — leiten Sie sie direkt in eine Datei oder einen Parser.
90-Tage-Obergrenze für Zeiträume
Abschnitt betitelt „90-Tage-Obergrenze für Zeiträume“Jeder Endpunkt, der from/to entgegennimmt, lehnt eine Zeitspanne von über 90 Tagen mit 400 ab. Rufen Sie Daten schrittweise ab (z. B. ein Aufruf pro Woche), wenn Sie einen längeren Verlauf benötigen — die Lebenszyklus-Zeitstempel des Tickets (calledAt, completedAt, …) ermöglichen es, Warte-/Bedienzeiten zu rekonstruieren, ohne dieselben Zeilen zweimal abzurufen.
Ratenlimits
Abschnitt betitelt „Ratenlimits“60 Anfragen pro Minute und Token (nicht pro IP — das Kontingent ist an das Token gebunden). Jede Antwort enthält:
X-RateLimit-Remaining: 42X-RateLimit-Reset: 1751328000000Ein 429 enthält zusätzlich Retry-After (in Sekunden). Warten Sie diese Zeitspanne ab, bevor Sie es erneut versuchen; eine geplante Synchronisierung alle paar Minuten bleibt bequem unter dem Limit.
Python + pandas
Abschnitt betitelt „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())Oder lesen Sie den CSV-Export direkt — pandas verarbeitet die gestreamte Antwort transparent:
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 (Web-Connector)
Abschnitt betitelt „Power BI (Web-Connector)“- In Power BI Desktop: Get Data → Web.
- Wählen Sie Advanced und erstellen Sie die URL mit Ihrem Datumsbereich, z. B.
https://api.jonot.io/v1/exports/tickets.csv?from=2026-06-01T00:00:00Z&to=2026-07-01T00:00:00Z. - Fügen Sie unter HTTP request header parameters einen Header namens
Authorizationmit dem WertBearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxhinzu. - Klicken Sie auf OK — Power BI erkennt die CSV-Datei und öffnet die Tabellenvorschau.
- Klicken Sie auf Load (oder zuerst auf Transform Data, wenn Sie die Spaltentypen festlegen möchten —
createdAt/calledAt/etc. werden als Text importiert; wandeln Sie sie in Power Query inDate/Timeum). - Richten Sie im Power BI-Dienst eine geplante Aktualisierung ein, wenn Sie regelmäßig Daten abrufen; halten Sie den Zeitraum pro Aktualisierung bequem unter 90 Tagen.