API für Entwickler
Die offene API von Vitrina: Menü, Bestellungen, Reservierungen, Gäste und Umsätze für Ihre Kasse, Ihren Küchenmonitor, Ihr CRM oder Ihre Buchhaltung. REST und JSON, Schlüssel mit Rechten, signierte Webhooks.
Was Sie damit tun können
- Menü: Kategorien, Gerichte, Preise und Verfügbarkeit je Standort sowie die Ausverkauft-Liste: ein Gericht aus dem Verkauf nehmen oder zurückholen
- Menü bearbeiten: Kategorien und Gerichte, Namen und Beschreibungen in den Sprachen Ihrer Gäste, Preise, Portionen, Modifikatoren, Reihenfolge und Sichtbarkeit
- Bestellungen: Liste mit Filtern, Positionen und Beträge, Küchen- und Ausgabestatus (angenommen, in Zubereitung, fertig, ausgegeben)
- Neue Bestellungen aus Callcenter, Kiosk oder einer anderen Website, mit denselben Preisen und Lieferregeln wie auf Ihrer Website; Kasse und Küche sehen sie sofort, und der Gast zahlt bei Erhalt
- Lieferung: wer liefert (nur der Vorname des Kuriers), wann die Bestellung abgeholt und wann sie zugestellt wurde: direkt in der Bestellung und als Ereignis
- Zahlungen und Erstattungen jeder Bestellung für den Abgleich, nur lesend
- Reservierungen: Liste, neue Reservierung und Statuswechsel (bestätigen, ablehnen, Gast erschienen oder nicht erschienen)
- Gäste: Profile und Kontaktdaten, nur mit eigener Berechtigung
- Bonuspunkte der Gäste: mit Begründung gutschreiben oder abziehen, mit eigener Berechtigung; der Saldo wird nie negativ, und jede Buchung wird protokolliert
- Tagesverkäufe für die Buchhaltung: Bestellungen, Umsatz, Rabatte, Erstattungen und Trinkgelder nach Zahlungsart und Kanal
- Standorte: Adressen, Kontakte und Öffnungszeiten
- Ereignisse (neue Bestellung, Statuswechsel, Zahlung, Stornierung, Erstattung, Lieferung, neue Reservierung, Ausverkauft-Liste und Menüänderungen) per Webhook an Ihren Server
Zahlungen annehmen, Geld erstatten oder Bestellungen stornieren kann die API nicht: Das Geld der Gäste bewegt nur das Lokal selbst. Deshalb zahlt der Gast Bestellungen aus der API bei Erhalt.
Zugang und Rechte
Den Schlüssel erstellt der Inhaber des Lokals im Adminbereich unter „API & Webhooks“: Er benennt die Integration und wählt Rechte und Standorte. Der Schlüssel wird nur einmal angezeigt (in der Datenbank bleibt nur sein Fingerabdruck) und lässt sich jederzeit widerrufen. Namen, Telefonnummern und Adressen der Gäste sieht die Integration nur mit dem Recht customers:read.
Rechte des Schlüssels
locations:read- Standorte: Adressen, Kontakte und Öffnungszeiten
menu:read- Menü, Preise und Verfügbarkeit der Gerichte
menu:write- Ausverkauft-Liste: ein Gericht aus dem Verkauf nehmen oder zurückholen
menu:manage- Menü bearbeiten: Kategorien, Gerichte, Preise, Portionen und Reihenfolge
orders:read- Bestellungen: Liste und Details, ohne Kontaktdaten des Gastes
orders:write- Küchen- und Ausgabestatus
orders:create- Neue Bestellungen mit Zahlung bei Erhalt
payments:read- Zahlungen und Erstattungen von Bestellungen, nur lesend
reservations:read- Reservierungen: Liste und Details
reservations:write- Neue Reservierung und Statuswechsel
customers:read- Name, Telefon, E-Mail und Adresse des Gastes in Bestellungen, Reservierungen und der Gästeliste
loyalty:write- Bonuspunkte eines Gastes gutschreiben und abziehen, nur zusammen mit dem Zugriff auf Gäste
reports:read- Tagesverkäufe für die Buchhaltung
Die erste Anfrage
Die API läuft auf dem Server des Lokals: Jeder Vitrina-Kunde hat einen eigenen Server und eine eigene Domain. Der Schlüssel steht im Header Authorization: Bearer vit_live_…; die Antwort ist JSON, immer im selben Umschlag: Daten, Metadaten und ein Fehler mit Code und Text in der Sprache der Anfrage.
curl https://api.example.com/api/open/v1/ping \
-H "Authorization: Bearer vit_live_…"{
"data": {
"ok": true,
"brand": "my-bistro",
"apiVersion": "2026-10-13",
"serverTime": "2026-10-13T09:30:00.000Z",
"clientName": "POS integration",
"scopes": ["menu:read", "orders:read", "orders:write"],
"cafeIds": []
},
"meta": null,
"error": null
}Webhooks
Webhook-Adressen legt der Inhaber im selben Bereich an und wählt für jede, welche Ereignisse sie erhält. Jede Anfrage ist signiert: Der Header Vitrina-Signature enthält den Sendezeitpunkt und einen HMAC-SHA256 über Zeitpunkt und Anfragetext, berechnet mit dem Geheimnis der Adresse. Namen und Kontaktdaten der Gäste enthalten die Ereignisse nur für Adressen mit aktivierter Option „Gastkontakte senden“.
Ereignisse
order.created- Neue Bestellung
order.status_changed- Bestellstatus geändert
order.paid- Bestellung bezahlt
order.cancelled- Bestellung storniert
order.refunded- Dem Gast wurden Geld oder Bonuspunkte erstattet
order.delivery_updated- Kurier zugewiesen oder abgezogen, Bestellung abgeholt oder zugestellt
reservation.created- Neue Reservierung
reservation.status_changed- Reservierungsstatus geändert
menu.availability_changed- Gericht aus dem Verkauf genommen oder zurückgeholt
menu.changed- Menü geändert: Kategorien, Gerichte, Preise oder Reihenfolge
import { createHmac, timingSafeEqual } from 'node:crypto'
const TOLERANCE_SECONDS = 300
export function isFromVitrina(rawBody, header, secret) {
const parts = header.split(',').map((part) => part.trim().split('='))
const t = parts.find(([name]) => name === 't')?.[1] ?? ''
const age = Math.abs(Date.now() / 1000 - Number(t))
if (!/^\d+$/.test(t) || age > TOLERANCE_SECONDS) return false
const hmac = createHmac('sha256', secret).update(`${t}.${rawBody}`)
const want = Buffer.from(hmac.digest('hex'))
return parts
.filter(([name]) => name === 'v1')
.map(([, value]) => Buffer.from(value ?? ''))
.some((got) => got.length === want.length && timingSafeEqual(got, want))
}Die Signatur gilt für den rohen Anfragetext, vor dem Parsen des JSON. Verwerfen Sie Signaturen, die älter als 5 Minuten sind; eine wiederholte Zustellung desselben Ereignisses trägt dieselbe Vitrina-Event-Id; daran erkennen Sie Duplikate.
Limits und Zuverlässigkeit
- 600 Anfragen pro Minute und Schlüssel, Spitzen bis 60 auf einmal; über dem Limit gibt es die Antwort 429 mit dem Header
Retry-After - Header
Idempotency-Keybei POST, PUT und PATCH: Eine Wiederholung mit demselben Schlüssel innerhalb von 24 Stunden liefert die erste Antwort, statt ein Duplikat anzulegen; für neue Bestellungen und Bonuspunkte ist er Pflicht - Listen kommen seitenweise: limit bis 200 und offset, in der Antwort die Gesamtzahl
- Antwortet Ihr Server nicht innerhalb von 10 Sekunden, senden wir das Ereignis mit wachsender Pause erneut: 8 Versuche über fast zwei Tage
- Eine Adresse, die 20 Zustellungen in Folge nicht annimmt, wird automatisch deaktiviert; das Zustellprotokoll wird 30 Tage aufbewahrt, und jedes Ereignis darin lässt sich erneut senden
Versionen
Die Version steht in der Adresse: /api/open/v1. Inkompatible Änderungen erscheinen nur als neue Version neben der alten, und die alte antwortet, solange sie genutzt wird. Das Revisionsdatum der Schnittstelle steht im Feld apiVersion jedes Ereignisses, derzeit 2026-10-13.
Vollständige Referenz
Alle Anfragen, Antworten und Fehlercodes stehen in der OpenAPI-Spezifikation auf dem Server des Lokals: die Seite /api/open/v1/docs und die Datei /api/open/v1/openapi.json für Client-Generatoren.
Für Integratoren
Sie entwickeln eine Integration für mehrere Lokale, etwa eine Kasse, einen Lieferdienst oder eine Buchhaltung? Schreiben Sie uns: Wir geben Ihnen einen Testzugang und helfen bei der ersten Anbindung.
Was es kostet
API und Webhooks sind in den Tarifen „Komplett“ und „Kette“ enthalten. Für „Start“ und „Restaurant“ auf Anfrage.