Zum Hauptinhalt springen
Vitrina

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.

Anfrage
curl https://api.example.com/api/open/v1/ping \
  -H "Authorization: Bearer vit_live_…"
Antwort
{
  "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
Signatur prüfen in Node.js
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-Key bei 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.

Tarife vergleichen