API-Referenz
Was Sie heute anbinden können: eine lesende API für Restaurantdaten und freie Zeiten, die Anmeldung per OAuth, ausgehende Webhooks und das Buchungs-Widget.
Basis-URL
https://platzeo.de/api/v1
Die API liest nur. Sie hat drei Endpunkte, und jede Anfrage gilt für genau ein Restaurant. Reservierungen, Gäste oder Treuekarten lassen sich über die API derzeit weder lesen noch ändern.
Authentifizierung
Jede Anfrage braucht einen API-Schlüssel oder ein OAuth-Zugriffstoken.
API-Schlüssel
Senden Sie den Schlüssel im Header X-API-Key. Im Header Authorization wird er nicht angenommen. Schlüssel beginnen mit plz_live_ und werden im Admin unter Einstellungen, API-Schlüssel erstellt. Ein Schlüssel gehört zu genau einem Restaurant, trägt die Berechtigungen, die Sie ihm geben, und kann ein Ablaufdatum haben. platzeo zeigt ihn nur einmal an, direkt nach dem Erstellen. Ein widerrufener oder abgelaufener Schlüssel wird mit 401 abgelehnt.
curl https://platzeo.de/api/v1/restaurants \ -H "X-API-Key: plz_live_..."
OAuth-Zugriffstoken
Ein Token aus dem OAuth-Ablauf senden Sie als Authorization: Bearer plz_at_.... Es gilt für das Restaurant, für das es freigegeben wurde.
Berechtigungen
Die API prüft zwei Berechtigungen. Ein Schlüssel braucht die des Endpunkts, den er aufruft. Andere Berechtigungen kann ein neuer Schlüssel nicht bekommen.
api.restaurants.readRestaurantprofil und Öffnungszeiten abrufen.
api.availability.readFreie Zeiten abrufen.
Bei OAuth heißt der Zugriffsumfang restaurants und steht für beide Berechtigungen. Den Umfang reservations dürfen Sie mit anfragen, er öffnet aber keinen Endpunkt: Er steht nicht auf der Freigabeseite und gehört nicht zur Freigabe. Welchen Umfang ein Token trägt, steht im Feld scope der Token-Antwort. Eine Anfrage nur nach reservations und jeder andere Name werden mit invalid_scope abgelehnt.
Endpunkte
GET/api/v1/restaurants
Das Restaurant, zu dem der Schlüssel oder das Token gehört. Die Antwort ist eine Liste mit genau einem Eintrag. Berechtigung: api.restaurants.read.
plan ist starter, pro oder kette; kette steht für den Tarif, der auf platzeo.de Max heißt. primaryColor und themeMode (light, dark, auto) sind die Einstellungen der Buchungsseite.
[
{
"slug": "ihr-slug",
"name": "Ihr Restaurant",
"plan": "pro",
"primaryColor": "#14422b",
"themeMode": "light"
}
]GET/api/v1/restaurant/{slug}/info
Name, Adresse, Telefon und Öffnungszeiten. Berechtigung: api.restaurants.read.
hours enthält jeden Wochentag als Text: die Zeiten der aktiven Schichten, mehrere durch Komma getrennt, oder „Geschlossen“ („Closed“ auf Englisch). Endet eine Schicht nach Mitternacht, steht dort die Uhrzeit des Folgetags, zum Beispiel 17:00–01:00.
Parameter lang: de oder en, die Sprache der Wörter in der Antwort. Ohne Angabe gilt die Sprache Ihrer Buchungsseite. Ein anderer Wert wird mit 400 INVALID_PARAMETER abgelehnt.
address und phone sind leere Texte, wenn nichts hinterlegt ist. cuisine ist immer eine leere Liste: Eine Küchenart lässt sich in platzeo nicht hinterlegen. Der Schlüssel bleibt für ältere Versionen des WordPress-Plugins erhalten.
{
"name": "Ihr Restaurant",
"address": "Musterstraße 1, 12345 Musterstadt",
"phone": "+49 30 1234567",
"hours": {
"monday": "Geschlossen",
"tuesday": "17:30–22:30",
"wednesday": "17:30–22:30",
"thursday": "17:30–22:30",
"friday": "11:30–14:30, 17:30–22:30",
"saturday": "11:30–14:30, 17:30–22:30",
"sunday": "10:00–14:30"
},
"cuisine": []
}GET/api/v1/restaurant/{slug}/availability
Die nächsten freien Zeiten für eine Online-Reservierung. Berechtigung: api.availability.read.
Parameter count: wie viele Zeiten Sie möchten, eine ganze Zahl von 1 bis 10. Ohne Angabe sind es 3. Parameter partySize: für wie viele Personen gesucht wird, eine ganze Zahl von 1 bis zur größten Gruppe, die das Restaurant online annimmt. Ohne Angabe sind es 2. Gesucht wird in den nächsten 7 Tagen.
Ein Wert außerhalb dieser Grenzen wird mit 400 abgelehnt und nie durch einen anderen ersetzt: INVALID_PARAMETER nennt den Parameter und seine Grenzen, PARTY_SIZE_TOO_LARGE im Feld max die größte mögliche Gruppe. Andere Parameter kennt der Endpunkt nicht (400 UNKNOWN_PARAMETER); ein Datum lässt sich nicht vorgeben. Die Antwort nennt in count und partySize, wofür sie gilt.
Die Antwort enthält genau die Zeiten, die auch die Buchungsseite in den nächsten sieben Tagen für diese Personenzahl anbietet, auch für große Gruppen, die das Restaurant auf mehrere Tische verteilt.
Jeder Eintrag hat date (JJJJ-MM-TT), time (HH:MM), request und maxGuests. request ist true, wenn eine Buchung für diese Personenzahl zu dieser Zeit eine Anfrage ist, die das Restaurant erst bestätigen muss: weil es alle Buchungen von Hand bestätigt oder weil die Gruppe über seiner Grenze für Sofortbuchungen liegt. maxGuests ist die größte Personenzahl, die die Buchungsseite zu dieser Zeit noch annimmt, als Buchung oder als Anfrage. Der Wert hängt nicht von partySize ab. Ist nichts frei, ist slots leer.
bookingOpen ist false, wenn das Restaurant gerade keine Online-Reservierungen annimmt. slots ist dann leer.
{
"slots": [
{ "date": "2026-10-09", "time": "18:00", "maxGuests": 8, "request": false },
{ "date": "2026-10-09", "time": "18:30", "maxGuests": 8, "request": false },
{ "date": "2026-10-09", "time": "19:00", "maxGuests": 4, "request": false }
],
"bookingOpen": true,
"partySize": 2,
"count": 3
}{slug} ist der Slug Ihres Restaurants, also der Teil vor .platzeo.de in der Adresse Ihrer Buchungsseite. Mit einem anderen Slug antwortet die API mit 404.
Fehler und Limit
Fehler kommen als JSON mit einem deutschen Satz im Feld error und einem festen code, an dem Ihr Programm den Fall erkennt. Das Limit liegt bei 100 Anfragen pro Minute je API-Schlüssel, bei OAuth je Person. Keine Antwort der API darf zwischengespeichert werden (Cache-Control: no-store).
400 INVALID_PARAMETEREin Parameter ist keine ganze Zahl in seinen Grenzen. Die Felder parameter, min und max nennen ihn.
400 PARTY_SIZE_TOO_LARGEpartySize ist größer als die größte Gruppe, die das Restaurant online annimmt. Das Feld max nennt sie.
400 UNKNOWN_PARAMETERDer Endpunkt kennt den Parameter nicht. Das Feld parameter nennt ihn.
401 UNAUTHENTICATEDKein Schlüssel oder Token, oder es ist unbekannt, widerrufen oder abgelaufen.
403 FORBIDDENDem Schlüssel oder Token fehlt die Berechtigung. Das Feld permission nennt sie.
403 TENANT_LOCKEDDas Restaurant ist gesperrt.
404 NOT_FOUNDDer Slug gehört nicht zum Restaurant des Schlüssels oder Tokens, oder den Endpunkt gibt es nicht.
405 METHOD_NOT_ALLOWEDDie API kennt nur GET. Der Header Allow nennt die erlaubten Methoden.
429 RATE_LIMITEDMehr als 100 Anfragen in einer Minute. Der Header Retry-After nennt die Wartezeit in Sekunden.
{
"error": "Dafür fehlt Ihnen die Berechtigung.",
"code": "FORBIDDEN",
"permission": "api.availability.read"
}OAuth 2.0
Anwendungen, die im Namen einer Person auf ein Restaurant zugreifen, nutzen den Authorization-Code-Ablauf mit PKCE. Es gibt kein Client-Secret, dafür ist PKCE mit S256 Pflicht. Clients registriert platzeo. Das WordPress-Plugin ist der Client wordpress-plugin.
GEThttps://oauth.platzeo.de/authorize
Startet die Freigabe im Browser. Parameter: response_type=code, client_id, redirect_uri, code_challenge, code_challenge_method=S256, scope und optional state. Die Person meldet sich bei platzeo an und erlaubt den Zugriff auf ein Restaurant. Darf sie für mehrere Restaurants Anwendungen verbinden, wählt sie auf der Freigabeseite eines aus. Danach geht es mit code und state zu redirect_uri, bei einer Ablehnung mit error=access_denied.
POSThttps://oauth.platzeo.de/token
Tauscht den Code gegen Tokens: grant_type=authorization_code mit code, redirect_uri, client_id und code_verifier. Erneuert Tokens: grant_type=refresh_token mit refresh_token und client_id. Der Body ist JSON oder ein Formular. Die Antwort darf nicht zwischengespeichert werden (Cache-Control: no-store).
POSThttps://oauth.platzeo.de/revoke
Trennt die Verbindung, zu der das Token gehört. Das Zugriffs- oder Refresh-Token steht im Header Authorization: Bearer oder im Formularfeld token. Ohne Token antwortet der Endpunkt mit 401, mit einem unbekannten oder schon widerrufenen mit 200.
curl https://oauth.platzeo.de/token \
-d grant_type=authorization_code \
-d client_id=wordpress-plugin \
-d code=... \
-d code_verifier=... \
--data-urlencode "redirect_uri=https://ihre-website.de/wp-admin/admin-post.php?action=platzeo_oauth_callback"
{
"access_token": "plz_at_...",
"refresh_token": "plz_rt_...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "restaurants"
}Der Code gilt fünf Minuten, nur einmal und nur für den Client und die redirect_uri, mit denen er angefordert wurde. Ein Zugriffstoken gilt eine Stunde. Beim Erneuern erhalten Sie ein neues Paar aus Zugriffs- und Refresh-Token, das alte ist danach ungültig.
Ein Refresh-Token gilt für genau einen Tausch. Erneuern zwei Anfragen im selben Moment mit demselben Token, bekommt eine das neue Paar und die andere 409 mit temporarily_unavailable: Die Verbindung besteht weiter, verwenden Sie das Paar der ersten Anfrage. Wird ein schon getauschtes Refresh-Token später als eine Minute nach dem Tausch noch einmal vorgelegt, ist eine Kopie im Umlauf. platzeo beendet dann die ganze Verbindung und antwortet mit invalid_grant.
Auf oauth.platzeo.de sind /authorize, /token und /revoke Kurzformen von /api/oauth/authorize, /api/oauth/token und /api/oauth/revoke.
redirect_uri muss genau einer registrierten Adresse entsprechen. Für das WordPress-Plugin ist die Adresse /wp-admin/admin-post.php?action=platzeo_oauth_callback jeder Website mit https erlaubt, für lokale Installationen auch mit http auf localhost, 127.0.0.1 und [::1]. Die Freigabeseite nennt den Host dieser Website. Ist die Anfrage fehlerhaft, zeigt platzeo der Person eine Seite mit dem Weg zurück und übergibt Ihrer Anwendung den Fehler an redirect_uri (invalid_scope, invalid_request, unsupported_response_type). Nur bei einem unbekannten Client oder einer nicht erlaubten redirect_uri leitet platzeo nirgendwohin.
Freigeben kann, wer im Restaurant externe Anwendungen verbinden darf: Inhaberinnen, Inhaber und die Restaurantleitung, dazu eigene Rollen mit diesem Recht. Wer es nicht darf, sieht eine Seite, die das erklärt, und kommt von dort mit error=access_denied zurück zu Ihrer Anwendung. Das Token kann nie mehr als die Person, die freigegeben hat.
Eine Verbindung endet, wenn Ihre Anwendung sie widerruft, wenn jemand sie im Admin unter Einstellungen → Anwendungen trennt, wenn die Person, die freigegeben hat, das Team des Restaurants verlässt oder ihr Passwort ändert, und nach zwölf Monaten ohne Nutzung (kein API-Aufruf und kein Erneuern). Danach antwortet die API mit 401 und der Token-Endpunkt mit invalid_grant; die Person muss neu verbinden. Fehler des Token-Endpunkts kommen mit Status 400 (409 im Fall oben) und den Feldern error und error_description.
Webhooks
platzeo ruft Ihre Adresse auf, wenn im Restaurant etwas passiert. Webhooks richten Sie im Admin unter Webhooks ein: Adresse, Ereignisse, eigene Header, Zeitlimit und Wiederholungen. Eine API zum Verwalten von Webhooks gibt es nicht. Die Adresse muss öffentlich erreichbar sein und https verwenden.
reservation.createdReservierung erstellt, online oder vom Team
reservation.updatedTag, Uhrzeit, Personenzahl, Tisch oder Wünsche geändert. Nicht bei einem Statuswechsel, der ein eigenes Ereignis hat.
reservation.confirmedReservierung bestätigt: sofort beim Anlegen, durch das Restaurant oder durch den Link in der E-Mail an den Gast
reservation.cancelledReservierung storniert oder Anfrage abgelehnt. cancelledBy nennt, durch wen.
reservation.seatedGast am Tisch
reservation.completedBesuch abgeschlossen
reservation.no_showGast nicht erschienen
guest.createdNeuer Gast
guest.updatedGast geändert
loyalty.card.createdTreuekarte erstellt
loyalty.stamp.addedStempel oder Punkte gutgeschrieben
loyalty.reward.redeemedBelohnung eingelöst
Anfrage
POST /ihr-endpunkt
Content-Type: application/json
User-Agent: platzeo-Webhooks/1.0
X-platzeo-Event: reservation.created
X-platzeo-Delivery: 0b6f6a52-6c1e-4c0e-9a51-3d8f3f1f2a77
X-platzeo-Attempt: 1
X-platzeo-Timestamp: 1791475200
X-platzeo-Signature: t=1791475200,v1=5d41...
X-platzeo-Payload-Version: 2
{
"id": "0b6f6a52-6c1e-4c0e-9a51-3d8f3f1f2a77",
"event": "reservation.created",
"version": 2,
"timestamp": 1791475200,
"restaurantId": "9b206577-1a4b-4497-9378-48b66f49c18c",
"data": {
"reservation": {
"id": "3a4b5c6d-7e8f-4a1b-9c2d-3e4f5a6b7c8d",
"status": "confirmed",
"date": "2026-04-20",
"time": "19:30",
"partySize": 4,
"durationMinutes": 120,
"tables": [
{
"id": "5f0c2f6e-9d1b-4c1e-8a57-2b1f0c3d4e5f",
"name": "Tisch 4"
}
],
"source": "online",
"occasion": "Geburtstag",
"notes": "Bitte ein Tisch am Fenster.",
"customFields": [
{
"label": "Kinderstuhl",
"value": "Ja"
}
],
"createdAt": "2026-04-15T14:30:00.000Z",
"updatedAt": "2026-04-15T14:30:00.000Z"
},
"guest": {
"id": "0d9c8b7a-6f5e-4d3c-9b2a-1f0e9d8c7b6a",
"firstName": "Anna",
"lastName": "Beispiel",
"email": "anna.beispiel@example.com",
"phone": "+49 30 1234567"
}
}
}version ist die Version der Inhalte, zurzeit 2. Sie steht auch im Header X-platzeo-Payload-Version. Neue Felder können jederzeit dazukommen. Fällt ein Feld weg oder ändert es seine Bedeutung, steigt die Version. Mit der Einstellung „Raw (nur Daten)“ besteht der Body nur aus dem Inhalt von data. Statt POST können Sie PUT oder PATCH wählen.
Inhalt der Ereignisse
Gesendet werden genau die folgenden Felder. Reservierungs-Ereignisse tragen data.reservation und data.guest, reservation.cancelled dazu cancelledBy: guest (über den Link in der E-Mail), restaurant oder expired (die E-Mail-Adresse wurde nicht rechtzeitig bestätigt). Gast-Ereignisse tragen data.guest. Treue-Ereignisse tragen data.card, loyalty.stamp.added dazu delta (gutgeschriebene Stempel oder Punkte), loyalty.reward.redeemed delta (abgezogen, negativ) und reward mit id und title; id ist null bei einem Stempelprogramm, dessen Belohnung keine eigene Kennung hat.
data.reservation: In allen Ereignissen, die mit reservation. beginnen.
idKennung der Reservierung
statuspending, confirmed, seated, completed, cancelled oder no_show
dateTag der Reservierung, JJJJ-MM-TT
timeUhrzeit, HH:MM
partySizePersonenzahl
durationMinutesgeplante Dauer in Minuten
tableszugewiesene Tische mit id und name; leer, solange kein Tisch zugewiesen ist
sourcewie die Reservierung entstand, zum Beispiel online, phone oder walkin
occasionAnlass, sonst null
notesWünsche des Gastes zu dieser Reservierung, sonst null
customFieldsAntworten auf Ihre eigenen Fragen im Buchungsformular, je label und value
createdAtangelegt, ISO 8601
updatedAtzuletzt geändert, ISO 8601
data.guest: In allen Reservierungs- und Gast-Ereignissen. Bei einer Reservierung ist guest null, wenn es Laufkundschaft ohne Namen ist.
idKennung des Gastes
firstNameVorname
lastNameNachname
emailE-Mail-Adresse, null wenn keine bekannt ist
phoneTelefonnummer, null wenn keine bekannt ist
data.guest, zusätzlich: Nur in guest.created und guest.updated.
marketingConsenttrue, wenn der Gast Werbung zugestimmt hat
createdAtangelegt, ISO 8601
data.card: In allen Ereignissen, die mit loyalty. beginnen. Der QR-Code der Karte wird nie gesendet.
idKennung der Karte
cardNumberKartennummer, wie sie auf der Karte steht
guestIdKennung des Gastes
programIdKennung des Treueprogramms
statusactive oder blocked
stampsStempel auf der Karte
pointsPunkte auf der Karte
rewardsRedeemedbisher eingelöste Belohnungen
issuedAtausgestellt, ISO 8601
expiresAtAblauf, ISO 8601, sonst null
reservation.cancelled
{
"data": {
"reservation": {
"id": "3a4b5c6d-7e8f-4a1b-9c2d-3e4f5a6b7c8d",
"status": "cancelled",
"date": "2026-04-20",
"time": "19:30",
"partySize": 4,
"durationMinutes": 120,
"tables": [
{
"id": "5f0c2f6e-9d1b-4c1e-8a57-2b1f0c3d4e5f",
"name": "Tisch 4"
}
],
"source": "online",
"occasion": "Geburtstag",
"notes": "Bitte ein Tisch am Fenster.",
"customFields": [
{
"label": "Kinderstuhl",
"value": "Ja"
}
],
"createdAt": "2026-04-15T14:30:00.000Z",
"updatedAt": "2026-04-15T14:30:00.000Z"
},
"guest": {
"id": "0d9c8b7a-6f5e-4d3c-9b2a-1f0e9d8c7b6a",
"firstName": "Anna",
"lastName": "Beispiel",
"email": "anna.beispiel@example.com",
"phone": "+49 30 1234567"
},
"cancelledBy": "guest"
}
}guest.created
{
"data": {
"guest": {
"id": "0d9c8b7a-6f5e-4d3c-9b2a-1f0e9d8c7b6a",
"firstName": "Anna",
"lastName": "Beispiel",
"email": "anna.beispiel@example.com",
"phone": "+49 30 1234567",
"marketingConsent": false,
"createdAt": "2026-03-02T09:15:00.000Z"
}
}
}loyalty.stamp.added
{
"data": {
"card": {
"id": "7c6b5a49-3827-4615-a0b9-c8d7e6f5a4b3",
"cardNumber": "PLZ-4821-7730",
"guestId": "0d9c8b7a-6f5e-4d3c-9b2a-1f0e9d8c7b6a",
"programId": "2e3f4a5b-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
"status": "active",
"stamps": 7,
"points": 0,
"rewardsRedeemed": 1,
"issuedAt": "2026-03-02T09:15:00.000Z",
"expiresAt": null
},
"delta": 1
}
}loyalty.reward.redeemed
{
"data": {
"card": {
"id": "7c6b5a49-3827-4615-a0b9-c8d7e6f5a4b3",
"cardNumber": "PLZ-4821-7730",
"guestId": "0d9c8b7a-6f5e-4d3c-9b2a-1f0e9d8c7b6a",
"programId": "2e3f4a5b-6c7d-4e8f-9a0b-1c2d3e4f5a6b",
"status": "active",
"stamps": 0,
"points": 0,
"rewardsRedeemed": 2,
"issuedAt": "2026-03-02T09:15:00.000Z",
"expiresAt": null
},
"delta": -10,
"reward": {
"id": "6b5a4938-2716-4504-b9a8-d7c6e5f4a3b2",
"title": "Gratis Kaffee"
}
}
}Welche Ereignisse eine Änderung sendet
Ändert eine Reservierung ihren Status, kommt genau ein Ereignis, das des neuen Status. reservation.updated kommt dann nicht zusätzlich. Beginnt eine Reservierung in einem Status mit eigenem Ereignis, folgt es direkt auf reservation.created: bei einer sofort bestätigten Online-Buchung und einer vom Team eingetragenen Reservierung reservation.confirmed, bei Laufkundschaft reservation.seated. Wer alle bestätigten Reservierungen braucht, abonniert also nur reservation.confirmed.
Gehören mehrere Ereignisse zu einer Aktion, sendet platzeo sie nacheinander in fester Reihenfolge: erst der Gast, dann reservation.created, dann der Status. Eine Wiederholung nach einem Fehlschlag kann später ankommen als das nächste Ereignis.
Test
„Testereignis senden“ im Admin schickt ein Beispiel des ersten Ereignisses, das der Webhook abonniert hat, mit erfundenen Daten in genau der Form oben. Der Body trägt zusätzlich "test": true (im Format „raw“ steht es neben den Daten), die Anfrage den Header X-platzeo-Test: true. Prüfen Sie eines von beiden, bevor Sie die Daten verarbeiten. Ein Test wird nicht wiederholt und zählt im Admin nicht zu den zugestellten oder fehlgeschlagenen Ereignissen.
Signatur
Jeder Webhook hat ein Secret, das mit whsec_ beginnt. Der Wert v1 im Header X-platzeo-Signature ist der HMAC-SHA256 über <timestamp>.<body> mit diesem Secret, hexadezimal geschrieben. Rechnen Sie mit dem Body genau so, wie er ankommt.
Zustellung
Als zugestellt gilt eine Antwort mit Status 2xx innerhalb des Zeitlimits (10 Sekunden, einstellbar von 1 bis 30). Weiterleitungen folgt platzeo nicht. Schlägt ein Versuch fehl, wiederholt platzeo die Zustellung nach 1 Minute, 5 Minuten, 30 Minuten und 2 Stunden, danach alle 6 Stunden. Voreingestellt sind drei Wiederholungen, einstellbar sind 0 bis 10. Nach der letzten stellt platzeo das Ereignis nicht erneut zu. Das Protokoll im Admin zeigt jeden Versuch.
Alle Versuche einer Zustellung haben dieselbe Zustell-ID (id im Body, Header X-platzeo-Delivery) und denselben Body. Kommt eine ID ein zweites Mal an, ist es eine Wiederholung: Verarbeiten Sie jede ID nur einmal. X-platzeo-Attempt zählt die Versuche. X-platzeo-Timestamp und die Signatur gehören zum einzelnen Versuch, timestamp im Body ist der Zeitpunkt des Ereignisses.
Buchungs-Endpunkte
Die Buchungsseite, das Widget und das WordPress-Plugin sprechen mit Endpunkten unter /api/booking/{slug}/. Sie gehören zum Buchungsformular, sind hier nicht beschrieben und können sich jederzeit ändern. Für Reservierungen auf Ihrer Website nehmen Sie das Widget.
Widget und Embed
Die Buchungsseite auf der eigenen Website: widget.js lädt Ihre Buchungsseite als iFrame, passt die Höhe automatisch an und meldet Buchungen als Events. Design, Formularfelder und Texte kommen aus dem Admin unter Buchungsseite. Es gibt nur eine Implementierung.
Snippet
<div data-platzeo-booking="ihr-slug"></div> <script async src="https://platzeo.de/widget.js"></script>
Der Loader setzt in den Container ein iFrame von https://ihr-slug.platzeo.de/embed. Bis es geladen ist, zeigt er ein kurzes „Lädt…“.
Binden Sie das Skript von platzeo.de ein und nicht als Kopie auf Ihrem Server oder in einem Bundle: Der Loader sucht die Buchungsseite neben der Adresse, von der er geladen wurde, und eine Kopie erhält keine Korrekturen. Aus demselben Grund gehört kein integrity-Attribut an das Skript.
Das Widget ist so breit wie sein Container. Geben Sie ihm mindestens 340 px, mit data-seamless mindestens 300 px. In einer schmaleren Spalte passt das Formular weiter ohne Scrollen zur Seite, die Tage im Kalender sind dann aber schmaler als 40 px.
Optionen
<div data-platzeo-booking="ihr-slug" data-theme="auto" data-primary="#14422b" data-lang="de" data-compact="1" data-id="reservierung" ></div>
data-platzeo-bookingSlug. Ihr Restaurant-Slug (Pflicht): Kleinbuchstaben, Ziffern und Bindestriche, wie in https://<slug>.platzeo.de. Bei jedem anderen Wert bindet der Loader nichts ein und meldet das in der Browser-Konsole.
data-themelight · dark · auto. Überschreibt das Theme der Buchungsseite. auto folgt der Systemeinstellung des Gastes.
data-primary#rrggbb. Überschreibt die Primärfarbe. Nur sechsstellige Hex-Werte; alles andere wird ignoriert, ebenso eine Farbe, die sich vom Hintergrund des Formulars nicht abhebt (etwa Weiß im hellen Theme).
data-langde · en. Sprache des Formulars. Ohne Angabe gilt die Sprache Ihrer Buchungsseite.
data-compact1. Blendet den Hero (Logo, Begrüßungstext) aus.
data-seamless1. Transparenter Hintergrund, keine äußere Karte. Das Theme richtet sich dann nach dem Hintergrund Ihrer Seite und nicht nach dem Gerät des Gastes, solange data-theme nicht light oder dark vorgibt. Erkennt der Loader nicht, ob Ihre Seite hell oder dunkel ist (ein Hintergrundbild ohne Hintergrundfarbe, ein Verlauf von hell nach dunkel), behält das Widget seinen eigenen Hintergrund und meldet das in der Browser-Konsole. Mit data-theme light oder dark wird es dann durchsichtig.
data-sectionsactivities · events · all. Zeigt unter dem Tischformular zusätzlich Ihre Aktivitäten, Ihre Veranstaltungen oder beides (mit Komma getrennt oder all). Standard: nur das Tischformular.
data-idText. Instanz-ID für Events, Standard platzeo-1, platzeo-2 … Je Seite eindeutig, höchstens 64 Zeichen.
data-min-heightpx. Höhe des iFrames, bis es seine eigene Höhe meldet. Standard 560.
data-scroll-offsetpx. Platz, der oben frei bleibt, wenn die Seite nach einem Schritt an den Anfang des Formulars springt, zum Beispiel die Höhe einer fixierten Kopfzeile. scroll-margin-top auf dem Container wirkt genauso.
Die Werte dürfen groß oder klein geschrieben sein.
JavaScript-API
Für Single-Page-Apps, Tabs und Overlays: Platzeo.mount(element, "ihr-slug", { theme, primary, lang, compact, seamless, sections, id, minHeight, scrollOffset }) bindet das Widget ein oder ersetzt das dort eingebundene und gibt die Instanz-ID zurück. Platzeo.unmount(element) entfernt es wieder, Platzeo.refresh() bindet nachträglich eingefügte Container ein.
Das Skript lädt asynchron, window.Platzeo gibt es also erst danach. Über window.platzeoReady läuft Ihr Code, sobald der Loader bereit ist, egal ob davor oder danach:
<div id="reservierung"></div>
<script>
(window.platzeoReady = window.platzeoReady || []).push(function (Platzeo) {
Platzeo.mount("#reservierung", "ihr-slug", { lang: "de", sections: "events" });
});
</script>
<script async src="https://platzeo.de/widget.js"></script>Eigenes iFrame
Sie können das iFrame auch selbst setzen. Die URL-Parameter theme, primary (sechsstelliger Hex-Wert ohne #), lang, compact=1, seamless=1, sections und id entsprechen den Data-Attributen. Mit data-platzeo-embed übernimmt widget.js die automatische Höhe.
Ein iFrame kann mit einem Termin öffnen, etwa von einem Link „Heute 19:00“ auf Ihrer Seite: date (JJJJ-MM-TT), time (HH:MM) und partySize (Personen). Ist der Termin für diese Personenzahl frei, ist er ausgewählt, und der Gast tippt nur noch auf „Weiter“. Ist nur der Tag frei, ist der Tag ausgewählt; sonst öffnet der Kalender im Monat des Tages und nichts ist ausgewählt.
<iframe data-platzeo-embed src="https://ihr-slug.platzeo.de/embed?id=reservierung&theme=auto" title="Reservierung" style="width:100%;border:0;min-height:560px" ></iframe> <script async src="https://platzeo.de/widget.js"></script>
Ein selbst gesetztes iFrame mit seamless=1 sieht den Hintergrund Ihrer Seite nicht. Steht widget.js auf der Seite, teilt der Loader ihm mit, ob die Seite dahinter hell oder dunkel ist, und das iFrame nimmt das passende Theme. Ohne widget.js nimmt es das helle Theme, theme=auto eingeschlossen; auf einer dunklen Seite geben Sie dann theme=dark an.
Ist das Theme Ihrer Buchungsseite dunkel und die Adresse nennt keines, behält das iFrame ohne widget.js seinen dunklen Hintergrund, statt helle Schrift auf eine Seite zu setzen, die es nicht kennt. Mit theme=dark oder theme=light ist es immer durchsichtig.
Die Erkennung liest Hintergrundfarben und Farbverläufe. Ein Hintergrundbild ohne Hintergrundfarbe auf demselben Element und ein Verlauf von hell nach dunkel gelten als unbekannt: Das Formular behält dann seinen eigenen Hintergrund, bis Sie das Theme angeben. Deklariert Ihre Seite color-scheme: dark, braucht ein iFrame ohne widget.js zusätzlich style="color-scheme:light", sonst legt der Browser eine weiße Fläche darunter.
Events
widget.js löst auf document zwei Events aus, zum Beispiel für Analytics oder um ein Overlay zu schließen:
document.addEventListener("platzeo:booking-confirmed", (e) => {
// e.detail = { id, slug, step: "done", status }
// status: "confirmed" | "pending" | "unverified"
if (e.detail.status === "confirmed") {
gtag("event", "reservation", { restaurant: e.detail.slug });
}
});
document.addEventListener("platzeo:step-changed", (e) => {
// e.detail.step: "datetime" | "guest" | "confirm" | "done"
});platzeo:step-changed kommt beim Laden des Formulars mit datetime und danach bei jedem Schritt. Nimmt das Restaurant gerade keine Online-Buchungen an, gibt es kein Formular und kein Event.
platzeo:booking-confirmed kommt, sobald der Gast das Formular abgeschickt hat, auch wenn die Reservierung noch nicht fest ist. detail.status sagt, was der Gast jetzt hat: confirmed ist eine bestätigte Reservierung, pending eine Anfrage, die das Restaurant noch annehmen muss, und bei unverified muss der Gast erst seine E-Mail-Adresse bestätigen. Soll Ihre Statistik nur feste Buchungen zählen, werten Sie confirmed aus.
Content-Security-Policy
Setzt Ihre Website eine Content-Security-Policy, braucht sie zwei Einträge: das Skript von platzeo.de und das iFrame Ihrer Buchungsseite.
Content-Security-Policy: script-src https://platzeo.de; frame-src https://ihr-slug.platzeo.de
Für mehrere Restaurants auf einer Website geht auch frame-src https://*.platzeo.de. Fehlt der Eintrag für das iFrame, zeigt der Loader an seiner Stelle einen Link zu Ihrer Buchungsseite. Fehlt der Eintrag für das Skript, bleibt der Container leer.
Fehlt Ihnen etwas?
Die API ist klein. Schreiben Sie uns, was Sie für Ihre Anbindung brauchen.
Zum Support