Entwicklerdokumentation

Buchungsablauf

Was das Widget von Anfang bis Ende tut – die API-Aufrufe in ihrer Reihenfolge, jeder Schritt für den Gast, die Anzahlung und ihre Zahlung, die Bestätigung.

Das Widget ist ein Client der öffentlichen API und nicht mehr: Es hält keinen Zustand auf unserer Seite, und jeder Bildschirm, den ein Gast sieht, ist das Ergebnis eines von sechs Aufrufen. Diese Anleitung geht die Aufrufe in der Reihenfolge durch, in der sie passieren – was das Widget in jedem Schritt zeigt und sendet und was Ihre Seite beobachten kann und was nicht. Wenn Sie statt des Widgets eine eigene Oberfläche bauen, ist das die Abfolge, die Sie nachbilden.

Die Aufrufe, in ihrer Reihenfolge

Wann Aufruf Wozu
Direkt nach renderBookingWidget GET /api/venues/{venueSlug} Das Profil der Location: ihre bookingDurations (welche Dauern ein Gast wählen darf) und extras (kostenpflichtige Zusatzleistungen)
Wenn der Gast Zeiten abfragt GET /api/venues/{venueSlug}/availability Die Slots des Tages für Typ, Datum, Personenzahl und Dauer
Nach der Wahl eines Datums, wenn showSpecialsInBookingFlow im Profil der Location nicht false ist GET /api/venues/{venueSlug}/specials Die Specials dieses Datums (date und days=1) für die Zeile „An diesem Tag“ und die Bestätigung – separat geladen, nie blockierend
Mit der ersten Verfügbarkeitsabfrage GET /api/venues/{venueSlug}/floor-plan Der Tischplan der Location, falls sie einen veröffentlicht hat – einmal geladen, nie blockierend
Wenn der Gast bestätigt POST /api/venues/{venueSlug}/reservations Die Buchung selbst
Wenn der Gast in der Bestätigung eine Anzahlung bezahlt POST /api/venues/{venueSlug}/payment-intents Nur für eine Buchung, die als Pending mit offener Anzahlung zurückkam – siehe Anzahlungen

Jeder Aufruf trägt den übergebenen publishableKey als X-BookDinePlay-Key, und die API antwortet nur, wenn die Origin der Seite auf der Liste dieses Schlüssels steht (Origins). Das Widget legt einen Payment Intent nur an, wenn der Gast eine Anzahlung bezahlen will – siehe Anzahlungen.

Schritt für Schritt

Das Widget rendert fünf Schritte unter einer Fortschrittsleiste. Während die Verfügbarkeit lädt, zeigt der Schritt einen Ladezustand; während die Reservierung läuft, zeigt der Button „Confirming...“ und ist deaktiviert; die Aufrufe für Location, Specials und Tischplan zeigen nichts an. Eine fehlgeschlagene Anfrage zeigt ein rotes Banner über dem aktuellen Schritt und lässt den Gast, wo er war.

1. Was buchen

Eine Karte pro Typ aus resourceTypes. Die Wahl setzt zugleich die Standard-Buchungsdauer der Location für diesen Typ, sodass eine für Darts gewählte Dauer nie auf einen Restauranttisch übergeht. Bei einem einzigen Typ ist er vorausgewählt, der Schritt erscheint trotzdem.

2. Datum und Personenzahl

Ein Datum (heute oder später), eine Personenzahl von 1 bis 12 (Standard 2) und – nur wenn die Location Gäste für diesen Typ eine Dauer wählen lässt und mehr als eine anbietet – eine Auswahl „How long?“, vorbelegt mit dem Standard der Location. „See available times“ prüft das Datum und sendet die Verfügbarkeitsabfrage. Sobald ein Datum gewählt ist, nennt eine Zeile „An diesem Tag“ die Specials dieses Datums (höchstens drei mit Namen, dann „+ n weitere“) unter den Feldern und erneut in Schritt 3, wenn die Location Specials in der Buchung zeigt; die Verfügbarkeitsabfrage wartet nie darauf.

3. Freie Zeiten

Die von der API gelieferten Slots, nur die freien, jeweils mit Zeitspanne, Name der Ressource und einem „from“-Preis, wenn der Slot einen trägt. Ein Tag ohne freie Zeiten zeigt „No open times for this date and party size.“ und den Hinweis, ein anderes Datum oder eine kleinere Gruppe zu versuchen. Hat die Location einen Tischplan mit platzierten Ressourcen dieses Typs veröffentlicht und ist mindestens ein Slot frei, wählt der Gast stattdessen eine Uhrzeit und dann einen Tisch auf dem Plan; „List view“ wechselt zurück zur Liste. Die Wahl eines Slots und „Continue“ – oder das Antippen eines Tisches auf dem Tischplan – führt zu Schritt 4.

4. Kontaktdaten und die optionale Anzahlung

Name und E-Mail müssen ausgefüllt sein, damit der Button aktiv wird; Telefon und Notizen sind im Formular optional. Wo zutreffend, zeigt der Schritt zusätzlich eine Auswahl „Spiele pro Person“ (1–10) für einen Slot mit Preis pro Spiel und die Extras der Location für diesen Ressourcentyp mit je einer Menge. Zuletzt ein Kontrollkästchen – „Secure my spot with a deposit“ –, standardmäßig nicht angekreuzt. „Confirm reservation“ sendet die Reservierung.

5. Bestätigung

„Reservation confirmed“ – oder „Reservation received“, wenn die Reservierung als Pending zurückkam – mit der Referenz (BDP-XXXXXX), der Location, dem Was und Wann der Buchung, der Personenzahl, dem Namen, der Preisschätzung und, falls zutreffend, dem Anzahlungsbetrag. Die API hat dem Gast bis dahin Referenz und Status per E-Mail geschickt. Eine Buchung, deren Anzahlung noch offen ist, zeigt zusätzlich einen Schritt „Pay deposit“ (Anzahlungen). Zeigt die Location Specials in der Buchung, stehen die Specials des gebuchten Datums unter „An diesem Tag“. „Make another booking“ setzt auf Schritt 1 zurück; Profil und Tischplan der Location bleiben erhalten und werden nicht erneut geladen.

Was das Widget sendet

Der Query-String der Verfügbarkeitsabfrage, gebildet aus den Schritten 1 und 2:

Parameter Wert
date Das gewählte Datum, lokal für die Location, yyyy-MM-dd
partySize Die gewählte Personenzahl
resourceType Der gewählte Typ
durationMinutes Nur wenn der Gast eine Dauer gewählt hat; sonst weggelassen, damit der Standard der Location für jede Ressource gilt

Der Reservierungs-Body, gebildet aus dem gewählten Slot und Schritt 4. Jedes Feld ist immer vorhanden; was nicht zutrifft, ist null:

Feld Wert
resourceType Der gewählte Typ
resourceId Die resourceId des gewählten Slots, damit genau diese Ressource gebucht wird
date Das gewählte Datum
start Der start des Slots
end Das end des Slots
partySize Die gewählte Personenzahl
games Spiele pro Person bei einem Slot mit Preis pro Spiel; sonst null
durationMinutes Die gewählte Dauer, wenn die Auswahl angezeigt wurde; sonst null
extras [{ "extraId": "…", "quantity": 1 }] für jedes Extra mit einer Menge über null; null, wenn keins
customerName Der Name, getrimmt
email Die E-Mail, getrimmt
phone Die Telefonnummer, getrimmt; optional – ein leerer Wert gilt als nicht angegeben, 3–40 Zeichen, wenn angegeben
notes Die Notizen, getrimmt; leere Zeichenkette, wenn leer
depositOptIn true, wenn das Kontrollkästchen angekreuzt war
{
  "resourceType": "RestaurantTable",
  "resourceId": "table-4a",
  "date": "2026-10-16",
  "start": "19:00",
  "end": "21:00",
  "partySize": 4,
  "games": null,
  "durationMinutes": null,
  "extras": null,
  "customerName": "Ada Lovelace",
  "email": "ada@example.com",
  "phone": "+49 30 1234567",
  "notes": "",
  "depositOptIn": false
}

Was Ihre Seite beobachten kann

renderBookingWidget gibt die Widget-Instanz zurück – oder null, wenn es das Rendern verweigert hat (Wenn es nicht rendert). Das ist die ganze Schnittstelle: Das Widget löst keine DOM-Events aus, nimmt keine Callbacks entgegen, und die Felder der Instanz gehören nicht zum Vertrag. Um auf Ihrer Seite auf eine abgeschlossene Buchung zu reagieren – Analytics, eine Dankeseite, Ihr eigenes CRM –, bauen Sie mit window.BookDinePlay.createClient – dem Headless-Client, auf dem das Widget selbst läuft – einen eigenen Ablauf auf denselben vier Aufrufen (Eigene Formulare).

Anzahlungen

Das Ankreuzen sendet depositOptIn: true. Eine Anzahlung ist dann nur erforderlich, wenn die Location Anzahlungen aktiviert hat und die Ressource – oder der Standard der Location für Spielressourcen – einen Anzahlungsbetrag trägt; alle drei oder keins (Anzahlungen). Ist sie erforderlich, kommt die Reservierung als Pending mit depositRequired: true und einem depositAmount zurück; das Widget zeigt „Reservation received“ und die Anzahlungszeile, und die E-Mail an den Gast nennt den Status Pending. Die Bestätigung bietet dann „Pay deposit“ an: Das legt einen Payment Intent über den ganzen depositAmount an und schickt den Gast auf die gehostete Seite des Zahlungsanbieters – im Widget werden nie Kartendaten eingegeben. „Have a voucher?“ öffnet ein Feld für einen Gutscheincode; der Gutschein zahlt, was er abdeckt, die Karte den Rest (voucherCode in der Anfrage). Deckt der Gutschein die ganze Anzahlung, gibt es gar keine Kartenzahlung, und der Schritt sagt direkt, dass die Buchung bestätigt ist. Der Schritt erscheint nur, solange die Buchung Pending ist und kein Gutschein einen Teil bezahlt hat, und nur, wenn das Profil der Location onlineDepositsAvailable meldet (Location-Profil) – eine Location ohne Online-Zahlungen, ohne Anzahlungen im Tarif oder ohne verkaufsfähiges Auszahlungskonto zeigt ihn nie. Die Location kann die Buchung weiterhin auch in ihrer Konsole bestätigen. Mit language: 'de' erscheint dieser Schritt auf Deutsch. Ohne Anzahlung – Kästchen nicht angekreuzt oder Location nicht dafür eingerichtet – ist die Reservierung sofort Confirmed.

Wenn ein Aufruf fehlschlägt

  • Profil oder Tischplan – das Widget macht ohne sie weiter: keine Extras, keine Dauerauswahl, die Liste statt des Plans.
  • Specials – es wird nichts angezeigt, auch kein Banner: Die Zeile und die Liste in der Bestätigung entfallen, und die Buchung läuft unverändert weiter.
  • Verfügbarkeit – „We could not load available times. Please check your connection and try again.“ Der Gast bleibt in Schritt 2.
  • Reservierung – „We could not confirm your reservation. Please review your details and try again.“ Der Gast bleibt in Schritt 4. Es ist dasselbe Banner für einen Validierungsfehler (400), einen inzwischen vergebenen Slot (409) und einen abgelehnten Schlüssel (401/403); der Netzwerk-Tab des Browsers zeigt den Problem-type – Fehler erklärt jeden.
  • Eine überholte Anfrage – klickt der Gast erneut, bevor eine Antwort da ist, wird die frühere Anfrage abgebrochen und ihre Antwort ignoriert.

Nächste Schritte

  • Azure Static Web Apps – das Widget auf eine Live-Seite bringen, von null bis zur eigenen Domain.
  • Reservierungen – jedes Feld der Buchung, die das Widget anlegt, und die 409, die es bekommen kann.
  • JavaScript-SDK – Optionen, Isolation und CSP-Regeln für die Seite, die es einbettet.