API for developers
The Vitrina open API: menu, orders, reservations, guests and sales for your POS, kitchen display, CRM or accounting. REST and JSON, scoped API keys, signed webhooks.
What you can do
- Menu: categories, dishes, prices and availability per location, plus the sold-out list: take a dish off sale or bring it back
- Menu editing: categories and dishes, names and descriptions in your guests’ languages, prices, portions, modifiers, order and visibility
- Orders: a filtered list, items and totals, kitchen and handover statuses (accepted, cooking, ready, handed over)
- New orders from a call centre, a kiosk or another website, with the same prices and delivery rules as on your own site; the POS and the kitchen see them at once, and the guest pays on receipt
- Delivery: who is bringing the order (the courier’s first name only), when it was picked up and when it was delivered: on the order itself and as an event
- Payments and refunds of every order for reconciliation, read-only
- Reservations: the list, new bookings and status changes (confirm, decline, the guest arrived or did not show up)
- Guests: profiles and contacts, only with a separate permission
- Guest points: credit or debit them with a reason, with a separate permission; the balance never goes negative, and every operation is logged
- Daily sales for accounting: orders, revenue, discounts, refunds and tips, by payment method and channel
- Locations: addresses, contacts and opening hours
- Events (a new order, a status change, a payment, a cancellation, a refund, a delivery update, a new booking, the sold-out list and menu changes) as a webhook to your server
The API cannot take payments, issue refunds or cancel orders: only the venue itself moves guests’ money. That is why guests pay for API orders on receipt.
Access and permissions
The venue owner creates a key in the admin panel, under “API & webhooks”: names the integration and picks its permissions and locations. The key is shown once (only its fingerprint stays in the database) and can be revoked at any time. Guests’ names, phone numbers and addresses are visible to the integration only with the customers:read permission.
Key permissions
locations:read- Locations: addresses, contacts and opening hours
menu:read- Menu, prices and dish availability
menu:write- Sold-out list: take a dish off sale or bring it back
menu:manage- Menu editing: categories, dishes, prices, portions and order
orders:read- Orders: list and details, without guest contacts
orders:write- Kitchen and handover statuses
orders:create- New orders paid on receipt
payments:read- Order payments and refunds, read-only
reservations:read- Reservations: list and details
reservations:write- New bookings and status changes
customers:read- Guest name, phone, email and address in orders, reservations and the guest list
loyalty:write- Crediting and debiting guest points, only together with guest access
reports:read- Daily sales for accounting
Your first request
The API runs on the venue’s own server: every Vitrina client has its own server and domain. Pass the key in the Authorization: Bearer vit_live_… header; every response is JSON in the same envelope: data, metadata and an error with a code and a message in the language of the request.
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
The owner adds webhook URLs in the same section of the admin panel and picks which events go to each one. Every request is signed: the Vitrina-Signature header carries the send time and an HMAC-SHA256 of the time and the request body, computed with the endpoint’s secret. Guest names and contact details go only to endpoints with “Send guest contacts” switched on.
Events
order.created- New order
order.status_changed- Order status changed
order.paid- Order paid
order.cancelled- Order cancelled
order.refunded- Money or points were returned to the guest
order.delivery_updated- A courier was assigned or removed, the order was picked up or delivered
reservation.created- New reservation
reservation.status_changed- Reservation status changed
menu.availability_changed- A dish was taken off sale or brought back
menu.changed- The menu changed: categories, dishes, prices or order
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))
}The signature covers the raw request body, before JSON parsing. Reject signatures older than 5 minutes; a repeated delivery of the same event carries the same Vitrina-Event-Id; use it to drop duplicates.
Limits and reliability
- 600 requests a minute per key, bursts of up to 60 at once; above the limit you get a 429 response with a
Retry-Afterheader - An
Idempotency-Keyheader on POST, PUT and PATCH: a retry with the same key within 24 hours returns the first response instead of creating a duplicate; it is mandatory when creating orders and adjusting points - Lists come in pages: limit up to 200 and offset, with the total count in the response
- If your server does not answer within 10 seconds, we resend the event with a growing pause: 8 attempts over almost two days
- An endpoint that fails 20 deliveries in a row is switched off automatically; the delivery log is kept for 30 days, and any event in it can be sent again
Versions
The version is in the URL: /api/open/v1. Breaking changes ship only as a new version next to the old one, and the old one keeps answering while it is in use. The contract revision date is in the apiVersion field of every event; currently it is 2026-10-13.
Full reference
Every request, response and error code is in the OpenAPI specification on the venue’s server: the /api/open/v1/docs page and the /api/open/v1/openapi.json file for client generators.
For integrators
Building an integration for several venues, such as a POS, a delivery service or accounting software? Write to us: we will give you test access and help with the first connection.
Pricing
The API and webhooks are included in the “Full” and “Chain” plans. For “Start” and “Restaurant”, on request.