Entwicklerdokumentation

Gutscheine

Geschenkgutscheine online verkaufen, einen ohne Schlüssel über seinen Code abfragen und Gäste damit Tab, Anzahlung oder Tickets bezahlen lassen.

Eine Location verkauft über diese Routen Geschenkgutscheine, und Gäste lösen sie am Tisch oder online ein. Es gibt drei Arten: einen Betrag (in Teilen einlösbar, bis das Guthaben aufgebraucht ist), einen Prozentrabatt auf eine Rechnung und einen Menüartikel. Die Location legt fest, was sie verkauft, zu welchem Preis und wie lange ein Gutschein gilt; in der Konsole stellt sie Gutscheine in jedem Tarif von Hand aus, der Online-Verkauf braucht Premium.

Zwei der Routen unten brauchen Ihren Schlüssel, wie jede Route unter /api/venues/**: die Angebote und der Checkout. Die dritte, die Abfrage per Code, braucht keinen: Wer den Code eines Gutscheins hat, hat den Gutschein. Zum Bezahlen mit einem Gutschein gibt es keine eigene Route – Tab-, Anzahlungs- und Ticketzahlung nehmen einen optionalen Gutscheincode an (Mit einem Gutschein bezahlen).

Der Code ist ein Credential

Ein Gutscheincode hat 20 Zeichen und wird in fünf Gruppen angezeigt (K7QM-2XRP-9DTA-HV3N-8W4F). Das letzte Zeichen ist ein Prüfzeichen, sodass ein Tippfehler vor jeder Anfrage auffällt; die SDKs prüfen es für Sie. Wer den Code hat, sieht den Wert des Gutscheins und kann ihn ausgeben, genau wie bei einer Geschenkkarte. Deshalb:

  • Loggen Sie ihn nie und setzen Sie ihn nie in eine eigene URL – nur die Abfrage unten trägt ihn im Pfad, und BookDinePlay entfernt ihn aus den eigenen Logs und Traces.
  • Senden Sie ihn sonst im Request-Body: Tab-Zahlung, Anzahlung und Ticket-Checkout nehmen ihn alle als voucherCode.
  • Zeigen Sie keinen Code, den Sie nicht vom Gast haben. Der Code entsteht erst, wenn der Gutschein bezahlt ist; er erreicht Käufer oder Beschenkte per E-Mail, nie über die Antwort des Checkouts.
  • Rechnen Sie mit einer Antwort für „nein“. Ein vertippter, unbekannter, unbezahlter oder fremder Code ist dasselbe 404 voucher-not-found, damit Codes nicht durchprobiert werden können.

Die reference (GV-…), die ein Checkout zurückgibt, ist kein Credential: Sie bezeichnet den Kauf für den Support und darf geloggt werden.

Endpunkte

GET /api/vouchers/{code}

Ohne Schlüssel. code ist der Gutscheincode in jeder Form, die ein Gast tippen oder scannen könnte: die Anzeigeform (K7QM-2XRP-9DTA-HV3N-8W4F), die 20 Zeichen ohne Bindestriche, jeweils auch in Kleinbuchstaben. Eine vollständige URL der Gastseite wird hier nicht angenommen: Nehmen Sie ihr letztes Segment. Senden Sie ihn prozentkodiert als ein Pfadsegment und halten Sie ihn aus Ihren eigenen Logs heraus – er ist ein Inhaber-Credential. Hängt nicht am Tarif: Ein Gutschein, der ausgegeben wurde, als der Tarif der Location es erlaubte, funktioniert auch nach einem Downgrade weiter.

Antwort 200 OK

Feld Typ Bedeutung
venueSlug, venueName string Die Location, die den Gutschein ausgegeben hat
displayCode string Der Code in seiner Anzeigeform
kind string Amount, Percentage oder Item
status string Active, PartlyUsed, UsedUp, Expired oder Voided
currency string ISO-4217-Währung aller Geldfelder
balance number oder null Was ein Amount-Gutschein noch bezahlen kann; null bei den anderen Arten
faceValue number oder null Der Wert, mit dem ein Amount-Gutschein ausgegeben wurde
percentage, maxDiscount number oder null Der Rabatt eines Percentage-Gutscheins und seine optionale Obergrenze in Geld
itemName string oder null Der Menüartikel eines Item-Gutscheins
expiresOn string Der letzte gültige Tag, Ortszeit der Location, yyyy-MM-dd
terms string oder null Die Gutscheinbedingungen der Location zum Zeitpunkt der Ausgabe
recipientName, giftMessage string oder null Was der Käufer für den Empfänger geschrieben hat
guestUrl string Die Gastseite dieses Gutscheins
qrSvg string Ein SVG-QR-Code von guestUrl

Die Antwort enthält nie die Buchungshistorie des Gutscheins oder Name und E-Mail-Adresse des Käufers. balance ist, was sich jetzt ausgeben lässt: Wert, den eine laufende Zahlung reserviert hält, zählt nicht mit.

Fehler. 404 mit dem Problemtyp https://bookdineplay.com/docs/api/errors/voucher-not-found für jeden Code, der zu keinem ausgegebenen Gutschein gehört – vertippt, unbekannt oder ein nie bezahlter Kauf. Ein abgelaufener oder entwerteter Gutschein ist kein Fehler: Er antwortet mit 200 und diesem status. Die Antwort ist für alle gleich, damit Codes nicht durchprobiert werden können. 429 mit einem Retry-After-Header, wenn ein Client mehr als 30-mal pro Minute fragt – die einzige Route der API mit Ratenbegrenzung, weil es keinen Schlüssel gibt, an dem man zählen könnte (Ratenbegrenzung).

curl

curl "https://api.bookdineplay.com/api/vouchers/K7QM-2XRP-9DTA-HV3N-8W4F"

JavaScript

const voucher = await client.voucher(code); // sendet keinen Schlüssel; null, wenn unbekannt oder vertippt (bei einem vertippten Code ganz ohne Anfrage)

C#

var voucher = await client.GetVoucherAsync(code, cancellationToken); // sendet keinen Schlüssel; null, wenn unbekannt

GET /api/venues/{venueSlug}/vouchers/offers

Was die Location gerade online verkauft. Antwortet in jedem Tarif: Wenn Gutscheine nicht online gekauft werden können, ist onlineSaleAvailable false, offers leer und unavailableReason nennt den Grund. Titel, Bedingungen und der Gültigkeitssatz folgen dem Accept-Language der Anfrage.

Antwort 200 OK

Feld Typ Bedeutung
venueSlug, venueName, currency string Die Location und die Währung aller Preise
onlineSaleAvailable boolean Ob ein Checkout gestartet werden kann
unavailableReason string oder null not-offered, validity-not-set, validity-too-short, payments-off, not-in-plan oder payouts-not-connected
offers array Ein Eintrag je Produkt: productId, kind, title, price (null, wenn der Käufer den Betrag wählt), customAmount, minAmount, maxAmount, itemName
terms string oder null Die Gutscheinbedingungen der Location
validityDescription string oder null Wie lange ein heute gekaufter Gutschein gültig ist

Zeigen Sie einem Gast für jeden unavailableReason denselben Satz, höchstens not-offered eigens: Die anderen Gründe betreffen die Einrichtung der Location, nicht etwas, das ein Gast ändern kann. Der Gutschein-Shop macht genau das.

curl

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

JavaScript

const offers = await client.voucherOffers();
if (!offers.onlineSaleAvailable) showNotAvailable(offers.unavailableReason);

C#

var offers = await client.GetVoucherOffersAsync("your-venue", cancellationToken); // null, wenn die Location unbekannt ist

POST /api/venues/{venueSlug}/vouchers/checkout

Einen Gutschein kaufen: öffnet eine Stripe-Checkout-Sitzung auf dem eigenen verbundenen Stripe-Konto der Location und gibt die URL zurück, zu der Sie den Käufer schicken. Braucht den Premium-Tarif, eingeschaltete Online-Zahlungen und ein Auszahlungskonto, das verkaufen darf. Der Code des Gutscheins existiert noch nicht: Er wird erst erzeugt, wenn die Zahlung bestätigt ist, und erreicht den Käufer oder die beschenkte Person per E-Mail. Senden Sie einen Idempotency-Key-Header, damit eine wiederholte Anfrage denselben Checkout zurückgibt statt einen zweiten zu öffnen; siehe Idempotenz-Probleme. Das .NET SDK und der Gutschein-Shop senden einen für Sie; bei client.checkoutVoucher übergeben Sie { idempotencyKey } selbst – ohne ihn sendet der JavaScript-Client keinen, und ein Wiederholungsversuch kann einen zweiten Checkout öffnen.

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

Feld Pflicht Bedeutung
productId ja Die productId eines Angebots
amount freie Beträge Der zu kaufende Wert, zwischen minAmount und maxAmount des Angebots
buyerName, buyerEmail ja Wer bezahlt
recipientName, recipientEmail, giftMessage nein Für wen der Gutschein ist; die Nachricht hat höchstens 500 Zeichen
deliverOn nein yyyy-MM-dd, Ortszeit der Location, von heute bis ein Jahr im Voraus: der Tag, an dem die E-Mail an die beschenkte Person geht. Braucht recipientEmail
language nein en oder de; Standard ist das Accept-Language der Anfrage, danach die Sprache der Location
successUrl, cancelUrl nein Wohin Checkout den Käufer schickt. Muss https sein und auf der Origin-Liste dieses API-Schlüssels oder der eigenen Gast-App der Plattform liegen; ohne Angabe gilt die eingebaute Dankeseite

Antwort 201 Created: reference (GV-…, nur zur Anzeige), checkoutUrl (dorthin schicken Sie den Käufer) und expiresAt (ab wann die Checkout-Sitzung keine Zahlung mehr annimmt).

Ein bezahlter Gutschein gilt mindestens ein Jahr ab dem Tag seiner Ausgabe. Ein Kauf, dessen Zahlung nie eintrifft, erzeugt keinen Gutschein; er wird 30 Tage nach Ablauf seines Checkouts gelöscht.

Fehler

Status Wann
400 Ein Feld ist ungültig (errors nennt es), eine Rücksprung-URL wird abgelehnt, oder die Gültigkeitsregel der Location gibt einem bezahlten Gutschein weniger als ein Jahr (voucher-validity-too-short)
400 errors["Idempotency-Key"]: Der Schlüssel ist länger als 200 Zeichen
403 feature-not-in-plan: Online-Verkauf braucht Premium
404 Keine Location mit diesem Slug
409 voucher-sale-not-available (Online-Verkauf aus, Produkt nicht online verkauft, Zahlungen aus oder kein Auszahlungskonto, das verkaufen darf) oder voucher-validity-not-set
409 idempotency-key-reused oder checkout-in-progress

curl

curl -X POST "https://api.bookdineplay.com/api/venues/your-venue/vouchers/checkout" \
  -H "X-BookDinePlay-Key: bdp_pk_your_publishable_key" \
  -H "Origin: https://www.your-venue.example" \
  -H "Idempotency-Key: 4f9c2a1e8b7d4c3f9e0a1b2c3d4e5f60" \
  -H "Content-Type: application/json" \
  -d '{ "productId": "3f2a1b4c5d6e4f708192a3b4c5d6e7f8", "buyerName": "Ben Buyer", "buyerEmail": "ben@example.com", "recipientName": "Ada" }'

JavaScript

const checkout = await client.checkoutVoucher(
  { productId, buyerName: 'Ben Buyer', buyerEmail: 'ben@example.com', recipientName: 'Ada' },
  { idempotencyKey: attemptKey } // ein crypto.randomUUID() je Versuch, beim Wiederholen derselbe
);
window.location.assign(checkout.checkoutUrl);

C#

var checkout = await client.StartVoucherCheckoutAsync("your-venue",
    new StartVoucherCheckoutRequest { ProductId = productId, BuyerName = "Ben Buyer", BuyerEmail = "ben@example.com", RecipientName = "Ada" },
    idempotencyKey: attemptKey, cancellationToken);

Mit einem Gutschein bezahlen

Ein Gast löst einen Gutschein online ein, indem er dessen Code zu einer Zahlung gibt, die er ohnehin macht. Die drei Zahlungen nehmen ein optionales voucherCode im Body; ohne ändert sich nichts.

Zahlung Feld Akzeptierte Arten Was zurückkommt
Ein Tisch-Tab, /api/qr/{token}/payment voucherCode Amount, Percentage voucherAmount, paidInFull
Eine Reservierungsanzahlung, /api/venues/{venueSlug}/payment-intents voucherCode Amount voucherAmount, cardAmount
Event-Tickets, /api/venues/{venueSlug}/events/{eventSlug}/tickets/checkout voucherCode Amount voucherAmount, amountDue

Für alle drei gelten dieselben Regeln:

  • Erst zahlt der Gutschein, die Karte zahlt den Rest. Der Wert wird reserviert, solange der Gast auf der Stripe-Seite ist, sodass er nicht zweimal ausgegeben werden kann; bricht der Gast ab, verfällt die Reservierung von selbst.
  • Die Karte zahlt mindestens den Mindestbetrag von Stripe – 0,50 € in EUR; Stripe legt ihn je Währung fest. Stripe lehnt kleinere Kartenzahlungen ab. Läge der Rest zwischen 0,01 € und 0,49 €, zahlt der Gutschein etwas weniger, sodass die Karte genau 0,50 € zahlt, und der Gutschein behält die Differenz: Ein 50-€-Gutschein auf einem Tab über 50,30 € zahlt 49,80 €. Beträgt der ganze Betrag 0,50 € oder weniger und deckt der Gutschein ihn nicht, lässt er sich dafür nicht verwenden: 409 mit reason below-card-minimum, bei allen drei Zahlungen.
  • Ein Gutschein, der alles deckt, öffnet keine Zahlungsseite. Die Zahlung ist sofort abgeschlossen, und checkoutUrl ist die Erfolgsseite – ein Client, der einfach checkoutUrl folgt, funktioniert also in beiden Fällen. Prüfen Sie paidInFull, cardAmount oder amountDue, um die Weiterleitung zu sparen.
  • Eine Erstattung geht beim Gutscheinteil auf den Gutschein zurück. Nur der Kartenteil geht zurück auf die Karte. Ein abgelaufener Gutschein wird um 30 Tage ab der Erstattung verlängert, damit der Gast den zurückgebuchten Wert noch nutzen kann. Ein Gutschein, den die Location entwertet hat, bleibt entwertet: Die Erstattung wird auf ihm vermerkt, den Wert klärt die Location direkt mit dem Gast.
  • Ein Prozentgutschein ist ein Rabatt auf die ganze Rechnung, vor jedem Betragsgutschein angerechnet und auf den offenen Betrag begrenzt. Er wird einmal eingelöst.
  • Kein Tarif-Gate. Bezahlen mit einem Gutschein und dessen Erstattung funktionieren in jedem Tarif. Die eigenen Bedingungen einer Zahlung gelten weiter – ein Tab braucht Bestellen, eine Anzahlung braucht Anzahlungen, Tickets brauchen Ticketverkauf –, und der Kartenteil braucht Online-Zahlungen wie ohne Gutschein.
  • Überall dieselben Probleme. Ein Code wird mit einem der Gutschein-Probleme abgelehnt, egal zu welcher Zahlung er gegeben wurde.

Artikelgutscheine löst das Personal am Tisch ein und wählt dabei die Rechnungszeile, die sie bezahlen.

Nächste Schritte

  • JavaScript-Gutscheine – der Gutschein-Shop, die Guthabenabfrage und die Gutscheinfelder in den Widgets.
  • .NET SDK – die typisierten Gutschein-Aufrufe.
  • Fehler – jedes Gutschein-Problem und was Sie anzeigen.