Anmelden um den Slug und den veröffentlichbaren Schlüssel Ihrer Location in jedem Beispiel zu sehen.
Ihr Konto hat noch keine Location, die Beispiele behalten daher ihre Platzhalter. Abmelden
Angemeldet als · . Legen Sie in der Konsole einen veröffentlichbaren Schlüssel an und laden Sie die Seite neu, um ihn hier zu sehen. Abmelden
Angemeldet als · . Die Beispiele zeigen den veröffentlichbaren Schlüssel Ihrer Location. Abmelden
Entwicklerdokumentation
Changelog
Was sich in der öffentlichen API, im JavaScript- und .NET-SDK und im WordPress-Plugin geändert hat, Release für Release, neueste zuerst.
Kuratiert aus den GitHub-Releases: Aufgeführt ist nur, was eine Integration bemerken kann; interne, Konsolen- und Infrastrukturänderungen bleiben weg. Versionen sind die vX.Y.Z-Tags; dieselbe Version benennt den CDN-Pfad, die NuGet-Pakete und das WordPress-Zip des Releases (Versionen und Releases).
v0.20.1 — 2026-10-31
- Apps — Die Android-App ist bei Google Play und die Windows-App im Microsoft Store verfügbar; bookdineplay.com und app.bookdineplay.com verlinken jetzt beide. Die Versionen im App Store folgen nach Abschluss der Prüfung durch Apple.
v0.20.0 — 2026-10-29
- E-Mails — Jede E-Mail von BookDinePlay (Buchungsbestätigungen, Event-Anmeldungen und Tickets, Gutscheine, Nachrichten der Location, Abrechnung) hat jetzt ein gestaltetes HTML-Layout neben der unveränderten Textfassung; E-Mails einer Location tragen den Hinweis „Gesendet von BookDinePlay im Auftrag von …“. Die Betreffzeilen bleiben gleich.
- Kontakt — Die veröffentlichte Kontaktadresse ist jetzt überall hello@threebit.io, auch in den AGB und im Auftragsverarbeitungsvertrag.
- Apps — Die BookDinePlay-Apps für iPhone, iPad, Mac, Android und Windows: Location-Verzeichnis, Buchung, QR-Bestellung am Tisch und für Location-Teams der Operator-Modus mit Tarifen in der App. Android App Links werden jetzt auch für Installationen aus Google Play bestätigt.
v0.19.0 — 2026-10-29
- API —
GET /api/venues/{venueSlug}/specials?date=&days=listet die Specials der Location für 1 bis 14 aufeinanderfolgende Tage abdate(Standard: das heutige Datum der Location). Die Route gibt es in jedem Tarif und sie braucht wie die übrigen Location-Routen einen API-Schlüssel; ein Special, das auf einen Menüeintrag verweist, liefert dessen Namen, Beschreibung, Bild und regulären Preis aufgelöst mit. - .NET SDK —
IBookDinePlayClienthatGetSpecialsAsync(venueSlug, date, days)dazubekommen. Handgeschriebene Implementierungen müssen es ergänzen, und jeder Konsument muss gegen das neueBookDinePlay.Sharedneu kompilieren (Mocks sind nicht betroffen). - JavaScript SDK —
client.specials({ date, days })undrenderSpecialsWidget({ container, venueSlug, apiBaseUrl, publishableKey, view, locale, theme }): die Specials von heute oder dieser Woche mit einer Markierung „Jetzt“ in der Zeitzone der Location; ohne Specials wird nichts angezeigt. - WordPress —
[bookdineplay_specials venue="…" view="week" language="de"]rendert die Specials von heute oder dieser Woche, mit denselben Attributenapi,themeundkeywie die anderen Shortcodes. - API —
GET /api/venues/{venueSlug}hatshowSpecialsInBookingFlowdazubekommen (Standardtrue): ob die Location die Specials des Tages in der Buchung zeigen möchte. WasGET /api/venues/{venueSlug}/specialsantwortet, ändert sich dadurch nicht (Location-Profil). - JavaScript SDK —
renderBookingWidgetzeigt die Specials des gewählten Datums: eine Zeile „An diesem Tag“ unter den Schritten für Datum und Uhrzeit und die Liste des Tages in der Bestätigung, wennshowSpecialsInBookingFlowder Location an ist (oder fehlt). Sie wird nach der Wahl eines Datums separat geladen und hält weder die Uhrzeiten noch die Buchung auf; schlägt die Anfrage fehl, wird nichts angezeigt. Das optionalelanguage: 'de'übersetzt sie. - API —
GET /api/venues?query=&city=&page=&pageSize=ist das Location-Verzeichnis der BookDinePlay-App: Locations, deren Betreiber zugestimmt hat und deren Konto aktiv ist, nach Name sortiert, höchstens 50 pro Seite. Es antwortet nur BookDinePlays eigenem App- und Plattform-Schlüssel; der Schlüssel einer Location bekommt403 platform-key-required. - API — Ein drittes Schlüssel-Präfix,
bdp_ak_, für BookDinePlays eigene Apps aus den Stores. Betreiber können ihn nicht anlegen, mit einemOrigin-Header wird er abgelehnt (403 app-key-from-browser), und er ist pro Schlüssel begrenzt (429 rate-limitedmitRetry-After); für veröffentlichbare und geheime Schlüssel ändert sich nichts (Authentifizierung). - .NET SDK —
IBookDinePlayClienthatListDirectoryAsync(query, city, page, pageSize)dazubekommen, undBookDinePlay.SharedhatVenueDirectoryEntry,VenueDirectoryPage,AppListingDtound das Enum-MitgliedApiKeyType.Appdazubekommen.ListDirectoryAsynchat eine Standardimplementierung, dieNotSupportedExceptionwirft, sodass handgeschriebene Implementierungen weiter kompilieren; jeder Nutzer muss neu kompilieren (Mocks sind nicht betroffen). - Operator API —
GET/PUT /api/operator/venue/app-listingliest und setztlisted, das für jede Location aus ist, bis der Betreiber zustimmt. EinPUTohne booleschen Wertlistedwird mit400abgelehnt. Nicht an den Tarif gebunden.POST /api/operator/venue/api-keyslehnt den TypAppmit400ab. - Operator API —
/api/operator/venue/specials: Specials einer Location auflisten, lesen, anlegen, ändern, archivieren und in der Vorschau ansehen. - Operator API —
GET/PUT /api/operator/venue/specials/settingsliest und setztshowInBookingFlow, das für jede Location an ist, bis der Betreiber es abschaltet. EinPUTohne booleschen WertshowInBookingFlowwird mit400abgelehnt. Nicht an einen Tarif gebunden. - Operator API —
GET /api/operator/venue/specials/print?date=&days=1|7&paper=A4|A5&lang=en|deliefert die Specials des Tages oder der Woche als druckbares PDF, oder503, wenn keine PDF-Engine verfügbar ist;GET /api/operator/venue/specials/days?date=&days=1|7liefert die Specials-Tage, aus denen die Konsole ihre Bilder zum Teilen zeichnet. Beide sind nicht an einen Tarif gebunden und bleiben verfügbar, solange das Abonnement der Location gesperrt ist. - Operator-API — Tarifkäufe in den eigenen Store-Apps von BookDinePlay:
GET /api/operator/billing/store(Abrechnungsquelle des Kontos, ob ein In-App-Kauf möglich ist, und das Kauf-Token),POST /api/operator/billing/app-store/transactionsundPOST /api/operator/billing/google-play/purchases(beim Store geprüft und dann dem Konto des Aufrufers zugeordnet). Ein Konto wird über genau eine Quelle abgerechnet; Stripe-Checkout und -Portal antworten bei einem über einen Store abgerechneten Konto mit409 store-billing. - Operator-API —
DELETE /api/operator/accountlöscht das Konto der angemeldeten Person (die Anmeldung selbst und den Operator-Zugang; die Geschäftsdaten der Location bleiben erhalten). Solange ein Store-Abo noch verlängert wird und dies der letzte Operator der Location ist, wird mit409abgelehnt; ist der Identitätsanbieter nicht erreichbar, antwortet die Route mit503 account-deletion-unavailable, ohne etwas zu löschen. - Onboarding —
POST /api/onboardingnimmt optionalbillingan (Web,AppStore,GooglePlay; StandardWeb): eine Store-Registrierung öffnet keinen Stripe-Checkout und wird durch den In-App-Kauf abgeschlossen.GET /api/onboarding/legal-documentsliefert die heute geltenden AGB und den Auftragsverarbeitungsvertrag zur Anzeige. Registrierungen sind ratenbegrenzt. - .NET SDK —
BookDinePlay.Sharedhat die Verträge für die Store-Abrechnung (AppStoreTransactionRequest,GooglePlayPurchaseRequest, den Store-Abrechnungsstatus) undOnboardingRequest.Billingdazubekommen; jeder Konsument muss neu kompilieren.
v0.18.1 — 2026-10-12
- Intern — An der öffentlichen API, den SDKs und dem WordPress-Plugin ändert sich in diesem Release nichts.
BookDinePlay.SdkundBookDinePlay.Sharedwerden jetzt per NuGet Trusted Publishing statt mit einem gespeicherten API-Schlüssel auf nuget.org veröffentlicht; die Pakete selbst entstehen genau wie bisher.
v0.18.0 — 2026-10-09
- JavaScript SDK —
window.BookDinePlay.renderVoucherShop({ container, venueSlug, apiBaseUrl, publishableKey, locale, theme })verkauft die Gutscheine der Location: Es listet die Angebote, nimmt Käufer und optional die beschenkte Person, eine Grußbotschaft und ein Versanddatum auf und schickt den Käufer zu Stripe Checkout. Eine Location, die Gutscheine nicht online verkaufen kann, zeigt statt eines Formulars einen klaren Hinweis „nicht verfügbar“; eine Guthabenprüfung für einen vorhandenen Gutschein steht in beiden Fällen darunter (Gutscheine). - JavaScript SDK — Neue Client-Methoden:
client.voucherOffers(),client.checkoutVoucher(input, { idempotencyKey }),client.voucher(code)(ohne Schlüssel: Es wird kein Schlüssel gesendet, und eine Zeichenkette, die kein Gutscheincode ist, ergibtnullohne Anfrage) undclient.payDeposit({ reservationReference, amount, currency, voucherCode }).BookDinePlay.helpers.parseVoucherCodeundformatVoucherCodelesen einen Code so wie die API, Prüfzeichen eingeschlossen. - JavaScript SDK — Der Checkout von
renderEventsWidgetfür eine kostenpflichtige Veranstaltung hat ein Feld „Have a voucher?“ (voucherCodein der Anfrage). Die Bestätigung vonrenderBookingWidgethat einen Schritt „Pay deposit“ für eine Buchung, deren Anzahlung noch offen ist – per Karte oder mit einem Gutschein; er erscheint nur, wenn die LocationonlineDepositsAvailablemeldet. Das optionalelanguage: 'de'übersetzt diesen Schritt. - API —
GET /api/venues/{venueSlug}liefert neuonlineDepositsAvailable:truenur, wenn die Location Zahlungen und Anzahlungen annimmt, ihr Tarif Online-Zahlungen und Anzahlungen enthält und ihr Auszahlungskonto verkaufen kann (Location-Profil). - API — Geschenkgutscheine.
GET /api/venues/{venueSlug}/vouchers/offerslistet, was eine Location online verkauft (in jedem Tarif;onlineSaleAvailableundunavailableReasonsagen, ob ein Checkout starten kann), undPOST /api/venues/{venueSlug}/vouchers/checkoutkauft einen über Stripe Checkout auf dem eigenen Konto der Location (Premium, ein Auszahlungskonto, das verkaufen darf; beachtetIdempotency-Keywie der Ticket-Checkout). Der Gutscheincode entsteht erst, wenn die Zahlung eintrifft, und erreicht Käufer und Beschenkte per E-Mail (Gutscheine). - API —
GET /api/vouchers/{code}ist eine neue Route ohne Schlüssel – die elfte: Der Code ist das Credential wie ein Ticketcode, behandeln Sie ihn so und loggen Sie ihn nie. Sie liefert Wert, Guthaben, Ablaufdatum und Status eines Gutscheins, hängt nicht am Tarif und antwortet für jeden Code, der kein Gutschein ist, mit demselben404voucher-not-found, damit Codes nicht durchprobiert werden können. Sie ist die erste Route der API mit Ratenbegrenzung: 30 Abfragen pro Minute und Client, danach429mitRetry-After(Ratenbegrenzung). - API — Ein Gutschein bezahlt online:
POST /api/qr/{token}/payment(das jetzt einen optionalen Body nimmt),POST /api/venues/{venueSlug}/payment-intentsundPOST …/events/{eventSlug}/tickets/checkoutnehmen ein optionalesvoucherCode. Erst zahlt der Gutschein, die Karte den Rest, mindestens 0,50 € – der Gutschein zahlt etwas weniger, wenn die Karte sonst unter dem Mindestbetrag von Stripe belastet würde. Ein Gutschein, der alles deckt, öffnet keine Zahlungsseite, undcheckoutUrlist dann die Erfolgsseite, sodass ein Client, der ihr folgt, weiter funktioniert. Eine Erstattung bucht den Gutscheinteil auf den Gutschein zurück; weder das Bezahlen mit einem Gutschein noch die Erstattung hängt am Tarif (Mit einem Gutschein bezahlen). - API — Neue nachgestellte Member:
voucherAmount/paidInFullaufTabPaymentResponse,voucherAmount/cardAmountaufPaymentIntentResponse,voucherAmount/amountDueaufEventTicketCheckoutResponse,voucherCredits/amountDueaufTableSessionResponse(vom Personal am Tisch angewendete Gutscheine),depositVoucherAmountaufReservationResponseundAdminReservationSummarysowievoucherAmountaufOperatorEventRegistrationDto. Alle sind null (bzw.false), wenn kein Gutschein beteiligt ist. Zwölf neue Problemtypen,voucher-not-foundbisvoucher-hold-live(Gutschein-Probleme). - API —
POST /api/venues/{venueSlug}/payment-intentsist strenger, mit und ohne Gutschein:amountundcurrencymüssen genau die Anzahlung sein, die die Buchung schuldet (sonst400), und eine Buchung, die auf keine Anzahlung mehr wartet – storniert, von der Location bestätigt, vorbei oder schon bezahlt –, wird mit409undreasondeposit-not-payablebzw.deposit-already-paidabgelehnt, statt eine zweite Zahlung zu öffnen (Payment Intents). - API — Neue Buchungsreferenzen haben sechs Zeichen (
BDP-XXXXXX), Gruppenreferenzen ebenso, damit eine viel genutzte Plattform keine Kollision mehr riskiert; eine Anlage, die doch kollidiert, wird mit einer neuen Referenz wiederholt. Früher ausgegebene Referenzen bleiben mit vier Zeichen gültig – behandeln Sie eine Referenz als undurchsichtige Zeichenkette beliebiger dieser Längen. Referenzen von Event-Anmeldungen (BDP-E-XXXX) bleiben unverändert. - .NET SDK —
IBookDinePlayClienthat vier Member bekommen:GetVoucherOffersAsync,StartVoucherCheckoutAsync,GetVoucherAsync(ohne Schlüssel:KeylessRouteHandlerentfernt ihn;nullfür jede Ablehnung) und eine ÜberladungStartTabPaymentAsync(token, voucherCode, …). Eigene Implementierungen müssen sie ergänzen, und jeder Verbraucher muss gegen das neueBookDinePlay.Sharedneu kompilieren (Mocks sind nicht betroffen).CreatePaymentIntentRequest.VoucherCodeundEventTicketCheckoutRequest.VoucherCodenehmen einen Gutschein in den bestehenden Aufrufen, undAddBookDinePlayClienterzeugt jetzt auch für den Gutschein-Checkout einenIdempotency-Key(.NET SDK). - WordPress —
[bookdineplay_vouchers venue="…" language="de"]rendert den Gutschein-Shop, mit denselben Attributenapi,themeundkeywie die anderen Shortcodes (WordPress-Plugin). - API — Menüartikel haben eine stabile
id:items[].idinGET /api/venues/{venueSlug}/menus(undMenuItemDto.Id, ein nachgestelltes Member) wird vom Server vergeben und übersteht eine Umbenennung – verweisen Sie auf einen Artikel überid, nicht übername. Null nur bei einem Artikel, der gespeichert wurde, bevor es IDs gab (Speisekarten). - Operator API —
PUT /api/operator/venue/menusträgt die Artikel-idebenfalls. Ein Artikel ohneidbehält die des gespeicherten Artikels derselben Karte mit demselben Namen, nur ein neuer Artikel bekommt eine neue; eineid, die die Location nicht hat, oder eine doppelt verwendete wird mit400(errors.menu) abgelehnt, und nichts wird gespeichert. - Operator API — Die Gutschein-Routen der Konsole unter
/api/operator/venue/voucher-settingsund/api/operator/venue/vouchers: Einstellungen, Ausgabe von Hand, die Liste, Entwerten, Änderung des Ablaufdatums, Abfrage und Einlösung am Tisch (der Code steht im Body, nie in der URL), Rückgängig, Erstattung eines Online-Verkaufs, erneuter Versand und Druck. Keine hängt am Tarif, außer dass der Online-Verkauf Premium braucht.DemoVenueResetResponsehat ein nachgestelltesvouchersDeletedbekommen. - Operator API — Version 1.1 der Nutzungsbedingungen und des Auftragsverarbeitungsvertrags deckt den Online-Verkauf von Gutscheinen ab. Sie ist in Kraft, deshalb meldet
GET /api/operator/melegalAcceptanceRequired, bis der Betreiber sie in der Konsole akzeptiert.
v0.17.0 — 2026-10-06
- Operator-API —
PUT /api/operator/venue/reservations/{reference}lehnt das Bearbeiten einer Buchung im StatusPaidButUnavailablejetzt mit409und dem Problemtypreservation-not-editableab. Eine solche Buchung belegt keinen Slot; wurde sie verschoben, bekam sie eine Uhrzeit, die nichts schützte, und ein anderer Gast konnte denselben Tisch buchen. Solche Buchungen werden stattdessen per Erstattung oder als „erledigt“ aufgelöst. - Intern — Darüber hinaus ändert sich an der öffentlichen API, den SDKs und dem WordPress-Plugin in diesem Release nichts. Es bringt eine für Tablets ausgelegte Reservierungskonsole (Zeitleiste als Standard, Tabs je Ressourcentyp, ein Reservierungsdialog, der per Tippen bearbeitet, eine Seite, die sich selbst aktualisiert), die Anzahlungen und „bezahlt, aber nicht verfügbar“ direkt auf der Zeitleiste zeigt.
v0.16.0 — 2026-09-30
- API —
POST /api/venues/{venueSlug}/events/{eventSlug}/registrationsundPOST /api/venues/{venueSlug}/events/{eventSlug}/tickets/checkoutakzeptieren jetzt einenIdempotency-Key-Header, mit demselben Vertrag wie bereits bei Reservierungen: bis zu 200 Zeichen, begrenzt auf die Location und auf das Konto, das ihn vorlegt, 24 Stunden lang gültig. Eine Wiederholung mit demselben Key und demselben Body gibt die ursprüngliche Antwort zurück, statt eine zweite Anmeldung anzulegen. Ein Key, der für einen tatsächlich anderen Body wiederverwendet wird, wird mitidempotency-key-reusedabgelehnt; ohne den Header ändert sich nichts (Events). - API — Beim Ticket-Checkout ist das mehr als ein Schutz vor Doppelbuchungen. Ein wiederholter
Checkout legte bisher eine weitere vorläufige Anmeldung an, die 31 Minuten lang Plätze
blockierte, während nur die
checkoutUrldes letzten Versuchs beim Aufrufer ankam — ein vorübergehender Fehler oder ein zweiter Klick sperrte also Kontingent für einen Kauf, den niemand abgeschlossen hat, und ein fast ausverkauftes Event konnte sich als ausverkauft melden, obwohl die Plätze nicht verkauft waren. Eine Wiederholung mit demselben Key gibt jetzt dieselbe Checkout-Sitzung zurück, statt eine zweite zu eröffnen, und die Reservierung des ersten Versuchs bleibt unangetastet. - API — Ein neuer Problemtyp beim Ticket-Checkout:
checkout-in-progress(409), für eine Wiederholung, die genau zwischen dem Blockieren der Plätze und der Rückgabe der Session-URL durch Stripe eintrifft. Kurz warten und mit demselben Key erneut versuchen — das ist eine Frage des Zeitpunkts, keine Ablehnung. - .NET-SDK — Ein mit
AddBookDinePlayClientregistrierter Client erzeugt jetzt auch für diese beiden Routen einenIdempotency-Key, wenn der Aufrufer keinen mitgibt — nicht mehr nur beim Anlegen einer Reservierung. Ein automatischer Wiederholungsversuch auf Transportebene erreicht die API damit unter einem einzigen Key. Ein selbst gesetzter Key wird nie ersetzt, und kein anderer Aufruf bekommt einen Header dazu. - Operator-API — Tickets innerhalb einer Anmeldung kommen jetzt in einer stabilen Reihenfolge
zurück, und der CSV-Export unter
GET /api/operator/venue/events/{id}/registrations.csvmit ihnen. Die Reihenfolge war bisher die, die die Datenbank zufällig lieferte — zwei Exporte unveränderter Daten konnten sich also voneinander unterscheiden.
v0.15.0 — 2026-09-30
- Intern — An der öffentlichen API, den SDKs und dem WordPress-Plugin ändert sich in diesem Release nichts. Es ergänzt eine Route für Plattform-Administratoren, mit der ein bestehender Mandant einen eigenen Konsolen-Zugang erhält — eine von BookDinePlay eingerichtete Location muss damit nicht mehr per Identitätsübernahme durch Mitarbeitende betreut werden —, und es stellt die eigenen Persistenztests auf eine Datenbank um, die eindeutige Indizes tatsächlich erzwingt: genau die Lücke, durch die der Deployment-Fehler aus v0.13.0 unbemerkt durchging.
BookDinePlay.Sharedbekommt drei nur für Administratoren nutzbare Vertragstypen (CreateOperatorRequest,UpdateOperatorRequest,OperatorSummary); sie kommen rein additiv hinzu, sind nur mit Plattform-Administrator-Zugang erreichbar, und kein bestehender Typ, kein Mitglied und keine Antwortform hat sich geändert.
v0.14.0 — 2026-09-29
- API — Ein Gast kann seine Tischrechnung per Karte bezahlen:
POST /api/qr/{token}/paymentfriert die Rechnung 31 Minuten lang auf ihre aktuelle Summe ein und gibt eine Stripe-Checkout-Sitzung auf dem verbundenen Konto der Location zurück (TabPaymentResponse { checkoutUrl, amount, currency, expiresAt }); die Rechnung schließt sich selbst, sobald die Zahlung eingeht –POST …/closeist also nicht zusätzlich nötig. Ohne API-Schlüssel wie der Rest der QR-Gruppe – der gedruckte Token ist das Zugangsmerkmal –, setzt aber einen Tarif mit Online-Zahlungen, eingeschaltete Zahlungen und ein abgeschlossenes Stripe-Auszahlungs-Onboarding voraus. Ein erneuter Aufruf während einer laufenden Zahlung gibt dieselbe Checkout-Sitzung zurück statt eine zweite bezahlbare zu eröffnen; einIdempotency-Key-Header ist deshalb nicht nötig (QR-Codes und Tisch-Sitzungen). - API — Während eine Rechnungszahlung läuft, wird
POST /api/qr/{token}/ordersmit409abgelehnt (die abzubuchende Summe steht schon fest), undGET /api/qr/{token}/sessionbekommt zwei neue, angehängte Felder:paymentPending(immer vorhanden,falsefür jede Rechnung ohne laufende Zahlung – bestehende Antworten bedeuten also unverändert dasselbe) undpaymentUrl, dieselbe Checkout-URL, sodass ein zweites Gerät am Tisch die laufende Zahlung anzeigt statt eine weitere zu starten. Bricht der Gast den Checkout ab, läuft das Einfrieren von selbst aus. - .NET-SDK —
IBookDinePlayClienthat ein neues Mitglied,StartTabPaymentAsync– handgeschriebene Implementierungen müssen es ergänzen (Mocks sind nicht betroffen), dieselbe 0.x-Praxis wie bei den zwei Mitgliedern in v0.12.0 und den fünf in v0.10.0. Es sendet wie die anderen QR-Aufrufe keinen API-Schlüssel. - API — Eine über Stripe gezahlte Anzahlung auf eine Reservierung kann jetzt erstattet werden, und eine Anzahlung, die für eine bereits vergebene Zeit eintrifft, geht nicht mehr verloren. Die Location entscheidet, was passiert, wenn ein Gast eine Buchung mit online gezahlter Anzahlung storniert – über das neue
depositRefundbeiGET/PUT /api/operator/venue/cancellation-policy(NoOnlineRefund– der Standard und das Verhalten jeder Location bis hierher –,RefundOnGuestCanceloderForfeitOnGuestCancel).POST /api/reservations/{cancelToken}/cancelbekommt einen neuen Problemtyp:502reservation-refund-failed, für eine erstattende Location, deren Erstattung nicht durchging – es wird nichts storniert und ein erneuter Versuch lohnt sich, weshalb es ein502ist und nicht das regelbasierte409reservation-deposit-not-refundable(Reservierungen, Fehler). - API —
reservation-deposit-not-refundablebedeutet jetzt die eigene Entscheidung der Location statt einer fehlenden Funktion: Eine Location, diedepositRefundvonNoOnlineRefundwegschaltet, erzeugt es gar nicht mehr, und eine Buchung, deren Anzahlung das Personal erlassen oder in Bar genommen hat, erzeugte es nie – dieser Fall war vorher von einer echten Online-Zahlung nicht zu unterscheiden und wurde mit ihr abgelehnt. - API —
AdminReservationSummaryhat ein neues, angehängtesdepositRefundedAt(null, solange die Anzahlung nicht vollständig erstattet wurde), beiGET /api/operator/venue/reservationsundGET /api/admin/reservations. - API — Ein
Idempotency-KeybeiPOST /api/venues/{venueSlug}/reservationsgilt jetzt zusätzlich zur Location auch nur für das Konto, das ihn gesendet hat. Jeder API-Key Ihrer Location kann einen Key wiedergeben, den ein anderer Ihrer Keys angelegt hat – eine Key-Rotation mitten im Vorgang, oder ein Anlegen über einen serverseitigen Secret-Key mit Wiederholung von anderswo, riskiert damit keine zweite Buchung mehr; und ein von Ihrem Konto verwendeter Key kann nicht mehr von den Keys eines anderen Kontos wiedergegeben oder blockiert werden, und auch nicht von den von BookDinePlay selbst gehosteten Buchungsseiten Ihrer Location, die jetzt einen eigenen Namensraum haben. Ihre eigenen Keys teilen untereinander weiterhin einen Namensraum – bewusst, denn sie gehören zu einem Konto. Für den üblichen Key als Zufalls-UUID pro Versuch ändert sich nichts, und ein vor diesem Release belegter Key funktioniert seine restlichen 24 Stunden weiter (Reservierungen). - Behoben — Eine Anzahlung, die direkt im Stripe-Dashboard der Location erstattet wurde, landet jetzt wieder an der Buchung. Ihr
charge.refundedpasste vorher auf überhaupt nichts, und der Status der Buchung änderte sich nie.
v0.13.1 — 2026-09-29
- Fixed (intern) — An der öffentlichen API, den SDKs und dem WordPress-Plugin ändert sich in diesem Release nichts. Es behebt die Datenspeicher-Initialisierung beim Deployment, die v0.13.0 fehlerhaft hinterlassen hatte: Die Seed-Routine für unsere eigenen Demo-Locations prüfte anhand der Id, ob ein Event bereits existiert, während die Datenbank die Eindeutigkeit über Location- und Event-Slug gemeinsam erzwingt — ein unter einer anderen Id bereits vorhandener Slug wurde beim Einfügen daher abgewiesen. Keine Kunden-Location, keine Reservierung und keine Integration war betroffen: Die API beantwortete Anfragen durchgehend normal, und das Datenbankschema war bereits aktuell.
v0.13.0 — 2026-09-29
- API — Eine buchbare Ressource kann jetzt platzweise statt exklusiv verkauft werden:
seatSoldunter Ressourcen (immer vorhanden, Standardfalse— jede bestehende Ressource verhält sich weiterhin wie bisher: eine Reservierung belegt die gesamte Ressource). Eine platzweise verkaufte Ressource lässt mehrere Reservierungen sich ein Zeitfenster teilen, bis zusammencapacityerreicht ist — eine Eventfläche mit 31 Plätzen geht bei einer Gruppe von vier Personen nicht mehr komplett vom Markt. Verfügbarkeit-Slots einer platzweise verkauften Ressource erhaltenseatsRemaining(„27 von 31 frei"); bei einer exklusiven Ressource fehlt es im JSON ganz, sodass bestehende Integrationen unverändert bleiben.POST/PUT /api/operator/venue/resourcesakzeptieren ein nullbaresseatSold— wird es bei einem Update weggelassen, bleibt der aktuelle Modus der Ressource unverändert (beim Anlegen gilt weiterhin exklusiv als Standard). - API —
POST /api/venues/{venueSlug}/reservationsakzeptiert einen optionalenIdempotency-Key-Header (bis zu 200 Zeichen, gültig für die Location, 24 Stunden lang berücksichtigt): Eine Wiederholung mit demselben Key und demselben Request-Body gibt die Original-Reservierung zurück – dieselbereference, derselbecancelToken– statt eine zweite anzulegen, sodass ein Client, der eine verlorene Antwort nicht von einer verlorenen Anfrage unterscheiden konnte, nicht mehr raten muss. Ein Key, der für einen tatsächlich anderen Body wiederverwendet wird, wird abgelehnt mit dem neuen409idempotency-key-reused; wird der Header weggelassen, ändert sich nichts (Reservierungen, Fehler). - SDKs — Der Headless-Client sendet den neuen Header über
reserve(input, { idempotencyKey }), das Buchungs-Widget erzeugt automatisch pro Versuch einen Key und verwendet ihn bei eigenen Wiederholungen nach einem fehlgeschlagenen Absenden erneut, und das .NET-SDK erhält eine zweiteCreateReservationAsync-Überladung mitidempotencyKeyvor dem Cancellation-Token — die bestehende dreiargumentige Signatur bleibt unverändert, sodass ein gegen ein älteresBookDinePlay.Sharedkompilierter Aufrufer weiterhin bindet. - .NET-SDK — Ein mit
AddBookDinePlayClientregistrierter Client erzeugt fürPOST /api/venues/{venueSlug}/reservationsjetzt selbst einenIdempotency-Key, wenn der Aufrufer keinen übergibt – pro Aufruf ein frischer Wert, angehängt vor jeder Wiederholung auf Transportebene, sodass eine automatische Wiederholung einer Anlage (der Resilience-Handler eines .NET-Aspire-Hosts wiederholt POST standardmäßig) die API unter einem einzigen Key erreicht statt als mehrere Buchungen. Zwei getrennte Aufrufe bekommen immer getrennte Keys, und ein selbst übergebener Key wird nie ersetzt. Kein anderer Aufruf erhält einen Header. - SDKs — Der Headless-Client erhält
client.registration(cancelToken)fürGET /api/registrations/{cancelToken}– die dritte der drei schlüssellosen Gast-Routen, die fehlte, während die anderen zwei bereits verfügbar waren, sodass eine Storno-Seite ein eigenesfetchschreiben musste, um dem Gast vor dem Button zu zeigen, was er gebucht hat. Gebaut wieclient.ticket(): kein Schlüssel-Header, kein Location-Segment, dieselbeBookDinePlayError-Zuordnung. Im .NET-SDK deckteGetRegistrationAsyncdas schon ab (Events). - API — Jedes Zeichenkettenfeld eines öffentlichen Requests wird jetzt an der Schnittstelle gegen genau die Grenze geprüft, mit der auch seine Spalte konfiguriert ist: Ein zu langer Wert wird mit
400und Nennung des Feldes abgelehnt, statt die Datenbank zu erreichen und dort als500zu scheitern. Am deutlichsten bei Reservierungen:emailwar aus dem Widget zuvor unbegrenzt und ist nun auf 256 Zeichen begrenzt — so, wie es die Event-Contracts schon hielten. Keine Grenze wurde gesenkt; geschlossen wird die Lücke, in der Schnittstelle und Spalte voneinander abwichen, weshalb auch ein generierter Ressourcen-Code nicht mehr überlaufen kann. - API — Eine Wiederholung mit
Idempotency-Key, derenextrasin anderer Reihenfolge ankommen, wird jetzt als derselbe Request erkannt. Der Fingerprint, der über „derselbe Request“ entscheidet, wird aus dem geparsten Body berechnet, hashte die Extras-Liste aber in Ankunftsreihenfolge — ein Client, der seinen Warenkorb aus einem Dictionary neu aufbaut, konnte deshalb mit409idempotency-key-reusedfür eine Buchung abgelehnt werden, die nie zustande kam. Extras werden vor dem Hashen sortiert; unterschiedliche Mengen kennzeichnen weiterhin einen tatsächlich anderen Request. Vor diesem Release geschriebene Claims werden weiterhin nach dem vorherigen Verfahren verglichen, sodass eine Wiederholung über das Upgrade hinweg in beiden Fällen unberührt bleibt. - Operator-API — Das Bearbeiten einer Reservierung ohne Verschieben — Personenzahl, Notizen, Telefonnummer — meldet nicht mehr
409„dieser Zeitraum wurde inzwischen gebucht“, wenn der Schreibvorgang aus einem unabhängigen Grund fehlschlägt. Die Konfliktprüfung fragte den eigenen Slot der Buchung erneut ab und traf dabei genau die Zeile, die bearbeitet wurde; diese wird nun ausgeschlossen, sodass ein unabhängiger Fehler als er selbst erscheint und nicht als Slot-Kollision, die es nie gab. - Fixed —
seatSoldundIdempotency-Keysind beide additiv: Eine Location, dieseatSoldnie setzt, erhält byteweise identischeavailability-Antworten, und eine Reservierungsanlage ohneIdempotency-Key-Header verhält sich genau wie bisher. Die eine Verhaltensänderung, die man kennen sollte, ist die Längenprüfung oben — ein Request mit einem zu langen Wert, der zuvor die Datenbank erreichte, erhält jetzt ein400.
v0.12.1 — 2026-09-23
- API — Zwei neue Problemtypen auf
POST /api/operator/venue/payouts/onboarding-link, die vorher ein500war, wenn Stripe ablehnte:409connect-not-enabled(die Plattform hat Connect nicht freigeschaltet — die Location kann nichts tun) und409connect-rejected(Stripe lehnt die Daten dieser Location ab — Land, Umsatzsteuer-ID oder die Form der Website-URL — und der Betreiber kann sie korrigieren und es erneut versuchen). Zwei Typen, weil der nächste Schritt des Betreibers unterschiedlich ist (Fehler). - Auszahlungen — Die Stripe-Application-Fee ist ausschliesslich die BookDinePlay-Provision. Vorher enthielt sie zusätzlich eine Schätzung der Stripe-Gebühr, die bei Direct Charges das Konto der Location ohnehin selbst zahlt — die Location wurde also doppelt belastet und der effektive Satz lag über den ausgewiesenen 5 %. Bei einem Ticket zu EUR 20,00 betraegt die Gebuehr jetzt EUR 1,00 statt EUR 1,55. Keine API-Struktur hat sich geaendert; Locations erhalten schlicht das, was die Preisseite verspricht.
- Behoben — Ein fehlgeschlagenes Auszahlungs-Onboarding sperrt eine Location nicht mehr 24 Stunden aus (Stripe speichert eine Antwort — auch einen Fehler — zu einem Idempotency-Key), und ein abgelaufener Stripe-Onboarding-Link erzeugt jetzt einen neuen, statt den Betreiber ohne Ausweg auf die Abrechnungsseite zurueckzuschicken.
v0.12.0 — 2026-09-23
- API – Bezahlte Events verkaufen echte Tickets:
POST /api/venues/{venueSlug}/events/{eventSlug}/tickets/checkoutöffnet eine Stripe-Checkout-Session auf dem eigenen verbundenen Konto der Location (EventTicketCheckoutRequest– dieselben Felder wie bei einer kostenlosen Anmeldung, plus optionalesuccessUrl/cancelUrl;201 EventTicketCheckoutResponse { reference, checkoutUrl, expiresAt, cancelToken });GET /api/registrations/{cancelToken}reiht sich in die bestehenden Ausnahmen für schlüssellose Routen ein (Ticketcode und Storno-Token) – die eigene Anmelde-/Ticket- und Zahlungsstatus-Seite eines Gasts (Warum drei Routen keinen Schlüssel brauchen). Vier neue Problemtypen:409ticket-sales-not-enabled(die eine gastseitige Ablehnung, die „Tarif ohne Ticketverkauf“, „Auszahlungskonto nicht verbunden“ und „Event nicht Paid“ zusammenfasst),409payouts-not-connected(nur auf betreiberseitigen Routen),409refund-not-available(eine eigene Stornierung eines Gasts für eine bezahlte Anmeldung, die die Rückerstattungsrichtlinie nicht mehr erlaubt) und403tenant-suspended(hier dokumentiert; ausgeliefert mit der Onboarding-Änderung in v0.11.0) (Events). - JavaScript-SDK –
client.checkoutEventTickets(eventSlug, input)startet die Checkout-Session; das Formular eines bezahlten Events im Events-Widget zeigt jetzt eine Live-Summe (Intl.NumberFormat) und einen „Bezahlen & anmelden“-Button, der zucheckoutUrlweiterleitet, statt in einer Bestätigung im Widget zu enden – der frühere statische Zustand „Tickets bald verfügbar“ ist weg, denn eine Premium-Location mit verbundenem Auszahlungskonto kann jetzt tatsächlich verkaufen. Neue OptionensuccessUrl/cancelUrlbeicreateClient/renderEventsWidget.ticket-sales-not-enabledundpayouts-not-connectedzeigen absichtlich denselben Satz (Events). - WordPress –
[bookdineplay_events]/[bookdineplay_event]bekommen die Attributesuccess_url/cancel_url, direkt an das Widget durchgereicht (WordPress-Plugin). - .NET-SDK –
IBookDinePlayClienthat zwei Member dazubekommen:CheckoutEventTicketsAsyncundGetRegistrationAsync– von Hand implementierte Klassen müssen sie ergänzen (Mocks sind nicht betroffen), derselbe 0.x-Präzedenzfall wie bei den fünf Membern aus v0.10.0.BookDinePlayApiExceptionhat die KonstantenTenantSuspendedType,PayoutsNotConnectedTypeundRefundNotAvailableTypedazubekommen (.NET-SDK).
v0.11.0 — 2026-09-23
- API – Die Selbstregistrierung (
POST /api/onboarding) verlangt jetzt Firmen- und Abrechnungsdaten in derselben Anfrage:company(Firmenname, Adresse, USt-IdNr., Rechnungs-E-Mail, Ansprechpartner), ein Abrechnungsintervallinterval(MonthlyoderYearly) und die rechtlichenacceptancesdes Mandanten; die Antwort liefert eine Stripe-Checkout-checkoutUrl, die eine 14-tägige Testphase mit vorab hinterlegter Karte startet. - API – Zwei neue Problemtypen:
403tenant-suspendedauf jeder/api/venues/**-Route, sobald das Abonnement einer Location ausgelaufen oder gesperrt ist oder eine Selbstregistrierung nie bezahlt wurde; und409billing-managed-by-stripebeiPUT /api/admin/tenants/{id}, wenn Tarif und Status des Mandanten von einem aktiven Stripe-Abonnement bestimmt werden.
v0.10.0 — 2026-09-16
- API – Events der Location. Eine Location auf Pro oder höher veröffentlicht Events in der Konsole; die öffentliche API listet sie (
GET /api/venues/{venueSlug}/events,?upcoming=falsefür vergangene), liest eines mit seinem Anmeldefenster (…/events/{eventSlug}–registration.openundreason) und meldet Gäste zu kostenlosen Events an (POST …/events/{eventSlug}/registrations) – mit einem namentlichen Ticket pro Teilnehmer, einerBDP-E-XXXX-Referenz, Ticketcodes mit QR-Seiten und einem Storno-Link; der Gast bekommt dasselbe per E-Mail (Events). - API – Zwei schlüssellose Routen:
GET /api/tickets/{code}undPOST /api/event-registrations/{cancelToken}/cancelbrauchen keinen API-Schlüssel und sind nicht tarifgebunden – Code und Token sind die gemailten Zugangsmerkmale des Gastes, wie das gedruckte QR-Token (Warum zwei Routen keinen Schlüssel brauchen). - API – Zwei neue Problemtypen bei der Anmeldung:
409registration-closedmitreason(closed,sold-out,past,not-open) undremaining: 0bei Ausverkauf sowie409ticket-sales-not-enabledfür ein bezahltes Event, bis der Online-Ticketverkauf kommt.POST …/events/{eventSlug}/tickets/checkoutexistiert als Stub, der Letzteres antwortet; eine Anmeldung bei einer Location, deren Tarif keine Events enthält, ist403feature-not-in-plan. Eine verletzte Anmelderegel ist eine400, derenerrors-Wörterbuch die Meldungen unterregistrationträgt. - JavaScript-SDK –
BookDinePlay.renderEventsWidget({ container, venueSlug, apiBaseUrl, publishableKey, layout, language, eventSlug, onNavigate, theme })rendert die Events einer Location als Karten, das Detail eines Events, das Anmeldeformular und eine Bestätigung mit Ticketcodes – in derselben isolierten Wurzel und mit denselben neun--bdp-*-Properties wie das Buchungswidget;eventSlugrendert ein Event für eine eigene Seite,onNavigate(slug, summary)leitet auf die Seiten der Website. Der Headless-Client bekommtevents(),event(),registerForEvent(),ticket()undcancelEventRegistration()(die letzten beiden senden keinen Schlüssel);BookDinePlayErrorhebttype,reason,remainingunderrorsvom Problem und ergänztmessages().createClientverlangtvenueSlugnicht mehr vorab – nur die an die Location gebundenen Aufrufe werfen ohne ihn, eine Ticket- oder Storno-Seite braucht also nurapiBaseUrlundpublishableKey(Events). - WordPress –
[bookdineplay_events venue="…" layout="grid|list" language="en|de"]rendert das Events-Widget und[bookdineplay_event venue="…" event="…"]ein Event direkt; beide nehmenapi,themeundkeywie der Buchungs-Shortcode (WordPress-Plugin). - .NET-SDK –
IBookDinePlayClienthat fünf Member dazubekommen:GetEventsAsync,GetEventAsync,RegisterForEventAsync,GetTicketAsyncundCancelEventRegistrationAsync– handgeschriebene Implementierungen müssen sie ergänzen (Mocks sind nicht betroffen).BookDinePlayApiExceptionträgtType,Reason,Remaining,Errors,MessagesundExtensionsplus die KonstantenRegistrationClosedTypeundTicketSalesNotEnabledType.AddBookDinePlayClientregistriert einenKeylessRouteHandler, derX-BookDinePlay-Keyund einenBearer bdp_…-Authorization-Header aus den beiden schlüssellosen Routen entfernt (.NET-SDK).
v0.9.0 — 2026-09-16
- API – Tarifstufen werden durchgesetzt. Ein Starter-Mandant kann keine Ressource vom Spieltyp (Billardtisch, Dartscheibe, Shuffleboard, Bowlingbahn, Eventfläche, Sonstiges) anlegen oder bearbeiten, den Raumplan öffnen oder Mitarbeiter verwalten – die Operator-API antwortet mit
403 feature-not-in-planund einerrequiredPlan-Extension, die den freischaltenden Tarif nennt (Fehler). - API – Bei einer Starter-Location lassen
resourcesundresourceTypesderen Ressourcen vom Spieltyp vollständig weg; Gäste sehen sie nie (Venue). - API – Die Verfügbarkeit für einen
resourceType, den der Tarif der Location nicht anbietet, liefert200mit leerenslotsundnotice: "resource-type-not-offered"; eine Reservierung für diesen Typ wird trotzdem mit demselbenfeature-not-in-plan-Problem wie bei der Operator-API abgelehnt.
v0.8.0 — 2026-09-16
- JavaScript-SDK –
BookDinePlay.createClient({ apiBaseUrl, publishableKey, venueSlug })– ein Headless-Client für Seiten mit eigenem Formular:venue(),floorPlan(),availability(),reserve(), RFC-7807-Fehler alsBookDinePlayError; das Widget läuft jetzt darauf, undrenderBookingWidgetlehnt einen Schlüssel ab, der kein veröffentlichbarerbdp_pk_…-Schlüssel ist (gibtnullzurück, mit Konsolenmeldung), statt zu rendern und mit 403 zu scheitern (Eigene Formulare). - API – Öffnungszeiten dürfen nach Mitternacht schließen (
opens18:00,closes02:00); Verfügbarkeit und Reservierungen folgen der Spanne in den nächsten Tag, Pausen bleiben auf denselben Tag beschränkt (Öffnungszeiten).
v0.7.0 — 2026-09-16
- Docs – Tutorials: Buchungsablauf (was das Widget von Anfang bis Ende tut) und Azure Static Web Apps (von null zu einer Live-Seite der Location); dieses Changelog. Keine Änderung an der öffentlichen API, den SDKs oder dem WordPress-Plugin.
v0.6.0 — 2026-09-16
- API – Jeder Aufruf von
/api/venues/**verlangt einen API-Schlüssel: im Browser einen veröffentlichbarenbdp_pk_…-Schlüssel von einer erlaubten Origin, auf einem Server einen geheimenbdp_sk_…-Schlüssel. Ein fehlender, falscher oder falsch eingesetzter Schlüssel wird mit einem von sechs RFC-7807-Problemtypen abgelehnt (Authentifizierung, Fehler). - API – Buchungsdauern sind je Ressourcentyp konfigurierbar: Das Profil der Location listet
bookingDurations, Verfügbarkeit und Reservierungen akzeptierendurationMinutes, und die Verfügbarkeit meldet die Dauer, die ihre Slots darstellen. - API – Verfügbarkeit und Reservierungsanlage lösen die eigene Buchungsdauer einer Ressource auf dieselbe Weise auf, sodass ein angebotener Slot nicht mehr wegen seiner Dauer abgelehnt werden kann; eine Gruppe, die mehrere Ressourcen braucht, wird von beiden Aufrufen gleich aufgeteilt.
- API –
phonebeim Anlegen einer Reservierung ist optional: 3–40 Zeichen, wenn angegeben; ein leerer Wert gilt als nicht angegeben. - JavaScript-SDK – Auf dem CDN veröffentlicht:
sdk/<version>/bookdineplay.js(unveränderlich, mit SRI-Hash insri.txtdaneben) undsdk/v0/bookdineplay.js(Fünf-Minuten-Alias).renderBookingWidgetverlangt jetztpublishableKeyund nimmttheme(auto,light,dark); neun--bdp-*-Custom-Properties gestalten das Widget von der Host-Seite aus;window.BookDinePlay.versionnennt das geladene Release (JavaScript-SDK, Theming). - JavaScript-SDK –
durationMinuteswird nur gesendet, wenn der Gast eine Dauer gewählt hat; sonst gilt der Standard der Location. - .NET-SDK –
BookDinePlay.SdkundBookDinePlay.Sharedsind auf nuget.org, versioniert im Gleichschritt mit dem Release (.NET-SDK). - WordPress – Das Plugin erscheint als
bookdineplay-<version>.zipam Release, lädt das SDK vomv0-Alias, speichert den veröffentlichbaren Schlüssel unter Einstellungen → BookDinePlay, und der Shortcode erhält einkey-Attribut (WordPress-Plugin). - Docs – Diese Website.
v0.5.0 — 2026-09-09
- Keine Änderung an der öffentlichen API, den SDKs oder dem WordPress-Plugin. Nur Betreiberkonsole.
v0.4.1 — 2026-09-02
- Keine Änderung an der öffentlichen API, den SDKs oder dem WordPress-Plugin. Nur Betreiberkonsole.
v0.4.0 — 2026-07-23
- API – Meldungen und Problem-Antworten sind lokalisiert: Senden Sie
Accept-Language: defür deutschetitleunddetail; Englisch ist der Standard (Fehler). Die Bestätigungs-E-Mail des Gastes verwendet die Sprache der Anfrage, die die Reservierung angelegt hat. - API – Buchbare Extras: Das Profil der Location listet
extras; eine Reservierung akzeptiertextras: [{ "extraId": "…", "quantity": 1 }]und liefert bepreisteextras-Zeilen undextrasTotal. - API – Preis pro Spiel: Ein Slot kann
pricingModel: "PerGame"tragen; eine Reservierung akzeptiert und liefertgames(1–10). - API – Gruppenbuchungen: Eine Gruppe, die für eine Ressource zu groß ist, bekommt einen Gruppen-Slot (
groupResourceCount,groupResourceNames); die Reservierung liefertgroupReferenceundgroupResources. - API – Neuer Ressourcentyp
BowlingLane; Essensbestellung ist eine Einstellung je Ressource (allowsFoodOrderingauf Ressourcen). - JavaScript-SDK, WordPress –
BowlingLanein der Liste der Ressourcentypen und in den Standard-typesdes Plugins; das Widget erfasst Spiele pro Person und Extras, wo die Location sie anbietet.
Releases vor v0.4.0 liegen vor den öffentlichen Integrationswegen und sind nicht aufgeführt.