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
Specials
Die Specials einer Location tageweise lesen – Gerichte und Angebote mit Preis, Wochentagen und Zeitfenster, in der Ortszeit der Location.
Die Specials, die eine Location anbietet, nach Kalendertag gruppiert: ein Gericht, das nur als Special existiert, oder ein Angebot auf eine Position der Speisekarte, jeweils mit Preis, den Wochentagen, an denen es läuft, und einem optionalen Zeitfenster pro Tag. Es erscheinen nur veröffentlichte Specials. Der Lesezugriff folgt denselben Schlüsselregeln wie der Rest von /api/venues/** (Schlüssel und Header), steht jedem Tarif offen und antwortet mit 404 und einem Problem-Body, wenn keine Location diesen Slug hat.
Endpunkte
GET /api/venues/{venueSlug}/specials
Abfrageparameter
| Parameter | Typ | Bedeutung |
|---|---|---|
date |
yyyy-MM-dd |
Der erste Tag der Antwort. Optional: ohne Angabe gilt der heutige Tag der Location, in ihrer Zeitzone. Muss zwischen 2000-01-01 und 9998-12-31 liegen |
days |
Ganzzahl | Wie viele Tage zurückgegeben werden, date eingeschlossen. Optional, 1 bis 14, Standard 1 |
Antwort 200 OK
| Feld | Typ | Bedeutung |
|---|---|---|
slug |
string | Die Location |
timezone |
string | IANA-Kennung der Zeitzone der Location; alle Daten und Uhrzeiten unten sind ihre Ortszeit |
currency |
string | ISO-4217-Währung aller Preise |
days[] |
object[] | Ein Eintrag je angefragtem Tag, in Reihenfolge, mit date und specials[]; die Liste kann leer sein |
Jeder Eintrag in specials[]:
| Feld | Typ | Bedeutung |
|---|---|---|
id |
string | Die Kennung des Specials |
kind |
string | Dish (ein Gericht mit eigenem Preis) oder MenuItem (eine Überschrift über einer vorhandenen Karten-Position) |
title, description |
string | Die Überschrift und eine optionale Beschreibung (nullable) |
imageUrl |
string | Das eigene Bild des Specials, sonst das der verknüpften Position (nullable) |
price |
decimal | Was der Gast zahlt |
regularPrice |
decimal | Der reguläre Preis der Position, nur vorhanden, wenn der Special-Preis niedriger ist, für eine Durchstreichung (nullable) |
menuItemId, itemName, itemDescription |
string | Die verknüpfte Karten-Position, aufgelöst (nullable; bei einem Gericht null) |
tags |
string[] | Die Tags der Position, etwa Ernährungshinweise; bei einem Gericht leer |
windowStart, windowEnd |
string | Das Zeitfenster pro Tag als HH:mm; beide null heißt ganztägig |
endsNextDay |
boolean | true, wenn das Fenster nach Mitternacht endet, etwa 22:00 bis 02:00 |
startsOn, endsOn |
string | Erster und letzter Tag, an dem es läuft, als yyyy-MM-dd; null heißt keine Grenze auf dieser Seite |
weekdays |
string[] | Die Wochentage, an denen es läuft, etwa "Wednesday"; leer heißt jeden Tag |
occurrenceDate |
string | Der Tag, an dem dieses Vorkommen begann: der aufgeführte Tag oder der Vortag |
continuesFromPreviousDay |
boolean | true für das späte Fenster von gestern, das um Mitternacht noch läuft |
Innerhalb eines Tages ist die Liste geordnet: zuerst die vom Vortag übernommenen Fenster, dann die Sortierung des Betreibers, dann ganztägige Specials vor solchen mit Zeitfenster, dann der Fensterbeginn.
Zeitzone
Alle Daten und Uhrzeiten sind Ortszeit der Location, in der timezone, die die Antwort nennt. Rechnen Sie auf Ihrer Seite um, nie umgekehrt.
- Ein Fenster gehört zu dem Tag, an dem es beginnt.
22:00bis02:00am Freitag ist das Special des Freitags und hatendsNextDay: true. - Die Liste jedes Tages beginnt mit den späten Fenstern des Vortags, die um Mitternacht noch laufen. Sie sind mit
continuesFromPreviousDay: truemarkiert und tragen ihroccurrenceDate; es genügt also, am Morgen danach nur den heutigen Tag abzufragen. - Ein Special läuft gerade, wenn die Uhren der Location eine Zeit innerhalb des Fensters zeigen, gezählt ab seinem
occurrenceDate. Vergleichen Sie mit der Ortszeit der Location, nicht mit der des Gastes. - In einer Nacht der Zeitumstellung kann ein Fenster eine Stunde kürzer oder länger sein. Eines, das in der wiederholten Herbststunde endet, schaltet sich aus und wieder ein.
Specials auf Karten-Positionen
Ein Special der Art MenuItem verweist über menuItemId auf eine Position der Speisekarten der Location (Speisekarten). Die Antwort löst sie auf: itemName, itemDescription und tags stammen von der Position, price ist der Special-Preis (oder der eigene Preis der Position, wenn das Special keinen setzt), und regularPrice wird nur gesendet, wenn der Special-Preis niedriger ist. Löscht der Betreiber die Position, verschwindet das Special aus dieser Antwort, statt einen ins Leere zeigenden Verweis zu zeigen.
Eine Antwort für demo-sportsbar kann so aussehen. Die Daten sind nur ein Beispiel: Die Specials der Demo-Location rollen weiter, die Datumsgrenzen, die Sie zurückbekommen, weichen also ab.
{
"slug": "demo-sportsbar",
"timezone": "Europe/Berlin",
"currency": "EUR",
"days": [
{
"date": "2026-10-28",
"specials": [
{
"id": "5be0a4c1e2f84d5f9a6e0c1d2b3a4f51",
"kind": "Dish",
"title": "Lunch special",
"description": "Soup of the day, burger or salad bowl, with a soft drink",
"imageUrl": null,
"price": 9.90,
"regularPrice": null,
"menuItemId": null,
"itemName": null,
"itemDescription": null,
"tags": [],
"windowStart": "11:30",
"windowEnd": "14:00",
"endsNextDay": false,
"startsOn": null,
"endsOn": null,
"weekdays": [
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday"
],
"occurrenceDate": "2026-10-28",
"continuesFromPreviousDay": false
},
{
"id": "5be0a4c1e2f84d5f9a6e0c1d2b3a4f52",
"kind": "MenuItem",
"title": "Wing Wednesday",
"description": null,
"imageUrl": "_content/BookDinePlay.App.Shared/menu/wings.webp",
"price": 8.00,
"regularPrice": 11.00,
"menuItemId": "af1cc7fd0772f60da833b1612f46fa69",
"itemName": "Buffalo wings",
"itemDescription": "Blue-cheese dip, celery",
"tags": [],
"windowStart": "17:00",
"windowEnd": "22:00",
"endsNextDay": false,
"startsOn": null,
"endsOn": null,
"weekdays": [
"Wednesday"
],
"occurrenceDate": "2026-10-28",
"continuesFromPreviousDay": false
},
{
"id": "5be0a4c1e2f84d5f9a6e0c1d2b3a4f53",
"kind": "Dish",
"title": "Burger of the week: smoky BBQ",
"description": null,
"imageUrl": null,
"price": 14.50,
"regularPrice": null,
"menuItemId": null,
"itemName": null,
"itemDescription": null,
"tags": [],
"windowStart": null,
"windowEnd": null,
"endsNextDay": false,
"startsOn": "2026-10-26",
"endsOn": "2026-11-01",
"weekdays": [],
"occurrenceDate": "2026-10-28",
"continuesFromPreviousDay": false
}
]
}
]
}Fehler
400– ein Validierungsproblem untererrors.date, wenndatekein Datum im Formatyyyy-MM-ddist, außerhalb von 2000-01-01 bis 9998-12-31 liegt; untererrors.days, wenndaysaußerhalb von 1 bis 14 liegt. Sind beide falsch, werden beide gemeldet.401– kein Schlüssel oder ein unbekannter.403– der Schlüssel gehört zu einer anderen Location, ein veröffentlichbarer Schlüssel kam von einer Origin, die nicht auf seiner Liste steht, oder ein veröffentlichbarer Schlüssel wurde ohneOrigin-Header gesendet. Siehe Was die API ablehnt.404– keine Location mit diesem Slug.
curl
curl "https://api.bookdineplay.com/api/venues/your-venue/specials?date=2026-10-28" \
-H "X-BookDinePlay-Key: bdp_pk_your_publishable_key" \
-H "Origin: https://www.your-venue.example"JavaScript
const client = BookDinePlay.createClient({
apiBaseUrl: 'https://api.bookdineplay.com', venueSlug: 'your-venue', publishableKey: 'bdp_pk_your_publishable_key'
});
const response = await client.specials({ date: '2026-10-28', days: 1 }); // null, wenn die Location keine Specials anbietet
for (const day of response?.days ?? []) for (const special of day.specials) {
console.log(day.date, special.title, special.price, response.timezone);
}C#
// `client` ist der IBookDinePlayClient aus AddBookDinePlayClient, registriert mit dem GEHEIMEN Schlüssel der Location
// aus der Konfiguration (builder.Configuration["BookDinePlay:ApiKey"]). Ein Server sendet keinen Origin-Header.
var response = await client.GetSpecialsAsync("your-venue", new DateOnly(2026, 10, 28), days: 1, cancellationToken);
foreach (var day in response?.Days ?? [])
{
foreach (var special in day.Specials)
{
Console.WriteLine($"{day.Date} {special.Title} {special.Price} ({response!.Timezone})");
}
}Das JavaScript-Beispiel nutzt den veröffentlichbaren Schlüssel. Das C#-Beispiel läuft auf einem Server und nutzt deshalb einen geheimen Schlüssel (bdp_sk_…) aus der Konfiguration und sendet keinen Origin-Header; liefern Sie einen geheimen Schlüssel nie an einen Browser aus. client.specials und GetSpecialsAsync antworten bei einer unbekannten Location mit null, der reine HTTP-Aufruf mit 404. renderSpecialsWidget zeichnet dieselben Daten ohne eigenen Code.
Betreiber: Specials speichern
Betreiber verwalten Specials über die Betreiber-API (Bearer-Token des Betreibers der Location), nicht über die öffentliche Oberfläche /api/venues/**. Senden Sie bei einem PUT immer kind und status: Er ersetzt den Datensatz vollständig, ein fehlender status wird zu Draft und nimmt das Special aus der Veröffentlichung, ein fehlendes kind wird zu Dish. Dasselbe gilt für die Datumsgrenzen: Lassen Sie endsOn (oder startsOn) weg, entfällt diese Grenze und das Special läuft unbegrenzt.
Nächste Schritte
- Venue – die anderen sechs Lesezugriffe für diese Location.
- Speisekarten – die Positionen, auf die ein Special der Art
MenuItemverweist.