Entwicklerdokumentation

Reservierungen

Eine Reservierung für einen angebotenen Slot anlegen – Anfragefelder, die zurückgegebene Reservierung, Anzahlungen, Gruppenbuchungen und jede Ablehnung.

Ein Aufruf bucht einen Slot. Senden Sie Ressourcentyp, Datum und Beginn, die der Gast aus der Verfügbarkeit gewählt hat, die Gruppengröße und die Kontaktdaten des Gastes; zurück kommt eine Reservierung mit einer Referenz, die der Gast nennen kann, einem Status sowie Preis und Anzahlung, die gelten.

Endpunkte

POST /api/venues/{venueSlug}/reservations

Request-Header

Header Erforderlich Bedeutung
Idempotency-Key nein Ein von Ihnen gewähltes, beliebiges Token (bis zu 200 Zeichen), gültig für diese Location UND für Ihr BookDinePlay-Konto, und 24 Stunden lang berücksichtigt. Jeder API-Key Ihres Kontos kann einen Key wiedergeben, den ein anderer Ihrer Keys angelegt hat – eine Key-Rotation mitten im Vorgang ist also unproblematisch. Alle Ihre eigenen Keys teilen bewusst einen Namensraum – sie gehören zu einem Konto –, erzeugen Sie also weiterhin einen Key pro Buchungsversuch, statt sich auf eine Trennung zwischen zwei Ihrer eigenen Integrationen zu verlassen; getrennt sind die Keys eines anderen Kontos sowie Buchungen, die für Ihre Location über die von BookDinePlay selbst gehosteten Seiten entstehen – diese können Ihre weder wiedergeben noch blockieren. Eine Wiederholung mit DEMSELBEN Key und DEMSELBEN Request-Body liefert die ORIGINAL-Reservierung zurück – dieselbe reference, derselbe cancelToken – statt eine zweite anzulegen. Hat ein Key bereits so eine Reservierung erzeugt, wird eine Wiederverwendung mit einem ANDEREN Body abgelehnt mit idempotency-key-reused, niemals still wiedergegeben oder still durchgelassen. Ein Key, dessen bisher einziger Versuch FEHLGESCHLAGEN ist (Validierung, kein Slot frei), hat noch nichts gespeichert – eine korrigierte Wiederholung unter demselben Key ist dann einfach ein normaler neuer Versuch, keine Abweichung. Weggelassen ändert sich nichts: Jeder Aufruf legt eine neue Reservierung an, genau wie bisher.

Request-Body (Content-Type: application/json)

Feld Erforderlich Bedeutung
resourceType ja Der Typ des Slots, z. B. RestaurantTable
resourceId nein Die resourceId des Slots, um genau diese Ressource zu bekommen. Weggelassen: die erste freie Ressource des Typs zu dieser Zeit
date ja Ortszeit yyyy-MM-dd
start ja Ortszeit HH:mm, ein start, den die Verfügbarkeit angeboten hat
end nein Ortszeit HH:mm; Standard ist start plus Buchungsdauer
durationMinutes nein 15–1440. Denselben Wert senden, mit dem Sie die Verfügbarkeit abgefragt haben, oder weglassen für den Standard der Location
partySize ja 1–200
games nein 1–10, bei Ressourcen mit Preis pro Spiel; Standard 1
customerName ja 2–120 Zeichen
email ja Eine gültige E-Mail-Adresse – dorthin geht die Bestätigung
phone nein 3–40 Zeichen, wenn angegeben; ein leerer Wert gilt als nicht angegeben
notes nein Bis 500 Zeichen, für die Location sichtbar
depositOptIn nein true, wenn der Gast einer Anzahlung zustimmt; wirkt nur, wenn die Location Anzahlungen aktiviert hat
extras nein [{ "extraId": "…", "quantity": 1 }] – Extras aus dem Profil der Location, die für diesen Ressourcentyp gelten, Menge 1–100

Antwort 201 Created – ohne Location-Header. Das Token im Body ist eine Zugangsberechtigung (siehe cancelToken unten); es in einem Header zu senden würde es in Zugriffsprotokolle, Proxy-Protokolle und Referer-Ketten bringen, sodass aus den Antwort-Headern nichts über die Reservierung ableitbar ist.

Feld Typ Bedeutung
id GUID Interne Id
reference string BDP-XXXXXX – was der Gast nennt und worauf sich ein Payment Intent bezieht. Behandle sie als undurchsichtigen Wert: Buchungen aus der Zeit vor den sechsstelligen Referenzen tragen vier Zeichen (BDP-XXXX) und bleiben gültig
status string Confirmed, oder Pending, wenn eine Anzahlung nötig und noch nicht bezahlt ist; später Cancelled, Completed, NoShow
venueSlug, resourceType, resourceName string Wo
date, start, end string Wann, in Ortszeit
partySize, customerName Wer
priceEstimate, currency decimal, string Der Preis der Buchung nach dem Modell der Ressource
depositRequired, depositAmount boolean, decimal oder null Ob der Gast zur Bestätigung eine Anzahlung leisten muss, und wie viel
createdAt ISO-8601-Zeitpunkt Wann die Reservierung angelegt wurde
groupReference, groupResources string oder null, object[] oder null Bei einer Gruppenbuchung: die gemeinsame Referenz und jedes Mitglied (resourceId, resourceName, partyShare)
games integer oder null Bei Preis pro Spiel
extras, extrasTotal object[] oder null, decimal oder null Bepreiste Extra-Positionen (extraId, name, unitPrice, quantity, lineTotal, currency, basis) und ihre Summe
cancelToken string oder null Die eigene Zugangsberechtigung des Gasts für GET /api/reservations/{cancelToken} und die Storno-Route – aus Protokollen heraushalten. Bei einer Gruppenbuchung von jedem Mitglied geteilt. Nur bei einer Reservierung von vor Einführung dieses Felds null
{
  "id": "cad35696-0a75-45b6-b986-8bed7eb00ac5",
  "reference": "BDP-KSQS7M",
  "status": "Confirmed",
  "venueSlug": "demo-sportsbar",
  "resourceType": "RestaurantTable",
  "resourceName": "Corner table",
  "date": "2026-10-16",
  "start": "15:00",
  "end": "17:00",
  "partySize": 4,
  "customerName": "Ada Lovelace",
  "priceEstimate": 0,
  "currency": "EUR",
  "depositRequired": false,
  "depositAmount": null,
  "createdAt": "2026-09-15T12:55:15.1526956+00:00",
  "groupReference": null,
  "groupResources": null,
  "games": null,
  "extras": null,
  "extrasTotal": null,
  "cancelToken": "dqN_AejenL2r7qXPdZuOxnLY9_BfVkTl"
}

Fehler

Status Wann
400 Ein Feld scheitert an der Validierung (errors nennt es); date/start fehlerhaft; die Location ist dann geschlossen; die Dauer ist keine, die die Location für diesen Typ anbietet; ein Extra gilt nicht
404 Keine Location mit diesem Slug
409 Keine Ressource dieses Typs ist zu dieser Zeit frei – sie wurde seit der Verfügbarkeitsabfrage vergeben. Neu abfragen und den nächsten Slot anbieten
409 Ein gesendeter Idempotency-Key wurde bereits für einen Request mit anderem Body verwendet – siehe idempotency-key-reused

curl

curl -X POST "https://api.bookdineplay.com/api/venues/your-venue/reservations" \
  -H "X-BookDinePlay-Key: bdp_pk_your_publishable_key" \
  -H "Origin: https://www.your-venue.example" \
  -H "Content-Type: application/json" \
  -d '{
    "resourceType": "RestaurantTable",
    "date": "2026-10-16",
    "start": "19:00",
    "partySize": 4,
    "customerName": "Ada Lovelace",
    "email": "ada@example.com",
    "phone": "+49 30 1234567",
    "notes": "Window seat if possible"
  }'

JavaScript

const response = await fetch('https://api.bookdineplay.com/api/venues/your-venue/reservations', {
  method: 'POST',
  headers: { 'X-BookDinePlay-Key': 'bdp_pk_your_publishable_key', 'Content-Type': 'application/json' },
  body: JSON.stringify({
    resourceType: 'RestaurantTable', date: '2026-10-16', start: '19:00', partySize: 4,
    customerName: 'Ada Lovelace', email: 'ada@example.com', phone: '+49 30 1234567',
    notes: 'Window seat if possible'
  })
});
if (response.status === 409) { /* Slot gerade vergeben – Verfügbarkeit neu abfragen */ }
const reservation = await response.json();
console.log(reservation.reference, reservation.status);

C#

try
{
    var reservation = await client.CreateReservationAsync("your-venue", new CreateReservationRequest
    {
        ResourceType = BookableResourceType.RestaurantTable,
        Date = "2026-10-16",
        Start = "19:00",
        PartySize = 4,
        CustomerName = "Ada Lovelace",
        Email = "ada@example.com",
        Phone = "+49 30 1234567",
        Notes = "Window seat if possible"
    }, cancellationToken);
    Console.WriteLine($"{reservation.Reference} {reservation.Status}");
}
catch (BookDinePlayApiException ex) when (ex.StatusCode == HttpStatusCode.Conflict)
{
    // Slot gerade vergeben – Verfügbarkeit neu abfragen
}

Sicher wiederholen mit Idempotency-Key – den Key einmal pro Buchungsversuch erzeugen und für jede Wiederholung DESSELBEN Versuchs wiederverwenden:

curl

key="resv-$(uuidgen)"
curl -X POST "https://api.bookdineplay.com/api/venues/your-venue/reservations" \
  -H "X-BookDinePlay-Key: bdp_pk_your_publishable_key" \
  -H "Origin: https://www.your-venue.example" \
  -H "Idempotency-Key: $key" \
  -H "Content-Type: application/json" \
  -d '{ "resourceType": "RestaurantTable", "date": "2026-10-16", "start": "19:00", "partySize": 4, "customerName": "Ada Lovelace", "email": "ada@example.com" }'
# Bei Timeout oder 502/504 den identischen Request mit DEMSELBEN $key wiederholen.

JavaScript

const idempotencyKey = crypto.randomUUID();
async function reserve() {
  const response = await fetch('https://api.bookdineplay.com/api/venues/your-venue/reservations', {
    method: 'POST',
    headers: {
      'X-BookDinePlay-Key': 'bdp_pk_your_publishable_key',
      'Content-Type': 'application/json',
      'Idempotency-Key': idempotencyKey
    },
    body: JSON.stringify({
      resourceType: 'RestaurantTable', date: '2026-10-16', start: '19:00', partySize: 4,
      customerName: 'Ada Lovelace', email: 'ada@example.com'
    })
  });
  return response.json();
}
// reserve() bei Timeout/502/504 erneut aufrufen – jedes Mal derselbe idempotencyKey.

C#

var idempotencyKey = Guid.NewGuid().ToString();
var reservation = await client.CreateReservationAsync("your-venue", new CreateReservationRequest
{
    ResourceType = BookableResourceType.RestaurantTable,
    Date = "2026-10-16",
    Start = "19:00",
    PartySize = 4,
    CustomerName = "Ada Lovelace",
    Email = "ada@example.com"
}, idempotencyKey);
// Eine Wiederholung nach Timeout/502/504 übergibt DENSELBEN idempotencyKey und erhält DIESELBE Reservierung zurück.

GET /api/reservations/{cancelToken}

Die eigene Buchungsübersicht eines Gasts anhand seines Storno-Tokens: was, wann, wo, Gruppengröße, Status, und ob der eigene Storno-Button des Gasts gerade angezeigt werden soll. Kein Schlüssel: Das Token in der URL ist selbst die Zugangsberechtigung, die die Bestätigungs-E-Mail enthielt – dieselbe Begründung wie bei den Ticket-/Anmelde-Routen für Events. Nicht tarifgebunden – der Gast hat gebucht, während der Tarif der Location es erlaubte. Eine Gruppenbuchung (mehrere Ressourcen mit gemeinsamem Token) wird als eine einzige Übersicht ausgegeben: partySize ist die gesamte Gruppe, und groupResources listet jedes Mitglied.

Antwort 200 OK

Feld Typ Bedeutung
reference string Die eigene Referenz der Buchung (bei einer Gruppenbuchung das erste Mitglied)
groupReference string oder null Die gemeinsame Referenz, die Gästen bei einer Gruppenbuchung gezeigt wird
venueSlug, venueName string Wo
status string Confirmed, Pending, Cancelled, Completed oder NoShow
resourceType, resourceName string Die (erste) Ressource
date, start, end string Wann, in Ortszeit
partySize integer Die gesamte Gruppe über alle Mitglieder
groupResources object[] oder null Bei einer Gruppenbuchung: jedes Mitglied (resourceId, resourceName, partyShare)
canCancel boolean Ob der eigene Storno-Button des Gasts gerade funktionieren würde
cancelNote string oder null Warum nicht, wenn canCancel false ist: bereits storniert, von der Location abgeschlossen (No-Show oder abgeschlossener Besuch), eine bezahlte Anzahlung ohne bisherigen Online-Erstattungsweg, oder die Storno-Richtlinie der Location erlaubt es gerade nicht (abgeschaltet, oder die Frist ist abgelaufen)
{
  "reference": "BDP-KSQS7M",
  "groupReference": null,
  "venueSlug": "demo-sportsbar",
  "venueName": "The Neon Tap",
  "status": "Confirmed",
  "resourceType": "RestaurantTable",
  "resourceName": "Corner table",
  "date": "2026-10-16",
  "start": "15:00",
  "end": "17:00",
  "partySize": 4,
  "groupResources": null,
  "canCancel": true,
  "cancelNote": null
}

Fehler — 404 für ein unbekanntes oder ungültiges Token.

curl

curl "https://api.bookdineplay.com/api/reservations/dqN_AejenL2r7qXPdZuOxnLY9_BfVkTl"

JavaScript

const booking = await (await fetch('https://api.bookdineplay.com/api/reservations/' + cancelToken)).json(); // sendet keinen Schlüssel

C#

using var response = await http.GetAsync($"api/reservations/{cancelToken}", cancellationToken); // sendet keinen Schlüssel

POST /api/reservations/{cancelToken}/cancel

Storniert die Buchung hinter einem Storno-Link und gibt ihren Slot sofort frei – bei einer Gruppenbuchung alle Mitglieder auf einmal, da sie ein gemeinsames Token teilen. Kein Schlüssel: Das Token ist die Zugangsberechtigung. Idempotent – ein zweiter Aufruf nach erfolgreicher Stornierung antwortet erneut mit 200. Nicht tarifgebunden. Kein Request-Body.

Antwort 200 OK — reference, groupReference, status (Cancelled).

{
  "reference": "BDP-KSQS7M",
  "groupReference": null,
  "status": "Cancelled"
}

Fehler — 404 für ein unbekanntes Token; 409 reservation-cancellation-not-allowed, sobald die Storno-Richtlinie der Location eine Online-Stornierung nicht mehr erlaubt (komplett abgeschaltet, oder die Frist ist abgelaufen – beides steuert der Betreiber); 409 reservation-deposit-not-refundable für eine Buchung mit online bezahlter Anzahlung bei einer Location, die Anzahlungen lieber telefonisch klärt als über einen Storno-Link – die Buchung bleibt unverändert; und 502 reservation-refund-failed bei einer Location, die sehr wohl erstattet, wenn die Erstattung selbst nicht durchging – ebenfalls ohne Änderung an der Buchung, aber einen erneuten Versuch wert. Prüfen Sie in allen Fällen zuerst canCancel bei GET /api/reservations/{cancelToken}, um den Hin- und Rückweg zu vermeiden.

curl

curl -X POST "https://api.bookdineplay.com/api/reservations/<cancelToken>/cancel"

JavaScript

const result = await client.cancelReservation(cancelToken); // sendet keinen Schlüssel

C#

var result = await client.CancelReservationAsync(cancelToken, cancellationToken); // sendet keinen Schlüssel; null bei unbekanntem Token

Anzahlungen

Eine Reservierung braucht eine Anzahlung, wenn drei Dinge zutreffen: Der Gast hat depositOptIn: true gesendet, die Location hat Anzahlungen aktiviert, und die Ressource (oder der Standard der Location für Spielressourcen) trägt einen Anzahlungsbetrag. Dann ist depositRequired true, depositAmount nennt den Betrag, und status bleibt Pending, bis die Location die Buchung bestätigt. Legen Sie als Nächstes einen Payment Intent über diesen Betrag an. Ohne Anzahlung ist die Reservierung sofort Confirmed.

Gruppenbuchungen

Übersteigt partySize die Kapazität einer Ressource und hat die Verfügbarkeit einen Gruppen-Slot angeboten, erstreckt sich die Reservierung über mehrere Ressourcen: groupReference ist die gemeinsame Referenz, und groupResources listet jedes Mitglied mit seinem Anteil an der Gruppe. Extras werden einmal für die ganze Gruppe berechnet.

Nächste Schritte