Ihre externen Systeme mit Zendesk-Daten synchron zu halten, kann sich wie eine nie endende Aufgabe anfühlen. Egal, ob Sie ein Data Warehouse aufbauen, Analysen durchführen oder Ticketinformationen mit Ihrem CRM synchronisieren, Sie benötigen eine zuverlässige Möglichkeit, nur das abzurufen, was sich seit Ihrem letzten Update geändert hat. Der inkrementelle Export der Zendesk API wurde genau für diesen Zweck entwickelt.
Im Gegensatz zu den Standard-API-Endpunkten, die für Echtzeitabfragen entwickelt wurden, sind inkrementelle Exporte speziell für die Massendatensynchronisation konzipiert. Sie ermöglichen es Ihnen, Datensätze abzurufen, die seit einem bestimmten Zeitpunkt erstellt oder aktualisiert wurden, was sie ideal für ETL-Pipelines und regelmäßige Datensynchronisierungen macht.
In dieser Anleitung erfahren Sie, wie Sie die inkrementelle Export API von Zendesk effektiv nutzen können. Wir werden die beiden Paginierungsansätze (Cursor-basiert und Zeit-basiert) behandeln, eine vollständige Python-Implementierung durchgehen und Best Practices für Produktionsdaten-Pipelines austauschen. Wenn Sie nach einer Möglichkeit suchen, Zendesk-Analysen zu erhalten, ohne eine benutzerdefinierte Infrastruktur aufzubauen, bietet eesel AI native Zendesk-Integrationen, die die Datensynchronisation automatisch übernehmen.
Was ist die inkrementelle Export API von Zendesk?
Die inkrementelle Export API ist eine Reihe von Endpunkten, die für den Massendatenexport und nicht für einzelne Datensatzabfragen entwickelt wurden. Während die Standard Tickets API sich hervorragend eignet, um ein bestimmtes Ticket abzurufen oder mit Filtern zu suchen, ist sie nicht für die effiziente Synchronisierung großer Datensätze optimiert.
So funktionieren inkrementelle Exporte: Sie geben eine Startzeit (als Unix-Epochen-Zeitstempel) an, und die API gibt alle Datensätze zurück, die seit diesem Zeitpunkt erstellt oder aktualisiert wurden. Bei Ihrer nächsten Synchronisierung verwenden Sie die Endzeit oder den Cursor aus der vorherigen Antwort als Ihren neuen Startpunkt. Dies erzeugt eine effiziente Synchronisierungsschleife, in der Sie nur geänderte Daten abrufen.
Die API unterstützt zwei Paginierungsmethoden:
- Cursor-basierte Paginierung verwendet einen undurchsichtigen Cursor-Zeiger, um die Position zu verfolgen. Sie ist konsistenter, eliminiert Duplikate und ist der empfohlene Ansatz, wenn sie verfügbar ist.
- Zeit-basierte Paginierung verwendet Start- und Endzeitstempel. Sie wird von allen inkrementellen Endpunkten unterstützt, kann aber doppelte Datensätze zurückgeben, wenn mehrere Elemente denselben Zeitstempel haben.
Sie können inkrementell Tickets, Benutzer, Organisationen, Ticket-Ereignisse, Talk-Anrufdaten, Chat-Konversationen, Help Center-Artikel und benutzerdefinierte Objektdatensätze exportieren. Für Teams, die umfassende Analysen erstellen, behandelt unser Leitfaden zur Zendesk Ticket API zusätzliche Endpunkte, die inkrementelle Exporte ergänzen.
Wann inkrementelle Exporte vs. Search API verwenden
Eine häufige Frage ist, ob inkrementelle Exporte oder die Search API zum Abrufen von Ticketdaten verwendet werden sollen. Der Hauptunterschied ist der Zweck: Inkrementelle Exporte sind für die Datensynchronisation konzipiert, während Search für die Abfrage konzipiert ist.
Verwenden Sie inkrementelle Exporte, wenn:
- Sie Daten in ein Data Warehouse oder ein externes System synchronisieren
- Sie jede Ticketänderung zuverlässig verarbeiten müssen
- Sie Analyse- oder Reporting-Pipelines erstellen
- Sie API-Aufrufe minimieren möchten, indem Sie nur Änderungen abrufen
Verwenden Sie die Search API, wenn:
- Sie bestimmte Tickets finden müssen, die komplexen Kriterien entsprechen
- Sie eine Suchoberfläche für Agenten erstellen
- Sie Echtzeitergebnisse mit erweiterter Filterung benötigen
Cursor-basierte vs. Zeit-basierte Paginierung: Welche sollten Sie verwenden?
Zendesk bietet beide Paginierungsmethoden an, aber die Cursor-basierte ist der klare Gewinner, wenn sie verfügbar ist. Hier sind die Unterschiede.
Cursor-basierte Paginierung (empfohlen)
Cursor-basierte Exporte verwenden einen undurchsichtigen Zeiger (den Cursor), um Ihre Position im Datensatz zu verfolgen. Nach Ihrer ersten Anfrage mit einer start_time verwenden nachfolgende Anfragen den cursor Parameter.
Hauptvorteile:
- Keine doppelten Datensätze, auch wenn Elemente Zeitstempel gemeinsam nutzen
- Konsistentere Antwortzeiten und Payload-Größen
- Bessere Leistung für große Datensätze
- Höhere Ratenbegrenzungen (10 Anfragen pro Minute für Tickets, 20 für Benutzer oder 60 mit dem High Volume API Add-on)
Unterstützte Ressourcen:
- Tickets
- Benutzer
- Benutzerdefinierte Objektdatensätze
So funktioniert es:
- Führen Sie eine erste Anfrage mit dem Parameter
start_timedurch - Extrahieren Sie
after_cursoraus der Antwort - Verwenden Sie den Parameter
cursorfür die nächste Anfrage - Wiederholen Sie den Vorgang, bis
end_of_streamwahr ist
Zeit-basierte Paginierung
Zeit-basierte Exporte verwenden Unix-Epochen-Zeitstempel, um Ihr Abfragefenster zu definieren. Jede Antwort enthält eine end_time, die Sie als start_time für Ihre nächste Anfrage verwenden.
Einschränkungen:
- Kann doppelte Datensätze zurückgeben, wenn mehrere Elemente denselben Zeitstempel haben
- Weniger konsistente Leistung
- Niedrigere Ratenbegrenzungen (10 Anfragen pro Minute)
Wann zu verwenden:
- Wenn Cursor-basiert nicht verfügbar ist (Ticket-Ereignisse, Organisationen, Talk-Daten)
- Für einfache Skripte, bei denen die Duplikatbehandlung nicht kritisch ist
Entscheidungsmatrix
| Faktor | Cursor-basiert | Zeit-basiert |
|---|---|---|
| Duplikatbehandlung | Keine (garantiert eindeutig) | Muss manuell dedupliziert werden |
| Leistung | Konsistent | Variabel |
| Ratenbegrenzung | 10-20/min (60 mit Add-on) | 10/min |
| Verfügbar für | Tickets, Benutzer, benutzerdefinierte Objekte | Alle Ressourcen |
Verwenden Sie Cursor-basiert, wann immer möglich. Die einzige Zeit, in der Sie Zeit-basiert verwenden sollten, ist, wenn Cursor-basiert für Ihren Ressourcentyp nicht verfügbar ist.
Erste Schritte: Authentifizierung und Voraussetzungen
Bevor Sie mit dem Programmieren beginnen, müssen Sie ein paar Dinge einrichten.
Erforderlich:
- Ein Zendesk-Konto mit Administratorrechten
- Ein API-Token (generieren Sie eines im Admin Center > Apps und Integrationen > APIs > Zendesk API)
- Python 3.7+ installiert
Python-Pakete:
pip install requests python-dotenv
Umgebungseinrichtung:
Erstellen Sie eine .env Datei, um Ihre Anmeldeinformationen sicher zu speichern:
ZENDESK_SUBDOMAIN=Ihre-Subdomain
ZENDESK_EMAIL=Ihre-E-Mail@firma.com
ZENDESK_API_TOKEN=Ihr-API-Token
Die inkrementelle Export API verwendet die Basic-Authentifizierung. Sie übergeben Ihre E-Mail-Adresse kombiniert mit /token als Benutzernamen und Ihr API-Token als Passwort.
Schritt-für-Schritt: Exportieren von Tickets mit Cursor-basierter Paginierung
Lassen Sie uns eine vollständige Implementierung für den Export von Tickets mit Cursor-basierter Paginierung durchgehen. Dieses Muster behandelt Paginierung, Ratenbegrenzung und Fehlerbehebung.
Der Code
import os
import time
import requests
from requests.auth import HTTPBasicAuth
from dotenv import load_dotenv
load_dotenv()
class ZendeskIncrementalExport:
def __init__(self):
self.subdomain = os.getenv('ZENDESK_SUBDOMAIN')
self.email = os.getenv('ZENDESK_EMAIL')
self.api_token = os.getenv('ZENDESK_API_TOKEN')
self.base_url = f"https://{self.subdomain}.zendesk.com/api/v2"
self.auth = HTTPBasicAuth(f"{self.email}/token", self.api_token)
def export_tickets(self, start_time=None, cursor=None):
"""
Export tickets using cursor-based pagination.
Args:
start_time: Unix timestamp for initial export (required for first call)
cursor: Cursor from previous response (for subsequent calls)
"""
url = f"{self.base_url}/incremental/tickets/cursor.json"
params = {}
if cursor:
params['cursor'] = cursor
elif start_time:
params['start_time'] = start_time
else:
raise ValueError("Either start_time or cursor must be provided")
try:
response = requests.get(url, auth=self.auth, params=params, timeout=30)
if response.status_code == 429:
# Rate limited - implement exponential backoff
retry_after = int(response.headers.get('Retry-After', 60))
print(f"Rate limited. Waiting {retry_after} seconds...")
time.sleep(retry_after)
return self.export_tickets(start_time, cursor)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as e:
print(f"Request failed: {e}")
raise
def full_export(self, start_time):
"""
Perform a complete export, handling pagination automatically.
"""
all_tickets = []
cursor = None
page_count = 0
while True:
data = self.export_tickets(
start_time=start_time if cursor is None else None,
cursor=cursor
)
tickets = data.get('tickets', [])
all_tickets.extend(tickets)
page_count += 1
print(f"Fetched page {page_count}: {len(tickets)} tickets")
# Check if we've reached the end
if data.get('end_of_stream'):
print(f"Export complete. Total tickets: {len(all_tickets)}")
return {
'tickets': all_tickets,
'final_cursor': data.get('after_cursor'),
'pages': page_count
}
cursor = data.get('after_cursor')
# Respect rate limits - sleep between requests
time.sleep(3) # 20 requests/min = 1 request per 3 seconds
if __name__ == "__main__":
exporter = ZendeskIncrementalExport()
# Start from 24 hours ago
import datetime
start_time = int((datetime.datetime.now() - datetime.timedelta(days=1)).timestamp())
result = exporter.full_export(start_time)
# Save the final cursor for next sync
print(f"Save this cursor for next run: {result['final_cursor']}")
Wichtige Implementierungsdetails
Das 1-Minuten-Ausschlussfenster: Die API schließt Daten aus der letzten Minute aus, um Race-Conditions zu vermeiden. Ihre end_time wird nie aktueller als vor einer Minute sein. Planen Sie Ihren Synchronisierungszeitplan entsprechend.
Ratenbegrenzung: Der Code implementiert exponentielles Backoff, wenn eine 429-Antwort empfangen wird. Der Retry-After Header teilt Ihnen genau mit, wie lange Sie warten müssen.
Cursor-Persistenz: Speichern Sie den endgültigen Cursor immer atomar mit Ihren Datenschreibvorgängen. Wenn Ihr Skript nach dem Schreiben von Daten, aber vor dem Speichern des Cursors abstürzt, verarbeiten Sie beim nächsten Lauf doppelte Datensätze.
Ausschließen gelöschter Tickets: Fügen Sie exclude_deleted=true zu Ihren Anfrageparametern hinzu, wenn Sie keine gelöschten Tickets in Ihrem Export wünschen. Gelöschte Tickets werden 90 Tage nach der endgültigen Löschung aufbewahrt, sodass sie in Exporten angezeigt werden, sofern sie nicht ausgeschlossen werden.
Arbeiten mit anderen inkrementellen Export-Endpunkten
Die gleichen Muster gelten für andere Zendesk-Ressourcen, obwohl sich die Endpunkt-URLs und die verfügbaren Paginierungsmethoden unterscheiden.
Benutzer und Organisationen
Diese folgen dem gleichen Muster wie Tickets:
url = f"{base_url}/incremental/users/cursor.json"
url = f"{base_url}/incremental/organizations.json"
Ticket-Ereignisse
Ticket-Ereignisse sind nur Zeit-basiert und enthalten eine Aufzeichnung jeder an Tickets vorgenommenen Änderung:
url = f"{base_url}/incremental/ticket_events.json"
params = {'start_time': start_time, 'include': 'comment_events'}
Der comment_events Sideload ist besonders nützlich, wenn Sie den tatsächlichen Kommentartext benötigen, nicht nur Metadaten über Änderungen.
Talk-Anrufdaten
Exportieren Sie Anrufdatensätze und Anrufbeine für die Sprachanalyse:
url = f"{base_url}/channels/voice/stats/incremental/calls.json"
url = f"{base_url}/channels/voice/stats/incremental/legs.json"
Ratenbegrenzung: 10 Anfragen pro Minute für Talk-Endpunkte.
Chat-Daten
Chat-Exporte verwenden Mikrosekunden anstelle von Sekunden für Zeitstempel:
url = f"{base_url}/chat/incremental/chats.json"
start_time_micro = start_time * 1000000
url = f"{base_url}/chat/incremental/agent_timeline.json?start_time={start_time_micro}"
Hinweis: Die Chat API erfordert, dass die Startzeit mindestens 5 Minuten in der Vergangenheit liegt.
Help Center-Artikel
Exportieren Sie Artikel-Metadatenänderungen:
url = f"{base_url}/help_center/incremental/articles.json"
Gibt bis zu 1.000 Artikel pro Seite zurück. Die next_page URL enthält eine neue Startzeit basierend auf dem Aktualisierungszeitstempel des letzten Artikels.
Behandeln von Ratenbegrenzungen und Fehlern
Produktionsdaten-Pipelines benötigen eine robuste Fehlerbehandlung. Hier ist, worauf Sie achten sollten.
Ratenbegrenzungs-Header
Cursor-basierte Endpunkte geben detaillierte Ratenbegrenzungsinformationen zurück:
Zendesk-RateLimit-incremental-exports-cursor: total=20; remaining=15; resets=45
Analysieren Sie diese Header, um Ihre Anfragen proaktiv zu drosseln, anstatt auf 429-Antworten zu warten.
Exponentielle Backoff-Strategie
Wenn Sie eine Ratenbegrenzung erreichen, verwenden Sie exponentielles Backoff mit Jitter:
import random
def backoff_with_jitter(attempt, base_delay=3):
"""Calculate delay with exponential backoff and jitter."""
delay = min(base_delay * (2 ** attempt), 60) # Cap at 60 seconds
jitter = random.uniform(0, delay * 0.1) # Add 0-10% jitter
return delay + jitter
for attempt in range(5):
try:
response = requests.get(url, auth=auth)
if response.status_code == 429:
delay = backoff_with_jitter(attempt)
time.sleep(delay)
continue
response.raise_for_status()
break
except requests.exceptions.RequestException:
if attempt == 4: # Last attempt
raise
delay = backoff_with_jitter(attempt)
time.sleep(delay)
Häufige Fehler und Lösungen
| Fehler | Ursache | Lösung |
|---|---|---|
| 401 Unbefugt | Ungültige Anmeldeinformationen | Überprüfen Sie das E-Mail-Format (muss /token enthalten) und das API-Token |
| 403 Verboten | Unzureichende Berechtigungen | Stellen Sie sicher, dass das Konto Administratorzugriff hat |
| 422 Unverarbeitbar | Ungültige start_time | Stellen Sie sicher, dass der Zeitstempel mindestens 60 Sekunden in der Vergangenheit liegt |
| 429 Zu viele Anfragen | Ratenbegrenzung überschritten | Implementieren Sie Backoff und beachten Sie den Retry-After Header |
| 500/502/503 | Zendesk-Serverfehler | Wiederholen Sie den Vorgang mit exponentiellem Backoff |
Testen mit Beispiel-Exporten
Zendesk bietet einen Beispiel-Export-Endpunkt mit strengeren Beschränkungen (10 Anfragen pro 20 Minuten), aber kleineren Antworten. Verwenden Sie dies für die Entwicklung und das Testen:
url = f"{base_url}/incremental/tickets/sample.json?start_time={start_time}"
Aufbau einer Produktionsdaten-Pipeline
Für den Produktionseinsatz benötigen Sie eine robustere Architektur als ein einfaches Skript.
Empfohlene Architektur
Geplanter Job (Airflow/Lambda/Cron)
↓
Inkrementelle Export API
↓
Datenvalidierung & Transformation
↓
Data Warehouse (Snowflake/BigQuery/Redshift)
↓
Analyse-Dashboard
Speichern des Cursor-Status
Verlassen Sie sich niemals auf lokale Dateien für die Cursor-Speicherung in der Produktion. Verwenden Sie einen persistenten Speicher:
import psycopg2
def save_cursor(cursor, last_sync_time):
conn = psycopg2.connect(database_url)
cur = conn.cursor()
cur.execute("""
INSERT INTO zendesk_sync_state (cursor, last_sync_time, updated_at)
VALUES (%s, %s, NOW())
ON CONFLICT (id) DO UPDATE SET
cursor = EXCLUDED.cursor,
last_sync_time = EXCLUDED.last_sync_time,
updated_at = EXCLUDED.updated_at
""", (cursor, last_sync_time))
conn.commit()
Deduplizierung für Zeit-basierte Exporte
Wenn Sie die Zeit-basierte Paginierung verwenden, implementieren Sie die Deduplizierung:
def deduplicate_records(records, key_fields):
"""
Remove duplicates based on composite key.
For tickets: (id, updated_at)
For ticket events: (id, created_at)
"""
seen = set()
unique = []
for record in records:
key = tuple(record.get(f) for f in key_fields)
if key not in seen:
seen.add(key)
unique.append(record)
return unique
tickets = deduplicate_records(tickets, ['id', 'updated_at'])
Überwachung und Benachrichtigung
Verfolgen Sie diese Metriken in Ihrer Pipeline:
- Synchronisierungsdauer und Datensatzanzahl
- Ratenbegrenzungstreffer und Wiederholungsanzahl
- Fehlgeschlagene Anfragen und Fehlerraten
- Datenaktualität (Zeit seit der letzten erfolgreichen Synchronisierung)
Richten Sie Benachrichtigungen ein für:
- Synchronisierungsfehler oder übermäßige Wiederholungen
- Ungewöhnlich niedrige Datensatzanzahl (mögliche API-Probleme)
- Datenaktualität, die Ihre SLA überschreitet
Alternative: Verwaltete Lösungen
Der Aufbau und die Wartung einer Daten-Pipeline erfordert Engineering-Ressourcen. Wenn Ihr Team Zendesk-Analysen ohne den Infrastrukturaufwand benötigt, bietet der AI Agent von eesel AI automatisierte Ticketanalysen, Berichte und Einblicke direkt aus Ihren Zendesk-Daten, ohne dass eine benutzerdefinierte Pipeline erforderlich ist.

Wichtige Best Practices und Einschränkungen
Bevor Sie die Bereitstellung in der Produktion vornehmen, sollten Sie diese Punkte beachten.
Best Practices
- Verwenden Sie immer die Cursor-basierte Paginierung, wenn sie verfügbar ist. Die Leistungs- und Konsistenzvorteile sind es wert.
- Speichern Sie Cursor atomar mit Datenschreibvorgängen. Verwenden Sie eine Transaktion, um sicherzustellen, dass Cursor und Daten immer synchron sind.
- Beachten Sie das 1-Minuten-Ausschlussfenster. Erwarten Sie keine Daten, die neuer als vor einer Minute sind.
- Implementieren Sie idempotente Schreibvorgänge. Entwerfen Sie Ihr Zielsystem so, dass doppelte Datensätze ordnungsgemäß verarbeitet werden.
- Überwachen Sie die Ratenbegrenzungs-Header. Proaktives Drosseln ist besser als reaktives Backoff.
Einschränkungen, die Sie kennen sollten
- Aufbewahrung gelöschter Tickets: Gelöschte Tickets verbleiben für etwa 120 Tage in den Exporten (30 Tage bis zur endgültigen Löschung, dann 90 Tage nach dem Scrubbing).
- Archivierte Tickets: Von Zendesk archivierte Tickets sind nicht in inkrementellen Exporten enthalten.
- Gesäuberte Daten: Nach 30 Tagen werden die Inhalte gelöschter Tickets gesäubert (durch "SCRUBBED" oder "X" ersetzt).
- Keine Echtzeitgarantien: Die API ist für Batch-Synchronisierungen konzipiert, nicht für Echtzeit-Streaming.
Beginnen Sie mit der effizienten Synchronisierung Ihrer Zendesk-Daten
Der inkrementelle Export der Zendesk API bietet Ihnen eine zuverlässige Möglichkeit, externe Systeme mit Ihren Supportdaten synchron zu halten. Durch die Verwendung der Cursor-basierten Paginierung, die ordnungsgemäße Behandlung von Ratenbegrenzungen und die ordnungsgemäße Speicherung des Status können Sie robuste Daten-Pipelines erstellen, die mit Ihrem Ticketvolumen skaliert werden können.
Wichtige Erkenntnisse:
- Verwenden Sie nach Möglichkeit die Cursor-basierte Paginierung für Tickets und Benutzer
- Implementieren Sie exponentielles Backoff für die Behandlung von Ratenbegrenzungen
- Speichern Sie Cursor atomar mit Ihren Datenschreibvorgängen
- Berücksichtigen Sie das 1-Minuten-Datenausschlussfenster in Ihrem Synchronisierungszeitplan
Der Aufbau einer benutzerdefinierten Pipeline ist sinnvoll, wenn Sie spezifische Datentransformationsanforderungen haben oder in proprietäre Systeme integrieren. Wenn Sie jedoch in erster Linie nach Analysen, Berichten und KI-gestützten Erkenntnissen aus Ihren Zendesk-Daten suchen, sollten Sie überlegen, ob eine verwaltete Lösung wie eesel AI Ihrem Team möglicherweise Monate an Engineering-Aufwand ersparen kann. Unsere Zendesk-Integration übernimmt die Datensynchronisation automatisch und ermöglicht Ihnen den sofortigen Zugriff auf Ticketanalysen, ohne eine einzige Zeile API-Code schreiben zu müssen.

Häufig gestellte Fragen
Diesen Beitrag teilen

Article by
Stevia Putri
Stevia Putri is a marketing generalist at eesel AI, where she helps turn powerful AI tools into stories that resonate. She’s driven by curiosity, clarity, and the human side of technology.



