Zum Inhalt springen
edoobox Docs
Kostenlos testen 7 Tage unverbindlich testen
Menü
Kostenlos testen 7 Tage unverbindlich testen

API: Buchungen mit CRM und anderen Systemen synchronisieren

Ein regelmässiger REST-Abgleich hält Buchungen in einem CRM, einer internen Übersicht oder einem Reporting aktuell. Er eignet sich auch als zusätzlicher Abgleich zu Webhooks. Diese Anleitung zeigt, wie Sie neue Buchungen vollständig abholen, wiederholte Verarbeitung beherrschen und spätere Änderungen bereits bekannter Buchungen berücksichtigen.

Abgleich vorbereiten

  1. Richten Sie einen eigenen API-Schlüssel mit Leserechten für die benötigten Ressourcen ein. Verwenden Sie die API: Erste Schritte für Authentifizierung und Header.
  2. Legen Sie fest, welche Daten das Zielsystem benötigt: Buchungs-ID, Angebot, Buchungsperson, Wartelistenstatus und Stornostatus sind ein möglicher Ausgangspunkt.
  3. Speichern Sie die Zuordnung zwischen edoobox-Buchung und Zieldatensatz sowie den zuletzt vollständig verarbeiteten Zeitraum dauerhaft in Ihrer Integration.
  4. Definieren Sie zwei Läufe: einen häufigen Abruf neuer Buchungen und einen regelmässigen Abgleich bereits bekannter Buchungen.

Die folgenden Abfragen verwenden GET /v2/booking/list. Host, API-Schlüssel, Token und edid müssen zur selben Umgebung und zum ausgewählten Konto gehören. Die API-v2-Referenz enthält die Endpunkte und die herunterladbare OpenAPI-Datei.

Buchung, Teilnehmende und Zeitstempel unterscheiden

FeldVerwendung im Abgleich
idStabile Zuordnung des Buchungsdatensatzes im ausgewählten Konto. Als opaken Wert unverändert speichern; keine interne Datenbanknummer daraus ableiten.
timeBuchungszeitpunkt. Damit können Sie Buchungen nach ihrem Erstellungszeitpunkt eingrenzen.
offerReferenz auf das gebuchte Angebot.
ownerReferenz auf die Buchungsperson. Eine Buchung kann weitere Teilnehmende enthalten.
canceledStornokennzeichen der Buchung. Den gelieferten aktuellen Wert im Zielsystem übernehmen.
waiting_listWartelistenkennzeichen. Für die Auswertung getrennt vom Stornokennzeichen berücksichtigen.

time ist kein Änderungszeitstempel. Eine heute geänderte oder stornierte Buchung von früher wird durch einen Filter auf heute erstellte Buchungen nicht automatisch gefunden. Der Buchungszeitpunkt bezeichnet auch nicht den Beginn des gebuchten Angebots.

Für Teilnehmendenlisten oder Einzelpositionen reicht die Buchungsperson allein nicht aus. Laden Sie bei Bedarf die zugehörigen Teilnehmenden beziehungsweise Buchungsdetails mit den dafür vorgesehenen Ressourcen. Die fachliche Unterscheidung erklärt Buchungsdetail.

Festes Zeitfenster für neue Buchungen wählen

Verwenden Sie für jeden Lauf eine feste untere und obere Grenze. Ein Beispiel ist time >= 2026-10-16T00:00:00Z und time < 2026-10-17T00:00:00Z. So ist klar, welcher Lauf eine Buchung an der Tagesgrenze verarbeitet. Übergeben Sie Datumswerte als ISO-8601-Zeichenfolge mit Zeitzone, zum Beispiel Z für UTC oder einen ausdrücklichen Offset. Rechnen Sie zurückgegebene Datumswerte für Vergleiche in dieselbe Zeitzone um.

Der Zeitfilter wird mit filter, dem Feld time und expression gesetzt. Die hier verwendeten Operatoren sind >= und <. Die allgemein sichtbaren Parameter from und to sind für diese Buchungsliste kein Ersatz für den gezeigten Feldfilter.

Überlappen Sie aufeinanderfolgende Abrufe bei Bedarf etwas, zum Beispiel um fünf Minuten. Das ist eine Entscheidung Ihrer Integration. Wiederholt gelesene Buchungen müssen anhand ihrer ID aktualisiert werden. Eine Überlappung ersetzt den Abgleich älterer Buchungen nicht.

Erste Seite mit Filter, Feldern und Sortierung abfragen

Das folgende serverseitige JavaScript-Beispiel baut eine Leseanfrage für das feste Zeitfenster. edid und accessToken stammen aus Ihrer erfolgreichen Authentifizierung. URLSearchParams übernimmt die URL-Kodierung der JSON-Parameter.

const url = new URL('https://app2.edoobox.com/v2/booking/list');
url.searchParams.set('fields', JSON.stringify([
  'id', 'time', 'offer', 'owner', 'canceled', 'waiting_list'
]));
url.searchParams.set('filter', JSON.stringify([
  { property: 'time', expression: '>=', value: '2026-10-16T00:00:00Z' },
  { property: 'time', expression: '<', value: '2026-10-17T00:00:00Z' }
]));
url.searchParams.set('order', JSON.stringify([
  { property: 'time', value: 'ASC' },
  { property: 'id', value: 'ASC' }
]));
url.searchParams.set('limit', JSON.stringify({ start: 0, reply: 100 }));
url.searchParams.set('response_type', 'array');

const response = await fetch(url, {
  headers: { edid, Authorization: `Bearer ${accessToken}` }
});
if (!response.ok) throw new Error('Buchungsseite konnte nicht geladen werden');
const page = await response.json();
if (page.error || !Array.isArray(page.data) || !page.limit) {
  throw new Error('Ungültige oder abgewiesene Buchungsantwort');
}
// page.data erst jetzt im Zielsystem verarbeiten.
// Weitere Seiten mit demselben Filter und angepasstem limit.start lesen.

fields ist eine JSON-Liste von Feldnamen, filter eine JSON-Liste von Bedingungen und order eine JSON-Liste von Sortierfeldern. Die Sortierrichtung steht in value. Mehrere Bedingungen dieser einfachen Filterliste werden mit UND verknüpft. Behalten Sie Filter und Sortierung beim Wechsel der Seite bei.

Die Sortierung nach time und anschliessend id ordnet auch Buchungen mit gleichem Zeitstempel eindeutig. Ohne ausdrückliche Sortierung verwendet die allgemeine Liste die ID aufsteigend.

Alle Seiten bis zum vollständigen Ergebnis verarbeiten

Eine Listenabfrage liefert standardmässig höchstens 100 Einträge; die maximale angeforderte Seitengrösse beträgt 2000. limit.start ist eine Startposition ab 0, limit.reply die Seitengrösse. Für die zweite Seite mit 100 Einträgen verwenden Sie {"start":100,"reply":100}.

  1. Prüfen Sie bei jeder Seite den HTTP-Status, error, den erwarteten Datenbereich und die Seitendaten.
  2. Verarbeiten Sie die Buchungen aus data. Mit response_type=array erhalten Sie eine Liste; standardmässig ist der Datenbereich ein Objekt mit Buchungs-IDs als Schlüsseln.
  3. Lesen Sie die bestätigten Werte limit.start, limit.reply und limit.total der Antwort. total bezieht sich auf die Treffermenge der aktuellen Abfrage.
  4. Berechnen Sie die nächste Position aus start + reply. Fordern Sie sie mit denselben Filtern an, solange sie kleiner als total ist.
  5. Erhalten Sie unerwartet eine leere Seite, obwohl weitere Treffer gemeldet sind, oder widersprüchliche Seitendaten, brechen Sie den Lauf zur Prüfung ab.

Eine fehlgeschlagene Seite zählt nicht als erfolgreiches Ende. Die Seitendaten beschreiben den jeweiligen Abruf; die Folge mehrerer Anfragen ist keine zugesicherte unveränderliche Momentaufnahme. Behalten Sie deshalb das feste Zeitfenster, die eindeutige Sortierung, Wiederholbarkeit und den ergänzenden Bestandsabgleich bei.

Doppelte Verarbeitung und Unterbrüche beherrschen

Speichern Sie pro Umgebung, Konto und Buchungs-ID genau eine Zuordnung zum Zieldatensatz. Wird dieselbe Buchung erneut gelesen, aktualisieren Sie diesen Datensatz. Verwenden Sie dafür eine eindeutige Zuordnung im Zielsystem, damit zwei gleichzeitig eintreffende Verarbeitungen keine zweite Buchung anlegen.

  1. Lesen Sie den zuletzt vollständig abgeschlossenen Verarbeitungsstand aus Ihrer eigenen Datenbank.
  2. Legen Sie die obere Zeitgrenze für den neuen Lauf einmal fest und verwenden Sie sie auf allen Seiten.
  3. Lesen und verarbeiten Sie alle Seiten. Speichern Sie Fortschritt und Fehler so, dass ein unterbrochener Lauf sicher wiederholt werden kann.
  4. Setzen Sie den dauerhaft abgeschlossenen Verarbeitungsstand erst auf die obere Grenze, wenn alle Seiten und alle Übernahmen erfolgreich waren.

Schlägt etwa Seite 3 fehl, bleibt der bisherige abgeschlossene Stand erhalten. Wiederholen Sie den Lauf mit derselben Abgrenzung; bereits übernommene IDs werden aktualisiert. Planen Sie die Übernahme im Zielsystem so, dass ein erneuter Abruf keine zweite Bestätigung, CRM-Aktivität oder andere Nebenwirkung auslöst.

Änderungen und Stornos älterer Buchungen abgleichen

Planen Sie zusätzlich einen regelmässigen Abgleich des Bestands, den Ihr Zielsystem weiter benötigt. Laden Sie die gespeicherten Buchungs-IDs erneut über GET /v2/booking/{id} oder lesen Sie den benötigten Bestand vollständig über die paginierte Buchungsliste. Übernehmen Sie die aktuellen Felder statt nur neue IDs anzuhängen.

Schliessen Sie beim Abgleich stornierte Buchungen nicht pauschal aus: Ein Filter auf ausschliesslich aktive Buchungen kann sonst verhindern, dass ein zuvor aktiver Zieldatensatz auf storniert gesetzt wird. Trennen Sie ausserdem Buchungsstatus, Warteliste, einzelne Teilnehmendenpositionen und Zahlungen fachlich. Das Stornokennzeichen allein belegt keine abgeschlossene Rückzahlung.

Fehlt eine zuvor bekannte Buchung, prüfen Sie Konto, Rechte, Filter und den gezielten Einzelabruf, bevor Sie im Zielsystem eine Löschung oder Stornierung auslösen. Halten Sie unklare Fälle zur Bearbeitung fest. Die Häufigkeit und der berücksichtigte Bestand richten sich nach Ihrem fachlichen Bedarf und den verfügbaren API-Kapazitäten.

Webhooks mit dem REST-Abgleich kombinieren

Die Anleitung zu Einrichtung und Betrieb von Webhooks führt durch API-Zugang, Topics, Empfang, Signaturprüfung, Nachkontrolle und Deaktivierung. Verwenden Sie sie gemeinsam mit dem hier beschriebenen REST-Abgleich.

Für Buchungen existieren beispielsweise die Topics post_Booking für das Anlegen und put_Booking für Buchungsänderungen. Prüfen Sie für Ihren Ablauf die tatsächlich konfigurierten Topics und die erhaltenen Ereignisse. Daraus ergibt sich keine Zusage, dass jeder denkbare fachliche Statuswechsel ein bestimmtes Ereignis erzeugt.

Führen Sie Webhook-Verarbeitung und REST-Abgleich auf dieselbe gespeicherte Buchungszuordnung. Ein Ereignis kann einen gezielten Abruf der betroffenen Buchung anstossen. Verarbeiten Sie Aktualisierungen derselben ID koordiniert und lesen Sie ihren aktuellen Zustand, damit ein später verarbeitetes älteres Ereignis keinen neueren Zustand überschreibt.

Planen Sie den Abgleich auch für doppelte, verspätete oder ausgebliebene Meldungen. Eine genau einmalige Zustellung, feste Wiederholungsabstände oder eine bestimmte Zustellreihenfolge werden mit dieser Anleitung nicht zugesichert. Der regelmässige Bestandsabgleich bleibt Teil Ihrer Integrationslogik.

Anwendungsbeispiel: Buchungsübersicht im CRM

Eine Organisation möchte neue Kursbuchungen im CRM anzeigen und spätere Stornos übernehmen. Die Integration führt beispielsweise alle 15 Minuten einen Abruf neuer Buchungen aus. Sie startet fünf Minuten vor dem letzten abgeschlossenen Verarbeitungsstand und verwendet eine zu Laufbeginn festgelegte obere Grenze. Beide Intervalle sind frei gewählte Betriebswerte.

  1. Die erste Einrichtung liest den vorgesehenen historischen Buchungsbestand über alle Seiten ein und speichert jede Buchungs-ID mit ihrer CRM-Zuordnung.
  2. Die laufenden Zeitfenster ergänzen neue Buchungen. Überschneidungen aktualisieren vorhandene Zuordnungen.
  3. Ein passender Webhook veranlasst einen gezielten Abruf und dieselbe Aktualisierung im CRM.
  4. Ein täglicher Bestandsabgleich liest die weiterhin benötigten älteren Buchungen erneut. So wird auch ein heute stornierter Datensatz berücksichtigt, dessen Buchungszeitpunkt mehrere Wochen zurückliegt.
  5. Ein fehlgeschlagener Lauf erzeugt einen bearbeitbaren Fehler mit Zeitpunkt und Schritt. Der abgeschlossene Verarbeitungsstand wird erst nach erfolgreicher Wiederholung fortgeschrieben.

Das Ergebnis ist eine aktuelle Buchungsübersicht mit nachvollziehbarem Abgleichsstand. Diese Integration erzeugt durch das Lesen weder eine neue Buchung in edoobox noch eine Rückerstattung. Für Zahlungsabgleiche wählen Sie zusätzlich die passenden Rechnungs- und Transaktionsressourcen.

Häufige Abgleichsfehler eingrenzen

BeobachtungPrüfung
Immer nur 100 BuchungenSeitendaten auswerten und weitere Startpositionen lesen; die erste Seite ist nur ein Ausschnitt.
Alte Stornos fehlenErstellungszeitfilter überprüfen und bereits bekannte Buchungen erneut lesen.
Doppelte CRM-DatensätzeEindeutige Zuordnung aus Umgebung, Konto und Buchungs-ID sowie gleichzeitige Verarbeitung prüfen.
Buchungen an der Tagesgrenze fehlenZeitzonen, inklusive Untergrenze, exklusive Obergrenze und den zuletzt vollständig abgeschlossenen Stand prüfen.
Datenbereich lässt sich nicht als Liste verarbeitenresponse_type und erwartete Antwortform abgleichen; das Standardobjekt ist nach IDs gegliedert.
Zugriff bricht während des Laufs abTokenlaufzeit, Schlüsselstatus und Leserechte prüfen; Fehler beheben und ab dem gesicherten Stand wiederholen.

Protokollieren Sie den Lauf, das Zeitfenster, die Seitenposition und die Fehlerkategorie. Tokens, Secret Keys und vollständige personenbezogene Buchungsantworten gehören nicht in frei zugängliche Protokolle.

Verwandte Anleitungen