DinnerSpots-API
Lies und schreibe Reservierungen, freie Zeiten, Betriebsferien und den Tischplan eines Restaurants aus deinen eigenen Systemen – etwa aus einem Chatbot für Instagram, Messenger oder WhatsApp, einem Kassensystem oder Zapier und Make.
Überblick
Die API gehört zum Reservierungssystem von Bontrivo. Jeder Schlüssel gilt für genau ein Restaurant. Alle Adressen beginnen mit:
https://dinnerspots.de/api/v1- Anfragen und Antworten sind JSON in UTF-8. Schicke bei
POST,PATCHundPUTden HeaderContent-Type: application/json. - Datumsangaben im Format
JJJJ-MM-TT, Uhrzeiten alsHH:MMin der Ortszeit des Restaurants (Europe/Berlin). Zeitstempel nach ISO 8601 mit Zeitzone. - Reservierungen erkennst du an ihrem 8-stelligen Code, z. B.
K7Q2MZ4P– derselbe Code, den Gast und Restaurant in den E-Mails sehen. - Neue Felder können jederzeit dazukommen. Ignoriere Felder, die du nicht kennst.
API-Schlüssel gehören auf deinen Server, nie in den Browser oder in eine App. Für Reservierungen auf deiner Website nimm das Widget – es braucht keinen Schlüssel.
Anmeldung
Schlüssel legst du im Bontrivo-Kundenportal unter Reservierungen → API & Webhooks an. Der Schlüssel wird nur einmal angezeigt – speichere ihn sofort an einem sicheren Ort. Verlorene Schlüssel widerrufst du dort und legst einen neuen an.
curl https://dinnerspots.de/api/v1/restaurant \
-H "Authorization: Bearer bt_live_…"Wenn dein Werkzeug keinen Authorization-Header setzen kann, geht auch X-Api-Key: bt_live_….
| Recht | Erlaubt |
|---|---|
| Lesen | Restaurant, freie Zeiten, Reservierungen, Betriebsferien und Tischplan abrufen. |
| Schreibrecht | Zusätzlich Reservierungen anlegen, ändern, bestätigen und stornieren, Betriebsferien eintragen und Webhooks verwalten. |
Einstellungen, Tischplan bearbeiten und Schlüssel verwalten geht nur im Kundenportal. Ein Restaurant kann bis zu 10 aktive Schlüssel haben – am besten einen pro angebundenem System.
Limits
- 120 Anfragen pro Minute und Schlüssel. Jede Antwort enthält
X-RateLimit-LimitundX-RateLimit-Remaining. Darüber antwortet die API mit429undRetry-After: 60. - Nach 20 fehlgeschlagenen Anmeldungen pro Minute ist eine Minute Pause.
- Anfragen dürfen höchstens 256 KB groß sein.
- Listen liefern höchstens 200 Einträge pro Seite.
Fehler
Fehler kommen immer im selben Format. code ist fest und für dein Programm gedacht, message ist ein deutscher Satz, den du Gästen oder Mitarbeitern zeigen kannst.
{
"error": {
"code": "validation_failed",
"message": "Bitte die markierten Angaben prüfen.",
"fields": {
"guest.last_name": "Bitte einen Namen angeben.",
"guest.email": "Bitte eine E-Mail-Adresse oder Telefonnummer angeben."
}
}
}| Status | code | Bedeutung |
|---|---|---|
| 400 | invalid_json | Der Body ist kein JSON-Objekt. |
| 401 | unauthorized | Kein oder ein ungültiger Schlüssel. |
| 403 | insufficient_scope | Der Schlüssel darf nur lesen. |
| 403 | restaurant_inactive | Das Kundenkonto des Restaurants ist nicht aktiv. |
| 403 | internal_only | Geht nur im Kundenportal. |
| 404 | not_found | Endpunkt, Reservierung, Schließzeit oder Webhook gibt es nicht. |
| 405 | method_not_allowed | Falsche Methode. Der Header Allow nennt die richtigen. |
| 409 | slot_unavailable | Die Uhrzeit ist nicht (mehr) frei. alternatives enthält bis zu vier freie Zeiten am selben Tag. |
| 409 | closed | Das Restaurant hat an diesem Tag geschlossen. closure enthält den Zeitraum. |
| 409 | booking_disabled | Das Restaurant nimmt gerade keine Online-Reservierungen an. |
| 409 | not_modifiable, not_cancellable | Die Reservierung ist schon abgeschlossen, abgesagt oder storniert. |
| 409 | invalid_transition | Dieser Statuswechsel geht nicht. allowed nennt die möglichen. |
| 409 | limit_reached | Höchstzahl an Schließzeiten oder Webhooks erreicht. |
| 413 | payload_too_large | Die Anfrage ist größer als 256 KB. |
| 422 | validation_failed | Angaben fehlen oder sind falsch. fields nennt sie einzeln. |
| 429 | rate_limited | Zu viele Anfragen. Warte so viele Sekunden, wie Retry-After angibt. |
| 500 | server_error | Fehler bei uns. Versuche es später erneut. |
Restaurant
GET/restaurantLesen
Stammdaten und Reservierungsregeln. booking.accepting ist false, solange das Restaurant keine Online-Reservierungen annimmt. booking.mode ist covers (feste Zahl an Plätzen pro Zeitfenster) oder tables (freie Tische laut Tischplan). booking_hours sind die Zeiten, zu denen reserviert werden kann (weekday 1 = Montag), last_seating ist der späteste Beginn.
{
"restaurant": {
"slug": "trattoria-da-luca",
"name": "Trattoria da Luca",
"address": {
"street": "Lange Reihe 12",
"zip": "20099",
"city": "Hamburg"
},
"phone": "+49 40 1234567",
"website": "https://trattoria-da-luca.de",
"dinnerspots_url": "https://dinnerspots.de/restaurant/trattoria-da-luca",
"widget_url": "https://dinnerspots.de/widget/trattoria-da-luca",
"booking": {
"accepting": true,
"auto_confirm": true,
"max_party_size": 8,
"slot_interval_minutes": 15,
"duration_minutes": 120,
"lead_minutes": 60,
"horizon_days": 60,
"mode": "tables",
"note": null
},
"booking_hours": [
{
"weekday": 2,
"day": "tuesday",
"opens": "17:00",
"closes": "23:00",
"last_seating": "21:30"
}
]
}
}Freie Zeiten
GET/availability?date=2026-10-17&party=4Lesen
Freie Uhrzeiten an einem Tag für eine Personenzahl. Es gelten dieselben Regeln wie bei der Online-Reservierung: Vorlaufzeit, Buchungszeitraum, Höchstzahl an Personen und die online buchbaren Tische. party ist 1 bis max_party_size, Standard 2. date ist standardmäßig heute.
{
"date": "2026-10-17",
"party_size": 4,
"accepting": true,
"closed": false,
"closure": null,
"slots": [
"18:00",
"18:15",
"19:30",
"19:45",
"21:00"
]
}Bei Betriebsferien ist closed true und closure enthält z. B. {"from": "2026-12-23", "to": "2027-01-06", "kind": "holiday", "kind_label": "Betriebsferien", "note": null}. closed ist auch true, wenn an diesem Wochentag keine Reservierungszeiten eingetragen sind. Nimmt das Restaurant gerade keine Online-Reservierungen an, ist accepting false und slots leer.
GET/availability/next?party=4&from=2026-10-17&days=14Lesen
Der nächste Tag mit freien Zeiten ab from (Standard: heute), gesucht über days Tage (1 bis 60, Standard 14). next ist null, wenn in diesem Zeitraum nichts frei ist oder das Restaurant gerade keine Online-Reservierungen annimmt. from liegt nie in der Vergangenheit.
{
"from": "2026-10-17",
"party_size": 4,
"accepting": true,
"next": {
"date": "2026-10-18",
"slots": [
"18:00",
"20:30"
]
}
}Reservierungen
So sieht eine Reservierung aus:
{
"reservation": {
"id": "K7Q2MZ4P",
"status": "confirmed",
"date": "2026-10-17",
"time": "19:30",
"party_size": 4,
"duration_minutes": 120,
"guest": {
"first_name": "Lena",
"last_name": "Brandt",
"email": "[email protected]",
"phone": "+49 151 2345678"
},
"occasion": "geburtstag",
"notes": "Mit Kinderstuhl, bitte",
"internal_note": null,
"source": "api",
"channel": "instagram",
"tables": [
{
"id": 12,
"label": "T4",
"kind": "table"
}
],
"cancelled_by": null,
"cancel_reason": null,
"created_at": "2026-10-04T14:02:11+02:00",
"updated_at": "2026-10-04T14:02:11+02:00",
"manage_url": "https://dinnerspots.de/reservierung/3f9c…"
}
}| Feld | Bedeutung |
|---|---|
status | pending (wartet auf Bestätigung), confirmed, seated (Gast ist da), completed, no_show, declined (abgelehnt), cancelled. |
occasion | geburtstag, jahrestag, date, business, feier oder null. |
notes | Wünsche des Gastes, höchstens 600 Zeichen. |
internal_note | Interne Notiz des Restaurants. Gäste sehen sie nie. |
source | Woher sie kam: online (DinnerSpots.de), widget (Website), api, phone, walk_in, partner (vom Restaurant eingetragen). |
channel | Kanal für die Statistik, z. B. instagram oder website. |
tables | Zugewiesene Tische und Barplätze aus dem Tischplan. |
manage_url | Link, unter dem der Gast seine Reservierung ändert oder storniert. Gib ihn nur an diesen Gast weiter. |
GET/reservationsLesen
Ohne Filter: alle Reservierungen von heute bis in 30 Tagen, sortiert nach Datum und Uhrzeit.
| Parameter | Bedeutung |
|---|---|
date | Ein Tag. |
from, to | Zeitraum, höchstens 92 Tage. |
updated_since | Alles, was sich seit diesem Zeitpunkt geändert hat, sortiert nach updated_at – ideal zum Abgleich. Ersetzt die Datumsfilter. |
status | Einer oder mehrere, mit Komma getrennt: pending,confirmed. |
q | Suche in Name, E-Mail, Telefon und Code. |
limit, offset | Seitenweise abrufen, limit 1 bis 200, Standard 50. |
{
"data": [
"…"
],
"has_more": true,
"next_offset": 50
}Ist has_more true, frag mit offset=next_offset die nächste Seite ab.
GET/reservations/{id}Lesen
Eine Reservierung über ihren Code.
POST/reservationsSchreibrecht
Legt eine Reservierung im Namen eines Gastes an. Es gelten dieselben Regeln wie bei der Online-Reservierung. Bestätigt das Restaurant automatisch, ist der Status confirmed, sonst pending.
curl -X POST https://dinnerspots.de/api/v1/reservations \
-H "Authorization: Bearer bt_live_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: ig-msg-7f3a91" \
-d '{"date":"2026-10-17","time":"19:30","party_size":4,"guest":{"first_name":"Lena","last_name":"Brandt","email":"[email protected]","phone":"+49 151 2345678"},"occasion":"geburtstag","notes":"Mit Kinderstuhl, bitte","channel":"instagram"}'| Feld | Pflicht | Bedeutung |
|---|---|---|
date, time | ja | Am besten eine Zeit aus /availability. |
party_size | ja | 1 bis max_party_size. |
guest.last_name | ja | Höchstens 80 Zeichen, ebenso guest.first_name. |
guest.email oder guest.phone | eins davon | Mit E-Mail-Adresse bekommt der Gast eine Bestätigung mit Link zum Ändern und Stornieren. |
occasion, notes | nein | Siehe oben. |
internal_note | nein | Notiz nur für das Restaurant. |
channel | nein | Kanal für die Statistik. Ohne Angabe wird der Name des Schlüssels verwendet. |
Antwort: 201 mit der Reservierung. Ist die Zeit inzwischen vergeben, kommt 409 slot_unavailable mit Alternativen – biete sie dem Gast direkt an:
{
"error": {
"code": "slot_unavailable",
"message": "Diese Uhrzeit ist nicht frei.",
"alternatives": [
"19:00",
"19:15",
"20:00",
"20:15"
]
}
}Tische zuweisen und die Verweildauer ändern kann nur das Restaurant im Kundenportal. Schickst du tables, duration_minutes oder source mit, antwortet die API mit 422.
Doppelte Buchungen vermeiden
Schicke bei POST /reservations einen Header Idempotency-Key mit, z. B. die ID der Chat-Nachricht (1 bis 64 Zeichen: Buchstaben, Ziffern, _ . : -). Kommt dieselbe Anfrage noch einmal, etwa nach einem Timeout, legt die API keine zweite Reservierung an. Sie antwortet mit 200, der ersten Reservierung und dem Header Idempotent-Replayed: true.
PATCH/reservations/{id}Schreibrecht
Ändert nur die Felder, die du mitschickst: date, time, party_size, guest, occasion, notes, internal_note. Geht bei pending, confirmed und seated, sonst 409 not_modifiable. Neue Zeiten müssen frei sein, sonst 409 slot_unavailable mit Alternativen.
{
"time": "20:00",
"party_size": 5,
"notify_guest": true
}Ändern sich Datum, Uhrzeit oder Personenzahl, bekommt der Gast eine E-Mail. Mit "notify_guest": false unterbleibt sie.
POST/reservations/{id}/statusSchreibrecht
Bestätigen, ablehnen, Gast als angekommen oder nicht erschienen markieren.
{
"status": "confirmed",
"notify_guest": true
}| Von | Nach |
|---|---|
pending | confirmed, declined |
confirmed | seated, completed, no_show |
seated | completed, confirmed |
completed | no_show, seated |
no_show | completed, confirmed |
Beim Bestätigen oder Ablehnen einer offenen Anfrage bekommt der Gast eine E-Mail, außer mit "notify_guest": false. Zum Stornieren gibt es einen eigenen Endpunkt.
POST/reservations/{id}/cancelSchreibrecht
Storniert eine offene oder bestätigte Reservierung, sonst 409 not_cancellable.
{
"by": "guest",
"reason": "Gast hat per Instagram abgesagt",
"notify": true
}by:restaurant(Standard) oderguest, wenn der Gast selbst abgesagt hat.reason: freiwillig, höchstens 255 Zeichen.notify: Standardtrue. Bei"by": "restaurant"bekommt der Gast eine E-Mail über die Stornierung. Bei"by": "guest"bekommt der Gast immer eine Stornobestätigung, und das Restaurant wird per E-Mail informiert. Mit"notify": falseentfällt nur die E-Mail ans Restaurant.
Betriebsferien und Schließtage
An eingetragenen Tagen sind online keine Reservierungen möglich, und Gäste sehen den Hinweis auf DinnerSpots.de und im Widget.
GET/closuresLesen
Alle aktuellen und kommenden Zeiträume. Mit ?include_past=true auch vergangene.
{
"data": [
{
"id": 31,
"from": "2026-12-23",
"to": "2027-01-06",
"kind": "holiday",
"kind_label": "Betriebsferien",
"note": "Wir sind ab 7. Januar wieder da.",
"created_at": "2026-10-04T10:15:00+02:00"
}
]
}POST/closuresSchreibrecht
{
"from": "2026-12-23",
"to": "2027-01-06",
"kind": "holiday",
"note": "Wir sind ab 7. Januar wieder da."
}kind:holiday(Betriebsferien, Standard),closed(geschlossen) oderevent(geschlossene Gesellschaft).toist standardmäßig gleichfrom– für einen einzelnen Tag reichtfrom.notesehen Gäste, höchstens 160 Zeichen. Ein Zeitraum umfasst höchstens 366 Tage, bis zu 200 kommende Zeiträume sind möglich.
Die Antwort (201) enthält neben closure auch affected_count und bis zu 50 affected_reservations: Reservierungen, die in den Zeitraum fallen. Sie werden nicht automatisch storniert – kläre sie mit den Gästen und storniere sie bei Bedarf einzeln.
DELETE/closures/{id}Schreibrecht
Entfernt einen Zeitraum. Antwort: {"deleted": true, "closure": {…}}.
Tischplan
GET/floorplanLesen
Bereiche (z. B. Gastraum, Terrasse) mit ihren Tischen, Barplätzen und Deko-Elementen. Alle Maße sind in Zentimetern: width × height ist die Größe des Bereichs, x/y die linke obere Ecke eines Elements vor der Drehung, w/h seine Größe. rotation (0 bis 359 Grad) dreht im Uhrzeigersinn um die Mitte des Elements. Den Tischplan bearbeitet das Restaurant im Kundenportal.
{
"floorplan": {
"areas": [
{
"id": 1,
"name": "Gastraum",
"width": 1000,
"height": 700,
"online_bookable": true,
"items": [
{
"id": 12,
"kind": "table",
"shape": "round",
"label": "T4",
"x": 200,
"y": 200,
"w": 100,
"h": 100,
"rotation": 0,
"seats_min": 2,
"seats_max": 4,
"online_bookable": true
},
{
"id": 20,
"kind": "bar",
"shape": "rect",
"label": "Bar",
"x": 600,
"y": 60,
"w": 300,
"h": 60,
"rotation": 0,
"seats_min": 1,
"seats_max": 6,
"online_bookable": false
}
]
}
],
"summary": {
"tables": 1,
"bar_seats": 6,
"seats": 10,
"online_seats": 4
}
}
}kind ist table, bar oder deco, shape ist rect oder round. Online buchbar ist ein Platz nur, wenn er selbst und sein Bereich online_bookable sind.
Webhooks
Statt regelmäßig nachzufragen, kann dich die API bei jeder Änderung sofort benachrichtigen. Sie schickt dann ein POST mit JSON an deine Adresse. Webhooks verwaltest du im Kundenportal oder mit einem Schlüssel mit Schreibrecht.
| Ereignis | Wann | Zusätzlich in data |
|---|---|---|
reservation.created | Neue Reservierung – egal ob online, über das Widget, die API oder vom Restaurant eingetragen. | – |
reservation.updated | Datum, Uhrzeit, Personenzahl, Gastdaten oder Notizen geändert. | previous mit date, time, party_size |
reservation.status_changed | Bestätigt, abgelehnt, angekommen, abgeschlossen, nicht erschienen. | previous_status |
reservation.cancelled | Vom Gast oder vom Restaurant storniert. | – |
closure.created | Betriebsferien oder Schließtag eingetragen. | – |
closure.deleted | Schließzeit entfernt. | – |
{
"id": "evt_5c1e9a0b7d2f4e6a8b3c1d0e",
"event": "reservation.created",
"created_at": "2026-10-04T14:02:11+02:00",
"restaurant": {
"slug": "trattoria-da-luca",
"name": "Trattoria da Luca"
},
"data": {
"reservation": {
"id": "K7Q2MZ4P",
"status": "confirmed",
"date": "2026-10-17",
"time": "19:30",
"party_size": 4,
"…": "…"
}
}
}POST/webhooksSchreibrecht
{
"url": "https://example.com/hooks/dinnerspots",
"events": [
"reservation.created",
"reservation.cancelled"
]
}Ohne events oder mit ["*"] bekommst du alle Ereignisse. Die Antwort enthält das secret zum Prüfen der Signatur – nur hier und beim Erneuern, also gleich speichern. Bis zu 5 Webhooks pro Restaurant.
Die Adresse muss mit https:// beginnen, öffentlich erreichbar sein (Port 443 oder 8443) und darf keine Zugangsdaten enthalten. Weiterleitungen folgen wir nicht.
Weitere Endpunkte
GET /webhooks | Alle Webhooks mit Zustand (active, failure_count, letzte Erfolge und Fehler). |
PATCH /webhooks/{id} | url, events oder active ändern. |
DELETE /webhooks/{id} | Webhook löschen. |
POST /webhooks/{id}/test | Schickt sofort ein Ereignis webhook.test und liefert das Ergebnis. Höchstens 10 pro Minute. |
POST /webhooks/{id}/secret | Neues Secret erzeugen. Das alte gilt sofort nicht mehr. |
GET /webhooks/{id}/deliveries | Die letzten Zustellungen mit Status (pending, delivered, failed), Versuchen und Antwortcode. |
Signatur prüfen
Jede Zustellung hat diese Header:
X-Bontrivo-Event | Name des Ereignisses. |
X-Bontrivo-Delivery | ID der Zustellung, z. B. dlv_4711. |
X-Bontrivo-Timestamp | Unix-Zeit in Sekunden, neu bei jedem Versuch. |
X-Bontrivo-Signature | v1= und HMAC-SHA256 über Zeitstempel + "." + Body mit deinem Secret, hexadezimal. |
Prüfe die Signatur über den unveränderten Body, bevor du ihn verarbeitest. Lehne Zeitstempel ab, die älter als 5 Minuten sind.
<?php
$secret = getenv('DINNERSPOTS_WEBHOOK_SECRET');
$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_BONTRIVO_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_BONTRIVO_SIGNATURE'] ?? '';
$expected = 'v1=' . hash_hmac('sha256', $ts . '.' . $body, $secret);
if (!ctype_digit($ts) || abs(time() - (int)$ts) > 300 || !hash_equals($expected, $sig)) {
http_response_code(401);
exit;
}
$event = json_decode($body, true);
// Jedes Ereignis nur einmal verarbeiten: $event['id'] bleibt bei Wiederholungen gleich
http_response_code(200);// Node.js mit Express
const crypto = require('crypto');
const express = require('express');
const app = express();
app.post('/hooks/dinnerspots', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.get('X-Bontrivo-Timestamp') || '';
const sig = Buffer.from(req.get('X-Bontrivo-Signature') || '');
const expected = Buffer.from('v1=' + crypto
.createHmac('sha256', process.env.DINNERSPOTS_WEBHOOK_SECRET)
.update(ts + '.' + req.body)
.digest('hex'));
const fresh = Math.abs(Date.now() / 1000 - Number(ts)) <= 300;
if (!fresh || sig.length !== expected.length || !crypto.timingSafeEqual(sig, expected)) {
return res.sendStatus(401);
}
const event = JSON.parse(req.body);
// … verarbeiten, dann schnell antworten
res.sendStatus(200);
});Zustellung und Wiederholungen
- Jede Antwort mit Status 200 bis 299 gilt als zugestellt. Antworte innerhalb von 10 Sekunden und erledige längere Arbeit danach.
- Bei Fehlern oder Timeout versuchen wir es erneut nach 1, 5 und 15 Minuten, dann nach 1, 3, 6, 12 und 24 Stunden.
- Die
iddes Ereignisses (evt_…) bleibt bei Wiederholungen gleich. Verarbeite jedeidnur einmal. - Die Reihenfolge ist nicht garantiert. Im Zweifel gilt
updated_at– oder du lädst die Reservierung frisch über die API. - Nach 10 endgültig fehlgeschlagenen Zustellungen in Folge pausieren wir den Webhook. Mit
PATCH /webhooks/{id}und{"active": true}schaltest du ihn wieder ein.
Beispiel: Chatbot für Instagram, Messenger und WhatsApp
Über die Meta-Plattform (Messenger-API für Instagram und Facebook, WhatsApp Business Platform) empfängt dein Server Nachrichten von Gästen und antwortet darauf. Die DinnerSpots-API liefert die freien Zeiten und nimmt die Reservierung an. So greift beides ineinander:
- Der Gast schreibt z. B. „Tisch für 4 am Samstag?“. Meta schickt die Nachricht an deinen Webhook bei Meta.
- Dein Bot fragt
GET /availability?date=…&party=4ab und schlägt die freien Zeiten vor. Ist nichts frei, hilftGET /availability/next. - Nach Auswahl der Uhrzeit fragt der Bot nach Namen und Telefonnummer oder E-Mail und legt mit
POST /reservationsdie Reservierung an – mit"channel": "instagram","facebook"oder"whatsapp"und der Nachrichten-ID alsIdempotency-Key. - Kommt
409 slot_unavailable, bietet der Bot diealternativesan. - Über den Webhook
reservation.status_changederfährt der Bot, wenn das Restaurant eine Anfrage bestätigt oder ablehnt, und kann dem Gast antworten.
// Ausschnitt: freie Zeiten für den Chat holen (Node.js 18+)
const API = 'https://dinnerspots.de/api/v1';
const headers = { Authorization: 'Bearer ' + process.env.DINNERSPOTS_API_KEY };
async function freieZeiten(datum, personen) {
const res = await fetch(API + '/availability?date=' + datum + '&party=' + personen, { headers });
const data = await res.json();
if (!res.ok) throw new Error(data.error.message);
if (data.closed) return { text: 'An diesem Tag haben wir leider geschlossen.' };
if (!data.slots.length) return { text: 'Da ist leider schon alles voll.' };
return { text: 'Frei sind: ' + data.slots.slice(0, 6).join(', ') + ' Uhr.' };
}Die Meta-Seite (App, Zugriffstoken, Freigabe durch Meta) richtest du selbst oder mit deinem Dienstleister ein. Gästedaten aus dem Chat landen über die API beim Restaurant – denk an den Hinweis in deiner Datenschutzerklärung.
Fragen?
Schreib uns an [email protected]. Die Übersicht der API bekommst du jederzeit ohne Schlüssel mit GET https://dinnerspots.de/api/v1.