Salt la conținutul principal
Vitrina

API pentru dezvoltatori

API-⁠ul deschis Vitrina: meniu, comenzi, rezervări, oaspeți și vânzări pentru POS-⁠ul, ecranul din bucătărie, CRM-⁠ul sau contabilitatea ta. REST și JSON, chei cu permisiuni, webhookuri semnate.

Ce poți face

  • Meniu: categorii, preparate, prețuri și disponibilitate pe locații, plus produsele epuizate: scoți un preparat de la vânzare sau îl readuci
  • Editarea meniului: categorii și preparate, denumiri și descrieri în limbile oaspeților, prețuri, porții, modificatori, ordine și vizibilitate
  • Comenzi: listă cu filtre, produse și sume, stările din bucătărie și de predare (acceptată, în preparare, gata, predată)
  • Comenzi noi din call center, de la un chioșc sau de pe alt site, cu aceleași prețuri și reguli de livrare ca pe site-⁠ul tău; POS-⁠ul și bucătăria le văd imediat, iar oaspetele plătește la primire
  • Livrare: cine duce comanda (doar prenumele curierului), când a ridicat-⁠o și când a livrat-⁠o: în comandă și ca eveniment
  • Plățile și rambursările fiecărei comenzi pentru reconciliere, doar citire
  • Rezervări: listă, rezervare nouă și schimbarea stării (confirmare, refuz, oaspetele a venit sau nu a venit)
  • Oaspeți: profiluri și date de contact, doar cu o permisiune separată
  • Punctele de fidelitate ale oaspeților: le adaugi sau le scazi cu un motiv, cu o permisiune separată; soldul nu ajunge pe minus, iar fiecare operațiune intră în jurnal
  • Vânzări pe zile pentru contabilitate: comenzi, încasări, reduceri, rambursări și bacșișuri, pe metode de plată și canale
  • Locații: adrese, contacte și program
  • Evenimente (comandă nouă, schimbare de stare, plată, anulare, rambursare, livrare, rezervare nouă, produse epuizate și modificări de meniu) prin webhook pe serverul tău

API-⁠ul nu încasează plăți, nu face rambursări și nu anulează comenzi: banii oaspeților îi mișcă doar localul însuși. De aceea, comenzile din API oaspetele le plătește la primire.

Acces și permisiuni

Cheia o creează proprietarul localului în panoul de administrare, în secțiunea „API și webhookuri”: dă un nume integrării și alege permisiunile și locațiile. Cheia se afișează o singură dată (în baza de date rămâne doar amprenta ei) și poate fi revocată oricând. Numele, telefoanele și adresele oaspeților integrarea le vede doar cu permisiunea customers:read.

Permisiunile cheii

locations:read
Locații: adrese, contacte și program
menu:read
Meniu, prețuri și disponibilitatea preparatelor
menu:write
Produse epuizate: scoți un preparat de la vânzare sau îl readuci
menu:manage
Editarea meniului: categorii, preparate, prețuri, porții și ordine
orders:read
Comenzi: listă și detalii, fără datele de contact ale oaspetelui
orders:write
Stările din bucătărie și de predare
orders:create
Comenzi noi cu plata la primire
payments:read
Plățile și rambursările comenzilor, doar citire
reservations:read
Rezervări: listă și detalii
reservations:write
Rezervare nouă și schimbarea stării ei
customers:read
Numele, telefonul, e-mailul și adresa oaspetelui în comenzi, rezervări și lista de oaspeți
loyalty:write
Adăugarea și scăderea punctelor de fidelitate ale oaspetelui, doar împreună cu accesul la oaspeți
reports:read
Vânzări pe zile pentru contabilitate

Prima cerere

API-⁠ul rulează pe serverul localului: fiecare client Vitrina are propriul server și propriul domeniu. Cheia se trimite în antetul Authorization: Bearer vit_live_…, iar răspunsul e JSON mereu în același plic: date, câmpuri tehnice și o eroare cu cod și mesaj în limba cererii.

Cerere
curl https://api.example.com/api/open/v1/ping \
  -H "Authorization: Bearer vit_live_…"
Răspuns
{
  "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
}

Webhookuri

Adresele pentru evenimente le adaugă proprietarul în aceeași secțiune a panoului și alege pentru fiecare ce evenimente primește. Fiecare cerere e semnată: antetul Vitrina-Signature conține momentul trimiterii și un HMAC-SHA256 al momentului și al corpului cererii, calculat cu secretul adresei. Numele și datele de contact ale oaspeților ajung în evenimente doar pe adresele cu opțiunea „Trimite datele de contact ale oaspetelui” bifată.

Evenimente

order.created
Comandă nouă
order.status_changed
S-⁠a schimbat starea comenzii
order.paid
Comandă plătită
order.cancelled
Comandă anulată
order.refunded
Oaspetelui i s-au returnat banii sau punctele
order.delivery_updated
Un curier a fost alocat sau retras, comanda a fost ridicată sau livrată
reservation.created
Rezervare nouă
reservation.status_changed
S-⁠a schimbat starea rezervării
menu.availability_changed
Un preparat a fost scos de la vânzare sau readus
menu.changed
S-⁠a schimbat meniul: categorii, preparate, prețuri sau ordine
Verificarea semnăturii în 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))
}

Semnătura se calculează din corpul brut al cererii, înainte de parsarea JSON. Respinge semnăturile mai vechi de 5 min; o livrare repetată a aceluiași eveniment are același Vitrina-Event-Id; după el elimini duplicatele.

Limite și fiabilitate

  • 600 de cereri pe minut pentru fiecare cheie, în vârf până la 60 deodată; peste limită primești răspunsul 429 și antetul Retry-After
  • Antetul Idempotency-Key la POST, PUT și PATCH: o repetare cu aceeași cheie în 24 h întoarce primul răspuns în loc să creeze un duplicat; pentru comenzi noi și puncte de fidelitate este obligatoriu
  • Listele vin pe pagini: limit până la 200 și offset, iar răspunsul conține numărul total
  • Dacă serverul tău nu răspunde în 10 s, retrimitem evenimentul cu pauze tot mai lungi: 8 încercări în aproape două zile
  • O adresă care nu a acceptat 20 de livrări la rând se dezactivează singură; jurnalul livrărilor se păstrează 30 de zile, iar orice eveniment din el poate fi retrimis

Versiuni

Versiunea e în adresă: /api/open/v1. Schimbările incompatibile apar doar ca versiune nouă lângă cea veche, iar cea veche răspunde cât timp e folosită. Data reviziei interfeței e în câmpul apiVersion al fiecărui eveniment, acum 2026-10-13.

Descriere completă

Toate cererile, răspunsurile și codurile de eroare sunt în specificația OpenAPI de pe serverul localului: pagina /api/open/v1/docs și fișierul /api/open/v1/openapi.json pentru generatoarele de clienți.

Pentru integratori

Construiești o integrare pentru mai multe localuri, de exemplu POS, serviciu de livrare sau contabilitate? Scrie-⁠ne: îți dăm acces de test și te ajutăm cu prima conectare.

Cât costă

API-⁠ul și webhookurile sunt incluse în pachetele „Complet” și „Lanț”. Pentru „Start” și „Restaurant”, la cerere.

Compară pachetele