Entwicklerdokumentation

Venue

Profil, Geschäftsdaten, Öffnungszeiten, Speisekarten, buchbare Ressourcen und Raumplan der Location lesen – die sechs GETs, mit denen jede Integration beginnt.

Sechs Lesezugriffe beschreiben eine Location vollständig. Sie sind günstig, auf Ihrer Seite cachebar und ändern sich nur, wenn der Betreiber etwas in der Konsole bearbeitet. Alle nehmen den Slug der Location im Pfad, brauchen einen Schlüssel (Schlüssel und Header) und antworten mit 404 und einem Problem-Body, wenn keine Location diesen Slug hat.

Endpunkte

GET /api/venues/{venueSlug}

Das öffentliche Profil der Location: Name, Beschreibung, Ort, Zeitzone, welche Ressourcentypen sie anbietet und – sofern vom Betreiber eingerichtet – kostenpflichtige Extras und die Buchungsdauern, die ein Gast je Ressourcentyp wählen darf.

Antwort 200 OK

Feld Typ Bedeutung
slug string Der Bezeichner, den Sie in der URL verwendet haben
name, tagline, description string Anzeigetexte in der Sprache der Location
city, country string Ort, wie Gäste ihn sehen
timezone string IANA-Zeitzone, in der jedes Datum und jede Uhrzeit dieser Location liegt
resourceTypes string[] Die Typen, die diese Location anbietet: RestaurantTable, BilliardTable, DartBoard, Shuffleboard, BowlingLane, EventArea
extras object[] oder null Kostenpflichtige Zusatzleistungen: id, name, description, price, currency, basis (PerPerson oder PerBooking), appliesTo (Ressourcentypen)
bookingDurations object[] oder null Je Typ: type, defaultMinutes, minMinutes, maxMinutes, stepMinutes, guestSelectable, options (die wählbaren Minuten, fertig für eine Auswahl)
{
  "slug": "demo-sportsbar",
  "name": "The Neon Tap",
  "tagline": "Sports bar, kitchen & game house",
  "description": "A neighbourhood sports bar where guests come to dine, drink, watch the match, and play. Reserve a table for the big game, book a billiard table or dart board by the hour, or take the whole mezzanine for a private event.",
  "city": "Berlin",
  "country": "Germany",
  "timezone": "Europe/Berlin",
  "resourceTypes": [
    "RestaurantTable",
    "BilliardTable",
    "DartBoard"
  ],
  "extras": null,
  "bookingDurations": [
    {
      "type": "RestaurantTable",
      "defaultMinutes": 120,
      "minMinutes": 60,
      "maxMinutes": 240,
      "stepMinutes": 30,
      "guestSelectable": false,
      "options": [
        120
      ]
    },
    {
      "type": "BilliardTable",
      "defaultMinutes": 60,
      "minMinutes": 60,
      "maxMinutes": 240,
      "stepMinutes": 30,
      "guestSelectable": true,
      "options": [
        60,
        90,
        120
      ]
    },
    {
      "type": "DartBoard",
      "defaultMinutes": 60,
      "minMinutes": 60,
      "maxMinutes": 240,
      "stepMinutes": 30,
      "guestSelectable": true,
      "options": [
        60,
        90,
        120
      ]
    }
  ]
}

Listen im Beispiel sind auf drei Einträge gekürzt.

Fehler404 keine Location mit diesem Slug; Schlüsselprobleme wie unter Fehler.

curl

curl "https://api.bookdineplay.com/api/venues/your-venue" \
  -H "X-BookDinePlay-Key: bdp_pk_your_publishable_key" \
  -H "Origin: https://www.your-venue.example"

JavaScript

const response = await fetch('https://api.bookdineplay.com/api/venues/your-venue', {
  headers: { 'X-BookDinePlay-Key': 'bdp_pk_your_publishable_key' }
});
const venue = await response.json();
console.log(venue.name, venue.resourceTypes);

C#

var venue = await client.GetVenueAsync("your-venue", cancellationToken);
if (venue is null) { /* keine Location mit diesem Slug */ }

GET /api/venues/{venueSlug}/business-info

Firmenname, Postanschrift und Kontaktdaten – was ein Impressum, ein Kartenlink oder eine Bestätigungs-E-Mail braucht.

Antwort 200 OK

Feld Typ Bedeutung
slug string Die Location
legalName string Das Betreiberunternehmen, wie es auf Belegen steht
addressLine1, addressLine2, city, postalCode, country string (addressLine2 nullable) Postanschrift
phone, email, website string (website nullable) Kontaktdaten, die die Location veröffentlicht
timezone string Dieselbe IANA-Zone wie im Profil
{
  "slug": "demo-sportsbar",
  "legalName": "Neon Tap Hospitality GmbH",
  "addressLine1": "Boxhagener Straße 42",
  "addressLine2": null,
  "city": "Berlin",
  "postalCode": "10245",
  "country": "Germany",
  "phone": "+49 30 5555 0142",
  "email": "hey@theneontap.example",
  "website": "https://theneontap.example",
  "timezone": "Europe/Berlin"
}

Fehler404 keine Location mit diesem Slug.

curl

curl "https://api.bookdineplay.com/api/venues/your-venue/business-info" \
  -H "X-BookDinePlay-Key: bdp_pk_your_publishable_key" \
  -H "Origin: https://www.your-venue.example"

JavaScript

const info = await (await fetch('https://api.bookdineplay.com/api/venues/your-venue/business-info', {
  headers: { 'X-BookDinePlay-Key': 'bdp_pk_your_publishable_key' }
})).json();
console.log(`${info.legalName}, ${info.addressLine1}, ${info.postalCode} ${info.city}`);

C#

var info = await client.GetBusinessInfoAsync("your-venue", cancellationToken);

GET /api/venues/{venueSlug}/opening-hours

Der Wochenplan plus datumsbezogene Ausnahmen (Feiertage, Veranstaltungen, früherer Schluss). Die Verfügbarkeit wendet sie bereits an; lesen Sie sie, um Öffnungszeiten anzuzeigen, nicht um Slots zu berechnen.

Antwort 200 OK

Feld Typ Bedeutung
slug, timezone string Die Location und die Zone, in der die Zeiten liegen
regular object[] Ein Eintrag je Wochentag: day (MondaySunday), isClosed, opens, closes (HH:mm, null wenn geschlossen)
special object[] Datumsausnahmen: date (yyyy-MM-dd), isClosed, opens, closes, note – ein Eintrag gewinnt an seinem Datum über den Wochentag

Zeiten über Mitternacht hinweg (opens 18:00, closes 02:00) gehören zu dem Tag, an dem sie beginnen.

{
  "slug": "demo-sportsbar",
  "timezone": "Europe/Berlin",
  "regular": [
    {
      "day": "Monday",
      "isClosed": true,
      "opens": null,
      "closes": null
    },
    {
      "day": "Tuesday",
      "isClosed": false,
      "opens": "16:00",
      "closes": "23:00"
    },
    {
      "day": "Wednesday",
      "isClosed": false,
      "opens": "16:00",
      "closes": "23:00"
    }
  ],
  "special": [
    {
      "date": "2026-12-24",
      "isClosed": true,
      "opens": null,
      "closes": null,
      "note": "Christmas Eve — closed"
    },
    {
      "date": "2026-12-31",
      "isClosed": false,
      "opens": "18:00",
      "closes": "02:00",
      "note": "New Year's Eve — late night"
    }
  ]
}

Fehler404 keine Location mit diesem Slug.

curl

curl "https://api.bookdineplay.com/api/venues/your-venue/opening-hours" \
  -H "X-BookDinePlay-Key: bdp_pk_your_publishable_key" \
  -H "Origin: https://www.your-venue.example"

JavaScript

const hours = await (await fetch('https://api.bookdineplay.com/api/venues/your-venue/opening-hours', {
  headers: { 'X-BookDinePlay-Key': 'bdp_pk_your_publishable_key' }
})).json();
for (const day of hours.regular) {
  console.log(day.day, day.isClosed ? 'geschlossen' : `${day.opens}–${day.closes}`);
}

C#

var hours = await client.GetOpeningHoursAsync("your-venue", cancellationToken);

GET /api/venues/{venueSlug}/menus

Jede veröffentlichte Speisekarte mit Gruppen und Positionen, bepreist in der Währung der Location. Das ist die Anzeige-Karte; woraus ein sitzender Gast bestellen kann, sind die menus der Tischsitzung (QR-Codes und Tischsitzungen).

Antwort 200 OK

Feld Typ Bedeutung
slug, currency string Die Location und die ISO-4217-Währung jedes Preises darunter
menus[] object[] id, name, description, groups[]
groups[] object[] name, description (nullable), items[]
items[] object[] name, description, price (decimal), currency, tags (string[], z. B. Ernährungshinweise), imageUrl (nullable)
{
  "slug": "demo-sportsbar",
  "currency": "EUR",
  "menus": [
    {
      "id": "kitchen",
      "name": "Kitchen",
      "description": "Served from open until one hour before close.",
      "groups": [
        {
          "name": "Small plates",
          "description": null,
          "items": [
            {
              "name": "Loaded nachos",
              "description": "Melted cheese, jalapeños, lime crema",
              "price": 9.50,
              "currency": "EUR",
              "tags": [
                "vegetarian"
              ],
              "imageUrl": "_content/BookDinePlay.App.Shared/menu/nachos.webp"
            },
            {
              "name": "Buffalo wings",
              "description": "Blue-cheese dip, celery",
              "price": 11.00,
              "currency": "EUR",
              "tags": [],
              "imageUrl": "_content/BookDinePlay.App.Shared/menu/wings.webp"
            },
            {
              "name": "Padrón peppers",
              "description": "Sea salt, olive oil",
              "price": 7.00,
              "currency": "EUR",
              "tags": [
                "vegan",
                "gluten-free"
              ],
              "imageUrl": "_content/BookDinePlay.App.Shared/menu/padron-peppers.webp"
            }
          ]
        },
        {
          "name": "Mains",
          "description": null,
          "items": [
            {
              "name": "Smash burger",
              "description": "Double patty, house sauce, fries",
              "price": 14.50,
              "currency": "EUR",
              "tags": [],
              "imageUrl": "_content/BookDinePlay.App.Shared/menu/smash-burger.webp"
            },
            {
              "name": "BBQ ribs",
              "description": "Slow-cooked, slaw, fries",
              "price": 19.00,
              "currency": "EUR",
              "tags": [],
              "imageUrl": "_content/BookDinePlay.App.Shared/menu/bbq-ribs.webp"
            },
            {
              "name": "Halloumi flatbread",
              "description": "Grilled halloumi, harissa, greens",
              "price": 13.00,
              "currency": "EUR",
              "tags": [
                "vegetarian"
              ],
              "imageUrl": "_content/BookDinePlay.App.Shared/menu/halloumi-flatbread.webp"
            }
          ]
        },
        {
          "name": "Sweet",
          "description": null,
          "items": [
            {
              "name": "Churros",
              "description": "Cinnamon sugar, chocolate",
              "price": 7.00,
              "currency": "EUR",
              "tags": [
                "vegetarian"
              ],
              "imageUrl": "_content/BookDinePlay.App.Shared/menu/churros.webp"
            }
          ]
        }
      ]
    },
    {
      "id": "bar",
      "name": "Bar",
      "description": "Draft, cocktails and zero-proof.",
      "groups": [
        {
          "name": "Draft beer",
          "description": null,
          "items": [
            {
              "name": "House lager 0.3L",
              "description": "Crisp pilsner",
              "price": 4.50,
              "currency": "EUR",
              "tags": [],
              "imageUrl": "_content/BookDinePlay.App.Shared/menu/lager.webp"
            },
            {
              "name": "Local IPA 0.5L",
              "description": "Hoppy, citrus finish",
              "price": 6.50,
              "currency": "EUR",
              "tags": [],
              "imageUrl": "_content/BookDinePlay.App.Shared/menu/ipa.webp"
            }
          ]
        },
        {
          "name": "Cocktails",
          "description": null,
          "items": [
            {
              "name": "Old Fashioned",
              "description": "Bourbon, bitters, orange",
              "price": 11.00,
              "currency": "EUR",
              "tags": [],
              "imageUrl": "_content/BookDinePlay.App.Shared/menu/old-fashioned.webp"
            },
            {
              "name": "Spicy margarita",
              "description": "Tequila, chilli, lime",
              "price": 10.50,
              "currency": "EUR",
              "tags": [],
              "imageUrl": "_content/BookDinePlay.App.Shared/menu/margarita.webp"
            }
          ]
        },
        {
          "name": "Zero proof",
          "description": null,
          "items": [
            {
              "name": "Craft soda",
              "description": "House-made, ask for today's flavour",
              "price": 4.00,
              "currency": "EUR",
              "tags": [
                "vegan"
              ],
              "imageUrl": "_content/BookDinePlay.App.Shared/menu/craft-soda.webp"
            }
          ]
        }
      ]
    }
  ]
}

Fehler404 keine Location mit diesem Slug.

curl

curl "https://api.bookdineplay.com/api/venues/your-venue/menus" \
  -H "X-BookDinePlay-Key: bdp_pk_your_publishable_key" \
  -H "Origin: https://www.your-venue.example"

JavaScript

const { menus, currency } = await (await fetch('https://api.bookdineplay.com/api/venues/your-venue/menus', {
  headers: { 'X-BookDinePlay-Key': 'bdp_pk_your_publishable_key' }
})).json();
for (const menu of menus) for (const group of menu.groups) for (const item of group.items) {
  console.log(menu.name, group.name, item.name, item.price, currency);
}

C#

var menus = await client.GetMenusAsync("your-venue", cancellationToken);

GET /api/venues/{venueSlug}/resources

Jede buchbare Ressource – Tische, Billardtische, Dartscheiben, Bahnen, Eventflächen – mit Kapazität, der für sie geltenden Buchungsdauer und ihrer Bepreisung.

Antwort 200 OK

Feld Typ Bedeutung
slug string Die Location
resources[] object[] Eine je Ressource
id, name, description string id ist das, was resourceId überall sonst bedeutet
type string Einer der Ressourcentypen
capacity integer Plätze oder Spieler
slotDurationMinutes integer Die wirksame Buchungsdauer: die eigene Überschreibung der Ressource, sofern gesetzt, sonst der Standard der Location für den Typ
slotDurationOverrideMinutes integer oder null Nur die Überschreibung; null, wenn die Ressource den Standard erbt
pricing object model (Free, PerHour, PerGame, PerSession, FixedFee, Deposit, MinimumSpend), amount, currency, depositAmount (nullable), minimumSpend (nullable), unitLabel (z. B. „pro Stunde“)
allowsFoodOrdering boolean Ob ein sitzender Gast aus der Tischsitzung bestellen kann
{
  "slug": "demo-sportsbar",
  "resources": [
    {
      "id": "table-2a",
      "name": "Window table",
      "type": "RestaurantTable",
      "capacity": 2,
      "description": "Seats up to 2. Reserved free of charge.",
      "slotDurationMinutes": 120,
      "pricing": {
        "model": "Free",
        "amount": 0,
        "currency": "EUR",
        "depositAmount": null,
        "minimumSpend": null,
        "unitLabel": "booking"
      },
      "allowsFoodOrdering": true,
      "slotDurationOverrideMinutes": null
    },
    {
      "id": "table-4a",
      "name": "Table 4",
      "type": "RestaurantTable",
      "capacity": 4,
      "description": "Seats up to 4. Reserved free of charge.",
      "slotDurationMinutes": 120,
      "pricing": {
        "model": "Free",
        "amount": 0,
        "currency": "EUR",
        "depositAmount": null,
        "minimumSpend": null,
        "unitLabel": "booking"
      },
      "allowsFoodOrdering": true,
      "slotDurationOverrideMinutes": null
    },
    {
      "id": "table-4b",
      "name": "Table 7",
      "type": "RestaurantTable",
      "capacity": 4,
      "description": "Seats up to 4. Reserved free of charge.",
      "slotDurationMinutes": 120,
      "pricing": {
        "model": "Free",
        "amount": 0,
        "currency": "EUR",
        "depositAmount": null,
        "minimumSpend": null,
        "unitLabel": "booking"
      },
      "allowsFoodOrdering": true,
      "slotDurationOverrideMinutes": null
    }
  ]
}

Fehler404 keine Location mit diesem Slug.

curl

curl "https://api.bookdineplay.com/api/venues/your-venue/resources" \
  -H "X-BookDinePlay-Key: bdp_pk_your_publishable_key" \
  -H "Origin: https://www.your-venue.example"

JavaScript

const { resources } = await (await fetch('https://api.bookdineplay.com/api/venues/your-venue/resources', {
  headers: { 'X-BookDinePlay-Key': 'bdp_pk_your_publishable_key' }
})).json();
const lanes = resources.filter(r => r.type === 'BowlingLane');

C#

var resources = await client.GetResourcesAsync("your-venue", cancellationToken);

GET /api/venues/{venueSlug}/floor-plan

Zonen und platzierte Ressourcen mit normalisierter Geometrie, um eine „Tisch auswählen“-Ansicht zu zeichnen. Eine Location ohne Plan antwortet mit 200 und leeren Listen – prüfen Sie tables.length, bevor Sie Ihre Oberfläche auf den Raumplan umschalten.

Antwort 200 OK

Feld Typ Bedeutung
slug string Die Location
zones[] object[] id (GUID), name, ordinal (Anzeigereihenfolge)
tables[] object[] resourceId, name, type, capacity, zoneId, x, y, width, height (alle 0–1, relativ zur Zone), shape (Rectangle oder Circle), rotation (Grad)
{
  "slug": "demo-sportsbar",
  "zones": [],
  "tables": []
}

Fehler404 keine Location mit diesem Slug.

curl

curl "https://api.bookdineplay.com/api/venues/your-venue/floor-plan" \
  -H "X-BookDinePlay-Key: bdp_pk_your_publishable_key" \
  -H "Origin: https://www.your-venue.example"

JavaScript

const plan = await (await fetch('https://api.bookdineplay.com/api/venues/your-venue/floor-plan', {
  headers: { 'X-BookDinePlay-Key': 'bdp_pk_your_publishable_key' }
})).json();
const hasPlan = plan.tables.length > 0;

C#

var plan = await client.GetFloorPlanAsync("your-venue", cancellationToken);

Caching

Keine dieser Antworten trägt einen Cache-Header, weil der Betreiber sie jederzeit ändern kann. Eine vernünftige Integration cacht sie Minuten, nicht Tage, und lädt bei 404 oder einem unbekannten Schema neu. Das Widget selbst liest Profil und Raumplan einmal pro Seitenaufruf und cacht nichts über Seitenaufrufe hinweg.

Nächste Schritte

  • Verfügbarkeit – aus Ressourcentyp und Datum buchbare Slots machen.
  • .NET-SDK – dieselben sechs Lesezugriffe als typisierte Methoden.