Zum Inhalt springen

Schreibgeschützte Analytics-API

Die HTTP-API api.jonot.io/v1/* bietet schreibgeschützten Zugriff auf die Ticket- und Warteschlangendaten Ihrer Organisation. Statt einer Admin-Anmeldung verwenden Sie ein Bearer-Token. Mit der API können Sie Daten in ein Data Warehouse, ein Business-Intelligence-Tool oder ein eigenes Dashboard importieren.

  1. Öffnen Sie admin.jonot.io/settings/integrations.
  2. Klicken Sie auf den Tab API tokens.
  3. Klicken Sie auf Create token, geben Sie ihm einen Namen (z. B. „Power BI“) und bestätigen Sie.
  4. 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.

Authorization: Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
StatusBedeutung
401Token fehlt, ist fehlerhaft, unbekannt oder wurde widerrufen.
402Gültiges Token, aber die Organisation hat die API-Funktion nicht aktiviert.
429Ratenlimit überschritten — siehe Ratenlimits unten.
400Ungültige Abfrageparameter oder ein Zeitraum von über 90 Tagen.

Gibt die Standorte und Warteschlangen Ihrer Organisation ungefiltert und unpaginiert zurück:

Terminal-Fenster
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.

Paginiertes Ticket-Lesen, beschränkt auf Ihre Organisation.

ParameterErforderlichWiederholbarHinweise
fromjaneinISO-8601, untere Grenze für createdAt, inklusive.
tojaneinISO-8601, obere Grenze, exklusive. Maximal 90 Tage Zeitspanne.
queueIdneinjaParameter wiederholen, um mehrere Warteschlangen zu filtern.
locationIdneinjaParameter wiederholen, um mehrere Standorte zu filtern.
statusneinjaEiner von WAITING, CALLED, COMPLETED, CANCELED, SKIPPED, NO_SHOW.
cursorneinneinUndurchsichtiger Wert aus nextCursor der vorherigen Seite.
limitneinneinStandard 100, maximal 500.
Terminal-Fenster
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 weder den Bearer-Hash des Tickets noch personenbezogene Daten, die Kunden eingegeben haben, etwa Name, Notizen oder Personenzahl. Sie enthalten nur IDs, Status und Zeitstempel des Ticketablaufs.

Paginierung: Ist nextCursor nicht null, übergeben Sie den Wert in der nächsten Anfrage als cursor. Verwenden Sie dieselben Werte für from, to und die Filter. nextCursor: null bedeutet, dass Sie das Ende des Zeitraums erreicht haben.

Dieser Endpunkt verwendet dieselben Filter wie /v1/tickets: from und to sind erforderlich, queueId, locationId und status können wiederholt werden. cursor und limit werden nicht unterstützt. Der gesamte passende Zeitraum wird als eine CSV-Antwort übertragen, daher gilt das Seitenlimit von 500 Zeilen nicht.

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,calledByDeviceSessionId
Terminal-Fenster
curl "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.csv

Die Antwort verwendet Transfer-Encoding: chunked. Auch ein Export über 90 Tage mit 100.000 Zeilen muss daher weder beim Server noch beim Client vollständig im Speicher liegen. Leiten Sie die Antwort direkt in eine Datei oder einen Parser.

Jeder Endpunkt mit from und to lehnt einen Zeitraum von mehr als 90 Tagen mit 400 ab. Rufen Sie für einen längeren Verlauf kürzere Zeiträume ab, zum Beispiel eine Woche pro Anfrage. Mit Zeitstempeln wie calledAt und completedAt können Sie Warte- und Bedienzeiten berechnen, ohne dieselben Zeilen zweimal abzurufen.

Jedes Token erlaubt 60 Anfragen pro Minute. Das Limit gilt für das Token, nicht für die IP-Adresse. Jede Antwort enthält:

X-RateLimit-Remaining: 42
X-RateLimit-Reset: 1751328000000

Ein 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.

Für eine Demo-Organisation gilt zusätzlich ein Limit von 50 Anfragen pro Tag. Das Minutenlimit gilt ebenfalls. Damit können Sie eine vollständige Integration testen: Warteschlangen auflisten, Tickets abrufen und einen CSV-Export erstellen. Für den Produktivbetrieb reicht das Tageslimit nicht. Bei einer Überschreitung antwortet die API mit 429 und nennt die Ursache im Antworttext:

{
"error": "demo_quota_exceeded",
"limit": 50,
"resetAt": "2026-01-02T09:00:00.000Z"
}

Auch CSV-Exporte aus Demos sind gekennzeichnet, damit eine exportierte Datei nicht mit Produktivdaten verwechselt werden kann: Der Dateiname erhält das Präfix demo-, die Antwort trägt den Header X-Jonot-Demo: 1, und eine zusätzliche Spalte demo wird an das CSV angehängt. Kostenpflichtige Exporte bleiben unverändert — keine zusätzliche Spalte, kein zusätzlicher Header. Der Wechsel zu einem kostenpflichtigen Tarif hebt das tägliche Kontingent auf und entfernt die Kennzeichnungen.

import requests
import 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}"},
)
  1. In Power BI Desktop: Get Data → Web.
  2. 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.
  3. Fügen Sie unter HTTP request header parameters einen Header namens Authorization mit dem Wert Bearer jot_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx hinzu.
  4. Klicken Sie auf OK — Power BI erkennt die CSV-Datei und öffnet die Tabellenvorschau.
  5. 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 in Date/Time um).
  6. 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.