HorecaPOS manual
This manual comes in three parts: first for the staff (waiters), then for the manager and finally for the administrator. Each part builds on the previous one: a manager can do everything the waiters can, and the administrator can do everything.
What your role is allowed to do is set by the administrator in Settings → Permissions. If you don't see a button, your role doesn't have permission for it (yet).
This manual is also in the POS: tap the © button at the bottom right of any screen and choose Manual, or open http://<kassa-pc>:3000/handleiding. See also the introduction and the API documentation.
Part 1 · Staff
Getting started
Signing in. Open the POS on the till, tablet or phone and enter your PIN (4 to 8 digits). You will then see the floor plan.
Opening a table. Tap a table. A free table gets a new order; at an occupied table you continue with the existing order. At the top you switch between rooms (for example Dining room and Terrace). For the counter use Quick sale, for takeaway orders Takeaway.
Ordering. Choose a category and tap the products. They appear on the receipt on the left. Optionally choose the course first (1 = straight away, 2 and 3 wait until you call them away). Tap Send order: the kitchen tickets then go to the kitchen and the bar. As long as you haven't tapped Send order, you can simply remove lines.
Checking out. Tap Checkout, choose Card / Bancontact, Cash or Gift card, optionally a tip, and confirm. With card payments the payment starts automatically on the card terminal. The receipt is printed; you can also email it.
Logging out. Log out when you are done, so nobody else works under your name. After 8 hours you are logged out automatically.
No internet? The POS simply keeps working. If the top bar shows No internet · card manually, enter the amount on the card terminal itself and choose Already paid on the terminal in the checkout screen.
Several groups at one table
Several groups can sit at one table, each with their own bill and their own receipt.
- Tap a table: free = new order; one group = straight to that group; several groups = choose first, or + New group (the name may be left empty).
- At the top of the order screen is the group bar: switch between groups, + Group, Group name (e.g. "Smith") and Split / move.
- Split / move: choose per line how many go along (e.g. 1 of 3× Lager) and to which group, or create a new group. This lets you move something that is on the wrong bill, or split afterwards so "everyone pays their own share". If a group becomes empty, it disappears.
- Several parts at once: with + Another part you set a part aside and choose the next one (e.g. fish and a Dry Martini to table 2, the rest to table 35). A part can also go to + Other table (as a new group there). With Move everything goes in one go. ½ splits a line in half, even a half bottle (0,667 becomes 2 × 0,3335).
- Merge: everything from one or more other tables (or groups at this table) onto this bill, in one go.
- Belgium: splitting or merging in one go is a single table change in the black box, as the FPS Finance requires (UC242, UC251, UC252, UC4119bis). If something is cancelled after ordering, or a discount is given on a line already ordered, it goes with the next message for that table (order, provisional bill, table change), otherwise with the sale: the old line negative and the new one positive (UC226, UC4102, UC4104, UC4107, UC4110).
- On the table screen an orange dot shows how many groups there are; the amount is the total of all groups.
- The receipt and kitchen ticket show "Table 5 - group 2" or "Table 5 - Smith".
Split the bill at checkout
Checkout works as always: All at once. In the checkout screen the bill can now also be split, with the buttons below Back and Checkout (so they always stay in view, without swiping):
- Split equally: use − and + to choose how many people (by default the number of guests, or 2 if the POS does not track guests). The screen shows the amount per person; everyone pays their share by card, cash or gift card (with a tip if they like). After each share it counts down ("3 people left"); the last person pays exactly the rest.
- Custom amount: someone pays a fixed amount (e.g. € 20); the rest stays open.
- By product…: opens Split / move to put products on a separate bill and check that out separately (as above).
A partial payment only records the payment; the bill stays open and the order screen shows "already paid … · still open …". The receipt (with all payments on it) comes with the last payment, as with a normal checkout. Card payments via the integration are for exactly the partial amount. Once part has been paid, lines can no longer be moved to another group and no more discounts can be added; removing is only possible if enough is still open. Every partial payment is logged.
Quick sale and takeaway (without a table)
At the top right of the table screen are Quick sale and Takeaway. Both immediately open an order without a table. Quick sale is a sale at the counter (eat-in VAT); Takeaway uses each product's takeaway VAT rate. With "Customer name" you add a name; it appears on the receipt ("Takeaway – Smith") and at the top of the kitchen ticket. Open orders without a table are listed under the room buttons ("No table: Takeaway #12 – Smith"), so you can find them again. If you go back without selling anything, the empty order disappears automatically.
Both buttons can be switched on or off per venue in Settings → Business, directly below the light/dark theme (on by default). Off = button hidden; orders without a table that are already open remain visible.
Delivery and time slots
Orders you take yourself at the till, for example by phone or at the counter, with the same rules as the webshop: delivery areas and a maximum number of orders per time slot. Turn on under Settings → Business → Delivery and time slots, directly below the Quick sale and Takeaway buttons (off by default).
- Delivery button on the table screen (next to Takeaway): enter name, phone and address (with Quick address entry on: look up postcode and house number). The till finds the delivery area and shows the delivery charge, the minimum and "free from". If the address is outside the areas, delivery is not possible.
- Delivery areas: by postcode (ranges and individual postcodes, e.g.
5000-5049, 5051, 5052 AB), within a radius in km from the business (as the crow flies) or an area on the map that you draw yourself. Radius and area only work with Dutch addresses (location via PDOK). Per area: delivery charge, minimum, free from and extra minutes; the first matching area from the top applies, so the types can be combined (e.g. first a few postcodes, then an area, then a radius for the rest). No areas set = deliver everywhere, with no charge or minimum. You set up the webshop's areas separately (webshop management). - Area on the map: for a delivery area, choose the type Area on the map and then Draw on the map. Click on the map to place points (at least 3); drag a point to move it, click a point to remove it, and drag the dot halfway along an edge to add a point in between. The map also shows the radius areas and the business. The map tiles come from OpenStreetMap, so the map needs an internet connection; delivery itself does not (except for looking up the address). If the address cannot be looked up, the POS says so instead of "outside the delivery areas".
- Delivery charges appear as a "Delivery charge" line on the order and are recalculated after every change (free from, no products = no charge), as long as nothing has been paid yet. Below the minimum checkout is not possible; the order screen shows how much more is needed, with the button Takeaway instead (delivery charge and minimum no longer apply).
- Time: As soon as possible (now + delivery time, plus the area's extra minutes) or a time slot today. If opening hours are set for Thuisbezorgd, they apply here too.
- Maximum per time slot (0 = no maximum; time slot 5 to 60 minutes): for Takeaway and Delivery combined; webshop orders in the till count too. If a maximum is set, Takeaway also asks for a time and full time slots cannot be selected. Two tills going for the last spot at the same time: one gets it.
- The kitchen ticket shows address, name, phone and time; in "Without table" and at the top of the kitchen ticket e.g. "Delivery – 18:30 Smith".
Extensions (all off by default; without these settings it works exactly as above):
- Own opening hours for takeaway and delivery (per weekday, e.g.
16:00-21:00or11:30-14:00, 17:00-22:00; past midnight is allowed:17:00-01:00; empty = closed that day). Off = as before (the times at Thuisbezorgd, if any, otherwise the whole day). - Closed days (e.g.
25-12-2026, 26-12-2026): no takeaway or delivery on those days. - Order ahead: 0 (today only, as before) to 14 days. In the Delivery/Takeaway window you then choose the day first; a later day is printed on the kitchen ticket before the time.
- Busy: this many extra minutes for "as soon as possible" (till and webshop). Can also be set quickly with the Webshop button in the top bar.
- Belgian addresses (postcode of 4 digits): with a radius or an area on the map, the till looks up the location via OpenStreetMap (Nominatim; street and town required).
- The webshop follows the till: the till leads. The webshop then uses the till's delivery areas, delivery and takeaway time, time slot, maximum per time slot, opening hours (if set here), closed days and days ahead, and counts the orders taken at the till in the time slot. Off = the webshop has its own settings (webshop management), as before. Turning takeaway/delivery on or off stays with the webshop.
Code: lib/bezorgen.ts, routes/bezorgen.ts, BezorgDialoog.tsx, BezorgInstellingen.tsx, BezorgKaart.tsx and lib/kaart.ts (the map, without an extra package; the same code is in the webshop as public/kaart.js).
Telephony: recognise the customer on a phone order
Settings → Telephony (off by default; switching it off keeps everything). Two separate switches:
- Look up customer by phone number for delivery and takeaway: type the number in the delivery screen and the POS shows the customer with their address and previous orders; Copy details fills in the name, email and address. Also works without a phone system.
- Caller ID: when a customer calls, the phone system (or the desk phone, the FRITZ!Box, the modem or the Android phone) reports the number. A notification appears on the screens showing who is calling: name, address, the latest orders (with the dishes and the amount, also from the webshop, Thuisbezorgd and the delivery platforms), the total and a reservation. Take delivery order or Take takeaway order opens the delivery screen with everything filled in (with Delivery and time slots on); the order is linked to the call and the notification disappears on all screens. Button 📞 in the top bar: the calls of the last 24 hours. Can be turned off per screen (Show notifications on this screen).
The search covers the loyalty card, the POS delivery and takeaway orders, the webshop, Thuisbezorgd, the delivery platforms and the reservations. Numbers are normalised (+31 6 1234 5678, 0031612345678 and 06-12345678 are the same; Belgian numbers too).
How the number comes in (more at once is possible; the same call counts once):
| Source | For | Set-up |
|---|---|---|
| Webhook / action URL | 3CX (CRM integration), Aircall, Voys / VoIPGRID, Yeastar P-Series, desk phones with an action URL for an incoming call (Fanvil, Grandstream, Mitel 6800/6900, Snom, Yealink: works with any phone system and provider), integration services (Zapier, Make, n8n, Power Automate) | the address from Settings → Telephony (/api/telefonie/oproep?sleutel=...&nummer=...), GET or POST, JSON, form or query; also via the portal: https://<portaal>/telefonie/<kassa-id>/oproep?sleutel=... |
| Asterisk (AMI) | Asterisk, FreePBX, Issabel, VitalPBX, Grandstream UCM | address, port (5038; Grandstream UCM 7777), AMI user and password (permissions call) |
| FRITZ!Box | FRITZ!Box with telephony | address (fritz.box) and port 1012; turn on the call monitor once with #96*5* |
| USB caller ID modem | analogue landline with caller ID display | serial port (COM3, /dev/ttyACM0), baud and init command (default AT+VCID=1) |
| Android phone | the built-in phone of a business Android phone | HorecaPOS app on that phone, Settings → Telephony → Pair this phone (Android 10+: choose the app as the caller ID app) |
The response contains the caller, also as contact (firstname, lastname, phone, email, address) for a 3CX CRM template. Outgoing and internal calls are not shown; Only these lines limits it to certain lines or desk phones. Calls are deleted after the retention period (default 30 days, GDPR). Test call simulates a number calling.
Code: apps/pos-server/src/lib/telefonie.ts, routes/telefonie.ts, packages/shared/src/telefonie.ts; screens Telefonie.tsx, BezorgDialoog.tsx; Android android-app/native/java/Beller*.java. Log: Telephony.
Own drivers: runs, cash handover and track & trace
For businesses with their own drivers. Turn it on under Settings → Business → Delivery → Own drivers (off by default). The driver does not need an app: they use a page in the browser on their own phone (if they prefer, they can use the Optimum Bezorger app: see Driver app below).
Creating a run. The till has a Runs button (showing the number of deliveries still to go out plus the runs that are on the way).
- Under Ready for delivery, tick the orders that are going along. These are the delivery orders from the till, the webshop and Thuisbezorgd (only own delivery; not those with a Thuisbezorgd driver).
- Choose the driver (a staff member) and the float they take along (by default the amount from the setting), and tap Create run.
- A QR code appears. The driver scans it with their own phone and sees, per address, the name, the address with a Route button (navigation), Call, the note, the requested time and what to collect. There is a change calculator (customer gives € 50 → change € 31,50). No login is needed. Only share the link with the driver: anyone who has it can see the addresses on this run. QR code for the driver creates a new link; the old one then stops working.
- Tap Depart when the driver leaves. The float is taken from the drawer (cash out, with the reason). The customer is told the order is on the way:
- for an order from the till by text message and/or email, if Messages to the customer is on (see Delivery and time slots);
- for the webshop as set up in the webshop (email, text message or push notification);
- for Thuisbezorgd via Thuisbezorgd.
If the run has not left yet, it can still be cancelled.
- On the road the driver taps, per address, Delivered, cash, Delivered, card (their own card terminal) or Delivered (already paid). The till sees this immediately. If the driver cannot report it, it can also be done in the till. Back at the business, the driver taps I'm back at the restaurant.
Cash handover. After the run, tap Checkout (permission Manage cash drawer):
- For each order, choose cash, card at the door, already paid or not delivered (returned). Whatever the driver reported is already filled in.
- The till settles every order with an outstanding amount, without a new receipt (the customer already has it; you can reprint under Receipts). An order that was not delivered is taken off the run and stays open, so it can go on a later run.
- You see what is expected: the float plus the cash received. Enter what the driver hands in, or count it by note and coin (Count by note and coin). The till shows whether it is correct, or how much is over or short.
- The float goes back into the drawer (cash in). The difference is shown with the run and in the log, and also comes back as a cash difference in the Z report.
Track & trace (turned on separately in the setting). When the order is on the way, the customer gets a link to a tracking page on the portal. The link is in the text message or email, and in the webshop on the status page (Track your driver). The tracking page shows:
- whether the order is being prepared, is on the way or has been delivered;
- the expected time: from the driver's location via the addresses that come first, otherwise the requested time;
- how many addresses are still ahead (without showing other addresses);
- with The driver live on the map, also the driver, the business and the customer's own address on a map (OpenStreetMap). The driver turns on location sharing on their own phone (Share my location). The location is only sent while the page is open; the page keeps the screen on.
The pages appear in the phone's language (all portal languages). In the till you can see with each run when the location was last updated (with a link to the map).
Privacy. The portal keeps the data of a run (names, addresses, phone numbers, the location) only while the run is in progress. Everything is deleted when the run is settled, or otherwise after 24 hours. The customer only sees their own order. The driver's location is only visible during the run, and no longer once the driver is back.
Route planning (optional)
Turn it on under Settings → Business → Delivery → Route planning (off by default; works with own drivers). The Runs window then has a Suggest runs button. The POS combines the orders still waiting to go out into runs:
- orders that are close together and whose requested times fall within the time window (default 30 minutes) go together;
- up to the maximum number of addresses per run (default 4), as long as the run (out, all addresses and back to the business) takes no longer than the maximum (default 45 minutes);
- for each run the best order, the distance (km), the travel time there and back and, per address, the expected arrival if leaving now. If that is later than the requested time, it shows later than requested.
Use this run ticks those orders, in that order; choose the driver and tap Create run. For a run that has not left yet, Best order puts the addresses in the fastest order (also on the driver's phone). Each run shows the distance and the travel time.
Settings: addresses per run, maximum run duration, the time window, the courier's speed (bike ~15, scooter ~25, car ~35 km/h in town) and the minutes per address (parking, ringing the bell, payment; default 2). The manager may also set these numbers: in the Runs window with the Set up route planning button (permission Set up route planning, on by default for the manager; can be changed under Settings → Permissions). Switching route planning on or off and the routing service (address, API key) remain with the administrator.
Distance and travel time, chosen by the manager:
- Estimate (default): straight-line distance times 1.35 (detour factor) at the driver's speed. Works without internet and without an account.
- OSRM: routes by road via an OSRM server. Enter the address (
https://, orhttp://on your own network). The public demo server (https://router.project-osrm.org) is only for occasional use; for daily use, set up your own OSRM server or use a provider. - OpenRouteService: routes by road with your own API key (free to create at openrouteservice.org, with a daily limit). The address defaults to
https://api.openrouteservice.organd can point to your own server. The key stays on the POS; the screens only show that it has been filled in.
Test tries out the service. If the service fails, planning falls back to the estimate and says so. An address whose location is unknown (no valid postcode and house number) appears in the suggestion under no known location and is not planned. The configuration export includes the settings, but not the key.
Code: lib/ritplanning.ts.
Driver app (optional)
Turn it on under Settings → Business → Delivery → Driver app (off by default; works with own drivers and the management portal). Each driver then pairs their own phone once, instead of scanning a QR code for every run:
- Under Paired phones, choose the driver (a staff member), optionally the name of the phone, and tap Pair phone.
- A QR code appears. The driver scans it in the Optimum Bezorger app (Pair button), or with the phone's camera: the page then opens in the browser. It also works without the app and can be added to the home screen.
- The pairing stays valid until you revoke it; the phone then immediately stops seeing anything. A new pairing for the same staff member replaces the old one (for example with a new phone).
The app or page shows all of the driver's own runs (every run the till creates for this driver), with the same buttons as for a run: Route, Call, amount to collect with change calculator, Delivered and I'm back at the restaurant. Can be turned on separately:
- Pick up orders yourself: the driver sees the deliveries that still need a run, ticks what they are taking and taps Take along. The till creates the run (or adds them to it if that driver already has a run that has not left yet); the standard float goes along. Anything another driver already took can no longer be picked.
- Depart yourself: Depart in the app does the same as in the till (float from the drawer, customers are notified).
- Live map: under Runs there is a Map button showing the business, all drivers who are on duty and the addresses still to be delivered. The driver turns On duty on and off themselves. The app also passes on the location with the screen off (Android: a notification in the status bar while sharing is on); the web page only while it is open. Without this setting the location is only shared during a run with track & trace.
The Android app is available on Google Play and on the portal's download page (/download/). An iPhone version is ready but will only be released once there is an Apple developer account; until then iPhones use the web page. A run the driver picked up themselves shows picked up in the app by the driver.
Code: lib/bezorgersapp.ts, in the portal src/volgen.mjs and the app in the horecapos-bezorger repo.
The log records who created a run, dispatched it, marked it delivered and settled it, with the amounts. Turning it off: no Runs button; runs and settings are kept.
On the portal: /bezorger/<sleutel> and /volg/<code>. Code: lib/bezorgers.ts, routes/bezorgers.ts, Bezorgers.tsx and in the portal src/volgen.mjs.
Alert for long lead time
A takeaway or delivery order that is ready later than promised: the till spots it and alerts you, and can send the customer an apology straight away, optionally with a credit voucher. Switch it on under Settings → Business → Delivery → Alert for long lead time (off by default).
- Which orders: takeaway and delivery with a promised time, from the till (delivery and time slots), the webshop and Thuisbezorgd.nl / Takeaway.com.
- Late: still not ready or on the way this many minutes (default 10) after the promised time. Ready or on the way means: everything ready on the kitchen display, the status ready or on the way in the webshop or at Thuisbezorgd, the ✉ Ready / ✉ On the way message to the customer, or paid. The till checks every minute.
- Alert: Late button in the top bar with the count (with a sound for a new one), showing for each order the promised time and how many minutes late it is. An order disappears automatically once it is ready or on the way, or with Dealt with; below that are those from the last 24 hours, with when they were ready. Everything is recorded in the log.
- Webshop: the guest's status page shows that it is taking longer, with the new expected time.
- This is not possible with Thuisbezorgd (the customer belongs to Thuisbezorgd): only the alert there. You can use your own text;
{naam},{zaak},{code},{korting}and{geldig}are filled in. - Credit voucher (only with Discount codes on): with the apology, a personal discount code for the next order (e.g.
SORRY-7K4Q2M), an amount or percentage, single use, valid for a set number of days, at the till and in the webshop. The codes do not appear in the list under Discount codes. If sending fails, the code expires. Using the button in the till requires the Give discount permission. - Off: the alerts and the issued codes are kept (also in the backup); the setting is included in the configuration export.
Code: lib/telaat.ts, routes/telaat.ts, TeLaat.tsx and packages/shared/src/telaat.ts.
The Send order button: what it does and when you need it
Tapping a product and tapping Send order are two separate steps:
- Tapping puts the product on the bill straight away (in the list on the left) as new. Only you can see it: the kitchen and the bar don't know about it yet. A new line is a draft: you can still remove it or change the quantity or options, without a void.
- Send order sends all new lines in one go: the tickets go to the kitchen and bar printers (and the kitchen display), and the lines are then marked ordered. From then on they can only be removed with a Void (void permission). The button shows how many new lines are waiting, e.g. Send order (3); if there are no new lines, the button is greyed out.
Why two steps? At the table you take the whole order (drinks, starter, main course), adjust things if the guest changes their mind, and then send it to the kitchen in one go, with one ticket per station instead of one ticket per product. That way the kitchen can get started long before anyone pays.
What else happens when you tap Send order:
- Courses: course 1 goes to the kitchen straight away; courses 2, 3 and 4 are sent along as HOLD and the kitchen only starts when you call that course (see Courses).
- Rounds: each Send order is one round; that is what ↻ Another round works with.
- Stock is deducted and a dosed tap is released.
- All-you-can-eat: if it is too much, too early or too late for the package, the till first asks whether it is allowed anyway.
- Belgium (GKS 2.0): the lines are first sent to the black box as pro forma; if that fails, nothing goes to the kitchen and they stay new.
- No connection: the order is saved and goes to the kitchen as soon as the connection is back. Printer off: the order still goes through and the ticket goes into the print queue (see Kitchen printer off or no kitchen display).
You can also check out directly. If you tap Checkout while there are still new lines on the bill, the till sends them first automatically, so the kitchen and the bar always get their ticket. At the bar or for takeaway you don't need to tap Send order first: tap the items and go straight to Checkout. If the automatic send fails (no connection, all-you-can-eat rule, black box), the checkout screen stays closed and you see why.
Rather not print a ticket for the bar when you check out straight away? Under Settings → Business → Ordering and checkout, tick Direct checkout without order ticket. Then only what you send with Send order goes to the kitchen and bar; whatever you check out straight away gets no order ticket.
Large or small Checkout button
With the Large "Checkout" button checkbox ticked, the order screen shows a large Checkout button directly below the ordered products: wide, tall and with the amount on it, so it is quick to hit. If part of the bill has already been paid, the button shows the amount still open. The small button at the bottom next to Send order is then hidden.
With the large button, the buttons in the checkout screen are large too: Checkout (for Card, Gift card and the other payment methods) and, for Cash, Exact cash and Checkout are wide and tall, easy to hit, even with dirty fingers (for example at a butcher's). The payment methods are a bit larger and the tip buttons a bit smaller, so everything stays on screen.
On a new installation the checkbox is off: then the small button at the bottom next to Send order and a checkout screen with normal buttons. Prefer large? In Settings → Business, directly below light/dark theme, tick Large "Checkout" button. A till that was already in use keeps what it had. The choice applies to all tills and tablets of the business.
Mark a product as "sold out"
Anyone can long-press a product in the order screen (or right-click it) and choose Sold out. The product then turns grey and can no longer be ordered on any till. In the same way you restore it with Available again. Every change is logged. The administrator can still do this in Settings → Products too. The till server also refuses a product marked "sold out" ("Cola" is sold out), so also from a tablet that hadn't received the change yet or orders stored offline; that tablet then shows "Could not send".
Kitchen display (KDS)
Alongside (not instead of) the kitchen ticket printers, the kitchen or bar can use a display. On a tablet/PC in the kitchen open http://<kassaserver>:3000/keuken, sign in with a PIN and choose the station: these are the same names as the printers (kitchen, bar, ...), so the display shows exactly what would be on that kitchen ticket. "All" shows all stations.
- One ticket per order, oldest first, with table/takeaway, number and how long it has been waiting (orange after 10, red after 20 minutes).
- Courses are shown separately; a course that has not been called away yet is grey and marked "WAITING for call away". Voids are struck through.
- Tap a line to mark it ready, or Ready for the whole ticket. The waiting staff then see "Kitchen: Table 5 is ready" in the top bar. With Settings → Business → Kitchen display → Sound for staff (off by default) the till also beeps ("ding-dong", no sound file needed). The browser only allows sound after the first tap on the screen; turn the tablet's volume up.
- Recall shows what was marked ready in the last hour, so anything tapped away by mistake can be brought back.
The display updates itself instantly. Kitchen tickets still print as usual; if you don't use the display, you won't notice any difference.
Kitchen display: sending on, order and course
Settings → Printers → Kitchen display. Each part can be switched on separately and is off by default; switching off keeps everything.
- Sending on between stations, for example cold → hot → pass. For each station you set a fixed next station; the ticket then shows a → hot button (and always Send to… to choose another station). Only the open lines of that station go along. A station does not need a printer: enter stations such as pass under Stations without a printer. Ready (and the notification to the waiter) only comes at the last station. On "All", a line that has been sent on shows where it is now. Every step is shown on the line and in the log.
- Reordering: drag tickets (mouse) or move them with ◀ ▶ (touchscreen). The order applies per station and to all screens of that station; new tickets are added at the end.
- Next course from the kitchen display: a ticket with a waiting course shows Request course 2. The waiter then gets "Kitchen requests course 2 for Table 5" (with sound) and calls it away as usual; the kitchen display shows "Course 2 requested · n min" until the course has been called away. Or choose Call away: the kitchen display then calls away the course itself, with the work ticket "CALL AWAY COURSE 2", just like the button on the till.
Kitchen printer off or no kitchen display
The POS always keeps working, even if the kitchen or bar printer is off (or out of paper, or the cable is loose) and even without a kitchen display:
- Ordering always goes through. The lines are immediately set to ordered, the bill is correct and checkout works as normal. Printers are addressed simultaneously and each printer gets at most about 4 seconds: a printer that is off doesn't keep the others (or the waiting staff) waiting long.
- Print queue. A kitchen ticket that could not be printed goes into the print queue. The till server retries it every 30 seconds for fifteen minutes; as soon as the printer works again it comes out, with PRINTED LATER at the top. If a later ticket on that printer succeeds, the waiting tickets follow right after it.
- After fifteen minutes the automatic retrying stops; Reprint now is still possible then.
- Kitchen display. If the order is on the kitchen display, the kitchen sees it there even when the printer is off. If you don't use a kitchen display, you don't miss anything: the POS never waits for "Ready" from the kitchen.
- The queue is only kept in the till server's memory (it is empty after a restart).
- The same goes for the receipt: if it fails, the checkout has still been completed (the POS reports "printing failed") and you can print a copy later under Receipts.
Courses (starter, main course ...)
The course buttons are only shown when they are needed: as soon as there is a set menu (composite product) on the order, or when something is already in course 2 to 4. With ordinary products, such as a cola, you don't see them and everything goes straight to the kitchen. There is nothing to set.
Below the order list is Course 1 2 3 4. By default course 1 is selected and everything works as always: "Send order" sends everything to the kitchen straight away, without course headings on the kitchen ticket. If you choose course 2 (or higher) before tapping products, then:
- they do go to the kitchen on "Send order", under "-- Course 2 · WAITING for call away --", so the kitchen can prepare;
- the order list shows "Course 2 · waiting" with a Call away button;
- on Call away the kitchen gets a ticket " CALL AWAY COURSE 2 " with what needs to be made now.
Course 1 always goes straight away. If course 2 has already been called, a dish added later in course 2 also goes straight away.
Allergens per product
Off by default: allergens are then not shown anywhere. Switch on via Settings → Business → Enter and show allergens per product.
- Settings → Products: tick the 14 EU allergens for each product (gluten, crustaceans, eggs, fish, peanuts, soy, milk, nuts, celery, mustard, sesame seeds, sulphites, lupin, molluscs). In the product list the abbreviations appear after the name.
- Order screen: each product button shows the abbreviations in small print (e.g.
Gl Me), and the ⚠ Allergens button in the group bar shows the full allergens for each product in the selected category, with an explanation of the abbreviations. - Changes to allergens are logged (old → new). If the setting is off, previously entered allergens are kept.
All-you-can-eat
Off by default. Turn it on via Settings → Business → All-you-can-eat (administrator only). You create one or more packages, e.g. Fish, Meat and Sushi, each with:
- a name (appears on the receipt: "Fish adult", "Fish child");
- a price per adult and per child (including VAT) and the VAT rate (default NL
LAAG, BEB); - the dishes included (€ 0): whole categories and/or individual products (also from other categories, e.g. fries with both Fish and Meat);
- a time limit in minutes (0 = none);
- rounds: at most this many dishes per person per round (0 = unlimited) and at least this many minutes between two rounds (0 = none);
- a waste surcharge per item (0 = none).
Use ↑ ↓ to set the order. It matters when a dish belongs to several packages: it then counts for the top one the group has chosen. Delete removes a package for new tables; tables already running keep their price lines (fewer people is still possible there, more is not).
At the table:
- On the order screen, above the receipt, you'll find + All-you-can-eat. Choose the number of adults and children per package; mixing is allowed (e.g. 2× Fish and 2× Meat). The price is added as lines on the bill; these are not sent to the kitchen. The group's number of guests becomes the total taking part (if the POS tracks the number of guests).
- For each package the bar shows: people, time remaining (red when time is up), which round it is with the maximum, and how long until the next round. Included dishes are marked AYCE on the buttons and appear on the receipt with the AYCE label for € 0. Everything not included in a chosen package (drinks, desserts ...) is charged as usual.
- Send order: each "Send order" with free dishes counts as a round, per package (only the packages whose dishes are included). Items tapped offline and sent later are not blocked.
- Edit: adjust the numbers per package. Fewer people counts as a void ("void" permission). Setting a package to 0 (or Stop for everything) is possible as long as no dishes from that package are on the bill yet.
- Surcharge (only if a chosen package has a waste surcharge): choose the quantity (and the package, if there are several); "Waste surcharge × quantity" goes on the bill.
- Checkout, splitting, discounts and the receipt work as always: the package prices, the surcharge and the drinks are ordinary lines with their own VAT.
- If the administrator switches all-you-can-eat off while groups are in progress, newly tapped dishes cost the normal price again; whatever is already on the bill stays.
- In the webshop (optional, off by default): with Also when ordering at the table via the QR code (webshop), a guest ordering at a table with a package sees the dishes that belong to it as Included for € 0, with the status at the top (people, round, time). Each order is a round, with the same rules as Send order; too many, too early or too late is refused by the webshop straight away. The guest simply pays for drinks and other dishes; everything goes on the table's bill. Off = the webshop charges the normal prices, as before.
Gift cards
Two switches under Settings → Business → Gift cards:
- Gift card as payment method at checkout: on by default, as it always was. Off = the Gift card button is not shown at checkout (nor under Refund via for a return), and the till server refuses gift card payments.
- Sell gift cards with balance: off by default. On:
- The order screen shows the Gift card button: choose the amount (€ 10, 25, 50, 100 or another amount) and let the till create a code, or scan the code of a pre-printed card. The gift card goes on the bill as a line (VAT code BON: no revenue, no VAT, not sent to the kitchen). There you can also check the balance for a customer.
- After checkout the gift card is active and the receipt printer prints a gift card with the amount, the code and a QR code.
- Redeeming: at checkout choose Gift card and scan or type the code (the Balance button shows the balance). The amount is deducted from the balance. If the balance is lower than the bill, the whole balance is used as a partial payment and you pay the rest by card or cash. The balance may be used in parts.
- Leave the code empty = gift card without a code, as before (e.g. an old paper voucher).
- Report → Gift cards (Manage gift cards permission, by default manager and administrator): search by code, outstanding balance, history per gift card, block (lost/stolen) and correct balance with a reason. This is recorded in the log.
- Reports: gift cards sold do not count as revenue and are listed separately (Gift cards sold); the money received does appear under the payment methods. Whatever is paid with a gift card is normal revenue (with VAT) under the Gift card payment method.
- Accounting: sold gift cards are booked as credit and redeemed gift cards as debit to the Gift cards account (customer credit).
- A sold gift card can be returned via Receipts → Return as long as it has not been used yet (balance = value). After the return the gift card is revoked (balance 0, blocked; shown in the gift card's history). If it has already been (partly) used, set the balance to 0 under Report → Gift cards and refund the remainder separately. A discount on a gift card is not possible.
Top-up credit (optional)
For clubs, sports canteens, youth centres and events: a gift card with balance becomes a top-up pass. Switch it on under Settings → Business → Top-up credit, below the gift cards (off by default; only works if Sell gift cards with balance is on).
- Pass or wristband: sell a gift card with Pre-printed card and scan the pass (an NFC/RFID reader that works as a keyboard, or a barcode). The pass number is then the code; the guest pays with it as with a gift card.
- Top up: order screen → Gift card → Top up credit: scan the gift card or pass and enter the amount. It goes on the bill as a line (VAT code BON: no revenue, no VAT, just like a sold gift card) and is added to the balance after checkout. The gift card's history shows Topped up.
- Maximum balance per gift card or pass (default € 500, can be set up to € 5,000).
- Refund remaining balance (checkbox, off by default; permission Manage cash drawer): after Check balance you see Refund remaining balance. The balance goes to € 0 and the amount appears as money out of the drawer on the X and Z report (Tegoed terugbetaald …).
- A top-up can be reversed via Receipts → Return as long as the balance is still at least that amount; the gift card or pass remains valid.
- Top up at the kiosk (optional): see Self-service kiosk.
Meal vouchers
Only for businesses in Belgium, off by default: Settings → Business → Checkout → Meal vouchers. Meal vouchers are an employee benefit: the employer loads them onto the employee's card (Edenred, Monizze or Pluxee). The guest pays with it on the normal card terminal; no connection with the issuers is needed.
- On: at checkout there is a Meal voucher button. Choose the issuer (only the issuers the business accepts) and let the guest hold the card against the card terminal, just like a card payment. Without a card terminal connection: the guest pays on the card terminal itself and you tap Checkout.
- No tip and no change with meal vouchers. If the balance is too low, the guest pays the rest another way (the bill stays open until everything is paid).
- Only for certain product groups (optional, e.g. food but no alcohol): then meal vouchers can cover at most the amount of those products on the bill. The checkout screen shows how much; the guest pays the rest another way.
- On the receipt: Meal voucher Pluxee (with the issuer after it).
- Z report and X report: a separate line per issuer (Meal voucher Edenred, … Monizze, … Pluxee).
- Accounting: a separate ledger account per issuer (Meal vouchers Pluxee (receivable) etc., by default 416100, 416200 and 416300), because the money comes from the issuer and not from the card terminal's bank.
- Required: an agreement with each issuer whose vouchers you accept, and a card terminal that accepts these cards (check this with your card terminal supplier).
Foreign currency
Cash payment in another currency, e.g. for British or American tourists, or Swiss francs in border regions. Off by default: Settings → Business → Checkout → Foreign currency. Add the currencies (CHF, CZK, DKK, GBP, HUF, NOK, PLN, SEK, TRY, USD) with a rate per currency: how many euros you charge for 1 unit (e.g. 1 GBP = € 1.15).
- Entered manually: a fixed rate; adjust it yourself when it changes.
- Live (ECB): the daily rate of the European Central Bank (reference rates, every working day around 16:00; free, no account needed). With a markup in percent (0-20) the rate is lowered by that much, so the business does not pay for the exchange itself. The POS fetches the rates itself when they are older than 6 hours; Update now fetches them immediately. Without internet the last rate stays.
- On: at checkout you see the Foreign currency button. Choose the currency; the POS shows how much it is in that currency. Enter what the guest gives: the POS converts it and gives the change in euros. If the guest wants nothing back, tick Change is tip: the change goes on the receipt as a tip, in Belgium in that currency (GKS 2.0, UC296).
- If the guest gives less than the full amount, it is a part; they pay the rest another way.
- On the receipt: the currency, the amount and the rate, and the change in euros.
- X and Z report: a separate line per currency (Foreign currency GBP, in euros), and under the cash drawer what is in the drawer in that currency. The change in euros is deducted from the money expected in the drawer; you count the foreign currency itself separately.
- Accounting: counts as cash, in euros.
Extra buttons for ordering and checkout
Buttons for things not every business needs. Everything is off by default; turn them on per button under Settings → Business → Ordering and checkout (permission Set up business, payments and printers). Off = the button appears nowhere in the POS and the POS server refuses the action. In the Netherlands everything works without a black box; in Belgium a button only works once that function has been tested with the black box (the button says so if that is not yet the case).
When opening a table:
- Track number of guests: the question "How many guests?" at a free table, the guests on the floor plan and in the order screen, and guests in the reports. See Number of guests.
When ordering (order screen, for whatever you tap next):
- Combine identical items (no button, on by default): tap the same product again (same options, not yet ordered) and the quantity goes up instead of adding a new line: 4 Cola on one line with the price times 4. − takes one off again, even if it has already been ordered (a void of one). With a note, seat or takeaway it stays a separate line; anything already ordered stays a separate line (a new round).
- − and + (before the price on every line): − takes one off, + adds one (same product, options and note; if Combine identical items is off, a new line instead). Not yet ordered and at 0: the line is removed. Already ordered: one off is a void, that line stays struck through (for the kitchen and the reports); one more becomes a new line that still has to be ordered. Tapping the price itself no longer removes anything. For a menu only −.
- Take away (eat in only): the guest takes this product away, e.g. a bottle of water or a dessert. That line gets the takeaway VAT rate (in Belgium label C), the rest of the bill the eat-in VAT rate. The receipt shows to go next to the line.
- Seat (at a table): tap through for seat 1, 2, 3 ...; the lines get that seat number (also on the kitchen ticket). In Belgium each line goes to the black box with the seat's cost centre (CHAIR, UC4123). One more tap after seat 12 = no seat again.
- Take back: the next product is added with -1, e.g. an empty bottle or cup (deposit). This only works for products with Returnable (deposit) (Settings → Products). If the whole bill is negative (only deposit returned, no sale), Checkout becomes a refund: cash back or by card (refunded on the terminal itself). In Belgium as a refund (REFUND, UC4108 and UC4114).
- Redeem SPV: the guest pays for a product or menu with a single purpose voucher (a voucher for exactly that product, e.g. "1 menu all-in"). Tap Redeem SPV and then the product on the receipt: it is added with -1 (same price and VAT, for a menu with its components), marked SPV. Not sent to the kitchen; it can simply be removed. You sell a voucher product in advance as a regular product; under Settings → Products tick SPV (voucher). In Belgium the line goes to the black box as VOUCHER at the sale (UC271).
- Deduct advance: see below.
- Open price (no button, per product): for a product with Open price the POS asks for the price, e.g. the dish of the day or an advance.
At checkout:
- Direct checkout without order ticket (not a button): by default Checkout first sends anything not yet ordered, so the kitchen and bar always get their ticket (see The Send order button: what it does and when you need it). On: whatever you check out straight away without tapping Send order first gets no order ticket, e.g. at the bar where you grab it yourself. Anything already ordered is unaffected.
- Pay separately (at a table, under Split the bill): choose what one guest pays now, even part of a line (½ for half a bottle). That becomes a separate part that you settle straight away; the rest stays on the bill, without splitting the bill first or moving it to another group. A percentage discount on the whole receipt is applied proportionally. Back without paying = everything back on the bill. In Belgium the sale stays at the table's location, without a table change (UC4103bis, UC4104).
- Guest left without paying (permission Close without payment, by default only manager and administrator): the bill is closed as a sale without payment, with a reason in the log. On the X and Z report and in the daily statement it appears as Unpaid (guest left); in the journal it goes to bad debt (default 4985 / 643000). In Belgium a sale without payment (UC4109).
Afterwards (Receipts):
- Correct price (permission Correct the price of a receipt, by default only manager and administrator): the price of a paid receipt was wrong, e.g. 50% discount instead of 5%. The POS creates a new receipt without a table with the lines of the old receipt reversed (negative, at what was paid then) and the same products again at the regular price. Apply the correct discount there and settle the difference (or refund if the new price is lower). The old receipt stays as it was; once per receipt, and not if something has already been returned. In Belgium the old lines are included as CORRECTION (UC4116).
Code: apps/pos-server/src/lib/kassaopties.ts, routes/kassaopties.ts; screen KassaOpties.tsx. Log: Setting changed, SPV redeemed, Correct receipt, Unpaid.
Deduct advance
An advance (deposit, e.g. for a party or a reservation) is sold as a regular product with Advance turned on (Settings → Products; always has an open price). Create one per VAT rate if the advance must be per rate (e.g. Advance food and Advance drinks), or one product if it is part of the quote. The guest pays the advance beforehand and gets a receipt.
Turn on: Settings → Business → Ordering and checkout → Deduct advance (off by default). At the final checkout, tap Deduct advance on the order screen and enter the receipt number of the advance. The POS adds the advance lines of that receipt to the bill with a negative quantity (same product, price and VAT). What has already been deducted cannot be deducted again. If the advance is more than the bill, the guest gets the difference back (refund). In Belgium the deducted lines go to the black box as a refund (REFUND) (UC4110, UC4111, UC4113). Log: Advance deducted.
Receipt by email
Off by default. Turn it on via Settings → Business → Receipt also by email.
SMTP_HOST=smtp.voorbeeld.nl
SMTP_PORT=587
SMTP_GEBRUIKER=kassa@voorbeeld.nl
SMTP_WACHTWOORD=...
SMTP_AFZENDER=bon@voorbeeld.nl
Restart the till after filling this in. Checkout then shows the field Also email the receipt (optional): leave empty = print only, as always; enter an email address = the same receipt (with VAT breakdown and fiscal lines) is also emailed to the guest, with the business name as sender.
- The email address is not stored; the log only shows "receipt N emailed to a***@domain.com" and whether it succeeded.
- If emailing fails (e.g. wrong login details), the receipt is still checked out and printed; the message tells you what went wrong.
- Not with a partial payment (splitting the bill): the receipt comes with the last payment, so enter the address there.
- Email afterwards: under Receipts each receipt has an Email button (Print a copy of a receipt permission). It emails the receipt marked COPY, just like a printed copy (registered as a copy in Belgium).
- No extra packages needed: the till talks to the mail server itself (STARTTLS on 587, TLS on 465).
Reservations
Turn it on under Settings → Business → Reservations (off by default). There you also set how many minutes beforehand a reserved table appears on the floor plan (default 60) and the default duration of a reservation (default 120 minutes).
- Reservations button in the top bar: overview per day (◀ ▶), with the number of reservations, guests and no-shows. + New reservation: name, phone, email, guests, date, time, duration, table (can be added later) and note. Reservations are made by staff; online booking is not available (yet).
- If the same table already has a reservation in that time slot, the till tells you; "Save anyway" is possible.
- Confirmation by email (checkbox, or later "Email") if there is an email address and a mail server (
SMTP_HOST, see Receipt by email). - On the floor plan a reserved free table is shown purple with "R 19:30 Jansen (4)". Tap it: "Jansen has arrived" opens the table with 4 guests and "Jansen" as group name; "Other guests" simply opens it.
- In the overview: Arrived (opens the table; without a table you choose one first), Edit, No-show, Cancel and Restore. Everything is recorded in the log.
- Bookings from online platforms: see Booking platforms below.
TheFork POS integration: table opens on arrival, bill sent back
With TheFork's POS API the till works together with TheFork Manager (off by default), in addition to fetching the bookings above. Switch it on under Settings → Booking platforms → TheFork POS integration; runs via the management portal.
- When you set a guest to Arrived or Seated in TheFork Manager, the table with the same name opens in the till, with the number of guests and a note: name, allergies and diet, prepayment, offer/discount and loyalty points (Yums). If that table already has an open order, it is linked. No table with that name: an alert, and you choose the table in Platforms.
- After payment the bill goes to TheFork (total and lines with name, product group, quantity and amount); TheFork then sets the booking to Left. With split payment, one bill with the total. If it fails, the till retries every quarter of an hour (for two days), or use Resend in Platforms.
- Pairing: the till shows a pairing code; enter it in TheFork Manager (Integrations → POS). The administrator enters the TheFork restaurant ID (Customer-id), or it is filled in automatically with the first order.
- Tick boxes: open table automatically, name, allergies and prepayment as a note, bill to TheFork.
- Requirement: Pin Voordeel has TheFork's API key (partners only) and has registered the till there as a POS (button in the management portal); TheFork puts the integration live after a test session.
TheFork documentation: https://docs.thefork.io/POS-API/introduction
Waiting list for walk-ins
For guests without a reservation who are waiting for a table. Turn it on under Settings → Business → Waiting list (walk-ins) (off by default). Only visible when SMS via CM.com is set up; otherwise the waiting list appears nowhere in the till (not even in the settings). Works separately from reservations: also when those are off. That is also where you set the text of the message (empty = "Hallo {naam}, uw tafel bij {zaak} is klaar. Wilt u zich melden bij de bediening?"; {naam}, {zaak} and {personen} are filled in).
- Waiting list button in the top bar, with the number of guests waiting (orange when someone is waiting). + Add to waiting list: name, phone (for the text), people, the quoted waiting time and a request (terrace, high chair).
- The list is in order of arrival, showing how long each guest has been waiting (red when it takes longer than quoted), with at the top the number of guests waiting, people and today's average waiting time.
- If the text fails, the reason is shown. Text again is possible.
- Seat: choose the table; the POS opens it with the number of guests (if the POS tracks the number of guests) and the name as group name (just like an arriving reservation).
- Gone (left or cancelled) and Restore. Below the list you see who was seated or left today, with how long they waited.
- Privacy: phone numbers are erased after a day; anyone still on the list after 12 hours is removed automatically. Adding, calling (with only the last 3 digits of the number) and seating are recorded in the log.
- Why not under Reservations? A reservation is for later (date, time, table in advance); the waiting list is for now (order, waiting time, text when the table is free). Hence a separate switch and button, with the same "open table" as for a reservation.
- Online on the waiting list (optional, off by default; only with the webshop): with Guests can also add themselves via the webshop, the webshop shows Waiting list (and there is a QR code for it at the door, in webshop management under Tables and QR). The guest enters name, phone, people and a request and sees their place live. In the till they appear in the list marked online; calling, seating and gone work as always, and the guest also sees it on their phone (they can cancel there too).
Loyalty card / points
Turn it on under Settings → Business → Loyalty card / points (off by default, then none of it is visible anywhere). There you also set: points per euro (0 = stamp cards only), after how many points a reward is given and how many euros discount that reward is worth.
- At the till, "+ Loyalty card" appears above the receipt: look up the customer by name or phone number, or create a new customer (name, optionally phone and email). The name and points balance then appear on the receipt.
- Redeeming: with enough points "Redeem 100 points: € 5 discount"; with a full stamp card "Free Coffee" (the coffee must be on the receipt). This becomes a discount line; anyone may remove it again.
- Points and stamps are only added and deducted at checkout: points on the amount after discount (excluding gift cards sold), stamps per item of a product with a stamp card (the free product does not count).
- On the receipt: earned, redeemed, balance and the progress of the stamp cards.
- Report → Customers (Manage loyalty card permission): search customers, edit details, correct points (with a reason), history, and delete (GDPR: name, phone and email removed; the history stays anonymous). At the bottom are the stamp cards per product (e.g. 10 coffees = 1 free).
- A return does not automatically reverse points earned; correct them if necessary under Report → Customers.
- Loyalty card with a number (optional): under Report → Customers → (customer) enter the card number (or scan the card into that field). With the barcode scanner, scanning that card links the customer to the receipt, at the till and on the kiosk. You can also search by card number under + Loyalty card.
Guest profile: VIP, dietary requirements and preferences (optional)
Turn on under Settings → Business → Guest profile, below the loyalty card (off by default; only works when the loyalty card is on). Then:
- On the order screen, "+ Guest profile" appears below the linked customer: tick VIP, choose dietary requirements (vegetarian, vegan, pescatarian, halal, kosher) and allergies (the 14 allergens), and type preferences (e.g. "regular table by the window", at most 300 characters). They then appear with the customer on the order screen, allergies in red. Can also be changed under Report → Customers → (customer) → Guest profile.
- If you tap a product containing one of the guest's allergens (see Allergens per product), the till first asks whether to add it anyway. Only what has been filled in for the product counts; if in doubt, always ask the kitchen.
- A VIP gets a ★ on the floor plan: on an open bill and on that customer's displayed reservation. When the guests of a reservation arrive, the till links the reservation's customer to the bill.
- Dietary requirements and allergies (and VIP) appear on the kitchen ticket for kitchen and bar:
GAST: VIP · Vegetarisch · allergie: Noten. - Dietary requirements and allergies are health data: only fill them in with the guest's consent. The log only records that the profile was changed, not the requirements themselves. Deleting the customer also removes the guest profile.
Favourites / quick buttons
Off by default. Settings → Business → Favourites / quick buttons:
- Best sellers: at the front of the group bar, the ★ Favourites button with the 12 best-selling products of the past 14 days (updated automatically). The order screen opens on the favourites.
- Choose yourself: on the order screen, long-press a product (or right-click) and choose ★ Favourite (quick button); again = remove. Manage products permission. All tills see it immediately.
- Entering items, options, menus, happy hour and "sold out" work on the favourites exactly as in the normal groups.
Another round
On the order screen there is the ↻ Another round button (as soon as something is on the bill, even if it has not been ordered yet). One tap adds the last round (everything sent in one go with "Send order", or what you just tapped) once more as new lines; then just tap Send order. Prices are the current ones (including happy hour).
- Long press (or right-click): choose yourself. Use ◀ ▶ to browse to earlier rounds, switch each product on/off (e.g. untick the food) and change the quantity with − / +. Options and notes are included.
- Sold-out products and menus are not included (enter menus separately). Also works without a connection.
- The lines are added as they appear on the bill: with Combine identical items on, one line per product (2 Cola); off, each line separately (2 × 1 Cola).
Table time on the floor plan
Every occupied table shows ⏱ 45m · 12m: how long the table has been occupied and how long ago something was last entered (tap and hold the table, or hover over it with the mouse, for the exact times). If nothing has been ordered for a while, the table gets an orange border: time to check in. You set the number of minutes under Settings → Business → Table time (default 20, 0 = no orange border). If nothing has been entered yet, the time counts from when the table was opened.
If several groups (separate bills) sit at one table, there is a line per group, e.g. G1 ⏱ 50m · 12m and Jansen ⏱ 10m (the group name, otherwise the group number). A group that has been idle too long gets an orange label and the table an orange border.
Move a whole table
The order screen has Move table. Choose the area (e.g. Terrace) and a table: all groups at the table move along, each with its own bill. If you choose an occupied table, the tables are merged (the groups are added). If you only want to move part of it, use Split / move as before. If everything has to go on one bill, use Merge.
Keep working offline (tablet without Wi-Fi)
If the connection between a tablet and the till server drops (Wi-Fi on the terrace, server briefly off), a yellow bar appears and the tablet keeps working with the last saved tables, products and open orders:
- opening tables, entering products and Send order are saved on the tablet (even if it restarts) and appear in the order list with a dotted border ("not sent yet");
- as soon as the connection is back, everything goes to the server in order, and only then does the kitchen ticket go to the kitchen. Each package has a key, so nothing arrives twice. If someone else opened the table in the meantime, the products are added to that order;
- checkout, discounts, splitting and the like only work with a connection; "Checkout" waits until everything for that table has been sent.
Number of guests
Optional and off by default: Settings → Business → Ordering and checkout → Track number of guests. Off = as few taps as possible: a free table opens with one tap, guests are not shown anywhere, and the report, dashboard and daily summary show no guests and no spend per guest.
On: when you tap a free table, the POS asks how many guests (large buttons 1-8, or type it in; "Skip" = 1). On the floor plan, an occupied table shows "3/4 ppl" (people/seats, yellow if more people are seated than there are seats). In the order screen you change it with the "3 ppl" button in the group bar; with multiple groups the table adds up all groups.
Without guest numbers everything keeps working: Split equally at checkout starts at 2, all-you-can-eat asks for the number of adults and children itself, and reservations and the waiting list keep their own number of guests (the table then opens without guests).
HACCP records
Every hospitality business must monitor and record food safety: in the Netherlands under the Hygiënecode voor de Horeca (Hygiene Code for the Hospitality Sector, inspected by the NVWA), in Belgium under the FAVV self-checking system (guide G-023). Switch on HACCP records under Settings → Laws and rules (off by default).
- Measuring points (manager): e.g. cold room, freezer, hot holding, core temperature after cooking, cooling down and goods receipt, with a minimum and/or maximum in °C and how often (every day, twice a day, every week or when used). Add default list gives you a starting point (chilling up to 7 °C, in Belgium up to 4 °C; freezer up to -18 °C; hot holding from 60 °C; cooking from 75 °C).
- Cleaning and checks: tasks per day, week (optionally on a fixed day) or month, with area and instructions, e.g. disinfect chopping boards, grease filters, pest control, check the thermometer.
- Recording (anyone who is logged in): the HACCP button in the top bar, showing how many are still open today. Enter a temperature or tick off a task (Done or Not done). If a temperature is outside the limit, a corrective action is required (e.g. "closed the door, discarded the product"). Records cannot be changed; you correct a mistake with a new record.
- Overview (permission Revenue per period): all records per period, the number of deviations and the missed records per day; as CSV (Excel) or to print / save as PDF for an inspection.
Tap system and flow meters
Every pour reported by a tap computer or flow meter goes on the bill, so nothing "leaks away". Turn it on under Settings → Tap system (off by default).
- Sources (administrator): the tap computer or flow meter system. Choose the brand; the till fills in a preset. From the Netherlands and Belgium: Van Duijnen Horeca (tap automation, Dashbar), Beconet (Multi-Tap), TapSystems, Horecatechniek Nederland, Heineken SmartDispense, WeissBeerger / AB InBev and BarTrack; also Gruber, Addimat, WMF / Hogatron (E-Protokoll), Drinkotec (ex-Hartec), , Berg, Easybar, Azbar, Scanabar, PourMyBeer, iPourIt, BeerBoard, US BeerSAVER, Bevchek, Capton/BarVision, Kegtron, Kegbot Kegboard, a "smart tap" or your own system. There are five ways to connect (Kegboard: see Controlled pouring and Kegboard below):
- Fields:
kraan(ortap,plu),ml(orcl,liter,volumewitheenheid) orporties,id(the same pour twice = booked once),tijdstip,tafel,bediening; one pour, a list or{ "taps": [...] }. - Network (TCP): the till connects to the tap computer (address and port) or listens on a port itself.
- Serial port: COM port or USB serial, 1200–115200 baud, 8N1, 7E1 or 7O1.
- For network and serial you set the message format (one message per line, or STX … ETX with an optional XOR check and ACK/NAK back) and the pattern of a message, with the parts
kraanorpluand optionallyml,cl,liter,porties,tafel,bedieningandid(e.g.kraan;mlor just a PLU per glass). Suppliers only give their exact format to installers; ask the supplier of the tap computer. Test pour sends a pour just as the tap computer would.
- Fields:
- Taps (manager): per tap or PLU the product and how it goes on the bill: per glass (glass in ml; a pour of 520 ml with 250 ml glasses = 2 glasses; from 50% it counts as a glass) or per litre (the product price is the price per litre; on the bill e.g. "Lager 0.33 l" for the right amount).
- On the bill: if the tap computer reports a table, the pour goes straight onto that table's open order. Otherwise it appears under Poured: the order screen shows the bar "… pours without bill"; select the pours and tap On this bill. The lines are marked ordered straight away (no ticket is sent to the bar) and the stock is deducted. The Poured button in the top bar shows everything that has no bill yet.
- Write off (permission Void): flushing, breakage, tasting, staff, free or other (with a note); this goes into the log. Too little for a glass (e.g. flushing) must be written off.
- Overview (permission Revenue per period): per tap poured, on the bill, written off (per reason), cancelled and still open, in litres, with the percentage sold, and as CSV.
- Reported pours cannot be changed (only processed).
Controlled pouring and Kegboard
With controlled pouring, a tap only opens after the glass has been rung up on the till, and then only for that amount. That way nothing is poured that is not on the bill. It only works when the tap system is on, and you turn it on per tap (off by default).
- Per tap (administrator, Settings → Tap system → Taps): tick Controlled pouring and choose how long the tap may stay open after ringing up (10–600 seconds, default 120). With Kegboard you also enter the relay (solenoid valve). Controlled pouring only works per glass.
- Ringing up: on Send order (or on direct Checkout) the till creates a release for each bill line with that product (number of glasses × glass in ml) and sends it to the tap computer. The pour that comes in afterwards belongs to that bill line. So it is not added to the bill a second time, nor to Poured. A pour without a release simply goes to Poured.
- Void of the line before anything is poured: the tap closes again. A release that is not poured in time expires; the tap never opens later after all.
- Releases in the order screen (a bar above the bill): see what is running, Stop, and Release again. Releasing again is only possible if nothing has been poured yet, so nothing extra is ever released. Test release (administrator) releases one glass without a bill; this is recorded in the log.
- How the release reaches the tap computer:
- Kegboard (Kegbot, open source, ESP32 with flow meters and solenoid valves; fully public protocol): the till sends a grant for the taps with that product, the relays and the amount. The board closes the tap itself when the amount is reached or the time is up.
- Network/serial: a configurable release command with
{kraan},{ml},{porties},{sec}and{id}(e.g.V{kraan};{ml}), sent in the source's message format (line or STX … ETX with XOR). Optionally there is a stop command. The supplier provides the exact command.
- Pair a Kegboard: under + Source, choose the brand Kegbot Kegboard. The board reports to the source; click Allow (or Deny). The board then receives its own key once, which the till stores only as a hash. Another device or a wrong key changes nothing on a paired board; if the board has lost its key, first use Unpair. The source shows the board's firmware, meters and relays. The taps are the meter numbers (0, 1 …). A card presented at the board is refused: payment is done at the till. If the tap system is off, the board keeps its messages and sends them later.
- At the source you set after how many seconds without flow the tap closes (5–300, default 30). For each tap, enter the meter number, the relay (solenoid valve) and how long the tap may stay open after ringing up.
Control music from the POS
Staff control the music from the POS touchscreen, so no separate screen is needed at the bar. Turn it on under Settings → Business → Screens and operation → Control music from the POS (off by default). The Music button then appears in the top bar: per source (e.g. Bar and Terrace) Play, Pause, Next, Previous, Louder, Quieter and a volume slider, along with what's playing now. Back to the POS closes the panel. Turning it off: the sources are kept.
- Playlist (Sonos, Bluesound and VLC): the queue with what's playing now. Tap a track to play it; with Edit you remove tracks (✕), move them up or down (↑ ↓; Sonos and Bluesound) or clear the playlist. With Choose other music you play a Sonos favourite (e.g. a station or Tunify channel) or playlist, or a BluOS preset.
- On a separate screen: the same controls and the playlist in large on
http://<kassaserver>:3000/muziek, e.g. on a second monitor next to the POS or a tablet at the bar (already signed in on the same device, otherwise with a PIN). - On a tablet or phone: a QR code with the address of that separate screen on the venue's network. A staff member scans it with their own tablet or phone (on the venue's Wi-Fi network) and signs in with their own PIN; Log out closes it again. See Second screen on a tablet or phone.
The manager adds the sources with + Music source, chooses how each one is connected and checks it with Test:
- Soundtrack (soundtrack.io): via the public API, with an API token (requested from Soundtrack) and a sound zone (Load zones). Play, pause, next, volume and what's playing.
- Sonos: the IP address of the speaker (for a group: the speaker leading the group). Works with anything playing on the Sonos, e.g. Tunify, Spotify or radio.
- Bluesound (BluOS): the IP address of the player; also works with anything playing on it, e.g. Tunify.
- VLC on the music computer: the web interface turned on (Tools → Preferences → Show settings: All → Interface → Main interfaces: Web, with a password under Lua); the IP address (optionally with
:poort, default 8080) and the password. - Own music computer (web addresses): for a music computer or box with a web address per button; GET or POST, and
{volume}(0-100) in the address for the volume. Without a Louder/Quieter address, the POS sets the volume step by step. - Music service web player: the web address of the web player or control page (e.g. the Tunify or Media Tools web player) opens in the POS under the Music button; if the service can't be shown inside another screen, use Open in a separate window.
The POS talks to the players from the server, so they must be on the same network as the POS (Soundtrack via the internet). Anyone who is logged in may control the music; setting it up requires the permission Set up business, payments and printers. The token and the password are never shown again and never appear in the log; the log only records the setup (on/off, sources), not every button press. The configuration export only includes on/off (the sources belong to a single business).
Second screen on a tablet or phone
The music and the cameras can also be shown on a staff member's own tablet or phone, as a second screen next to the POS. The Music or Cameras window has the On a tablet or phone button: it shows a QR code with the address, e.g. http://192.168.1.20:3000/muziek or .../camera.
- Connect the tablet or phone to the venue's Wi-Fi network.
- Scan the QR code with the camera (or type the address into the browser).
- Sign in with your own PIN. You only see what you're allowed to: the music for everyone, the cameras only with the View camera feeds permission.
- Done: Log out at the top right. If the sign-in has expired (e.g. the tablet was idle overnight), the screen asks for the PIN again.
Tip: add the page to the tablet's home screen (in the browser: Add to Home Screen) and it opens like an app.
That's why the POS looks up the IP address of the POS PC on the network (if the PC has more than one, e.g. Wi-Fi and cable, you choose the network). On the management portal (remote POS) it is the portal's address. The POS generates the QR code itself, without internet.
Pairing tablets: one button to the tablet (optional)
Even easier: pair a tablet once, and the POS sends the music or the cameras to that tablet with one button. Turn it on under Settings → Business → Screens and operation → Tablets as second screen (off by default).
- On the tablet: open
http://<kassaserver>:3000/tablet(the setting shows On a tablet or phone with the QR code), log in with a PIN and give the tablet a name, e.g. Bar tablet. Pair. - On the POS: the Music or Cameras window now has the button To Bar tablet (with a green dot when the tablet is on). Tap it: the tablet opens that screen by itself. For music, the chosen source goes along (e.g. Terrace).
- On the tablet: Close goes back to waiting; Unpair this tablet removes the pairing.
Keep the page open on the tablet; if the tablet is off or asleep, it opens the screen as soon as it is on again. The tablet stays logged in as the staff member who logged in on it: sending and viewing the cameras is only possible with the View camera feeds permission. In the setting, the administrator sees which tablets are paired and whether they are on, and can rename or remove them. The tablet keeps its own key; the POS only stores a hash of it. Turning it off: paired tablets are kept. The log shows who paired, renamed or removed a tablet.
Pick-up screen for takeaway
A screen for guests with Preparing on the left and Ready on the right, with large numbers, as in a chip shop or fast-food restaurant. Turn it on under Settings → Business → Screens and operation → Pick-up screen for takeaway (off by default).
No pairing needed: on a TV with a browser (smart TV, stick or mini PC), a tablet or a second monitor, open the till address followed by /oproep, e.g. http://192.168.1.20:3000/oproep. The setting and the Call window have the buttons On a separate screen and On a tablet or phone (QR code with the address). No sign-in needed: the screen only shows numbers. Tap the screen once so the browser is allowed to play sound.
What appears on it:
- takeaway orders from the till, the webshop and Thuisbezorgd (and optionally also counter orders without a table, with quick sale), from the last 12 hours;
- as soon as something has been sent to the kitchen or bar (or the webshop order is set to preparing), the number appears under Preparing;
- Ready is set automatically when the kitchen display reports the whole order ready or the webshop order is set to ready. The number flashes briefly and the screen plays a ding-dong;
- a ready number stays on for the number of minutes set (default 10), or until Picked up;
- orders from the kiosk (see Self-service kiosk) always appear as soon as they are paid or will be paid at the till, also for "eat here", with the pickup number from their receipt;
- optionally also orders for couriers of Thuisbezorgd, Uber Eats, Deliveroo and HubRise (tick box Also orders for couriers …): with the platform's order number and the platform's name underneath, so the courier can see when their order is ready. Picked up then also tells the platform that the courier has it (just like in the platform's window).
The number: for the webshop, Thuisbezorgd and the delivery platforms, the order number the guest or courier already has; otherwise the pick-up number (1 to 999). It is printed large on the receipt, with an explanation that the number will appear on the screen when the order is ready (in the receipt language).
Optional (off by default, in the setting):
- Announce the number with a voice: for a new ready number the screen says e.g. "Number 42, your order is ready." in the chosen language (Dutch, English, German, French, Spanish, Italian, Portuguese, Polish, Turkish or Arabic). The voice comes from the browser of the screen and sounds different per device; tap the screen once after opening it. After the chime, if sound is on too.
- Order status on the phone: a QR code appears under the pickup number on the receipt. The guest scans it, sees their number and the status (ordered, being prepared, ready, collected) and gets a notification when the order is ready. This runs via the management portal, so the till must be connected to it. Not for the webshop and Thuisbezorgd (they have their own status) and not for the kiosk (it has its own setting).
The till has the Call button (showing how many orders are still being prepared):
- Ready marks a number as ready by hand (without a kitchen display, or when it is quicker). For a webshop or Thuisbezorgd order the status is updated too, so the guest is notified as well.
- Back puts it back under Preparing.
- Picked up removes it from the screen (with Undo).
In the setting you also choose whether the first name is shown next to the number (off by default, for privacy) and whether the screen plays sound. Turning it off: no Call button and no pick-up number on the receipt; the settings are kept. The log shows who manually set what to ready, back or picked up.
Clocking in and out
Clocking is off by default: then it is not visible anywhere in the till (no button in the top bar, not on the login screen, no Working hours tab). Turn it on via Settings → Business, under Staff clock in/out:
- Off: not used. If you turn clocking off later, it is no longer visible anywhere, but hours already clocked are kept (nothing is deleted); turn it back on and they are there again.
- On: staff can clock in and out. After logging in the till asks whether you want to clock in (Not now is allowed). The top bar then shows Clock in or Clocked in 17:02; tap it to clock out.
- Required: clock in first after logging in, otherwise you cannot use the till. Clocking out logs you out immediately.
Staff who don't use the till (e.g. the kitchen) clock on the login screen: tap Clock in / out and enter your PIN. This toggles between in and out, without logging in.
When clocking is on, the administrator sees in Settings → Working hours:
- who is clocked in now (and can clock out someone who forgot);
- the hours worked per employee per period, with all shifts, and a CSV download (hours also as a decimal number for payroll);
- edit or add shifts (tap a shift, or + Add shift). Every change is recorded in the log with the old and new times.
In Belgium every clock-in and clock-out is also reported to the black box. If it cannot be reached, clocking does not go through (just like checkout). Whether this fully meets the Belgian staff registration requirements still has to be confirmed.
Weighing and labels (scale)
When the scale is on (Settings → Scale), products can have a price per kilo. All other products stay per piece.
- Weighing: tap a product with a price per kilo (the button shows e.g.
12,95/kg). The Weighing window shows the weight from the scale (e.g. an Aclas OS6X, or the scale the POS itself runs on) live; green = stable. Put the product on the scale and tap Add as soon as the weight is stable. The price is price per kilo × weight (rounded to the cent); a container (tare) of the product is deducted automatically. If the product has options, they come next. - More scales: if there are several scales, choose at the top of the window which one you weigh on. Each POS/tablet remembers its choice.
- By hand: no scale (or manual entry allowed)? Then type the weight:
0,512or1,2is kilos,512or512 gis grams. - TS6X label: scan the label's barcode with the barcode scanner on the order screen (just scan, nothing needs to be open), or tap Label and scan or type the 13 digits. The product (PLU) and the weight come from the label. If the label shows a price, the till charges exactly that price.
- The screen, the receipt and the customer display show the weight, e.g.
Gehakt 6,63with0,512 kg x € 12,95/kgbelow it; on the kitchen ticket0,512 kg Gehakt. Splitting, moving and returns are done in kilos. - A weighed product only works with a connection to the till server (the weight comes via the till server).
Uber Eats, Deliveroo and HubRise
Besides Thuisbezorgd.nl / Takeaway.com, orders from Uber Eats (Netherlands and Belgium), Deliveroo (Belgium only; Deliveroo left the Netherlands at the end of 2022) and everything on HubRise (incl. Uber Eats, Deliveroo, Just Eat/Takeaway.com and smaller ordering apps) also come into the till. Each platform can be switched on separately under Settings → Delivery platforms (off by default; switching off keeps everything). The tab shows per platform in which countries it operates and warns if it does not operate in the business's country.
- Switch it on, then Log in to Uber Eats and link store (the business logs in with its own Uber Eats account). If the account has several stores, enter the store ID and log in again. Uber Eats must first approve Pin Voordeel as a partner for this.
- Deliveroo: direct, via the portal. Enter the site ID (location ID) and the brand ID. Without tablet (default): the till accepts or rejects; with tablet: the business accepts on the tablet and the portal only reports whether the order is in the till.
- HubRise: the till fetches the orders itself (every 20 seconds, no portal needed).
- Per platform: accept automatically, kitchen ticket straight to kitchen/bar and (Uber Eats, Deliveroo) send menu automatically after a change and Send menu now. The menu contains the products ticked under Products on the Uber Eats and Deliveroo menu, with options; sold out is passed on too.
Orders. An order becomes a regular order (bezorgen or afhalen, group name <platform> <nummer>) with the platform's prices: products are recognised by their ID (from the menu), code or PLU number; unknown = a separate line with the platform's price (and an alert); delivery fees, surcharges and discounts as separate lines; if the total still does not match, a "Difference" line. The kitchen ticket goes straight to kitchen/bar. Platforms button in the top bar (with the number of open orders; orange when something needs accepting): accept or reject (with reason), being prepared, ready, out for delivery, delivered or picked up, cancel, and Complete (paid online). Whatever the platform supports is sent back (Uber Eats: accept, reject, cancel; Deliveroo: accept, reject, being prepared, ready, picked up; HubRise: all statuses). If the business delivers itself (own delivery), the order also appears under Runs, and departure and delivered are passed to the platform automatically. A cancellation by the platform makes the order lapse. If the till has not been connected to the portal for more than 2 minutes, the portal rejects a new Uber Eats order and tells Deliveroo (with tablet) that it failed, so the business sees it on the tablet.
Code: apps/pos-server/src/lib/bezorgplatforms.ts, routes/bezorgplatforms.ts; screens Bezorgplatforms.tsx. Portal side: horecapos-portaal/src/platforms.mjs. Log: Delivery platforms (on/off, settings, orders). Everything is included in the till's backups.
Smaller platforms in the Netherlands and Belgium (Homie, Hebtrek, sneleten.nl, Bistroo ...) have no public POS integration; if they are on HubRise, they work via HubRise. Otherwise: see the backlog.
Cash recycler (closed cash system)
Off by default: cash works as usual. With a closed cash system, staff do not handle the cash: the customer or staff member puts the money into the machine, which counts it, checks for counterfeit money and gives change.
- Machines the till talks to directly:
- CashDro (3, 4+, 5, 7, S Compact; NuKassa, KluisKassa): over the network (web service). Turn on Web Integration on the CashDro and create a separate user for the till.
- Cashmatic (SelfPay 460/860/1060; in Belgium Xpos): over the network (port 50301) with a Cashmatic user.
- Azkoyen Cashlogy (POS1000, POS1500): via the CashlogyConnector on a Windows PC next to the machine (port 8092).
- CashKeeper: via CKMonitor on a Windows PC (port 16501).
- Glory CASHINFINITY (CI-5, CI-10, CI-10X; also via Cikam): via the machine's controller (FCC). Still beta: have the first integration checked by Glory or your dealer.
- External: other software controls the machine and talks to the till (such as Cikam, ImaCash for 25 brands, the software of CashGuard/StrongPoint (Merlin), PayComplete (SUZOHAPP), Gunnebo SafePay or French brands such as CashMag).
- Test machine: without hardware, for practice or demonstration. With Test connection you check the address and login. Put the machine on your own network (never exposed to the internet) and use a separate user for the till, not an administrator.
- Checkout with Cash: Pay at the cash recycler starts the payment for the amount (cash-rounded if that is on, plus tip; when splitting the bill, the share). The screen shows what has been inserted and what is returned; the till only completes the checkout once the machine reports done. Cancel = the machine returns the money. If the machine could not give all the change (too few coins), it shows how much must come from the cash drawer. A successful payment that has not yet been checked out (e.g. tablet failed) is found again with that order.
- Cash only via the machine (on by default): the till server then only accepts cash with a successful payment at the machine for exactly that order and that amount. Off = ordinary cash in the drawer too.
- Cash drawer (Report → Cash drawer, permission Manage cash drawer): Check contents (per coin and note, with Cashmatic, Cashlogy, Glory and the test machine), Pay out with a reason (e.g. change for the drawer), Refill and Skim (change stays; with Cashmatic). Expected in the cash drawer does not count the money in the machine (that is shown separately below: In the cash recycler), but does count the change that had to come from the drawer.
The © button
At the bottom right of every screen (PIN, floor plan, ordering and kitchen) there is a small © button. It opens the OptimumPOS details: logo, address, phone, email and website. The icon is stored locally in the app, so it also works without internet. The same icon is the app icon (browser tab and home screen).
Part 2 · Manager
Getting started
By default a manager can do everything a waiter can, and in addition give discounts, process returns, close the day, manage the cash drawer and view the log and stock, among other things. Most of this is under the Report button:
- Interim total (X): revenue so far, without closing the day.
- Cash drawer: float, cash in/out and opening the drawer.
- Close day (Z): at the end of the day; a new day starts afterwards.
- Previous Z reports, Revenue per period and Dashboard.
- Log, Gift cards and Customers.
Stock
Off by default. Turn it on via Settings → Business → Track stock. Off = not visible anywhere in the till.
- For each product you choose under Settings → Products → (product) → Stock:
- No: as always;
- Per product: each sale deducts 1 (e.g. bottles, cans), with an alert level for "almost out";
- Via ingredients: a recipe, e.g. hamburger = 1 bun + 150 g meat + 1 slice of cheese. Each sale deducts the ingredients.
- Settings → Stock (Manage stock permission, by default manager and administrator):
- Products and Ingredients: the stock level, with sold out / almost out; filter "only (almost) out" and export to CSV.
- For each product or ingredient you book a Delivery (+), a Count (=) (the counted quantity becomes the new level) or a Write off (−) (breakage, past date; reason required).
- Create ingredients with a unit (pc, g, kg, ml, cl, l, portion, bottle, keg) and alert level.
- History: all changes (sale, void, delivery, count, write-off) with who and when. Management actions are also recorded in the log.
- Stock is deducted on Send order (or at checkout for items checked out directly). A void adds it back. Splitting and moving do not count twice. For menus the dishes are deducted, not the menu line. Returns (credit note) are not added back (returned items usually cannot be sold again); book them as a delivery if needed.
- When the stock is out (or there is too little of an ingredient for one more), the product is automatically set to sold out on all tills. When almost out, the product button shows N left. After a delivery or count it can be ordered again immediately. The till server also refuses the product ("Pils" is sold out (stock 0)), so even from a tablet that did not know yet.
- Stock may go below 0 (e.g. two tablets at the same time, or ordered offline); the count puts it right again.
- Order list: Settings → Stock → Order list. For each product (per product) and each ingredient you set, besides the alert level, top up to and the supplier. The order list shows everything at or below the alert level (without alert level: at 0), per supplier, with the suggestion top up to − level. Quantities can be adjusted and ticked on/off. Then Print (receipt printer), Copy (for email or WhatsApp), Export (CSV), and after delivery Delivered: book as delivery (books everything in at once). With the checkbox at the top you also see what is not out yet, to order extra.
- Options: an option group (Settings → Products → Options) has a Stock button. Enter the ingredients per item for each option, e.g. Extra cheese = 1 slice of cheese, Fries = 150 g fries. When the option is chosen, those ingredients are deducted per item (even if the product itself does not track stock; they are added back on a void). If an ingredient is out, the option shows as (sold out) on the till and cannot be chosen.
Order from suppliers
Off by default. Turn on under Settings → Stock → Order from suppliers (only with Track stock on). Off = the order list works as usual.
- Suppliers (Suppliers tab): choose one from the list or create your own supplier. The list has wholesalers and cash & carry (Sligro, Sligro-ISPC/Sligro-M, HANOS, Makro, De Kweker, Horeca Totaal, Van Zon, zegro, Lekkerland), foodservice (Bidfood and Bidfood Belgium, Solucious, Chefs Culinar, Java, Q-Food, Agora Culinair, VHC Jongens/Kreko/Actifood, Hocras, Van Hoeckel ...), drinks wholesalers (De Klok, Henk Smit, Horesca, De Monnik, Hansen, Dranken Geers ...), brewers and soft drinks (Heineken via Sligro, AB InBev/BEES, Alken-Maes, Haacht, Duvel Moortgat, Martens, Coca-Cola, Spadel, Grolsch, Bavaria), fresh-produce suppliers (Van Gelder, Driessen, FiliusKaas, Bakkers Brigade, Rungis ...), non-food (Bunzl, Takeaware, Supplierz), the online wine shop Vinify.nl and ordering platforms (Apicbase, Exact Horeko, Growzer, inOne, Cuisin.io, OrderXL). Only suppliers from the business's country are listed. If you choose one, the ordering method, file and columns are already set correctly; each supplier shows how to order there.
- Per supplier: customer number, order via:
- Email: the order as an email (with a table) to the order email address, optionally a copy, with the order list attached: CSV, Excel, CSV for Care4Fresh (many fresh-produce wholesalers), UBL 2.1 Order (Peppol BIS Order), EANCOM ORDERS (D96A in the Netherlands, D01B/HO2C in Belgium) or cXML. Replies go to the business's email address.
- File: the till creates the file, you upload it in the supplier's web shop (e.g. Bunzl Snel bestellen:
artikel;aantal, Takeaware:SKU,Quantity). Separator, header row and columns can be set (artikel,ean,omschrijving,aantal,eenheid,prijs,totaal; withartikel=SKUyou give the header your own name). - Integration (cXML): a cXML OrderRequest with customer number and shared secret to the supplier's order address, the way purchasing systems send them to Sligro, HANOS and Bidfood. You get the address, customer number and secret from the supplier (Sligro: koppelingen@sligro.nl). The secret is never shown on screen again.
- Both integrations can also use a username and password (Basic) and extra headers (one per line, e.g.
X-Api-Key: ...). - Upload (SFTP/FTPS): the till places the file (EANCOM, UBL, CSV, Excel ...) itself in a folder on the supplier's server, the way many wholesalers accept EDI orders. SFTP (SSH), FTPS (explicit on port 21 or implicit on port 990) or, only on your own network, FTP. Log in with a password or SSH key (OpenSSH, PEM or PuTTY .ppk; ed25519, ECDSA or RSA). Create key creates a key pair in the till; you send the public key to the supplier. Test connection logs in and looks for the folder. The fingerprint of the SFTP server is recorded on the first connection and checked after that (a different server does not get the password); for FTPS with your own certificate you pin the certificate's fingerprint. No extra software is needed.
- Print: the order on the receipt printer, to phone it through.
- Passwords, keys, tokens and headers are never sent back to the screen (leave empty = keep, Clear = remove).
- Request integration: for a supplier, the till drafts an email requesting an integration (cXML, EDI via SFTP/FTPS, UBL/Peppol or the supplier's own API) with the business details (name, address, VAT number, customer number, GLN) and what is needed; for EDI with the public key. Edit and send; a copy and the replies go to the business email address. The date of the request is shown with the supplier. For Sligro it goes to koppelingen@sligro.nl, otherwise you enter your account manager's address.
- A custom supplier (not from the list) can do everything except what the supplier itself has to offer: email, file and printing always work; an integration or upload only with that supplier's details.
- Order days and delivery: order days, cut-off time, delivery time (the requested delivery date on the order) and a minimum order amount. Automatic: on order days, from that time, the till itself prepares an order (you review it) or sends it immediately (by email, upload or integration; below the minimum order amount it is only prepared). Once a day per supplier.
- Per product (Settings → Products → (product) → Stock, under Per product) and per ingredient: Order from (the supplier), order code at that supplier, EAN, per pack (crate of 24 = 24), the name of the pack and the purchase price per pack. The alert level is the moment to order; Top up to is how much there should be then.
- Purchase orders (Purchase orders tab):
- Suggested order per supplier: everything at or below the alert level. What has already been ordered but not yet arrived (on the way) is taken into account, so you do not order anything twice. Suggestion = top up to − stock − on the way (without Top up to: up to the alert level), rounded up to whole packs. Adjust quantities and Create order.
- An order is first prepared (as a draft): quantities, free lines (without product, e.g. napkins), note and delivery date can still be changed. Then Send (in the supplier's way or, for once, differently). If it fails (e.g. the supplier rejects it), the reason is shown and you can try again.
- Received: per line the quantity received (already set to the ordered quantity); the stock is increased per pack (2 crates of 24 = 48), with the order in the history.
- Every file (CSV, Excel, UBL, EANCOM, cXML) can also be downloaded separately.
- Sent, failed, received and cancelled are recorded in the log. The ordinary Order list keeps working; if a product has a supplier from the list, it appears there under that name.
Review management
Read and reply to reviews from Google and Trustpilot in the POS. Turn it on under Settings → Loyalty and reviews → Review management (off by default, then none of it is visible anywhere). Read and reply under Report → Reviews (permission Read and reply to reviews, by default also for the manager). If you turn it off, the integrations and the reviews are kept.
- Each business then only taps Connect to Google and signs in with its own Google account for the Business Profile. A Places key can also be set up centrally (the costs are then for the supplier). Trustpilot is per business: each business has its own Trustpilot Business account (the API comes with a paid subscription), and that is where the key, the secret and the business user ID come from. In the POS, each option shows "Who handles this?".
- Supplier's app (via the customer portal): if the supplier's Google app and/or Trustpilot app are in the customer portal (see the README of horecapos-portaal, "Reviews: supplier apps"), the administrator chooses Supplier's app under Sign-in and keys (the default for a new connection if the portal has the app). The business taps Connect to Google or Sign in with Trustpilot and signs in with its own account; the POS itself waits until sign-in is complete (every 3 seconds, at most 15 minutes) and fetches the tokens from the portal once. Refreshing also goes via the portal. No client ID, secret or API key needed in the POS; for Trustpilot you do need the domain and, for replies, the business user ID. Trustpilot public then reads via the portal's key. Requires
PORTAAL_URLandPORTAAL_SLEUTEL. Own app or API key keeps working as described below. - Who owns the reviews: they stay on the business's own Google Business Profile and own Trustpilot page, and the POS only stores them in its own till database. Replies appear under the business's name. The portal only passes the sign-in on (in memory, at most 15 minutes, can be fetched once) and stores no reviews or tokens; the name of the supplier's app only appears on the consent screen.
- Sign up yourself: each platform has a link to create a Google Business Profile (business.google.com/create) or a Trustpilot Business account (business.trustpilot.com) yourself, and for Trustpilot a link to the plans (business.trustpilot.com/plans). Signing up and paying is done with the platform itself; there is no API for that.
- Then Connect to Google and sign in with the account that manages the Business Profile. One location in the profile = selected straight away; more = choose in the POS.
- Google Places (read only): with the Place ID and an API key for the Places API (or
GOOGLE_PLACES_API_KEY): the average, the number of reviews and the 5 most relevant reviews. Replying is not possible this way. - Trustpilot Business (read and reply): API key and API secret of an application in Trustpilot Business (Integrations → API; or
TRUSTPILOT_API_KEYandTRUSTPILOT_API_SECRET), the domain of the business (the POS looks up the business unit) and, for replies, the business user ID of the person replying. - Trustpilot public (read only): only the API key.
- The POS fetches every 30 minutes (and right after connecting; Fetch now). The POS does not store the guest's email address and order number (which Trustpilot passes on).
- Report → Reviews: average, number per star, without reply and unread; filter by platform, stars, without reply and unread. Per review Reply (at most 4000 characters; everyone can read it), Edit reply, Remove reply and Read. A new or changed review is unread. The log shows review_beantwoord and review_antwoord_weg.
- Disconnecting keeps the fetched reviews.
Text and email marketing
Messages to loyalty card customers who gave their consent. Without the loyalty card, neither can be turned on.
- Consent per customer and per channel: when adding a new customer at the till you'll see the tick boxes "Customer wants to receive offers by text" and "... by email" (off by default). Under Report → Customers you can view and change the consent (with the date it was given) and a birthday (day and month only). Unsubscribe: untick and save.
- Menu updated immediately: if you turn marketing or the loyalty card on or off, the till sends the menu to the webshop again within a few seconds (only if something changed), so the checkbox appears or disappears straight away.
- Consent via the webshop: if the business has a webshop, checkout shows the checkbox "I want to receive offers by email/text" (only the channels that are on; unticked by default). When such an order comes in, the till looks up the customer by phone number (otherwise email address), creates them if needed and records the consent with the date. A missing number or address for an existing customer is filled in; the log shows klant_toestemming with source webshop.
- Report → Marketing (permission Manage loyalty card): at the top, how many customers gave consent for text and for email.
- Campaigns (one-off): name, text or email, (subject,) message with
{naam},{zaak}and{punten}, and optionally only customers who haven't visited for a while or have at least a certain number of points. View shows how many customers it goes to, the message as the customer will receive it and the number of texts per customer. Send test to your own number or address. Then Send: the till sends in the background (at most 1000 at a time) and counts what was sent and what failed. Nobody gets the same campaign twice; if the till stops halfway, Continue sending picks up with those who haven't received anything yet. - Sending via Mailchimp or Klaviyo (with a connection to a chosen list, see below): for an email campaign, under Send via you choose the till (its own mail server, as above), Mailchimp or Klaviyo. The till then first updates the list (unsubscribes, points), creates a campaign there for exactly the selected customers who are on the list (Mailchimp: a fixed group on the audience; Klaviyo: a separate list for the campaign) and sends it with the default sender of the audience or account. Mailchimp/Klaviyo fills in
{naam}and{punten}for each customer; the service's unsubscribe link is shown below. No limit of 1000 at a time and no personal discount code ({code}). If it fails, the campaign stays a draft with the message attached. The Marketing tab is also there when only the connection is active (then only campaigns via Mailchimp/Klaviyo; Send test uses the till's mail server). Automated messages are always sent by the till itself; in Mailchimp/Klaviyo you create them as a Customer Journey or Flow. Klaviyo key: also write access to Campaigns and Templates (if you already logged in: log in again). - As a push notification via the webshop (if Push notifications with offers is switched on in webshop management): under Send by choose Push notification (webshop as an app), with a title (max. 60 characters) and a short text (max. 200 characters; only
{zaak}is filled in, because the webshop does not know who the guest is). The till sends the promotion via the management portal to the webshop, which sends it to the guests who turn on Offers as notifications there; tapping opens the webshop menu. After a few seconds the promotion shows how many were delivered. Max. 3 per day, together with what the business sends from webshop management; otherwise the promotion stays a draft with the reason added. The Marketing tab is also available when only this is switched on (without loyalty card or email marketing). No discount code or selection (days, points); to test: on your own phone, turn on Offers as notifications in the webshop. - Automatic: a birthday message (on the birthday, once a year) and "we miss you" (after a set number of days without a visit, once each time the customer stays away). On/off per message; they only go out during the day (10:00–20:00).
- Personal discount code (optional, per message or promotion; only if Discount codes is on under Settings → Business): each customer gets their own code, e.g.
TERUG-7K4Q2M(birthdayJARIG-…, promotionACTIE-…), as a percentage or a fixed amount, optionally with a minimum order amount, usable once, valid for the set number of days after sending (default 30) and at the till and/or in the webshop. Put{code}and{geldig}in the text where you want them; otherwise the till adds below the message "Uw kortingscode: … (10% korting, aan de kassa of in de webshop, geldig t/m …)". View and Send test show a sample code (TERUG-VOORBEELD, does not work). If sending fails, the code is not created. The promotion shows how many codes have been issued and used. - Unsubscribe is below every message: in a text "Unsubscribe? Call ... or tell us on your next visit", in an email an unsubscribe link to the business's email address (including the Unsubscribe button in Gmail and Outlook). A reply to the email goes to the business.
- Privacy (GDPR): only customers with consent and a number or address; no numbers or addresses in the log, but per campaign how many were sent and failed. If you delete a customer, they are also removed from the mailing list.
- Costs: texts go through your own CM.com account (more than 160 characters = more texts per customer). Gmail and other mail servers have a daily limit; with many customers, send in batches.
Tips per staff member
Under Settings → Business → Tip (only if "Show tip buttons at checkout" is on) you choose how tips per staff member appear on the interim total (X), the Z report (receipt and email) and Revenue per period (also in the CSV):
| Choice | Distribution |
|---|---|
| Off (default) | only the tip total, as always |
| Own tips each | tips from the bills each person checked out themselves |
| Pool by hours | all tips together, by clocked-in hours in that period (requires clock in/out; nobody clocked = equal) |
| Equal pool | all tips together, split equally among those clocked in (without clocking: whoever entered or checked out something) |
Leftover cents go to whoever is closest to the next cent, so the total always adds up. It is an overview: the till pays nothing out (you can do that with "Money out of the drawer"). Old Z reports stay as they were.
Z report by email
Under Settings → Business → Email Z report to, enter the administrator's email address once (more addresses: separate with a comma, max. 3). After Close day the Z report is then sent automatically to that address, alongside the printed receipt. Empty = no email, as always.
- Emailing happens in the background, so a slow mail server does not hold up the end-of-day closing.
- Failed or needed again: Report → Previous Z reports → (report) → Email again (marked COPY).
Summary of the day (optional)
If there is an address under Email Z report to, the checkbox With a short summary of the day at the top of the email appears below it (off by default). On = a few lines in plain language at the top of the Z report email, using only the till's own data (no AI, nothing leaves the till):
- revenue, receipts and guests and the spend per receipt, compared with the same period a week earlier (in percent); if there was nothing then, it says so;
- the 5 best-selling products, and what stands out: products of which at least 3 more or fewer were sold than last week;
- the number of voids (compared with last week) and the busiest hour (receipts and revenue).
The Z report itself (receipt and email) stays exactly the same. Preview for today shows the summary from the last end-of-day closing until now. The summary is in Dutch, just like the Z report email.
Dashboard
Dashboard tab in Report (Revenue per period permission), read-only:
- Revenue per hour as a chart: the chosen day (blue) next to the same day last week (grey). Today is compared with last week up to the same time, so the percentage is fair. Use ◀ ▶ or the date to choose another day.
- Tiles: revenue (± % vs. last week), receipts and average per receipt, average spend per guest (eat-in only; takeaway/delivery not included) for that day and for the chosen period.
- Top 10 products and busiest hours over the last 7, 28 or 90 days. Busiest hours is a heat map of weekday × hour (average revenue per open day) with the three busiest hours above it, handy for the staff rota.
Gift cards sold do not count as revenue, and discounts and menu headers are not in the top 10 (as in the other reports). A day runs from 00:00 to 24:00.
Extra reports
Three extra tabs in Report, each switched on separately via Settings → Business → Management and reports → Extra reports (off by default: then no tab). They require the same permission as Revenue per period and are read-only. Period: this week, last week, this month, last month, the last 90 days, this year or custom (at most just over a year).
- Menu engineering: per product, how often it was sold (share of all items sold) compared with what it earns per item (margin = selling price excluding VAT minus the cost price). Each product gets a classification: Star (popular and high margin: leave as is), Plowhorse (popular, low margin: raise the price a little or make it cheaper), Puzzle (rarely sold, high margin: give it more visibility) and Dog (rarely sold, low margin: take it off the menu or replace it). Popular = at least 70% of an equal share; high margin = at least the average margin per item sold. The cost price comes from Apicbase (Settings → Recipes), otherwise from the product's purchase price (purchase price per package divided by the number per package), otherwise from the recipe of ingredients with a purchase price (Stock). Products without a cost price are listed separately at the bottom. Optionally per category (
?groep=). - Promotions and codes: per discount code, per campaign from Marketing (the personal codes combined) and per happy hour: how often used (receipts; for a happy hour also the items), how much discount, the revenue and the average per receipt.
- Waste: what was written off from stock (Settings → Stock, Write off (−)), per reason (capitals and spaces do not matter) and per product or ingredient, with the value at cost price; and what was cancelled after it had already been sent to the kitchen or bar, with the sales and cost value.
Discounts
A manager or administrator sees the % Discount button next to the total in the order screen:
- on the whole receipt or on one line;
- as a percentage (10, 15, 20, 25, 50, 100% = free, or enter your own) or as a fixed amount;
- always with a reason (Staff, Regular customer, Complaint, Promotion, Own use or type your own).
The discount appears as a separate line on the receipt ("Discount 10%", with the reason below it) at the same VAT rate, so the total and VAT breakdown are correct. On the whole receipt the discount is split per VAT rate. To remove it: tap the amount of the discount line. If a line with its own discount is voided, that discount is dropped with it. If you remove a product from a receipt with a percentage discount on the whole receipt, the POS recalculates that discount over what remains (in Belgium UC226); a fixed amount stays and is spread over the lines again at checkout. If nothing is left to pay because of a 100% discount, close with "Close (nothing to pay)". Discounts are shown in the log, and in the X/Z report and the period overview as "of which discount". When a receipt with a discount is returned, the discount is applied proportionally.
Discount codes (optional)
Codes with a discount on the whole receipt, for example for a promotion (ZOMER10). Turn on under Settings → Business → Discount codes (off by default); create the codes under Settings → Discount codes (permission Manage products):
- discount as a percentage or a fixed amount, optionally with a minimum order amount, valid from/until and at most this many times (empty = unlimited);
- per code: at the till and/or in the webshop (the till sends the codes along with the menu; usage counts for the till and webshop together).
The order screen has the Discount code button (anyone may enter a code; the code is created in advance by the business). The discount appears as the line "Discount code CODE" on the receipt, split across the VAT rates; one code per receipt, and not once (part of) the bill has been paid. If you remove the line again or the order is cancelled, the usage no longer counts. Removing a used code turns it off (the reports stay correct). Everything is in the log (Discount code). Code: lib/kortingscodes.ts, routes/kortingscodes.ts, Kortingscodebeheer.tsx, KortingscodeDialoog.tsx.
They do not appear in the list under Settings → Discount codes (the number per promotion does, under Report → Marketing) and are passed on to the webshop as long as they are valid and unused.
Reports and end-of-day closing
Report button in the top bar:
- Interim total (X): revenue, VAT, payment methods, per group and the cash drawer since the previous end-of-day closing. Can also be printed. Closes nothing.
- Close day (Z) (manager or administrator): count the cash drawer (the difference with opening float + cash is shown), enter the opening float for the next day, close. The Z report gets a sequential number, is saved and printed on the receipt printer. Not possible while orders are still open. Optional: Count per coin and note (counting aid) fills in the counted amount for you; the count per coin/note then also appears on the Z report. Typing the total yourself works as always.
- Cash drawer (manager or administrator, optional):
- Money out of the drawer (bank deposit, expense, tips paid out) or money in the drawer (change) with amount and reason. The drawer opens and a slip with a signature line is printed to keep with the cash (can be turned off). It counts towards expected in the drawer and is listed per line on the X and Z report.
- Enter or correct today's opening float (normally you enter it at the end-of-day closing for the next day).
- Open drawer without sale, with a reason.
- Everything is recorded in the log. If you don't use this, the end-of-day closing works exactly as before (opening float + cash = expected in the drawer).
- Below the revenue is the number of guests (people from the checked-out orders) and the average per guest, also on the printed X/Z report.
- Revenue per period (manager or administrator): today, yesterday, this/last week, this/last month, this year or choose your own from-to. Shows revenue, VAT, payment methods, tips, guests, product groups, per day and per staff member. Export (Excel/CSV) gives you a file for the accountant (semicolons and comma decimals, opens directly in Dutch Excel).
- Previous Z reports: list with revenue and cash difference; open them and print a copy (marked "COPY").
Export to your accounting
Report → Revenue per period → Accounting export (journal) (permission Revenue per period) creates a CSV with one journal entry per day, ready to import into e-Boekhouden, Exact, SnelStart, Twinfield etc. (via their CSV/general journal import), or one of the formats below (UBL, XAF and ready-made for 14 packages).
One document per day (KASSA-JJJJMMDD) that always balances (debit = credit):
| Side | What |
|---|---|
| Debit | receipts per payment method (cash, card, gift card, online, other), incl. tips |
| Credit | revenue per VAT rate (excl. VAT) and VAT payable per rate |
| Credit | tips (payable to staff, not revenue) |
| +/- | rounding difference (cash rounding to 5 cents) |
| +/- | money in/out of the drawer (cash management) against suspense accounts, and cash difference from the Z report |
Returns and discounts are already in the receipts and reduce revenue. Columns: Datum; Boekstuk; Dagboek; Rekening; Omschrijving; Debet; Credit; Btw-code; Btw-% (semicolons, comma decimals). After downloading, the till reports whether there are days that do not balance or have a larger difference than rounding.
Next to the button you choose the format (the choice is remembered in the browser). The same journal, but formatted so that the package can import it directly. The list only shows the formats for the business's country (Settings → Business), first the standards (CSV, UBL, XAF), then the packages in alphabetical order:
| Format | File | Importing into the package |
|---|---|---|
| General (CSV) | journaal_…csv | any package with a CSV/journal import (map the columns) |
| UBL 2.1 / Peppol (XML), NL and BE | journaal_…_ubl.xml (multiple days: .zip) | one "daily receipts" invoice per day to Kassaverkopen (already paid) according to Peppol BIS Billing 3.0, with one line per VAT rate and the revenue account in AccountingCost; only revenue and VAT (payment methods, tips, rounding, drawer and cash difference do not belong in an invoice). For uploading into Adsolut, Billit, BUNNI, DigiBoox, Expert/M, Moneybird, Popsy, Rompslomp, Storecove and TriFact365, among others; not for sending via the Peppol network. Name, VAT number and address come from Settings → Business |
| XML Auditfile Financieel (XAF 4.0), NL | journaal_…_xaf.xaf | audit file of the Dutch Tax Administration (Belastingdienst) (XSD XmlAuditfileFinancieel4.0): one file for the period, ledger, VAT codes, periods and one general journal transaction per day; can be imported into Caseware, Exact Reeleezee and Visma Cash, among others |
| AccountView (XML), NL | journaal_…_accountview.xml | XML entries (VFPData, one transact per entry line with dj_code, period, inv_date, inv_nr, acct_nr, trn_desc and amount: debit positive, credit negative), one document per day in the general journal; import with an import definition (Document → Importeren → Importdefinitie aanmaken, type XML); the field names are AccountView's own, so map them 1-to-1 once. Have the first import checked |
| AFAS Profit (XML) | journaal_…_afas.xml | XML for the UpdateConnector FiEntries (financial entries), one entry per day with year, period, company and journal; import into Profit via Import → XML; enter the company number (default 1) |
| Asperion (CSV), NL | journaal_…_asperion.csv | FMUTA layout (Extra → Import financiële mutaties), one header line per day plus the entry lines; Asperion sets up the import definition via its helpdesk |
| Daily statement (HTML), NL and BE | journaal_…_dagstaat.html | readable daily statement per day (revenue per VAT rate, payment methods, tips, cash difference) and totals; print as PDF or email, for packages without import (Accountable, Dext, Dexxter, Jortt, Kleisteen, MoneyMonk) |
| e-Boekhouden.nl (CSV) | journaal_…_eboekhouden.csv | Date; Document number; Description; General ledger account; Amount (debit positive, credit negative); VAT code GEEN (the VAT is already on the VAT accounts); Import → Entries, type general journal |
| Exact Online (XML) | journaal_…_exact.xml | eExact-XML (topic GLTransactions): one general journal entry per day (type 90) in the journal; Import/export → Import XML |
| InformerOnline (TXT), NL | journaal_…_informer.txt | tab-separated general journal (Geavanceerd → Memoriaal → uploaden); the journal must be a number 1–99 (otherwise 90) |
| KING ERP (XML), NL | journaal_…_king.xml | KING_JOURNAAL: one posting batch (not final) with one journal entry per day |
| KOMAS (CSV), NL | journaal_…_komas.csv | KOMAS free format (0401 Importeren journaalposten): Datum; Grootboek; Omschrijving; Bedrag |
| Odoo (CSV), NL and BE | journaal_…_odoo.csv | Accounting → Journal Entries → Import records; journal and account by name or code |
| Sage BOB 50 (Excel), BE | journaal_…_bob.xlsx | Importation de données externes → Opérations diverses (map the columns once) |
| SAP Business One (ZIP), NL and BE | journaal_…_sapb1.zip | Data Transfer Workbench, Journal Entries: JournalEntries.csv and JournalEntries_Lines.csv |
| SnelStart (CSV) | journaal_…_snelstart.csv | Date; Document number; Description; General ledger account; Debit; Credit (dd-mm-yyyy, decimal comma, without BOM); import as general journal, you choose the journal when importing |
| Twinfield (XML) | journaal_…_twinfield.xml | journal transactions as draft (destiny="temporary"), the accountant makes them final; enter the company code (empty = the company you import into) |
| Winbooks (CSV), BE | journaal_…_winbooks.csv | K_DOC.CSV, one document per day in the journal (Winbooks numbers it itself) |
| Yuki (XML) | journaal_…_yuki.xml | Journal-XML (GeneralJournal), one general journal entry per day, same structure as the live link; company ID optional |
Overview: which accounting package works which way
By segment, in alphabetical order. NL/BE = the country in which the package works: under Settings → Accounting → Accounting package you only see the packages for the business's country (Dutch packages do not work in Belgium and vice versa). Live = the till posts every day by itself (choose under Settings → Accounting → Accounting package); on request = there is an API, but it first requires partner registration or approval from the supplier (let us know). File = the format under Accounting export. Where both are possible, you can use both. The list is in packages/shared/src/boekhoudcatalogus.ts and also appears under Settings → Accounting.
| Package | NL | BE | Live | File | Note |
|---|---|---|---|---|---|
| Small businesses and freelancers | |||||
| Accountable | – | ✓ | – | Daily statement (HTML, for PDF or email) | |
| AccountView (Visma) | ✓ | – | on request | AccountView (XML), General (CSV) | File: XML entries for an import definition (Document → Importeren); the generic CSV also works with an import definition. Live via the AccountView.Net API after applying to AccountView. |
| Acumulus | ✓ | – | ✓ | – | Live as a paid sales invoice per day, with one line per VAT rate. |
| AFAS Profit | ✓ | – | ✓ | AFAS Profit (XML) | |
| Asperion | ✓ | – | on request | Asperion (CSV) | Live after registering as an API partner with Asperion. |
| Billit | – | ✓ | on request | UBL 2.1 / Peppol (XML) | Upload UBL via Fast input; live after approval by Billit. |
| BUNNI | ✓ | – | – | UBL 2.1 / Peppol (XML) | No public API documentation yet. |
| Dexxter | – | ✓ | – | Daily statement (HTML, for PDF or email) | |
| DigiBoox (Visma DigiBTW) | ✓ | – | – | UBL 2.1 / Peppol (XML) | |
| e-Boekhouden.nl | ✓ | – | – | e-Boekhouden.nl (CSV) | Also for former Ficsus customers. |
| Exact Online | ✓ | ✓ | ✓ | Exact Online (XML) | |
| Exact Reeleezee | ✓ | – | – | XML Auditfile Financieel (XAF 4.0) | |
| Horus | – | ✓ | ✓ | – | |
| InformerOnline | ✓ | – | – | InformerOnline (TXT) | |
| Jortt | ✓ | – | – | Daily statement (HTML, for PDF or email) | No import: post the daily revenue as income with the daily statement as an attachment. |
| KING | ✓ | – | on request | KING ERP (XML) | Live after partner registration with KING Software. |
| Kleisteen | ✓ | – | – | Daily statement (HTML, for PDF or email) | |
| KOMAS (Adfinis) | ✓ | – | – | KOMAS (CSV) | |
| Minox | ✓ | – | on request | – | Live after a partner link via Minox. |
| Moneybird | ✓ | – | ✓ | UBL 2.1 / Peppol (XML) | |
| MoneyMonk | ✓ | – | – | Daily statement (HTML, for PDF or email) | MoneyMonk is getting an API for integrations in 2026. |
| Octopus | – | ✓ | on request | – | Live after requesting a software house ID from Octopus. |
| Popsy / Allegro | – | ✓ | – | UBL 2.1 / Peppol (XML) | |
| Rompslomp | ✓ | – | – | UBL 2.1 / Peppol (XML) | |
| Sage BOB 50 | – | ✓ | – | Sage BOB 50 (Excel) | |
| Silvasoft | ✓ | ✓ | ✓ | – | Live as a sales entry per day, with one line per VAT rate; payment methods, tips and cash difference are not included. |
| SnelStart | ✓ | – | ✓ | SnelStart (CSV) | |
| Twinfield | ✓ | – | ✓ | Twinfield (XML) | |
| Visma Cash | ✓ | – | on request | XML Auditfile Financieel (XAF 4.0) | API with a key from CASHWeb; the record layout for entries is still being confirmed. |
| Visma eAccounting | ✓ | – | on request | – | Live after approval by Visma (partner registration). |
| Winbooks | – | ✓ | on request | Winbooks (CSV) | |
| Wolters Kluwer Adsolut | – | ✓ | on request | UBL 2.1 / Peppol (XML) | UBL with the revenue account per line; in Adsolut turn on "grootboekrekening verwerken bij verkopen". |
| Wolters Kluwer Expert/M | – | ✓ | – | UBL 2.1 / Peppol (XML) | |
| Yuki | ✓ | ✓ | ✓ | Yuki (XML) | |
| International | |||||
| QuickBooks Online | ✓ | ✓ | ✓ | generic CSV | No Dutch or Belgian edition: check the VAT settings. |
| Xero | ✓ | ✓ | ✓ | generic CSV | |
| Zoho Books | ✓ | ✓ | ✓ | generic CSV | |
| Enterprise and chains | |||||
| Exact Globe+ | ✓ | ✓ | – | Exact Online (XML) | Same XML as Exact Online; have the first import checked. |
| Microsoft Dynamics 365 Business Central | ✓ | ✓ | ✓ | – | |
| Odoo | ✓ | ✓ | ✓ | Odoo (CSV) | |
| Oracle NetSuite | ✓ | ✓ | on request | generic CSV | |
| SAP Business One | ✓ | ✓ | ✓ | SAP Business One (ZIP) | |
| Unit4 ERPx | ✓ | ✓ | – | generic CSV | |
| Platforms and aggregators | |||||
| Apicbase | ✓ | ✓ | on request | – | Sales per receipt for stock and food cost: integration under Settings → Recipes (not as an accounting package). |
| Caseware | ✓ | ✓ | – | XML Auditfile Financieel (XAF 4.0) | |
| Combidesk | ✓ | – | on request | – | Combidesk builds and manages the link itself (to Exact, Moneybird, SnelStart and Twinfield, among others); on request as a partner. |
| Dext | ✓ | ✓ | – | Daily statement (HTML, for PDF or email) | Email the daily statement (PDF) to your Dext address. |
| Jamix | ✓ | ✓ | on request | – | Sales for stock and food cost via the JAPI interface of Jamix; custom work on request from Jamix. |
| Omniboost | ✓ | ✓ | on request | – | Passes data on through the Omniboost partner programme to many accounting and hotel systems. |
| Storecove (Peppol) | ✓ | ✓ | on request | UBL 2.1 / Peppol (XML) | |
| TriFact365 | ✓ | – | – | UBL 2.1 / Peppol (XML), Daily statement (HTML, for PDF or email) | |
| Any other package | ✓ | ✓ | – | generic CSV, UBL or XAF (NL) |
Have the accountant check the first import. The layout is in packages/shared/src/journaalexport.ts (with tests).
Settings → Accounting (Set up business, payments and printers permission): journal code (default MEM) and the general ledger account per item. Empty = example account (NL: 8000/8010/8020 revenue, 1500/1510 VAT, 1000 cash, 1100 card; BE: 7000xx revenue, 451000 VAT, 570000 cash). Have the accountant fill in the real accounts.
Link with an accounting package
Live links with Acumulus, AFAS Profit, Microsoft Dynamics 365 Business Central, Exact Online, Horus, Moneybird, Odoo, QuickBooks Online, SAP Business One, Silvasoft, SnelStart, Twinfield, Xero, Yuki and Zoho Books. After each day the till posts the same journal as the export above (revenue and VAT per rate, payment methods, tips, rounding, drawer and cash difference) as a general journal entry in the chosen package, with the journal and ledger accounts from Settings → Accounting. At most one package is ever on.
- The list is grouped by segment (Small businesses and freelancers, International, Enterprise and chains) and only shows the packages that work in the business's country; the server rejects a package from another country (400) and does not post with it (409). Directly below it the administrator gets exactly the fields for that package; connecting and the list of posted days are below the ledger accounts, with the overview of all packages for this country below that. If two were on at the time of the update (in an older version this was possible), Exact Online stays on and the other package is switched off.
| Package | Country | Connect with | What the till posts |
|---|---|---|---|
| Acumulus | NL | contract code, user and password of an API user | one paid sales invoice per day with one line per VAT rate; Acumulus emails errors to ACUMULUS_FOUTMAIL |
| AFAS Profit | NL | environment, token, administration | general journal (FiEntries) |
| Business Central | NL, BE | tenant, environment, company, client ID and secret of a Microsoft Entra app (API.ReadWrite.All) | lines in the general journal with the Journal code |
| Exact Online | NL, BE | log in (OAuth, own app: see Exact Online below; Belgium: start.exactonline.be) | general journal entry in the journal (e.g. 90) |
| Horus | BE | log in (OAuth, app below), optional file | miscellaneous operation |
| Moneybird | NL | API token, optional administration | general journal (general journal document) |
| Odoo | NL, BE | address, database, user, API key | journal entry in the journal with the short code (e.g. MISC) |
| QuickBooks Online | NL, BE | log in (OAuth, app below; QUICKBOOKS_OMGEVING) | journal entry; accounts by number |
| SAP Business One | NL, BE | Service Layer address, database, user, password | journal entry (JournalEntries) |
| Silvasoft | NL, BE | user and API key | sales entry to the relation Kassaverkopen, one line per VAT rate (payment methods, tips and cash difference are not included) |
| SnelStart | NL | connection key and subscription key | general journal |
| Twinfield | NL | log in (OAuth, app below), optional office | journal transaction |
| Xero | NL, BE | log in (OAuth, app below), optional organisation | manual journal; accounts by code |
| Yuki | NL, BE | API key, optional administration | general journal (GeneralJournal) |
| Zoho Books | NL, BE | log in (OAuth, app below; European data centre by default), optional organisation | journal entry; accounts by code |
- OAuth (Horus, QuickBooks, Twinfield, Xero, Zoho): register an app with the package once.
- For some packages the API fields cannot be fully confirmed from the public documentation (incl. Horus, Zoho Books, the sign in Business Central and the structure in SAP Business One): always have the accountant check the first entry.
- Exact Online: posts the journal as a general journal entry in the chosen company.
- Choose under Settings → Accounting → Accounting package → Exact Online (default Off). Belgium: the till automatically uses
start.exactonline.be. - Settings → Accounting → Exact Online: Connect to Exact Online opens the Exact login; afterwards it shows which company the till is connected to. Under Journal, enter the code of a general journal in Exact (e.g.
90) and make sure the ledger accounts exist in Exact. - When: right after Close day and then every hour, for all past days (up to and including yesterday) from Post from (by default the day of connecting; your accountant already has the earlier days). Each day once; days without revenue are skipped. Post now is always possible.
- Errors (an account doesn't exist in Exact, the day doesn't balance, no internet) are shown with the reason next to that day; the till tries again later, and the following days wait until it succeeds (so the order stays correct). In the log: "exact_geboekt".
- VAT is posted to the VAT ledger accounts (without a VAT code, just like in the export). Have your accountant check the first entries.
- Exact: a connection keeps working as long as the till uses it (a new token every 10 minutes, each time with a new refresh token). If it is revoked or unused for too long, the till asks you to Reconnect. Unpair deletes the tokens; whatever has been posted stays.
- Choose under Settings → Accounting → Accounting package → Exact Online (default Off). Belgium: the till automatically uses
- AFAS Profit: environment number (e.g.
12345; production, test or acceptance), the token of an app connector with the UpdateConnector FiEntries and the company number (default 1). Journal = the code of a general journal in AFAS (e.g.90). - Journal = number or name of a general journal; if there is only one general journal, the till uses that one. Ledger accounts must be numbers.
- Twinfield: log in with OAuth. Without that app the till cannot connect. The till looks up the cluster and the administration (empty = the first); journal = the code of a general journal (e.g.
MEMO). Posts as final (destiny="final"). - Yuki: the company's API key (Yuki → Settings → Web services); company empty = the first one for that key. Posts a general journal entry (GeneralJournal); Yuki does not use a journal code.
- When: right after Close day and every hour, for all past days from Post from (default the day of connecting; with another package again from that day). Each day once per package; days without revenue are skipped; on an error the reason is shown next to that day and the following days wait. Post now is always possible. In the log: "boekhoudpakket_geboekt".
- Keys and tokens are never shown on screen (leave empty when reconnecting = keep). Nothing is posted from the copy of the till on the portal.
Cash register audit file (XAA)
For Dutch businesses, Report → Revenue per period has the button Cash register audit file (XAA) next to the accounting export: the XML Auditfile Afrekensystemen 3.2 of the Dutch Tax Administration (Belastingdienst) and the XML Platform (SRA) over the selected period (at most just over a year; permission Revenue per period). This is the file the Belastingdienst recommends for supplying a till's data during a tax audit or to the accountant; the rules are set out in the Handreiking voor een betrouwbaar afrekensysteem (Guide to a reliable checkout system, docs/xaa).
In the file (auditfile_kassa_<van>_tm_<tot>.xml, schema docs/xaa/XmlAuditfileAfrekensystemen3.2.xsd):
- master data: the business (name, VAT number, address), the VAT codes, all staff members (with role and creation date; plus
SYSTEEMfor what the till does itself, such as the webshop and integrations) and all items with their group; - events: everything from the log in the period (signing in and out, cash drawer opened, end of day, settings and prices changed, void, discount, return, copy receipt, clocking in and out ...) and the opening of the till day with the opening float, each with the Belastingdienst code (18001 sign-in, 18003 drawer, 18006 installation change, 18008 Z report, otherwise 18999);
- cash transactions: every receipt (sale, return and pro forma, with the receipt number, the staff member and the fiscal status if it is not in order) with all lines (item, group, quantity, price, VAT; also discounts, gift cards, menu headers and lines cancelled before checkout, the latter with amount 0), the VAT per rate, the rounding, the payments per payment method (cash, card, gift card, online; tip separately) and the cash in/out of the cash drawer.
Amounts are positive with C (sale, money received) or D (return, payout); times are in Dutch time with offset. All keys are the database ids without hyphens, so they can be traced back in the till.
Signing (chapter 6 of the specification): if Optimum POS has set up a certificate, the audit file comes signed in an envelope (XML Signature) and the file is named …_ondertekend.xml; otherwise it is a plain audit file, and the till reports this when downloading.
Payment on account
Business customers (a company that has lunch collected every week, a hotel, a club) buy on account and pay later, with an invoice. Switch it on under Settings → Invoices → Payment on account (only with Invoices on; off by default).
- Customers: under Report → On account you add the business customers with the details for the invoice (name, address, VAT number, KvK/company number, Peppol ID, email), optionally a credit limit (the maximum that may be outstanding) and their own payment term (otherwise the one for invoices), and whether the invoice is sent straight away.
- Checkout: payment method On account, choose the customer (showing what is already outstanding and the credit limit). The receipt is a normal sale: revenue and VAT on that day, in Belgium simply via the black box, with "On account" on the receipt. The till creates the invoice straight away (UBL/Peppol and for printing) for the amount still outstanding with the due date, and sends it as set for invoices (email, Peppol via Billit/Storecove/Banqup or your own address). On account is one amount for the rest of the bill (paying part another way first is allowed), without a tip; a gift card cannot be sold on account. Above the credit limit the till refuses.
- Paying: the customer pays in store by cash, card or gift card (Report → On account → Payment received; part payments too). That is not a new sale and not a new receipt: cash goes in as cash in the drawer (the drawer opens), and everything appears on X and Z under Received on account. Once everything is paid, the invoice is marked "paid". Online payment is not part of it.
- Bank transfer: if an IBAN is entered under Invoice details, it is shown on the invoice (and in the UBL), with "You can also pay on the premises". If the customer has paid by transfer, record it with Payment received → Paid (bank): not in the drawer, but on the X and Z reports under Received on account. Without an IBAN the invoice says "To be paid on the premises". In Belgium a structured communication (+++123/4567/89012+++, derived from the invoice number) is shown on the invoice and in the UBL, so the bank passes it on.
- Bank: match transfers without retyping, see below.
- Credit (money in advance): under Report → On account → Deposit credit you put money in advance on a customer's account, in cash (the drawer opens) or by card, e.g. for a series of lunches. At the next sale on account the credit is deducted from the invoice first; if the invoice is for more, the rest remains outstanding. The credit is shown with the customer (credit € ...), on X and Z under Received on account (Credit deposited, With customer credit) and in the journal as received in advance (default 1640 / 460000). In Belgium the deposit goes to the black box as money in (signMoneyInOut) (UC4100).
- Collective invoice (per customer, off by default): with One invoice for all receipts the customer does not get an invoice yet for a sale on account. The receipt stays open on the customer (Receipts not yet invoiced, counts towards the limit) and can already be paid. With Create collective invoice (e.g. at the end of the month) all open receipts go onto one invoice, each line preceded by its receipt number; anything already paid is shown as paid. A return to the account appears as negative lines. Off = one invoice per sale, as always. In Belgium one invoice with all receipts in the black box (signInvoice, UC4121 and UC4122).
- Belgium: if the customer later pays a sale on account (cash, card, gift card or bank transfer), the POS reports this as a payment correction on the receipt: from customer credit to the actual payment method (signPaymentCorrection, UC4118).
- Overview: outstanding invoices with the due date (overdue in red), and per customer the invoices and payments. Under Settings → Invoices there is a column Outstanding.
- Accounting: in the journal the sale on account goes to Accounts receivable (default 1300 in the Netherlands, 400000 in Belgium; can be set under Settings → Accounting) and the payment goes from cash, card, gift card or bank (default 1050 / 550000) to accounts receivable. XAA: payment method "On account".
- Permission: Check out on account and receive payments on account (default waiter no, manager yes). Everything is recorded in the log.
- Off: the customers, invoices and payments are kept (also in the backup); the switch is included in the configuration export, the customers are not (they belong to one business).
- In the webshop (optional, off by default): with Also in the webshop, business customers order online on account (takeaway and delivery). Under Report → On account you create a customer code for each customer and give it to them; the till only stores an encrypted version, so you see it only once. New customer code = the old one no longer works; Remove customer code = that customer can no longer order online on account. The webshop enforces the credit limit. In the Webshop window you complete such an order with Complete (on account): checkout on account, with the invoice straight away.
Bank: match transfers to invoices
Under Report → On account → Bank the till looks up the invoice on account for each incoming payment:
- Import bank statement: the file from your online banking, as CAMT.053 (XML, all banks in the Netherlands and Belgium), MT940 (.sta/.940) or CODA (.cod, Belgium). Incoming payments only; importing a statement twice does not create duplicate lines.
- Matching: by the invoice number or the structured communication in the description (certain), otherwise by amount (and name): then it is a suggestion. Each line can be matched (to the suggestion or another invoice), ignored or later matched anyway. Matching = Paid (bank) on the bank date, never more than is outstanding; not in the drawer.
- Bank connection (PSD2, optional): under Settings → Invoices → Bank connection the till fetches the incoming payments itself every hour via Enable Banking (banks in the Netherlands, Belgium and the rest of Europe). Choose the bank and log in to it (business account); the consent is valid for 180 days, after which you reconnect. Disconnecting withdraws the consent; the incoming payments are kept. Without a contract with Enable Banking this only works for your own accounts (restricted production).
- Automatic matching (off by default): an incoming payment that certainly belongs to an invoice is booked against it straight away (also when importing).
- Permission: matching requires Check out on account and receive payments on account; setting up the bank connection requires Set up business, payments and printers. Importing, connecting, fetching and matching are recorded in the log.
- Off: with payment on account switched off the till fetches nothing; the incoming payments and the connection are kept (also in the backup).
Camera feeds in the POS
All of the business's camera feeds on one page, without a separate screen or app. Turn it on under Settings → Business → Screens and operation → Camera feeds in the POS (off by default). The Cameras button then appears in the top bar for anyone with the View camera feeds permission (manager and administrator by default; can also be turned on for waiters under Settings → Permissions). All cameras are shown side by side; tap a camera for a large view. Turning it off: the camera systems are kept.
Also as a separate screen: On a separate screen opens http://<kassaserver>:3000/camera (e.g. a monitor behind the bar), and On a tablet or phone shows a QR code: a staff member scans it with their own tablet or phone and signs in with their own PIN (there too only with the View camera feeds permission). On a narrow screen the cameras are stacked. See Second screen on a tablet or phone.
The manager adds the camera systems with + Camera system, checks them with Test and chooses for each camera its name and whether it's on the page:
- Hikvision, Dahua, Axis and Reolink: a camera or recorder (NVR) in the network: the IP address (optionally with
:poort), a user (preferably view-only) and the channels, e.g.1-8or1,3,5. Login with Basic or Digest; https with your own certificate is fine. - Synology Surveillance Station: the address of the NAS (default port 5000, with https 5001) and a user; Fetch cameras fetches the cameras with their names.
- UniFi Protect: the address of the console (https) and a local account; Fetch cameras.
- ONVIF: any camera or recorder with ONVIF (e.g. Hanwha, Bosch, Uniview, Annke); Fetch cameras looks up the photo address for each video source.
- Own web address: a photo (JPEG), an MJPEG stream or an
rtsp://address. - Camera system web page (e.g. Frigate, Blue Iris or go2rtc): opens in the POS under the Cameras button (or in a separate window).
Without ffmpeg: the photo.
Privacy: the POS fetches the images from the camera system and only passes them on; nothing is stored (no recordings, no cache). Users and passwords stay on the server and never appear on screen or in the log. The log shows who viewed the cameras. The page requests the images themselves with a key (valid for 12 hours, as long as the staff member is signed in), because an image in the browser can't send a token. The configuration export only includes on/off.
Log of sensitive actions
Report → Log (manager or administrator) shows who did what and when.
- Choose a period (today, yesterday, this week, this/last month or your own from-to), what you want to see (by default Sensitive actions, or e.g. only voids and discounts, or All) and optionally one staff member.
- At the top, per staff member: number and amount of voids (removed after ordering), discounts and returns, and how often the drawer was opened without a sale, money out of the drawer, receipt copies, pro formas and manual card payments. Tap a name to see only that staff member. Also the number of times a wrong PIN was entered.
- Below that, every action with time, who, what and a readable description (e.g. "2x Cola removed after ordering € 5,60 · table 4 · reason: customer changed their mind").
- Download (CSV) for Excel.
What is recorded: voids, discounts (and their removal), returns, receipt copies, pro formas, manual card payments, opening the drawer, cash in/out of the drawer, opening float, end-of-day closing, moving lines or tables, closing empty orders, changing product price/name/VAT, new or deleted products, changing staff and settings, adjusting working hours, logging in and out, wrong PINs and clocking in and out. With payment on account also: customers, sales and payments on account, importing bank statements, the bank connection and fetching from the bank. With the alert for long lead time: late orders and apologies sent. With Mailchimp or Klaviyo: connecting, choosing a list, disconnecting and unsubscribes from there. With music control: on/off and adding, editing and removing music sources. With camera feeds: who viewed the cameras (at most once per half hour per staff member), on/off and the camera systems. With alerts: every alert, how it was handled and switching it on and off.
Alerts: fraud and anomalies
Settings → Alerts. Two parts, each switched on separately and off by default; switching off keeps all alerts and settings. Anyone with the Configure alerts permission (by default the manager and the administrator) can set it up; anyone allowed to view the log can see and handle the alerts. The till checks every 5 minutes (and with Check now); not on the shadow till.
Fraud and theft detection (per staff member, per business day from 05:00), each rule switched on or off separately with its own threshold:
- voids after the pro forma: removed after the guest had already seen the bill;
- voids, discounts and returns: from a number of times, or from a total amount (0 = not by amount);
- no-sale drawer open (Open drawer button);
- bill open a long time: ordered but still not paid after a number of minutes.
Anomaly alerts, compared with the same weekday and time in recent weeks (default 4; days without revenue don't count, at least two comparison days):
- revenue so far more than the margin below (and/or above) usual, only from a set normal revenue amount;
- kitchen time (order to the kitchen until ready on the kitchen display) in the last hour above the margin, or above a fixed number of minutes;
- voids today above the margin, only from a minimum number.
Each alert is raised once (per rule, staff member and day; kitchen time at most once per hour) and goes to:
- the till: Alerts (n) button in the top bar with the alerts of the past day, week or 30 days; Dealt with with a note. Other screens only get a notice without names;
- push notification with ntfy (free app; ntfy.sh or your own server, topic and optionally a token), Pushover (the app's API token and the user key) or Telegram (bot token and chat ID);
Each channel has a Test message button. Tokens and keys stay on the till (the screens only see whether they are filled in). An alert is not proof: check the bill and the log and discuss it with the staff member.
Receipts: copy and return (credit note)
Receipts button in the top bar:
- List of receipts since the last end-of-day closing, or the last 7 days; an older receipt can be found by its number.
- Print copy: the same receipt marked "COPY" (in Belgium with the FDM block of the original receipt). Recorded in the log.
- Return / credit note (manager or administrator): choose per line how much is returned, a reason and how the money is refunded (cash, card, gift card, other). The old receipt stays untouched: a new credit note is added with its own number in the journal (ticket type
retour, negative amounts, sent to the FDM as NR in Belgium). You can never return more than was sold. In the X and Z report the return counts as negative revenue. - With CCV or another terminal: first refund on the terminal itself and then tick "Already refunded on the terminal".
- Cash with rounding to 5 cents: the amount to refund is also rounded.
- Back to the account (sale on account): if the receipt was on account for a business customer, choose On account. The amount is deducted from the outstanding invoice and the POS immediately creates a credit note (in UBL a CreditNote, type 381, with a reference to the invoice; in Belgium signed with signInvoice, UC4122). No more than what is outstanding on the invoice can go back to the account; refund the rest in cash or by card. The credit note is listed under Invoices and you send it like an invoice.
Cash drawer with sensor and drawer per staff member
Off by default. Set up under Settings → Payments → Cash drawer.
- Sensor: many drawers report via the receipt printer whether they are open or closed (ESC/POS
DLE EOT 1, DK port pin 3). This only works with a network receipt printer. Tap Measure: drawer closed and Measure: drawer open; if there is a difference, apply the correct setting (high = open or low = open). No difference = this drawer (or cable) has no sensor. No answer from the printer = unknown, never "closed".- Do not check out while the drawer is open: the till server then refuses a new checkout with "The cash drawer is still open".
- Own drawer per staff member: a receipt printer can open two drawers (drawer 1 and drawer 2). Choose each staff member's drawer; the till then opens the drawer of whoever is logged in on cash checkout, money in/out of the drawer and Open drawer. Under Report → Cash drawer you then see Drawer per staff member: opening float per staff member, cash (excluding the cash recycler), expected, Count and the difference per person (in the log as
ladetelling). The ordinary end-of-day closing stays as it is. - Test drawer 1 and Test drawer 2 open the drawer to check it.
- Open drawer without sale is (with a reason) always recorded in the log and in the cash register audit file (XAA), as required by the Dutch Tax Administration (Belastingdienst) (exceptions such as "no sale").
Part 3 · Administrator
Getting started
Installing. You install HorecaPOS with the installer for your system, available on the OptimumPOS download page: Android (app), Windows (installer), macOS (installer for Macs with Apple Silicon and Intel), Linux (graphical installer, or the .deb or .rpm package), Raspberry Pi (graphical installer or .deb for a Raspberry Pi 3, 4 or 5 with 64-bit Raspberry Pi OS) and Chromebook (the Android app from Google Play). Choose for all users for a POS server that tablets and the kitchen display connect to, or just for me for only a till on that device. The installer sets up everything that is needed, including the database, and makes a backup every night. To update, install the new version: your data stays in place. The installer starts in the language of your computer (otherwise English); on Windows and Linux you can choose another language on the first screen. The POS then starts straight away in that language. The .deb and .rpm packages and the Android app follow the system language, otherwise Dutch.
The administrator sets up the till via Settings. There you find tabs such as Business, Staff, Permissions, Working hours, Products, Happy hour, Stock, Floor plans, Payments, Printers, Accounting, Backups, Import/export and Database. Which tabs a manager also sees depends on the permissions.
Database. Under Settings → Database (administrator only) you choose between MySQL / MariaDB, the built-in database and PostgreSQL; when you switch, all data comes along (see Database). If Optimum POS already set a fixed address during installation, that address applies and there are no input fields. Otherwise you fill in the Server, Port, Database, User and Password yourself. The till stores them itself, shows them filled in again afterwards, and you can always change them with Change MySQL/MariaDB details or Change PostgreSQL details. Leaving the password empty means: keep the stored password (for the same user). The installer and an update do not change DATABASE_URL or the chosen database.
Accounting
Everything for accounting is under Settings → Accounting. Fill in the journal and the ledger accounts together with your accountant. If you want the till to post the daily revenue by itself every day, choose your package at the top under Accounting package, Exact Online included: you only see the packages that work in your business's country. Right below it you fill in that package's details and connect. For packages you log in to (such as Exact Online, Twinfield or Xero), first fill in the app: client ID and client secret. If Optimum POS fixed the package or a setting during installation, you will not see that choice or that field. There you will also find an overview of all packages: which can be linked live and which get a file. You create a file under Report → Revenue per period → Accounting export: choose your package's format, or UBL (Peppol), XAF or a daily statement. Always have your accountant check the first entry or import.
For a Dutch business there is also Cash register audit file (XAA): the XML Auditfile Afrekensystemen of the Dutch Tax Administration (Belastingdienst) with all receipts, lines, payments and events of the till over the selected period. You give it to your accountant or, during a tax audit, to the Belastingdienst.
Payroll and scheduling
If your staff clock in and out, Settings → Working hours shows Payroll and scheduling at the bottom, in two blocks. Under Payroll administration you choose your payroll package or (in Belgium) your social secretariat, and enter for each staff member their personnel number in that package. Then you create the file with the hours worked and the revenue per staff member for a period, and import it into your payroll package. Under Staff scheduling you choose your scheduling system: with Deputy, Dyflexis and Shiftbase the revenue goes automatically every hour, with the others you create a revenue file. This way you see the wage costs next to the revenue in your scheduling. If you work without clock in/out, you can still send the revenue to your scheduling: it is then at the bottom of Settings → Accounting, under Revenue to your scheduling. If Optimum POS fixed something during installation, you will not see that choice or that field.
Backups
The till makes a backup automatically every night, and always before an update. Under Settings → Backups you see all backups (when, by whom or automatic, size) and you can make one yourself with Create backup. If the last backup is more than two days old, a red warning appears: contact Optimum POS in that case.
Restoring is done with the Restore button next to a backup. Everything that happened after that backup is then lost. You have to tick a box and enter your own PIN again. The till first makes a safety backup of the current state and then logs everyone out. In Belgium this cannot be done from the till (the black box counters keep running); there Optimum POS does it.
Database
Under Settings → Database (administrator only) you see where the till keeps its data. At the top is the current database with program, version, tables, rows and address or folder. For staff and tablets the till works the same with every database. On Windows, macOS, Linux and Raspberry Pi you choose from three databases:
- MySQL / MariaDB: a separate database program (MySQL 8.0 or newer, MariaDB 10.6 or newer), for example on a server or NAS you already have. All data is then stored in ordinary tables in MySQL or MariaDB, readable by your own reporting or BI software. The till calculates exactly as with PostgreSQL.
- Built-in (PGlite): part of the till itself, nothing to install. The best choice for most businesses, and the database on Android and Chromebook.
- PostgreSQL: a separate database program on the till PC or elsewhere in the network.
When MySQL or MariaDB? If your business already has a MySQL or MariaDB server, if your IT administrator works with it, or if you want to read the data in your own reporting, Excel or BI software. In doubt? Choose built-in: it works straight away.
What do you need for MySQL or MariaDB?
- MySQL 8.0 or newer, or MariaDB 10.6 or newer, reachable from the till server.
- A separate database for the till (or for the tills of a chain), with the character set utf8mb4.
- A database user who may create, alter, rename and drop tables in that database (CREATE, ALTER, DROP, INDEX, SELECT, INSERT, UPDATE, DELETE), for example like this:
CREATE DATABASE horecapos CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
CREATE USER 'horecapos'@'localhost' IDENTIFIED BY 'wachtwoord';
GRANT ALL PRIVILEGES ON horecapos.* TO 'horecapos'@'localhost';
If MySQL or MariaDB runs on another computer, put the IP address of the till server instead of localhost in the last two lines.
Migrating to MySQL / MariaDB:
- Under MySQL/MariaDB address, fill in the fields: Server (default localhost), Port (default 3306), Database (default horecapos), User and Password; the same for MariaDB. If the address is already set, the fields are already filled in; if you leave the password empty, the stored password is kept (for the same user). The till saves the address itself; if Optimum POS has already set a fixed address, that address applies and there are no fields. If the till already runs on MySQL/MariaDB, you change the details later with Change MySQL/MariaDB details. Optimum POS sets up an encrypted connection for you.
- Tap Test connection: you see the program and version, or why it fails.
- Tap Migrate to MySQL/MariaDB, tick that you understand and enter your own PIN.
Migrating works in every direction between the three databases, and all data comes along:
- The till briefly accepts no requests (usually less than a minute); tablets then carry on by themselves.
- First the till makes a backup of the current state (under Settings → Backups).
- Everything goes to the new database and the till counts per table whether everything is there exactly.
- Only when everything matches does the till continue on the new database. Signed-in staff stay signed in.
If anything fails, nothing changes and the till keeps working on the old database. The old database stays in place, so you can always go back. Till data that was already in the new MySQL/MariaDB or PostgreSQL database is replaced. This also works in Belgium: the black box counters are carried over exactly.
Backups and restoring work the same with all three databases (Settings → Backups). A backup from one database can be restored in any other, including a PostgreSQL backup in MySQL or MariaDB.
What is in MySQL or MariaDB? Every table of the till, with the same name and columns (times in UTC). Each table gets the extra key column _hp_sleutel, and in the helper tables _horecapos_stand, _horecapos_kolom, _horecapos_reeks and _horecapos_wijziging (log of changes, kept for 14 days) the till keeps track of the state, the column types, the counters and the changes. Other programs read the data; only the tills write.
How it works: the till calculates in a fast working copy on the till server and writes every change to MySQL/MariaDB in the same step. If that fails, the change does not go through and the till shows an error, so keep MySQL/MariaDB reachable. On startup the till reads everything from MySQL/MariaDB.
Several tills on one database. As with PostgreSQL, several tills can use the same MySQL/MariaDB database, for example each location of a chain with its own till server. Changes are made one after another and each till first takes over what the others did, so nothing is lost when changes happen at the same time. If a till restores a backup or a till with a newer version updates the database, the other tills automatically read everything in again; so update all tills at the same time. A till that was off for more than 14 days reads everything in again on startup.
During installation you also choose the database: MySQL / MariaDB, built-in (recommended) or PostgreSQL with its address. If it cannot be reached, the till installs itself with the built-in database; you can migrate here afterwards. An update keeps the choice.
Linking tablets and displays
- On each tablet/till, open the address of the till server, e.g.
http://192.168.1.20:3000, and add it as a shortcut to the home screen (Chrome: Add to Home screen). - Kitchen screen:
http://192.168.1.20:3000/keuken. - Customer display (facing the customer, optional):
http://192.168.1.20:3000/klantscherm, see Customer display. - The screens find the till server automatically (same address, port 4000).
Customer display
A screen on the till that faces the customer. The customer sees roughly what has been ordered and, very clearly, the amount and how it is being paid. It has no controls: the screen simply follows what the till does. Off by default; turn it on via Settings → Business → Customer display. On a till PC with two screens the till turns it on automatically the first time; if you turn it off afterwards, it stays off. Without a customer display (off, or none connected) everything works exactly as always: the till sends the image in the background and staff never notice an error or a missing screen.
What the customer sees:
- Idle (nobody checking out): the business name and your own welcome text (Settings → Business; empty = "Welcome").
- Ordering: the products with quantity and amount (identical lines combined, a menu as one line with the items in small print below, discount as one line), and the total in large print. Amounts already paid in a split checkout are shown below. With Settings → Business → Product photos → on the customer display a small photo is shown with each product.
- Checkout: the payment method (Card, Cash, Gift card), the tip and, in large print, To pay. Cash: what the customer hands over and the change, once that has been entered on the till. Card: "Follow the instructions on the card terminal".
- Thank you: after checkout, "Thank you!" with the amount paid for a few seconds (cash: the customer's change), then back to the idle screen.
Connecting, in two ways (both set up on the device itself):
- Second monitor on the POS PC (Windows, Linux/Raspberry Pi, macOS): automatic. When you sign in and after installation, the POS puts the customer display full screen on the smallest screen that is not the main screen (the rightmost one if they are the same size); on Windows always on a different screen than the POS (the POS is on the touchscreen and also opens by itself at startup). Size and position come from the system, so any format works. Without a second screen nothing happens. On Windows a closed customer display comes back by itself; on Linux and macOS the shortcut HorecaPOS customer display in the menu puts it back in place. On Windows it opens in the kiosk mode of Chrome (or Edge): full screen, without a title bar and without the taskbar (close with Alt+F4). It follows the POS on the same PC without a pairing code.
- In every browser, a long press never brings up the browser menu anywhere, and no prompt to translate the page appears.
- POS closed = customer display closed. If the POS software stops (Restart, an update, the POS stopped or removed), the customer display also closes after just over 10 seconds; once the POS is running again, it comes back by itself. On Windows it also closes if you only close the POS window. Under Wayland (Linux) the POS cannot close the window itself.
- Customer display closed by accident? On Windows it comes back by itself after a few seconds, as long as the POS is open and the second screen is connected.
- Always just one customer display. On Windows the customer display only runs in kiosk mode on the second screen. A customer display in the POS window (e.g. restored by Edge after a power cut, or opened with the button in the POS) closes by itself within a few seconds; the proper customer display then takes its place.
- Nobody logged in = welcome only. If the POS is on the PIN screen (also after a restart or logging out), the customer display only shows the welcome text, never the previous bill.
- On Windows you can also turn off automatic opening with the checkbox Open customer display automatically ... in the installer.
- On Linux the POS moves the window with wmctrl (included in the package). Under Wayland (e.g. Raspberry Pi OS with labwc) this is not possible: move the customer display to the second screen yourself once (the browser remembers it), or choose X11 in raspi-config. On macOS the Mac asks for permission under Accessibility the first time.
- Manually: Settings → Business → Customer display → Open customer display (second monitor). In Chrome and Edge (also on a Chromebook) the button places the window straight onto the customer display (the first time the browser asks for permission); one click on the customer display makes it full screen. In other browsers: drag it and press F11.
- Android POS with a built-in customer display (e.g. Sunmi D2/T2) or a monitor via HDMI/USB-C: also automatic. As soon as the app is on a POS, the customer display appears on the second screen; plugging in and out works immediately.
- Sunmi T1 mini / T2 mini with the small text display (2 lines): the app automatically shows the amount there: Total, To pay, for cash Change, after payment Thank you! and when idle the name of the business. The customer display must be switched on.
- iPad (operator screen) with an external screen via HDMI/USB-C or AirPlay: the app automatically puts the customer display on that screen (prepared; the iOS app has not been released yet).
- Chromebook: as an operator screen in Chrome, the button Open customer display (second monitor) works as described above. In the Android app the customer display appears on the second screen automatically as soon as ChromeOS passes that screen to Android apps; if it does not, use a separate device with a pairing code.
- Separate device (tablet or own PC next to the till): open
http://<kassaserver>:3000/klantscherm. The screen shows a pairing code of 6 characters at the bottom right. Enter it on the till under Settings → Business → Customer display → Pair. Unpair sets the screen back to the pairing code. The pairing is saved per till (in that till's browser), so each till can have its own customer display.
The customer display does not ask for a PIN (there is nothing to operate) and only shows the image of the till it is paired with. The image is only kept in the till server's memory; after a restart the screen is empty until the next change. The setting (on/off and welcome text) is included in the backup and in Import/export (Other settings).
Digital receipt via QR (optional)
Off by default. Turn it on via Settings → Business → Kitchen and customer display → Digital receipt (the option appears when the customer display is saved as on). After checkout a QR code appears with Thank you; it then stays for 45 seconds instead of a few seconds. The guest scans it with their own phone and sees the receipt exactly like the paper receipt (same text, on a Belgian till also with the FDM block). On the phone they can print the receipt, save it as a PDF or download it as a text file.
- It goes through the management portal:
https://kassa.<portaal>/__bon/<kassa>/<sleutel>. So the till must be connected to the portal; otherwise no QR code appears and nothing changes. - The key is random and cannot be guessed, and is valid for 30 days. After that the till cleans it up automatically. The portal stores nothing.
- Works with a second monitor and with a separate customer display. The paper receipt and the receipt by email keep working as usual.
Customer display when idle: slideshow (optional)
Off by default. Turn it on via Settings → Business → Kitchen and customer display → Customer display when idle. When there is no bill on the customer display, the slides alternate (by default every 8 seconds, adjustable from 4 to 60):
- Promotions: the happy hours (if happy hour is on), with the discount, the days and times and the products or categories; the ones running now come first, with "Now!".
- Featured products (at most 12, for example new on the menu), with price and (if product photos on the customer display are on) the photo. A sold-out product is skipped.
- The loyalty card: points per euro, the reward and the stamp cards (only if the loyalty card is on).
- Custom texts: at most 5, each on its own slide (for example "New from Friday: our summer menu").
Without slides the customer display shows the welcome screen, as always.
Happy hour
Off by default. Turn it on via Settings → Business → Use happy hour; the Settings → Happy hour tab then appears.
- Per happy hour: name (shown on the receipt), days, from–to (may run past midnight, e.g. 23:00–01:00), discount in % or a fixed price, and for which product groups and/or individual products.
- Within that time slot the till automatically charges the happy hour price when items are entered (never more expensive than normal; with a fixed price, options are added as usual). The product button shows the old price crossed out with the new price and HH; the order and the receipt show the name of the happy hour. Items already entered keep their price.
- Daily deal: tick All day (00:00–24:00) and choose the day(s), e.g. spareribs for a fixed price every Tuesday.
- Season: tick Only in a season (every year) and choose from and until (day and month, e.g. 1 June to 31 August; spanning the new year is allowed, e.g. 1 December to 28 February). Outside the season the happy hour does not apply.
- Changes are recorded in the log.
Dayparts and seasons
Off by default. Turn it on via Settings → Business → Dayparts and order types → Menu per daypart and season; the Settings → Dayparts tab then appears. If you turn it off, all products can always be sold again and the dayparts are kept.
- Per daypart: name (e.g. Breakfast, Lunch, Dinner, Summer menu), days, from–to (may run past midnight; All day = 00:00–24:00), optionally a season (every year, day and month), and which categories and/or individual products belong to it.
- Products and categories that are in one or more dayparts can only be sold while one of those dayparts is running; anything that is not in any daypart can always be sold. The order screen only shows what can be sold now and switches automatically when a daypart starts or ends; the server refuses the rest ("not available now, only at Breakfast").
- The webshop shows and charges the same menu (at the time of ordering).
- A different price on a certain day or in a season is a happy hour (daily deal, see above).
- Menu per location: each till (branch) has its own products, dayparts and prices.
- Changes are recorded in the log.
Menu and prices per order type
Off by default. Turn it on via Settings → Business → Dayparts and order types → Menu and prices per order type. If you turn it off, the normal price applies everywhere again and everything can be sold everywhere; the prices entered are kept.
- In Settings → Products, per product: Takeaway price and Delivery price (empty = the normal price) and Sold for (dine-in, takeaway, delivery; at least one). For a category also Sold for, for all products in that category.
- For a takeaway or delivery order, the order screen shows the price for that order type and only what is sold for it; the server charges that price and refuses the rest. Happy hour, menus and options are calculated with that price.
- The VAT rate for takeaway (on the product) is separate from this, as always.
- For pick-up and delivery, the webshop shows the prices and products for that choice (when switching, the menu page reloads), and at the table those for dine-in.
- Export and import of the configuration (Settings → Import/export) include the prices per order type, "sold for", the dayparts and the season of happy hours.
Menus
Off by default. Turn it on via Settings → Business → Use menus.
- A menu is a normal product (with the menu price) for which you set up components under Settings → Products → (product) → Menu:
- fixed: always this product (e.g. "Drink: House wine");
- choice: choose 1 (or more) from a product group, optionally limited to certain products (e.g. "Main course: choose 1 from Main courses").
- Per component the course (1 = immediately, 2/3 = wait until called).
- When you enter the menu, you choose the dishes for each component. For each dish (including fixed ones) you can choose the options as for an individual product (cooking preference, extra cheese; required options must be chosen) and a note. Option surcharges are added to the menu price. The menu appears as one line with the dishes (and their options) below it.
- The dishes go to the kitchen/bar as separate lines (kitchen ticket and kitchen screen), in their own course. The menu line itself does not.
- For VAT, the menu price is split across the components in proportion to their normal price, so food and drinks each get the correct rate. The receipt shows the menu with the total price and the dishes below it.
- If the menu itself has options (e.g. size), you choose them at the top of the menu window. They are shown with the menu line on the receipt, and with each dish of the menu on the kitchen ticket and kitchen screen as "(menu)".
- Removing/voiding is done per whole menu (tap the menu line).
- Split / move: choose the menu line; the dishes move along. With 2× the same menu you can also move 1 (header and dishes are split).
- Without a connection you can still enter menus; they are saved on the tablet and sent as soon as the connection is back (just like individual products).
- Happy hour can also apply to a menu.
Recipes and cost price (Apicbase)
Integration with Apicbase (recipes, cost price, stock and purchasing) via the Apicbase Generic POS API (off by default, each part can be switched on or off separately). Set up under Settings → Recipes (permission Set up business, payments and printers). The POS talks to Apicbase itself (outgoing traffic only, no portal needed).
- Connect (all to be filled in by the administrator), in one of three ways:
- Paste token: in Apicbase Library Settings → API Settings → New token → Service Account Token (scopes accounts, library, sales); paste the access token and refresh token;
- Log in with the business's own API-app (client-id and client secret from API Settings): Log in to Apicbase, then paste the code Apicbase shows;
- An expired token (after 7 days) is renewed automatically by the POS with the refresh token.
- Outlet: Fetch outlets and choose this business's outlet. The POS sets the POS there to Generic POS API with its own location-id (editable; default
HORECAPOS-…, unique per POS). - On, with checkboxes:
- Products, groups and options to Apicbase: product groups, products (PLU = the product's PLU number, otherwise the code, otherwise the id), options as modifiers, with price and VAT. Automatically after every change (after one minute) and every day. In Apicbase you then link each POS product to a recipe;
- Every paid receipt to Apicbase: oldest first, at most 100 at a time, within a quarter of an hour after payment (and every 5 minutes). Discount is spread over the lines; open amounts, disposables surcharge and deposit appear as separate products in Apicbase; weighed products as 1 piece with the total amount. If it fails, the POS stops (Apicbase wants the receipts in order) and tries again later: checkout is not affected. When switching on, you choose from which day (default from now);
- Fetch cost per portion (every 6 hours): per linked recipe the food cost (ingredients and waste), with personnel cost, the selling price and the margin according to Apicbase. Calculated using the cheapest supplier, the last ordered price or the average stock value;
- Take over selling price from Apicbase (off by default): set the selling price of linked products in the POS (recorded in the log).
- At the bottom: Cost price per product with cost price, cost price with personnel, price in the POS, cost price % and margin. Buttons Send catalogue now, Send receipts now and Fetch cost prices now.
Code: apps/pos-server/src/lib/apicbase.ts, routes/apicbase.ts; screen Apicbase.tsx. Log: Apicbase. Requirement: the Apicbase API module. For the Pin Voordeel app for all customers: partnership and certification with Apicbase (see the backlog). Documentation: https://developers.apicbase.com/docs/generic-pos-api-guide
Hotel software: charge to room
For a restaurant or bar at a hotel: charge the bill to a guest's room. Off by default: Settings → Hotel (permission Set up business, payments and printers).
- One list with all hotel software (The hotel's hotel software). Built-in integrations:
- Mews (Connector API: client token and access token, the restaurant's service and, per VAT rate, the Mews VAT code), apaleo (your own app with client ID and client secret, the property ID; per VAT rate optionally the VAT type) and Cloudbeds (API key and property ID), each with a test and a live environment;
- Oracle OPERA Cloud (OHIP), protel (protel I/O), RoomRaccoon, Booking Experts, Amadeus (XMLPOS), VIPS, Stayntouch, Clock PMS+, Guestline (Rezlynx), Hotelogix, eviivo, Little Hotelier, Shiji and Infor HMS (Databridge). After choosing, exactly the fields that belong to that hotel software are shown (keys, hotel ID, if needed the address of their API and, per VAT rate, their code), with a short explanation of what to request from the supplier. These integrations are built according to the suppliers' documentation; have the supplier confirm the integration and try it first with Test connection and one receipt;
- a demo (four suites, rooms 4 to 7) to try it out;
- Sirvoy, as a half integration and only with Sirvoy Pro. Sirvoy has no API for a POS to add anything to a booking, not even via a file (the CSV import only creates new bookings). With it, the POS knows the guests (room, name, arrival, departure): searching under Charge to room, and self-service at the kiosk and in the webshop work as usual. The receipt does not reach Sirvoy automatically: after checkout it is listed under Settings → Hotel in Still to enter in Sirvoy, with the room, the guest, the receipt number and the amount per VAT rate. The hotel adds it manually as an extra to the booking and clicks Entered (undo with Not yet after all). Required:
- preferably a POS connected to the management portal: the address then runs via the portal (
https://<portaal>/hotel/<kassa-id>/sirvoy?sleutel=...) and no port needs to be opened in the hotel. Otherwise the POS itself must be reachable from the internet over https (own domain with certificate or port forwarding; Sirvoy requires TLS 1.2 or higher) and you enter that address; - The address is shown only once; the POS stores only the hash. Creating a new address = the old one stops working;
- preferably a POS connected to the management portal: the address then runs via the portal (
Sirvoy only sends something when a booking changes: bookings from before connecting become known to the POS only after a change in Sirvoy. Messages may arrive out of order; a message older (generatedAt) than what the POS already has is skipped. In the hotel = not cancelled and not checked out, checked in or arriving today or earlier, and departing today or later. Test connection shows how many bookings came in.
All hotel software is available in the Netherlands and/or Belgium. Test connection checks the details. Code per integration: apps/pos-server/src/lib/pms/<naam>.ts.
- Self-service (off by default): hotel guests charge their order to their room themselves, at the kiosk and/or in the webshop (pickup and delivery, not ordering at the table). They enter their room number and surname; the POS checks with the hotel software whether that guest is currently staying in that room. With a maximum per order (default € 150), and after 5 failed attempts within fifteen minutes the guest must go to the front desk first. The message never reveals who is staying in a room.
- Checkout: when the integration is on, there is the payment method Charge to room. Look up the guest by name or room number (only guests currently staying at the hotel) and tap Charge to room .... The POS posts the receipt per VAT rate to the guest's hotel bill; the guest pays at check-out.
- Belgium: if the order is already registered at a table with the black box, it is first moved from the table to the room (signCostCenterChange to ROOM, UC4101); the receipt goes to the black box as room credit (ROOM_CREDIT).
- If posting to the hotel software fails (no internet), the sale is still recorded and the posting is shown as Failed under Settings → Hotel, with Retry.
- Reports and accounting: Charge to room (hotel) is a separate payment method on the X and Z report, in the daily statement and in the audit file (XAA).
Code: apps/pos-server/src/lib/hotel.ts, routes/hotel.ts, the integrations in lib/pms/, catalogue packages/shared/src/hotelcatalogus.ts; screen Hotel.tsx. Log: Hotel. Secrets (tokens) are stored only in the database, never on screen.
Wine management with Vinify
Settings → Wine management (off by default; switching it off keeps everything). Vinify keeps track of the wine cellar, the wine list and the stock, and is the main source of the wines. In line with Vinify's POS requirements, the POS offers an API that lets Vinify:
Authenticate, using all three methods Vinify supports (the administrator chooses which are on):
- API ID and API key (
X-Api-IdandX-Api-Key, orAuthorization: Bearer <id>:<sleutel>); - API key and API secret with a signature:
X-Api-Key,X-TimestampandX-Signature= hex HMAC-SHA256(secret,<timestamp>\n<METHODE>\n<pad met query>\n<sha256 van de body>), at most 5 minutes old.
The POS creates the key and the secret (shown once); the screens only show whether they are filled in. Reachable via the portal at https://<portaal>/vinify/<kassa-id>/... (no port opened on the premises; the address is in Settings → Wine management). Which products are wine: whatever Vinify creates, plus the groups you tick. If Vinify provides an address to send sales to, the POS also sends them itself (push, with a token): after every paid receipt and every 5 minutes whatever has not yet gone through. Vinify enables the HorecaPOS integration (hello@vinify.no). Everything is in the log. Not to be confused with Vinify.nl, an online wine shop: it is listed under the suppliers (Order from suppliers).
Quick address entry with postcode and house number
Turn on under Settings → Business → Quick address entry (off by default; only for a business in the Netherlands). Type the postcode and house number (also with a letter or addition, e.g. 12A or 12-1) and tap Find address: street, house number, postcode and town are filled in. If there are several addresses at that number (12, 12A, 12B), choose the right one. You can still change everything yourself afterwards.
- In the business details (Settings → Business, above the address).
- For a loyalty card customer: at the till when adding a new customer and under Report → Customers. For this, customers get an (optional) address: street and house number, postcode and town.
- The addresses come from the free PDOK Location Server (the official addresses of the Netherlands, BAG): no account or key needed, but internet is. Without internet or for a Belgian address, just type the address yourself.
Notification of a new version
Turn it on under Settings → Business → Update notification (off by default).
- Till updated: if the till server has been updated while a tablet still has the old screens open, the top shows "The till has been updated (version …)" with Refresh. The tablet checks every 5 minutes, when the screen becomes visible again and after a server restart.
- Update available: if the till is linked to the management portal (
PORTAAL_URL/PORTAAL_SLEUTEL) andNIEUWSTE_VERSIEis filled in there, users allowed to manage settings see "Update available: version …" (with the explanation fromUPDATE_NOTITIE). Later hides the notification on that tablet until there is a newer version again. Updating works as always withscripts\windows\update.cmd(see Updating).
Booking platforms
Bookings from TheFork, Formitable, Zenchef, Resengo (Belgium only), OpenTable (Netherlands only), PlanPanther, RestoManager and Aqqo (Netherlands only) appear automatically in the till and on the floor plan. Switch on under Settings → Booking platforms (off by default). Only possible if Reservations is switched on.
- Venue country: you can only choose platforms that work in the venue's country (Resengo only in Belgium, OpenTable and Aqqo only in the Netherlands). The server checks this too.
- Several platforms at once: you can connect several platforms side by side, for example TheFork and Formitable. Two platforms never get the same table in the same time slot; the second reservation then comes in without a table.
- + Connect platform: choose the platform and enter the details. Secrets (client secret, callback key) are never shown in the overview; leave empty = keep, Clear = remove.
- TheFork (public B2B API): Restaurant UUID, Client ID and Client Secret (request them from TheFork). If the till cancels, it also cancels at TheFork.
- Formitable, Zenchef, Resengo, OpenTable, PlanPanther, RestoManager, Aqqo: their API is for partners only or not public (PlanPanther, RestoManager and Aqqo: a POS integration is arranged in consultation with them). Formitable events (
booking.created,.changed,.canceled,.checkin,.checkout) are recognised. - On the floor plan: if a table in the till has the same name as the platform's table and is free in that time slot, the booking goes on that table; otherwise without a table (choose one on arrival). A booking that comes in again is updated, not duplicated. The overview shows "via TheFork".
- Status: if the platform cancels or reports a no-show, the till adopts it. Anything already marked as arrived in the till stays arrived.
- Report back (no-shows sent back): enter a callback URL (for example from your integration service). The till sends every change made in the till (arrived, no-show, cancelled, paid with amount) as JSON:
{ platform, id, status, statusEn, bedrag, valuta, tafel, tijdstip, gemeldOp }(amount in cents, only when paid), withAuthorization: Bearer <terugmeld-sleutel>if you enter one. If it fails, the till retries every minute and the error is shown at the platform. Anything that came from the platform itself is not sent back. - Test booking: creates a booking as the platform would send it.
- Remove: the connection and the key are deleted; the bookings stay.
- All changes are recorded in the log (without secrets).
Loyalty programmes and reviews
Two separate switches under Settings → Loyalty and reviews (both off by default, then none of it is visible anywhere). If you turn them off, the settings and anything that has already happened are kept.
Loyalty programme from another platform: the guest earns points with Joyn (Belgium) and/or Piggy (Leat; the Netherlands and Belgium). This is separate from the POS's own loyalty card, which can simply stay on alongside it.
- More at once: in Belgium Piggy and Joyn can be on together, each with its own details (choose the platform, fill in, Save; Edit and Delete per platform). The guest gets a separate QR code on the receipt, a separate link in the emailed receipt and a separate button in the webshop for each programme, and earns points once per order for each programme. Whatever was already set up simply keeps working.
- QR code on the receipt: after checkout, a QR code with "Scan and earn points with ..." appears below the receipt. The emailed receipt contains a link, and the webshop (collection and delivery) shows a button on the order page and a link in the confirmation email. An order earns points only once: receipt, email and webshop use the same unique code (the order number). You can turn off "QR code on the printed receipt"; the email and the webshop still get the link.
- Piggy, method "QR code and link": enter the address of your Piggy customer portal, the Shop UUID and the Account secret (Piggy Business Dashboard). Works without internet: the POS creates the link itself.
- Piggy, method "Credit straight away": also enter a personal access token (Piggy → Marketplace → Private App). If the POS emails the receipt and the guest with that email address is already a member, the POS credits the points straight away; the receipt then says "Points credited with Piggy". The POS never creates a new member; no member (or no email address) = the QR code.
- Joyn, method "QR code and link": with the Joyn partner key, shop reference and shared secret (request them from api-integration@joyn.be). Works without internet. The QR code is valid for 2 hours.
- Joyn, method "Via the API": with the shop API key (turn on the integration in the Joyn merchant portal). At checkout the POS requests a loyalty code from Joyn. Redeeming works as usual on the Joyn-iPad.
- Create sample link: checks that the details are correct (a link for € 10; open it only to have a look).
- Only the platforms of the business's country can be selected; the secrets are stored only in the database and never appear on screen (leave empty = keep).
Ask for reviews: after the visit, one email with a button to Google and/or Trustpilot.
- A few hours later (adjustable, default 3) the guest gets the email, in the language of the receipt.
- Webshop: for collection and delivery, the webshop sends the email itself, a few hours after the order has been completed at the POS, in the guest's language.
- Google: paste the review link from your Business Profile (Google → your Business Profile → Ask for reviews,
https://g.page/r/.../review) or enter the Place ID. - Trustpilot: enter your business's domain (the button goes to
trustpilot.com/evaluate/<domein>). If you have a Trustpilot invitation address (Automatic Feedback Service,...@invite.trustpilot.com), enter it as well: the email is then sent to Trustpilot as BCC, with the name, email address and receipt number hidden, and Trustpilot sends the invitation itself (no separate Trustpilot button then). Only Trustpilot with an invitation address: the POS emails for Trustpilot only. - Not too often: the same guest (email address) gets at most one request per period (default 90 days; 0 = every time). For this the POS stores only a hash of the address; the email address itself is deleted as soon as the email has been sent (if sending fails, after three attempts, and otherwise after 14 days).
- QR code on the receipt (optional): also a QR code for a review below the printed receipt.
- Sample email and Delete pending emails (the addresses are then deleted immediately). The log shows review_gevraagd with a***@domain.com.
- Google and Trustpilot forbid rewarding reviews and asking only happy guests ("review gating"). That is why the POS asks everyone the same way and gives nothing in return for a review.
- Read and reply to reviews in the POS: see Review management below.
Mailchimp and Klaviyo integration
Your loyalty card customers in your own email program: under Settings → Business → Mailchimp and Klaviyo (below text and email marketing). There is no switch: without a connection with a chosen list, nothing happens.
- Connect: with an API key (Mailchimp: Profiel → Extra → API keys; Klaviyo: a private key
pk_…with write access to Lists, Profiles, Subscriptions, Events, Campaigns and Templates). The client secret and the key are never shown again (leave empty = keep). Then choose the list (Mailchimp: audience). - Customers: anyone who consented to email goes to the list (subscribed), with first name, last name, phone, birthday and points (Mailchimp: field
PUNTEN, created by the till itself; Klaviyo: propertypunten). Consent withdrawn, email address changed or customer deleted: unsubscribed. Only what changed is sent again. With a connection, the till (and the "offers" tick box in the webshop) also asks new customers for email consent, and it can be changed under Report → Customers, even without the built-in email marketing. - Unsubscribing: anyone who unsubscribes in Mailchimp or Klaviyo no longer has email consent in the till either (log: "unsubscribed in Mailchimp"). The till never resubscribes someone who unsubscribed themselves.
- Orders: every paid receipt of a customer on the list is sent as an event (Mailchimp:
bestelling, with amount, receipt number and quantity; Klaviyo:Placed Order, with the value in euros). Use it to set up automated emails in your email program, e.g. after the first order or when someone hasn't visited for a month. Receipts from before the list was chosen are not sent. - Campaigns: under Report → Marketing you can also send a campaign via Mailchimp or Klaviyo (see Text and email marketing); the till then creates the campaign there and sends it.
- Updating: every 5 minutes, or with Update now. Disconnecting: removed from the till; everything stays in Mailchimp and Klaviyo. Keys are stored in the database (included in the backup, not in the configuration export).
Code: lib/mailinglijst.ts, routes/mailinglijst.ts and MailingKoppelingen.tsx.
BI and data export
Sales data to Power BI, Looker Studio, Excel, Google Sheets, Tableau, Qlik Sense, Metabase, a BI service (for example YourBI, BI4Horeca or Moore DRV) or your own data warehouse. Switch it on under Settings → BI and data export (off by default). Read-only: an integration cannot change anything in the till. No guest data.
- Data: receipts (including credit receipts), products sold (receipt lines), payments, turnover per day, turnover per hour, voids, products, staff (without PIN) and hours worked. Amounts in euros with a full stop as decimal separator, times in the business's local time.
- + Integration: choose the package and the method. Each package supports one or more methods; you can have several integrations at once (even for the same package).
- The package retrieves the data itself (API): the till issues a read-only key once. Period with
?van=&tot=(YYYY-MM-DD) or a fixed address with?periode=(today, yesterday, 7d, 30d, 90d, 365d, week, month, last month, year); at most 366 days, at most 200,000 lines. The key inAuthorization: Bearer,X-Sleutelor?sleutel=. - Via the portal: if the till is linked to the customer portal, the same address also works from outside the premises, without opening a port:
https://<portaal>/bi/<kassa-id>/<gegevens>?periode=90d&formaat=csv&sleutel=.... This way the Power BI service refreshes it on schedule (without a gateway) and Google Sheets can retrieve it with=IMPORTDATA("...")(also the source for Looker Studio). The till shows the address with the integration. - Chain overview via the customer portal (several businesses): one address and one key for all your tills together. In every till that should take part, turn on Chain overview via the customer portal (below the BI switch) and create a key in the customer portal under My POS systems → BI for all your businesses. Then:
https://<portaal>/bi/keten/<gegevens>?periode=90d&formaat=csv&sleutel=hpk_.... The portal fetches the data from each till and merges it, withkassaIdandzaakon each line. Tills that are offline or not taking part are listed inontbrekend(JSON) and in theX-Ontbrekendheader. The till itself needs no key of its own for this; turning it off in the till or in the customer portal stops it. - With a token, it is sent as
Authorization: Bearerand a signature is included inX-HorecaPOS-Handtekening(sha256=HMAC of the content). If it fails, the till retries every minute; nothing is sent twice. With from it also sends older receipts. - The till delivers files: every day (at a set time, the previous day; missed days are caught up) or every hour (today so far), as CSV (comma, or semicolon for Dutch Excel) or JSON, to a folder on the POS computer (for example a OneDrive or SharePoint folder for Power BI or Excel), an FTP(S) or SFTP server or by email. File names:
horecapos_<gegevens>_<datum>.csv. - Send test (push) and Export now (file) with the integration.
- Download yourself: choose data, period and format.
- Power BI template (
.pbit): a ready-made report for Power BI Desktop, via Download Power BI template under BI and data export. First create an API connection (Power BI). In the model: a table per dataset with the correct types, a calendar (year, month, week, weekday), relationships (date → calendar, receipt lines → products, hours worked → employees) and measures (revenue incl. and excl. VAT, VAT, tips, receipts, guests, average per receipt and per guest, quantity sold, product revenue, paid, voids, hours worked, revenue per hour worked). Three pages: Overview (key figures, revenue per day, weekday and hour, payment methods), Products (per group and per product) and Staff (hours and revenue per employee). Via the portal, the Power BI service also refreshes it on a schedule. - Secrets (token, password, key) never appear in the overview; leave empty = keep, Clear = remove. Everything is recorded in the log (without secrets).
Payroll and scheduling
With Clock in/out on (Settings → Business), Settings → Working hours shows Payroll and scheduling at the bottom (permission Manage settings), in two separate blocks. If clocking is off, there are no hours: then only the Staff scheduling block (the revenue, live or as a revenue file) is shown at the bottom of Settings → Accounting, under the heading Revenue to your scheduling:
- Payroll administration (payroll): choose the payroll package or (Belgium) the social secretariat, fill in its fields and for each staff member their personnel number in that package. Then you create for a period the file with the hours worked (closed shifts, per staff member per day of clocking in) and the revenue per staff member (excl. VAT, what he/she checked out): ready-made for Loket.nl (Variabele gegevens, total per staff member over the period, header row
aanslnr;persnr;ploeg;<looncomponent>) and SD Worx Belgium (Tijdsregistratie, fixed positions, per staff member per day), otherwise the hours list (CSV: Datum; Personeelsnummer; Naam; Uren; Omzet excl. btw). Staff members without a personnel number are not included in the Loket or SD Worx file; the till reports who they are. - Staff scheduling (WFM): choose the scheduling system. Sending again overwrites. In addition the revenue list (CSV per day and hour, excl. and incl. VAT) and for Strobbo the Excel file for Importeer omzet.
- Only packages that work in the business's country, per group and in alphabetical order; the server refuses a package from another country (400).
- Keys and tokens are never shown on screen.
- Affects the accounting: the payroll package posts the wage costs in the accounting, the till posts the revenue (Settings → Accounting). AFAS Payroll and Exact Online Loon are in the same environment as the accounting of AFAS and Exact.
- This is not possible on the copy of the till on the portal (the till in the business does it).
- For a number of packages the API is not public or only for partners (e.g. Loket, Nmbrs, Nostradamus, Employes, Shyfter, Planday, Eitje): these are listed as on request; until then the file. The layout for SD Worx and Strobbo comes from their documentation: have the first import checked.
| Package | NL | BE | Live | File | Note |
|---|---|---|---|---|---|
| Payroll software and payroll providers | |||||
| ADP | ✓ | ✓ | on request | Hours list per staff member and day (CSV) | Integration via ADP (on request); until then the hours list per staff member and day. |
| AFAS Payroll | ✓ | – | on request | Hours list per staff member and day (CSV) | Payroll administration in AFAS Profit (same environment as the accounting in AFAS); integration on request, until then the hours list. |
| BCS HR | ✓ | – | on request | Hours list per staff member and day (CSV) | Integration via BCS (on request); until then the hours list. |
| Buddee | ✓ | – | on request | Hours list per staff member and day (CSV) | HR and payroll software; integration on request, until then the hours list per staff member and day. |
| Employes | ✓ | – | on request | Hours list per staff member and day (CSV) | Employes has an API for hours worked (token from the customer); the integration will follow after coordination with Employes. Until then the hours list. |
| Exact Online Loon | ✓ | – | on request | Hours list per staff member and day (CSV) | Payroll administration in Exact Online (same environment as the accounting in Exact); integration on request, until then the hours list. |
| Humanwave | ✓ | – | on request | Hours list per staff member and day (CSV) | Integration via Humanwave (on request); until then the hours list. |
| Loket.nl | ✓ | – | on request | Loket.nl Variabele gegevens (CSV), Hours list per staff member and day (CSV) | File for Werkgever → Collectieve mutaties → Importeren → Variabele gegevens (hours per staff member over the period). Live via the Loket API after signing up with Loket. |
| Nmbrs | ✓ | – | on request | Hours list per staff member and day (CSV) | Hours list per staff member and day, to transfer into Nmbrs. Live via the Nmbrs API after registering an app with Nmbrs. |
| Salar (Van Winckel) | ✓ | – | – | Hours list per staff member and day (CSV) | Hours list per staff member and day for the payroll bureau; the import format of Salar is not public. |
| Social secretariats | |||||
| Acerta | – | ✓ | on request | Hours list per staff member and day (CSV) | Social secretariat: you get the layout of the performance file from Acerta; until then the hours list. |
| Group S | – | ✓ | on request | Hours list per staff member and day (CSV) | Social secretariat: you get the layout of the performance file from Group S; until then the hours list. |
| Liantis | – | ✓ | on request | Hours list per staff member and day (CSV) | Social secretariat with an API that Liantis releases per company; until then the hours list. |
| Partena Professional | – | ✓ | on request | Hours list per staff member and day (CSV) | Social secretariat: you get the layout of the performance file from Partena; until then the hours list. |
| SD Worx | ✓ | ✓ | – | SD Worx Tijdsregistratie (TXT), Hours list per staff member and day (CSV) | Belgium: Tijdsregistratie file (fixed positions, per staff member per day) for "Tijdsregistratie importeren". Netherlands: the hours list. |
| Securex | – | ✓ | on request | Hours list per staff member and day (CSV) | Social secretariat: integrations run via partners; until then the hours list. |
| Scheduling and time tracking | |||||
| Book'u | – | ✓ | on request | Revenue per day and hour (CSV) | Book'u files the Dimona declarations; a till integration is available on request. Until then the revenue list. |
| Deputy | ✓ | ✓ | ✓ | Revenue per day and hour (CSV) | Live: the revenue per hour goes to Deputy (Sales) every hour. You create a permanent token in Deputy under API integrations. |
| Dyflexis | ✓ | – | ✓ | Revenue per day and hour (CSV) | Live: the revenue per hour goes to Dyflexis (information streams) every hour. You get the API token via Dyflexis. |
| Eitje | ✓ | – | on request | Revenue per day and hour (CSV) | Eitje connects via its partner programme; until then the revenue list per day and hour. |
| Exact Horeko | ✓ | – | on request | Revenue per day and hour (CSV) | Integration via Horeko (on request); until then the revenue list. |
| Fooks | ✓ | – | on request | Revenue per day and hour (CSV) | Fooks builds till integrations itself; until then the revenue list per day and hour. |
| L1NDA | ✓ | – | on request | Revenue per day and hour (CSV) | L1NDA builds till integrations together with partners; until then the revenue list per day and hour. |
| Mr. Einstein | ✓ | – | on request | Revenue per day and hour (CSV) | HR, rotas and wage costs for hospitality; Mr. Einstein builds till integrations together with the POS supplier (apply via mreinstein.nl/contact). Until then the revenue list per day and hour. |
| Nostradamus | ✓ | ✓ | on request | Revenue per day and hour (CSV) | Nostradamus accepts the revenue via its till interface (API token and the business's domain, after applying to Nostradamus); until then the revenue list per day and hour. |
| Plan-Me | – | ✓ | on request | Revenue per day and hour (CSV) | Plan-Me files the Dimona declarations; a till integration is available on request. Until then the revenue list. |
| Planday | ✓ | ✓ | on request | Revenue per day and hour (CSV) | Planday has an open API for till systems; the integration will follow after coordination. Until then the revenue list. |
| Shiftbase | ✓ | – | ✓ | Revenue per day and hour (CSV) | Live: the revenue per day goes every hour to the department's logbook in Shiftbase. You create the API key in Shiftbase under App center. |
| Shyfter | – | ✓ | on request | Revenue per day and hour (CSV) | Shyfter files the Dimona declarations and accepts revenue per day via its API; the integration will follow after coordination with Shyfter. Until then the revenue list. |
| Strobbo | ✓ | ✓ | – | Strobbo revenue import (Excel), Revenue per day and hour (CSV) | Excel file for Planning → € → Importeer omzet (revenue per day per workplace). |
| Tamigo | ✓ | ✓ | on request | Revenue per day and hour (CSV) | Integration via Tamigo (on request); until then the revenue list. |
| Werktijden.nl | ✓ | – | – | Revenue per day and hour (CSV), Hours list per staff member and day (CSV) | Werktijden.nl records the hours itself and does not (yet) accept revenue via its API; the lists are there for comparison. |
| XPS Logic | ✓ | – | on request | Revenue per day and hour (CSV) | XPS Logic focuses on flexible and temporary agency staff; an integration is available on request. Until then the revenue list. |
Legal requirements in Belgium and the Netherlands
What the law requires and what HorecaPOS does for it (have your accountant confirm what applies to your business):
| Country | Requirement | HorecaPOS |
|---|---|---|
| Belgium | Registered cash register system (GKS 2.0) with black box for hospitality businesses that must comply (incl. with more than € 25.000 annual revenue from meals, excl. VAT) | link with the black box (FDM), the mandatory data on the receipt and the counters on the Z report (country Belgium under Settings → Business, FDM_API_KEY and FDM_TERMINAL_ID); at the top of Settings → Business you choose whether the business is GKS-obligated: Yes = check out only with a working black box, No = without, with a declaration by the admin (renewed every year); as long as nothing is chosen, checkout is not possible. The till counts the revenue from meals and warns above € 25.000 |
| Belgium | E-invoicing via Peppol: since 1 January 2026, invoices between Belgian VAT-registered businesses must be structured electronic invoices (UBL, Peppol BIS 3); till receipts to consumers are not covered | export of daily turnover as UBL according to Peppol BIS Billing 3.0 for the accounting package (Accounting export); and invoices from a receipt for business customers (Settings → Invoices): UBL according to Peppol BIS Billing 3.0 plus a printable invoice, sent by email, via Billit to the Peppol network, to your own address or downloaded (see Invoices for business customers) |
| Belgium | Hospitality VAT since 1 March 2026: takeaway meals and non-alcoholic drinks 12% (eat-in and takeaway), alcohol 21%, meals the customer still prepares themselves (fondue, gourmet) 6% | VAT assistant (Settings → Laws and rules): the type per product, the correct rate immediately or from a date; the descriptions of rates A/B/C have been updated |
| Netherlands | Alcohol Act: no alcohol for young people under 18, including online sales and delivery (check age on delivery) | Age check: products containing alcohol; in the webshop the customer confirms 18+ themselves (box not pre-ticked) with a notice that their age will be checked on delivery; "18+" on kitchen ticket, delivery slip and receipt |
| Netherlands | Disposable cups and containers (SUP): since 2024 a separate, visible price for plastic disposable packaging for takeaway and delivery | Disposables charge per product, as a separate line on the receipt (product's VAT) and separately in the turnover |
| Netherlands | Deposit on cans and plastic bottles | Deposit per product (€ 0.15 / € 0.25), separate line without VAT for takeaway and delivery, separately in the turnover |
| Netherlands | Cash payments: since 1 January 2026 no € 3,000 or more in cash for goods | Warning for takeaway and delivery (also at the cash machine); confirming is possible and is recorded in the log |
| Netherlands and Belgium | VAT change: a rate or a product gets a different VAT percentage from a certain date | Schedule VAT change: the till carries it out on the day itself (in Belgium per product, the letters A/B/C/D are fixed) |
| Netherlands | Accommodation (overnight stays) 21% since 1 January 2026 | VAT rate configurable per product |
| EU | Omnibus Directive: a struck-through "was" price may only be the lowest price of the last 30 days | the webshop only strikes through against the lowest price of 30 days (the till keeps the price history; happy hours that recur every week count too) |
| EU | European Accessibility Act (since 28 June 2025): webshops accessible (WCAG 2.1 AA) | the webshop works with keyboard and screen reader ("Skip to content" link, visible focus, labels) and has an accessibility statement (link at the bottom) |
| Netherlands | XML Auditfile Financieel (XAF): the standard of the Dutch Tax Administration (Belastingdienst) for transferring (part of) the accounting records; XAF 4.0 is mandatory from 2027 | export as XAF 4.0 (Accounting export) |
| Netherlands | Reliable checkout system: keep the till data (all receipts, corrections and events) and be able to supply it digitally during a tax audit; for this the Dutch Tax Administration (Belastingdienst) recommends the XML Auditfile Afrekensystemen (XAA) | export as XAA 3.2 (Report → Revenue per period → Cash register audit file), optionally signed with the supplier's certificate |
| Belgium | Attendance registration with a registered cash register system: recording the start and end of employees' working time in the cash register system | Clock in/out (Settings → Business; Required = clock in first) is recorded in the black box |
| Belgium | Dimona: declare every employment (including flexi-jobs and students) to the RSZ before it starts | this is done by your social secretariat or scheduling tool (e.g. Shyfter, Book'u, Plan-Me); HorecaPOS supplies the hours worked and the revenue (Settings → Working hours → Payroll and scheduling) |
| Netherlands | Recording of working and rest times (Working Hours Act, Arbeidstijdenwet) | Clock in/out with the hours worked per staff member, adjustable by the manager (with log), and the hours list for the payroll package |
| Netherlands and Belgium | HACCP / food safety: record temperatures (chilling, freezer, hot holding, cooking, cooling down, goods receipt) and cleaning; NL Hygiënecode voor de Horeca (NVWA), BE FAVV self-checking (guide G-023) | HACCP records in the POS (Settings → Laws and rules, HACCP button at the top): measuring points with limits, cleaning and check tasks, mandatory corrective action for a deviation, cannot be changed, overview with missed records as CSV or print (see HACCP records) |
| Netherlands and Belgium | Retention obligation (NL 7 years, BE 10 years) | receipts, Z reports and the log are stored in the database and in the backups; the log cannot be changed or deleted from the till |
Laws and rules
Settings → Laws and rules (administrator; the VAT assistant also with the Manage products permission). Everything is off by default; without these settings the till works as always.
- Alcohol age check (18+): under Products tick Contains alcohol (or use the VAT assistant). For takeaway and delivery with alcohol, "18+" appears on the kitchen ticket, the receipt and in the order screen. In the webshop the customer confirms they are 18 or over (the box is not pre-ticked) and sees that their age will be checked on delivery.
- Disposables charge (Netherlands): an amount per product (guide prices: cup € 0.25, meal container € 0.50, small container € 0.05). For takeaway and delivery the till automatically adds a "Disposables charge" line to the receipt (with the product's VAT); it follows the products automatically (the database keeps track of it, even after voiding, moving or a different order type) and appears separately in the turnover. No charge for eat-in. Thuisbezorgd.nl and the webshop charge their own fee.
- Deposit (Netherlands): per product (€ 0.15 can/bottle, € 0.25 large bottle), "Deposit" line without VAT, only for takeaway and delivery.
- Cash € 3,000 or more (Netherlands, prohibited for goods since 1-1-2026): for takeaway and delivery a warning at checkout and at the cash machine; the staff member can confirm (e.g. catering as a service), which is recorded in the log. Eating and drinking on the premises is a service: no warning.
- VAT assistant: the type per product (meal, non-alcoholic drink, alcoholic drink, food without preparation, other; first a guess based on the name and the group). The till shows the correct rate for eat-in and takeaway (Belgium since 1-3-2026: meals and soft drinks 12%, also takeaway; alcohol 21%; food without preparation 6%. Netherlands: 9% and 21%) and applies it, immediately or from a date.
- Schedule VAT change: a product to a different rate, or (Netherlands only) a rate with a new percentage, from a date. The till carries it out on that day itself (checked every quarter of an hour, and at start-up).
Invoices (mandatory between businesses in Belgium) are described under Invoices for business customers. Still to do: GKS 2.0, find out the status of the certification (see docs/backlog-concurrenten.md).
Invoices for business customers
Settings → Invoices (administrator; off by default): switch on Invoices for business customers (UBL / Peppol). Once it is on, below it you will find Payment on account, the Invoice details, the Peppol services, the Bank connection (with payment on account) and the list of all invoices. In Belgium e-invoicing between businesses has been mandatory since 1-1-2026.
- Invoices for business customers: Receipts → choose the receipt → Invoice. Enter the customer (or choose a previous customer); the till creates a numbered invoice (e.g. F2026-0001, sequential per year), as UBL according to Peppol BIS Billing 3.0 and as an invoice to print or save as PDF. Send by email (both as attachments, optionally with a copy to the accountant), via Billit to the Peppol network (
BILLIT_API_KEY,BILLIT_PARTY_ID), via Storecove (STORECOVE_API_KEY,STORECOVE_LEGAL_ENTITY_ID; the recipient is taken from the customer's Peppol ID, e.g. 0208 → BE:EN, 0106 → NL:KVK, otherwise by email via Storecove) or via Banqup from Unifiedpost (BANQUP_CLIENT_ID,BANQUP_CLIENT_SECRET,BANQUP_SPACE_ID;BANQUP_SANDBOX=1for the test environment; Banqup validates the UBL and delivers it itself), to your own address (FACTUUR_HTTP_URL, e.g. an accounting package or another Peppol service) or download. One invoice per receipt; the receipt has already been paid, so "paid". KvK/company number, IBAN, Peppol ID, prefix and payment term under Invoice details. All invoices at the bottom of the tab (permission Revenue per period). - Keys, secrets and headers are never shown (only "set"; leave empty = keep, Clear = remove) and are not written to the log (only which fields changed). They are stored in the database (
vestiging.peppol_gegevens): included in backups, not in the configuration export.
Self-service kiosk
Guests order themselves on a stand or tablet, like in a fast-food restaurant, and pay at the till or by card at the kiosk. The ordering screens are part of the till itself, so the menu, prices, options, set menus, happy hours, day parts, photos, allergens, languages and the receipt all come from the till and don't need to be set up anywhere else. The kiosk runs the PinPortal Kiosk 2 app (Android, including Sunmi, and Windows, Linux and macOS), which shows the page and prints the receipt. Off by default.
Switching on and setting up (administrator): Settings → Business → Screens and operation → Self-service kiosk.
- Choose what the guest can pick: Eat here and/or Take away (take away uses the takeaway price and the takeaway VAT rate, if set).
- Welcome text, after how many seconds without touch the kiosk goes back to the start (the basket is then emptied), and which product groups are on the kiosk (nothing ticked = all).
- Anything else?: tick product groups (e.g. drinks, desserts); at the basket the kiosk then suggests a few products from them.
- Payment, per kiosk (see Adding and linking a kiosk):
- At the till (default, like the old kiosk): the guest orders, gets a pickup number and pays at the till. No card terminal is needed at the kiosk.
- By card at the kiosk: the guest pays on the card terminal at the kiosk.
- The guest chooses: at the till or by card. If the kiosk has no card terminal, it is at the till.
- To the kitchen (when paying at the till): right away after ordering at the kiosk (default), or only once it has been paid at the till.
- Receipt: on the kiosk's printer (default), on the till's receipt printer, or no receipt (just the number on the screen). When paying at the till, the kiosk prints a slip with the number and not paid yet; the receipt comes when the bill is settled at the till.
- Order status on the phone (optional, off by default): a QR code appears on the kiosk receipt and on the final screen. The guest scans it, sees their number and the status (ordered, being prepared, ready) and gets a notification when the order is ready. This runs via the management portal, so the till must be connected to it.
- Alcohol and products sold per kilo are never on the kiosk: without staff, age cannot be checked and there is no scale.
- Barcode scanner (optional, everything off by default): tick what a scan on the kiosk may do:
- a product in the basket (the product's code);
- a discount code;
- a loyalty card (the guest earns points);
- a gift card or prepaid card as payment. If there is enough balance, the order is paid straight away. Otherwise the card pays part and the guest pays the rest by card or at the till (this is then also allowed on a card-only kiosk). After such a partial payment the guest can no longer cancel; the order appears in the till as Kiosk … · number.
The scanner itself is set up on the kiosk: in the PinPortal Kiosk 2 app under admin → Barcode scanner (as a keyboard, the built-in scanner or a COM port), with a scanner test. A scanner that works as a keyboard also works without the app.
- Top up credit (optional, off by default; only works if top-up credit is on): the kiosk start screen then shows Top up credit. The guest scans their pass or gift card (or types the code), sees the balance and chooses an amount. You set the amounts yourself (1 to 6, default € 10, € 20 and € 50). Payment works as set for the kiosk: by card, or at the till with the pickup number. After checkout the amount is added to the balance. Such a top-up does not go to the kitchen, does not appear on the pick-up screen and gets no QR code. The maximum balance of top-up credit also applies here.
- Charge to my room (hotel integration, off by default; Settings → Hotel → Self-service): the basket then shows Charge to my room. The hotel guest enters room number and surname; if that matches a guest currently staying in that room, the order goes to the kitchen and is charged to the room as paid (see Hotel software: charge to the room).
- Belgium (black box): anything not yet tested with the black box is automatically switched off on the kiosk (gift card or credit as payment, top-up, discount code, menus, options with a surcharge, happy hour), just like at the POS.
Adding and linking a kiosk
- Under Kiosks, enter a name (e.g. Kiosk entrance) and choose Add kiosk. You get a link code of 6 digits (valid for 30 minutes).
- Choose for the kiosk how the guest pays: at the till by default. If it is a kiosk with a card terminal, choose by card or the guest chooses, and choose this kiosk's card terminal (from Settings → Payments).
- Open the kiosk page on the kiosk:
- in the business: in the app under management → Vast adres, the address shown with the setting, e.g.
http://192.168.1.20:3000/kiosk; - or via the management portal (https, also if the kiosk is not on the same network): link the kiosk address shown with the setting to the app's kiosk code, just like with the old kiosk.
- in the business: in the app under management → Vast adres, the address shown with the setting, e.g.
- Enter the link code on the kiosk. Done: the kiosk remembers its own key. Link again gives a new code; Remove unlinks it.
Each kiosk shows whether it is online.
How the guest orders
- Start screen with the welcome text; the guest chooses their language (all POS languages) and taps to order.
- Eat here or take away.
- The menu per product group, with photos, the price (with happy hour), allergens and what is sold out. Products with choices or a set menu open the choice window.
- The basket: change quantities and optionally Anything else?.
- Order (paying at the till): the guest sees their pickup number large on the screen with the amount, gets the slip and pays at the till. In the till the order is open as Kiosk Entrance · 42 (the number the guest gives); settle the bill as usual. After that it shows as paid on the pickup screen, and goes to the kitchen if that was only to happen after payment.
- Pay by card: the till puts the amount on this kiosk's card terminal (the same card payment link as at the till). If it fails, the guest can try again or cancel (or, if the guest may choose, pay at the till after all). Only when the payment has succeeded does the order go to the kitchen and get settled. The guest sees their pickup number large on the screen and gets the receipt.
- After a few seconds the kiosk goes back to the start.
During an outage: alert and emergency mode (in the kiosk app, admin → Bij storing; off by default). If the kiosk cannot reach the till, it shows Even gesloten. Two extras:
- Teams, Slack, Discord, ntfy, Home Assistant, Make or Zapier), and a hersteld message when it works again. With Testmelding sturen you check the address.
- Emergency mode: the kiosk saves a simple menu, passed on by the kiosk page: products without options or set menus, at the eat-in price (or the takeaway price if that is the only option).
- If the till is gone for a while (default 60 seconds), the guest orders from that menu.
- The guest pays by card or at the counter. Card payment is only possible if Pinbetaling is switched on in the app.
- Two emergency receipts are printed: one for the guest (N1, N2 …) and one for the counter/kitchen. They state that they are not a till receipt.
- When the till comes back, the kiosk page puts the emergency orders into the till as Nood N… <kiosk>. They do not go to the kitchen (it already had the emergency receipt) and do not appear on the pick-up screen.
- Paid by card and the same amount as in the till: settled as Manual card payment. Otherwise (paying at the counter, or a different amount) the order stays open for the waiting staff.
- Everything is recorded in the log.
- Belgium: with the registered cash register system (GKS, black box) every sale must go through the till and the FDM immediately. Emergency mode is then probably not allowed; check first. In Belgium the kiosk app only switches it on after an extra confirmation, and the till shows a warning for the kiosk.
In the till a kiosk order is an ordinary order (takeaway or eat-in, named Kiosk Entrance) in the name of the staff member Kiosk. The till creates it itself; nobody can log in with it. Do not set it to inactive, or the kiosk cannot order. Kiosk orders appear in the reports, in Receipts and on the pickup screen. An order that is not completed on the kiosk (not ordered or not paid by card) expires by itself after 30 minutes.
Card payments in test mode (Settings → Payments)? Then the kiosk doesn't really take payments; handy for trying it out. Without internet, card payment is not possible; the kiosk then says you can order at the counter.
Outage: if the till cannot be reached, the kiosk app shows "Temporarily closed" and resumes by itself. If the kiosk runs via the management portal and the internet goes down, the app can fall back on the till on the local network (in the app: admin → Extensions → Fall back on the local network during an outage); the kiosk passes that address on itself.
Switching off: the kiosk says it is closed for a moment. The kiosks and settings are kept. The log records on/off, the settings, added and removed kiosks, linking and cancelled orders.
Digital menu board
The menu with prices on a TV (or another monitor with a browser), straight from the till. Off by default; turn it on via Settings → Business → Screens and operation → Digital menu board. Then open http://<kassaserver>:3000/menubord on the TV (or use the On a separate screen / On a tablet or phone button with the QR code). No login and no pairing.
- Per category the products with price, in the till's order. Choose which categories (and in which order), 1 to 4 columns, dark or light, your own heading (empty = the business name), product photos and allergens.
- Always up to date: the board fetches the menu every 10 seconds (and immediately after a change), so a sold-out product (struck through with Sold out, or removed from the board), empty stock, a happy hour (promotional price with the normal price struck through, and the name and end time at the top) and the dayparts (only what is on sale now) show correctly by themselves.
- If not everything fits on the screen, the pages alternate (by default every 12 seconds, adjustable from 5 to 120).
Staff and PINs
Settings → Staff (administrator only): add staff, change name, role and PIN, and set them to inactive.
- Roles: waiter (ordering, checkout, X report), manager (also discounts, returns, closing the day, cash drawer and log) and administrator (everything, including all Settings). That is the default; what waiters and managers may do can be adjusted (see Permissions per role).
- PIN of 4 to 8 digits, unique among active staff. PINs are only stored encrypted (hashed) in the database and cannot be read back.
- Permanent deletion is not possible (receipts and the log refer to the staff member); inactive = can no longer log in.
- There is always at least one active administrator left.
- Different role, new PIN or inactive: that staff member's current sessions are ended immediately.
- Belgium: optionally the national register number for staff registration.
- Language: the screen language for this staff member (or "Device language"). After logging in, the till is immediately in that language; the staff member can also change it themselves with the little flag at the bottom right (see Languages).
- Tip: replace the demo PINs 1111 and 2222 before the till goes live.
Log in with a card (optional)
Off by default. To turn it on: Settings → Staff, tick Log in with a card (NFC, RFID or iButton). Required: a USB card reader that works as a keyboard (for NFC or RFID cards, key fobs, wristbands or iButton keys). Such a reader "types" the card number and presses Enter; no driver or connection is needed.
- Linking: tap the staff member, then Link card and hold the card against the reader. A card belongs to one staff member. Use Remove card if it is lost.
- Logging in: on the login screen, hold the card against the reader. The PIN also keeps working as usual.
- Clocking in and out (if turned on): on the login screen tap Clock in / out and hold the card against the reader.
- The card number is only stored encrypted (hash) in the database, just like the PIN. Inactive staff members cannot log in with their card either.
- Off: log in with the PIN only, as always. Linked cards are kept.
Permissions per role
Settings → Permissions (administrator only): tick per role what waiters and managers may do. By default everything is exactly as above (as the till always did); a box that differs is coloured.
| Permission | Waiter | Manager |
|---|---|---|
| Remove lines after ordering (void) | yes | yes |
| Give discount / remove discount | no | yes |
| Mark product as "sold out" | yes | yes |
| Print a copy of a receipt | yes | yes |
| Return (credit note) | no | yes |
| Check out on account and receive payments on account (only with payment on account on) | no | yes |
| Interim total (X report) | yes | yes |
| Close day (Z report) | no | yes |
| Revenue per period | no | yes |
| Manage cash drawer | no | yes |
| Manage gift cards (only with gift cards with balance) | no | yes |
| Read and reply to reviews (only with review management on) | no | yes |
| Manage loyalty card (only with the loyalty card on) | no | yes |
| View log | no | yes |
| View camera feeds (only with camera feeds on) | no | yes |
| Manage stock (only with stock on) | no | yes |
| Managing products | no | no |
| Manage floor plans | no | no |
| Set up business, payments and printers | no | no |
| View and edit working hours | no | no |
- The administrator may always do everything. Changing staff and permissions always remains reserved for the administrator (otherwise someone could give themselves more permissions).
- Buttons and tabs a role is not allowed to use are hidden for that role; the till server checks this too. If a manager is given e.g. Manage products, they see the Settings button with only the Products tab.
- Changes apply immediately on all tills and are recorded in the log. Reset to default puts everything back as it was.
Business details
Settings → Business (administrator only): name, address, postcode, town, phone and VAT number of the location. These appear at the top of every receipt and pro forma. The text at the bottom of the receipt can also be set here (several lines allowed; empty = no text; default "Bedankt en tot ziens!"), and below it the receipt language (Dutch by default; see Languages). A preview of the receipt updates live. After saving, the next receipt uses the new details immediately. The country and fiscal details (GKS) deliberately cannot be changed here. In Belgium the VAT number is mandatory. With the Round cash payments to 5 cents checkbox (off by default) the total is rounded for cash payments (€ 6,62 → € 6,60, € 6,63 → € 6,65); the difference appears as "Rounding" on the receipt. Card payments always stay exact to the cent.
Managing products
Log in as administrator and choose Settings → Products.
- Add, edit (name, price, group, VAT rate for eat-in and takeaway, name on receipt, code, sold out) and delete product groups and products. Groups and products can each get their own colour; a product with a colour gets a coloured button on the order screen (text automatically white or dark for readability).
- Change the order by dragging a group or product by ≡. This works with a mouse and with your finger on a tablet. Exactly that order then appears on the order screen; open till screens update themselves immediately.
- Deleting removes a product from the till, but old orders and the fiscal journal still know the product. A group can only be deleted when it is empty.
- Options: open a product or product group and add option groups under "Options", such as "Cooking" (exactly one, required), "Sauce" (at most one) or "Extra" (several, with minimum and maximum; empty maximum = unlimited). Each option has a name and a surcharge (may be negative, e.g. -0,50). Option groups of a product group apply to all products in that group, on top of the product's own options. Order with ▲▼. Deleting is always possible: existing orders and receipts keep the chosen options themselves. The server also checks required options and the maximum.
- Photo per product: see Product photos.
- Price per kilo, PLU number and tare (only when the scale is on): see Setting up the scale. Without the checkbox a product stays per piece.
Product photos
Each product can have a photo.
- Setting a photo: Settings → Products → choose the product → Choose photo (on a tablet or phone you can also use the camera directly). The photo is resized in the browser to at most 512 × 512 pixels (JPEG, usually 20–80 kB) and saved immediately; Other photo replaces it, Delete photo removes it. The product list shows a small photo in front of the name. Only with the Manage products permission; jpg, png and webp, at most 512 kB.
- The administrator chooses what to show under Settings → Business → Product photos, independently and off by default:
- Product photo on the order screen buttons: the photo at the top of the product button, with the name and price below it.
- Product photo with the products on the customer display: a small photo in front of each line on the customer display (the customer display itself must also be on). Products without a photo stay as they are; if it is off, everything works exactly as before.
Barcode scanner
With a barcode scanner on the till you scan products, discount codes, loyalty cards and gift cards. Turn it on under Settings → Scanner (tab next to the printers and the scale; off by default). Tick what a scan on the order screen does:
- Product on the receipt: the product with that code (Settings → Products, field Code; e.g. the EAN barcode on the packaging). With choices, a menu or a price per kilo, the choice window or the scale opens first, just like when tapping. Scanning on the order screen under Print labels does this too; that keeps working as before.
- Discount code on the receipt (if Discount codes are on).
- Loyalty card: the customer with that card number is added to the receipt (if the loyalty card is on). If you scan an unknown code on a receipt with a customer, the till asks whether it is their new card.
- Gift card or prepaid card: the till shows the balance (if gift cards with balance are on). Payment is done under Checkout → Gift card; you can also scan the card there.
The till checks the products first, then the loyalty cards, the gift cards and the discount codes. Scanning works on the order screen when you are not in an input field. In an input field the code simply goes into that field.
Scanner test: under Settings → Scanner you see the code for each scan and what the till makes of it, even while the scanner is still off. If it doesn't work:
- Set the scanner to keyboard (USB-HID), with an Enter after the code. Most scanners already do this.
- Set a built-in scanner (e.g. on a Sunmi POS) to keyboard input in the device's scanner settings.
- The labels of the TS6X scale (weight and price) are handled by the scale itself, even with the scanner on.
On the kiosk you set up the scanner separately (Settings → Business → Kiosk); see Self-service kiosk.
Print labels
Product labels with the name, the price and a barcode, on a label printer (Brother, Dymo, Zebra ...) installed on the computer or tablet. Turn on under Settings → Business → Print labels (off by default). There you also choose the format of the label (38 × 25, 57 × 32, 62 × 29 or 100 × 50 mm) and whether the price and the barcode are printed on it. Print sample prints one test label.
- Settings → Products → (product) → Labels: choose the number and Print.
- Purchasing → (received order) → Print labels: for each product, as many labels as were received (received order units × quantity per order unit; not ingredients). At most 500 labels at a time.
- The till opens the print dialog: choose the label printer and the paper size of the roll there. Each label is one page.
- The barcode is the product's code (Settings → Products): 8 or 13 digits with a valid check digit = EAN (12 digits: the check digit is added), otherwise Code 128 (letters, digits and punctuation, up to 30 characters). No code, no barcode.
- Scanning on the order screen (checkbox, off by default): a barcode scanner that acts as a keyboard adds the product with that code, with the usual choices (options, scale, allergy). Not together with the TS6X scale, which has its own labels with weight and price.
- Permission: Manage products or Manage stock.
Setting up the scale (A&D, Aclas, Adam Equipment, Avery Berkel, Avery Weigh-Tronix, Balanzas Marques, Baxtran, Bizerba, Brecknell, CAS, Datalogic, Dibal, DIGI, Dini Argeo, Excell Precision, Gram, Ishida, Kern & Sohn, Mettler Toledo, Minebea Intec, Ohaus, Precia Molen, Precisa, Rice Lake, Rongta, Sartorius, Star Micronics, T-Scale, UWE, Wedderburn, Wintec, Zebra)
Separate tab Settings → Scale (Set up business, payments and printers permission, by default administrator only; the tab is always there, even if the scale is still off). Off by default: the till then works exactly as before. Can't see the tab?
Automatic search. If nothing has been set up yet, the till searches automatically when you open this section (the Search button does it again):
- the POS (server) itself runs on an Aclas PC or AI scale (TS6X, TS3X, TS5EX/NX/GX, iS6X, iS2X, iR6X, Ti6X, iL8X; device make/model: Windows via WMI, Android via
getprop, Linux via DMI) and the Aclas Scale Module responds? Then that scale is set up as On this device, and the label scale too; on Linux (no Scale Module) the built-in scale on the internal port found (/dev/ttyS...) as "TS6X (ingebouwd)", with the model; - is there an OS6X on a COM/USB port? Each port is tried at 9600, 4800, 2400 and 19200 baud: first listening briefly (continuous), then sending
W(Toledo), and otherwise Dialog 06 (9600, 7 data bits, odd parity: requesting status).
Found = filled into the form with the Enable and use button: one tap and it works. (Searching sends a W to every free COM port; a port that is in use, e.g. by the card terminal, is skipped.)
All Aclas scales. For each scale you choose the model; the POS then knows how it can be connected. There are two kinds:
- On this device (set up once): the POS runs on the scale (PC or AI scale). With Windows or Android it weighs via the Aclas Scale Module, without port, speed or protocol; with Linux (no Scale Module) via the scale's internal port (usually
/dev/ttyS0or/dev/ttyS1), with port, speed and protocol. There is only one per POS; Search finds it automatically. A PC or AI scale (TS6X, iS6X ...) is always On this device: it can appear only once in the list, and the other PC/AI models can then no longer be chosen. A TS6X elsewhere in the venue can still print labels (then only turn on Scan labels). - Connected (several at once): the scale is connected to the POS server by cable (RS232/USB), Bluetooth or the network. As many as needed (up to 8), each with its own name.
One list, two tick boxes. All scales are in one list. For each scale you tick what it does: Weigh at the till (the POS asks for the weight when ordering) and/or Scan labels (the scale prints a label with a barcode that the POS scans, and receives the PLUs from the POS). A PC or AI scale such as the TS6X can do both; an LS label scale only labels. Labels can come from one scale per venue.
| Model | Type | Connections | In the POS |
|---|---|---|---|
| OS6X | POS scale | RS232, USB, Bluetooth | connected, several at once |
| OS2X | POS scale | RS232, USB | connected, several at once |
| CS6X, CS3X | Cash register scale | RS232, USB, Ethernet, wifi | connected, several at once |
| TS6X, TS3X, TS5EX, TS5NX, TS5GX | PC scale (Windows, Android, Linux) | RS232, USB, Ethernet, wifi | on this device (1x), also as label scale |
| iS6X, iS2X, iR6X, Ti6X, iL8X | AI scale with product recognition (Windows, Android, Linux) | RS232, USB, Ethernet, wifi | on this device (1x), also as label scale |
| iS5X, OiT2X | AI scale (Linux only) | RS232, USB, Ethernet | connected or as label scale |
| LS2S, LS2RX, LS2CX, LS2NX, LS5SX, LS5RX, LS5CX, LS5NX, LS6CX, LS6RX, LS6NX | Label scale | RS232, Ethernet, wifi | scan labels and PLUs |
| PS1CX, PS1DX, PS6CX, PS6DX | Price computing scale | RS232 | connected, several at once |
| PS1BX | Price computing scale without connection | none | weight by hand |
| LH15X | Hanging scale with label printer | RS232, Ethernet, wifi | connected or as label scale |
A&D, Adam Equipment, Avery Berkel, Avery Weigh-Tronix, Balanzas Marques, Baxtran, Bizerba, Brecknell, CAS, Datalogic, Dibal, DIGI, Dini Argeo, Excell Precision, Gram, Ishida, Kern & Sohn, Mettler Toledo, Minebea Intec, Ohaus, Precia Molen, Precisa, Rice Lake, Rongta, Sartorius, Star Micronics, T-Scale, UWE, Wedderburn, Wintec and Zebra. The commonly used models of these brands are included for which it is established how the POS talks to them (to be tested = the protocol is not literally stated in a source; the POS chooses the most obvious one). All connected (several at once), or as a label scale whose label the POS scans:
| Brand | Model | Type | Connection | Protocol (factory default) | In the POS |
|---|---|---|---|---|---|
| A&D | EK-i (incl. EK-610i), HV-WP | Cash register scale (weight only) | RS232, EK-i also USB | Continuous (stream mode), 2400 baud, 7E1 | connected, several at once |
| Adam Equipment | Swift | Price computing scale | RS232, USB (optional) | Continuous (continuous to PC), 9600 8N1 (to be tested) | connected, several at once |
| Avery Berkel | FX110, FX120, FX131 (built-in with scanner) | Cash register scale | RS232, FX131 also USB | Mettler Toledo 82/7 = Toledo 8217 (POS sends W), 9600 baud, 7E1 | connected, several at once |
| Avery Berkel | FX125 | Price computing scale | RS232 | Checkout-Dialog 06 (9600, 7O1) | connected, several at once |
| Avery Berkel | Xs, XTs, XTi | Label scale | Ethernet, Wi-Fi, USB | own PLUs on the scale | scan labels |
| Avery Weigh-Tronix | 7820, 7829, ZP900 | Cash register scale | RS232, 7820 also USB, ZP900 also USB and Ethernet | NCI (POS sends W), 9600 baud, 7E1 | connected, several at once |
| Balanzas Marques | BM1000P TOP | Cash register scale (weight only) | RS232 | METTLER (POS sends W, Toledo), 9600 baud, 7E1 | connected, several at once |
| Balanzas Marques | BM5 Junior Tower Label, BM500 ETQ | Label scale | Ethernet, USB, RS232, BM500 ETQ also wifi | own PLUs on the scale | scan labels |
| Baxtran | TW, VW, XTA, XTA-P | Price computing scale | RS232 | Toledo (POS sends W), 9600 baud, 7E1 | connected, several at once |
| Bizerba | CS 300 (also built-in) | Cash register scale | RS232 | Checkout-Dialog 06 (9600, 7O1) | connected, several at once |
| Bizerba | K-Class Flex, KH II | Label scale | Ethernet | own PLUs on the scale | scan labels |
| Brecknell | 6702U, 6710U, 6720U | Cash register scale | RS232, USB (virtual COM port) | NCI (POS sends W), 9600 baud, 7E1 | connected, several at once |
| CAS | PD-II, PDN, PDI, PDS-B | Cash register scale | RS232, PDN also USB and Bluetooth, PDI also USB | ECR type 2 = Toledo (POS sends W), 9600 baud, 7E1 | connected, several at once |
| CAS | CL3000, CL5500, CL7200 | Label scale | Ethernet, USB, RS232, CL5500 and CL7200 also wifi | own PLUs on the scale | scan labels |
| Datalogic | Magellan 9300i, 9400i, 9800i (scanner with scale) | Cash register scale | RS232 (separate scale port), USB | Mettler Toledo 8217 (POS sends W), 9600 baud, 7E1 | connected, several at once |
| Dibal | KS-400, D-POS 400 | Cash register scale | RS232, D-POS 400 also USB | Checkout-Dialog 06 (9600, 7O1) | connected, several at once |
| Dibal | G-325, PI-100 | Price computing scale | RS232 | Checkout-Dialog 06 (9600, 7O1) | connected, several at once |
| Dibal | M-500 (Mistral), D-900, CS-2200 | Label scale | Ethernet, Wi-Fi, USB | own PLUs on the scale | scan labels |
| DIGI | DS-781 | Price computing scale | RS232 | DIGI Type B (POS sends ENQ), 9600 8N1 | connected, several at once |
| DIGI | SM-120, SM-6000 | Label scale | Ethernet, Wi-Fi | own PLUs on the scale | scan labels |
| Dini Argeo | DFW, DGT, 3590E | Cash register scale (weight only) | RS232, USB, Ethernet, DFW and 3590E also wifi | Continuous (ST,GS, 0.512,kg), 9600 8N1 | connected, several at once |
| Excell Precision | TPE, AM4, FD4-P, FDP4-P, GE4, GEP4 | Price computing scale | RS232 | Continuous (ST,GS,+0.876kg), 9600 8N1 (except TPE, to be tested) | connected, several at once |
| Gram | XFOC RS, XFOC+ RS, ZFOC RS | Price computing scale | RS232, USB (Gram cable) | Gram (POS sends ENQ, then DC1), 9600 8N1 (XFOC to be tested) | connected, several at once |
| Ishida | Uni-3, Uni-5, Uni-7, Uni-9 | Label scale | Ethernet, Wi-Fi, USB | own PLUs on the scale | scan labels |
| Kern & Sohn | RPB, RFC | Price computing scale | RS232, USB | Checkout-Dialog 06 (Prot = DLG-06, 9600, 7O1) | connected, several at once |
| Kern & Sohn | RFE (price), IFB, EOC | Price computing / cash register scale | RS232 | Continuous, 9600 8N1 | connected, several at once |
| Mettler Toledo | Ariva-S | Cash register scale | RS232, USB (virtual COM port) | Toledo 8217 (POS sends W), 9600 baud, 7E1 | connected, several at once |
| Mettler Toledo | Viva | Cash register scale | RS232 | Toledo 8217, 9600 baud, 7E1 | connected, several at once |
| Mettler Toledo | bPlus, UC Evo | Label scale | Ethernet, Wi-Fi | own PLUs on the scale | scan labels |
| Minebea Intec | Signum, Combics, Midrics, Puro | Cash register scale (weight only) | RS232, USB, Signum and Combics also Ethernet | Continuous (SBI, automatic printing), 9600 8N1 | connected, several at once |
| Ohaus | Aviator 7000 | Price computing scale | RS232 or USB | Checkout-Dialog 06 (9600, 7O1) | connected, several at once |
| Ohaus | Valor 7000, Ranger 3000, Ranger 4000, Ranger 7000, Defender 3000 | Cash register scale (weight only) | RS232, USB, Ethernet | Continuous (Auto Print Continuous), 9600 8N1 | connected, several at once |
| Precia Molen | DP400 | Cash register scale | RS232, USB | Checkout-Dialog 06 (9600, 7O1) | connected, several at once |
| Precia Molen | DPOS CR, C 210 B, C 210 C | Price computing scale | RS232 | Checkout-Dialog 06 (9600, 7O1; C 210 to be tested) | connected, several at once |
| Precia Molen | Corail 500 | Label scale | Ethernet, Wi-Fi | own PLUs on the scale | scan labels |
| Precisa | XB, XT, LS, LX (precision balances) | Cash register scale (weight only) | RS232, LS and LX also USB | Continuous (print mode CONTINUOUS), 9600 8N1 | connected, several at once |
| Rice Lake | BenchPro BP-S, BenchPro BP-R | Cash register scale | RS232 | BP-S Toledo 8213, BP-R NCI (both: POS sends W), 9600 baud, 7E1 (to be tested) | connected, several at once |
| Rongta | RLS1000, RLS1100 | Label scale | Ethernet, RS232, wifi | own PLUs on the scale | scan labels |
| Sartorius | Entris, Quintix | Cash register scale (weight only) | RS232, USB | Continuous (SBI, automatic printing), 9600 8N1 | connected, several at once |
| Star Micronics | mG-T12, mG-T30, mG-T60, mG-S8200 | Cash register scale (weight only) | RS232, USB (virtual COM port) | Continuous, 9600 8N1 (to be tested) | connected, several at once |
| T-Scale | PA10, PA15, PEA10 | Label scale | Ethernet | own PLUs on the scale | scan labels |
| UWE | ASEP | Price computing scale | RS232 | Continuous, 9600 8N1 (to be tested) | connected, several at once |
| Wedderburn | TSDS983 | Cash register scale | RS232 | DIGI Type B (POS sends ENQ), 9600 8N1 (to be tested) | connected, several at once |
| Wedderburn | TSDS781T, TSDS782T | Price computing scale | RS232 | DIGI Type B, 9600 8N1 (to be tested) | connected, several at once |
| Wedderburn | TSSM120 | Label scale | Ethernet, RS232 | own PLUs on the scale | scan labels |
| Wintec | ScalePOS ACS-S60E (POS with built-in scale) | Cash register scale | internal COM6 (Windows) or COM4 (Android) | Continuous, 9600 8N1 (to be tested) | connected |
| Zebra | MP7000, MP72 (scanner with scale) | Cash register scale | RS232 (AUX port) | SASI = Toledo (POS sends W), 9600 baud, 7E1 (to be tested) | connected, several at once |
- A&D EK-i and HV-WP: set the scale to stream (EK-i:
prt 0; from the factory it is set to the PRINT key) and the POS to Continuous with 2400 baud and 7E1 (the A&D factory setting). The message isST,+00512.00 g(US= moving,OL= overload). - Adam Equipment Swift: set the scale to continuous to PC (8N1); the POS is then set to Continuous.
- Avery Berkel FX110, FX120 and FX131: on the scale choose the protocol Mettler Toledo 82/7 and set the POS to Request (Toledo) with 7E1 (9600 baud). Dialog 06 also works. The FX125 (with price display) has no Toledo: use Dialog 06 there. The POS sets this up automatically when you choose the model.
- Avery Weigh-Tronix 7820, 7829 and ZP900 and Brecknell 6702U, 6710U and 6720U: NCI, the Weigh-Tronix protocol. The POS sends
W(just like with Toledo), the scale answers with the weight (1.234KG) and a status line, which says whether it is moving, overloaded or underloaded. The POS is set to Request (Toledo) with 7E1 (9600 baud). USB works as a virtual COM port. With the ZP900, connect the POS to port 2 (NCI). With the 67xxU, the scale can also be set to 8213 (SCP03). - Balanzas Marques BM1000P TOP: on the COM port choose protocol B (METTLER) and 9600 baud, 7 data bits, even parity; the POS is then set to Request (Toledo) with 7E1.
- Baxtran TW, VW, XTA and XTA-P (price-computing scales; VW and XTA-P with pole): in the scale's RS232 menu choose the protocol Toledo, 9600 baud and 7 data bits with even parity (7E1); the POS is then set to Request (Toledo) with 7E1. The POS sets this up automatically when you choose the model. CONT (the scale sends by itself) also works: then set the POS to Continuous with the same speed and data bits. Connect with the RS232 cable (9-pin) or a USB-to-RS232 cable.
- Bizerba CS 300: Checkout-Dialog 06 (the Bizerba specification): the POS sends the price per kilo, the verified scale calculates the amount. If the scale asks for check codes, you get them from Bizerba or the supplier.
- CAS PD-II, PDN, PDI and PDS-B (the PDS-B is sold by LRE, among others): choose ECR type 2 (Toledo) on the scale and set the POS to Request (Toledo) with 7E1 (9600 baud).
- Datalogic Magellan 9300i, 9400i and 9800i: set the Scale Interface Type of the separate scale port to Mettler Toledo 8217 and the POS to Request (Toledo) with 7E1.
- Dibal KS-400, D-POS 400, G-325 and PI-100: on the scale choose the protocol Checkout_Dialog06 (protocol 24) and 9600 baud, 7 data bits, odd parity (parameter type 5); the POS is then set to Dialog 06. The D-POS 400 can also connect via USB.
- DIGI DS-781: set the scale to Type B / standard command (data transmission
00011); the POS sendsENQand gets net weight, tare, price per kilo and amount back. - Dini Argeo DFW, DGT and 3590E: set the serial port to continuous transmission (9600 8N1); the POS is then set to Continuous.
- Excell Precision TPE (and generation 4 of the AM4, FD4-P, FDP4-P, GE4, GEP4): set the RS232 output to continuous (9600 8N1); the POS is then set to Continuous.
- Gram XFOC RS, XFOC+ RS and ZFOC RS: protocol Gram (9600 8N1). The POS sends
ENQ, the scale answersACK, the POS sendsDC1and the scale sends the weight:SOH STX S/U/F teken gewicht eenheid BCC ETX EOT(S= stable,U= moving,F= error; BCC = XOR of the status up to and including the unit). Connect with RS232 or the Gram USB cable. - Kern & Sohn RPB and RFC: set
Prot = DLG-06on the scale (the POS connection is option 965-419); the POS is then set to Dialog 06. RFE, IFB and EOC: continuous transmission (8N1), the POS on Continuous. - Mettler Toledo Ariva/Viva: set the scale to the Toledo protocol (8217) and the POS to Request (Toledo) with Data bits / parity = 7E1 (Mettler: 9600 baud, 7 data bits, even parity; the Ariva can also connect via USB as a virtual COM port). The POS sets this up automatically when you choose the model.
- Minebea Intec Signum, Combics, Midrics and Puro and Sartorius Entris and Quintix: SBI with automatic printing (9600 8N1); the POS is then set to Continuous. The message is
N + 0.512 kg; without a unit it is still moving. - Ohaus Aviator 7000: in the scale's settings (step 20) choose the protocol Dialog 06; the POS is then set to Dialog 06. RS232 or USB, depending on the cable.
- Ohaus Valor 7000, Ranger 3000/4000/7000 and Defender 3000 (weighing without price): set the scale to Auto Print Continuous (9600 baud, 8N1) and the POS to Continuous. The scale sends
0.512 kg G; a?after the weight means it is still moving. The Ranger 7000 can also connect via Ethernet (TCP port 9761). - Precia Molen DP400, DPOS CR and C 210 (the retail scales have been part of Dibal since 2025): Dialog 06 (9600 7O1), just like Dibal. If it does not work with the C 210, try Request (Toledo) with 7E1.
- Precisa XB, XT, LS and LX: set the print mode to CONTINUOUS and 9600 8N1, without date, time and ID on the line; the POS is then set to Continuous. Without a unit the weight is still moving.
- Rice Lake BenchPro BP-S (Toledo 8213) and BP-R (NCI): the POS is set to Request (Toledo) with 7E1.
- Star Micronics mG-T and mG-S8200: via RS232 or USB (virtual COM port, with the Star driver) on Continuous.
- UWE ASEP: RS232 to PC/POS, the POS on Continuous (to be tested).
- Wedderburn TSDS983, TSDS781T and TSDS782T are DIGI scales under their own number: DIGI (Type B), just like the DIGI DS-781. If that does not work, try Request (Toledo) with 7E1.
- Wintec ScalePOS ACS-S60E: the POS runs on the ScalePOS itself; the built-in scale is on COM6 (Windows) or COM4 (Android), 9600 8N1. Choose Continuous; if it sends nothing, Search finds the right protocol.
- Zebra MP7000 and MP72: the RS232 AUX port is set to SASI at the factory (9600 7E1, the POS sends
W): set the POS to Request (Toledo) with 7E1. - Label scales of these brands (Avery Berkel, Balanzas Marques, Bizerba, CAS, Dibal, DIGI, Ishida, Mettler Toledo, Precia Molen, Rongta, T-Scale, Wedderburn) are standalone systems with their own PLU file. Turn on Scan labels for the scale and set the same barcode as on the scale (EAN-13, starting 20–29, PLU and weight or price). You set the PLUs on the scale itself or with the brand's software; Send to TS6X and Download PLU file are only available for Aclas.
The same list is in the POS under Settings → Scale → All scales (ACLAS_MODELLEN in packages/shared/src/weegschaal.ts, with the brand per model).
Fill in as little as possible: when you choose a model, the POS prepares the rest the way the brand sets it at the factory: connection COM port / USB on the first free port, 9600 baud (A&D: 2400) and the brand's protocol (Toledo: Aclas with 8N1, and with 7E1 Avery Berkel FX, Avery Weigh-Tronix, Balanzas Marques, Baxtran, Brecknell, CAS, Datalogic, Mettler Toledo, Rice Lake and Zebra; Dialog 06: Avery Berkel FX125, Bizerba, Dibal, Kern & Sohn RPB/RFC, Ohaus Aviator and Precia Molen; DIGI Type B: DIGI and Wedderburn; Gram: Gram; Continuous: A&D, Adam Equipment, Dini Argeo, Excell Precision, the other Kern & Sohn, Minebea Intec, the other Ohaus, Precisa, Sartorius, Star Micronics, UWE and Wintec), and a name (e.g. OS6X, OS6X 2). A PC or AI scale becomes On this device (e.g. TS6X (ingebouwd); on Linux on the internal port /dev/ttyS0). If something is wrong, Search finds the right port, speed and protocol.
On this device (Aclas Scale Module): the scale shows the legal-for-trade weight; the POS sends the price per kilo and the tare (as preset tare) and takes over the amount the scale calculates, just like with Dialog 06.
- Android: the Aclas app AclasScaleDriver (
com.aclas.aclasscaledriver) is usually already on the scale; if not, installaclas-android/AclasScaleDriver.apk. The HorecaPOS app talks directly to that app's service, so no extra library is needed. - Linux: Aclas has no Scale Module for Linux. Just choose the model (e.g. TS6X): the connection then becomes On this device (internal port) on
/dev/ttyS0, 9600 baud, Toledo. The built-in scale is usually on/dev/ttyS0or/dev/ttyS1; Search tries them and fills in the right port, speed and protocol. Here too it can be added only once.
Aclas software is included with the POS: the Scale Module for Windows (aclas-module), AclasScaleDriver for Android (aclas-android) and the Aclas Sync SDK for Windows and Linux (aclas-sdk). Aclas allows us to ship them. The Windows and Linux installers include them; nothing to download or install separately.
Bluetooth (e.g. the OS6X): pair the scale first. Windows turns it into a COM port (Bluetooth settings → More Bluetooth options → COM ports), Linux /dev/rfcomm0: enter that port. In the Android app you enter the Bluetooth address (00:11:22:AA:BB:CC); the app asks once for permission for Nearby devices and connects via Bluetooth SPP.
AI scales (product recognition): the camera recognises the product in the Aclas software on the scale. Weighing works via the Scale Module (on this device) or the RS232 port; AI label scales print a label with a barcode after recognition, which the POS scans (as with the TS6X).
Aclas AI Recognition Plugin (AI scale with the POS on it, e.g. the iS6X with Windows): the Aclas plugin recognises the product and types its barcode into the POS, just like a scanner (followed by Enter); the order screen adds the product with its weight to the order. This is how you set it up:
- For the scale, turn on Scan labels with the same barcode as in the plugin. Recommended: starts with
27, PLU 5 digits, weight (Aclas type 17): the POS then calculates with the price per kilo itself. Using the price (type 12, starts with22) also works. - For that scale, turn off Weigh at the till: the plugin and the Scale Module cannot access the scale at the same time. The weight comes from the barcode. If the plugin responds during Search, the POS suggests this setup and does not start the Scale Module. Without an activation code the plugin still weighs and calculates the amount, but does not recognise any products.
- In the plugin itself: the barcode under Scale and Barcode Format Settings → Default Barcode Format (type 17), and in the window settings the point where the plugin clicks and types the code. Choose an empty spot on the order screen for this, not a button. The business teaches the plugin new products itself on the scale (AI training).
- Give the weighable products a PLU number and send the PLUs to the scale (Send to TS6X or the PLU file); the plugin recognises by PLU number.
- The POS only lets the plugin recognise while the order screen is open on the scale itself (
POST /aiplugin/resume, on closing/aiplugin/suspend, port 5003 on the scale; the first time also EmployeeMode: the scale's customer display shows no products). On other POS devices and tablets and via the management portal nothing happens. - The plugin always starts in Resume and cannot report its state. That is why the order screen sends resume again every 30 seconds; if that stops (screen closed, plugin or scale restarted), the POS puts the plugin on Suspend within a minute and keeps it there.
- The plugin requires an activation code from Aclas per scale (linked to the serial number). Works on Windows now; the Aclas Android version will follow (the POS does the same there).
Aclas OS6X (POS scale at the till, RS232/USB; the other connected scales work the same way):
- One or more scales (at most 8), each with a name (e.g. Counter, Bar) and its own connection: COM port / USB (
COM3on Windows,/dev/ttyUSB0on Linux/Android) with the speed, or network via a serial-to-network converter (IP address and TCP port, e.g. 4001). - Protocol: Request (Toledo) = the POS sends
Wand the scale answers with the weight (Toledo 8217, how the OS6X is usually set; also the status messages not stable/overload/below zero) or Continuous = the scale keeps sending the weight itself (ST,GS, 0.512kg,US= not stable) or Dialog 06 (calibrated), see below, or DIGI (Type B) = the POS sendsENQand the DIGI answers with status, net weight, tare, price per kilo and amount (37 characters:<status> <toestand> CR 0<netto> CR 4<tarra> CR U<kiloprijs> CR T<bedrag> CR LF; condition bit 1 = stable, bit 2 = below zero, bit 3 = overload, bit 4 = underload), or Gram = the POS sendsENQ, waits forACK, sendsDC1and readsSOH STX <S/U/F> <teken> <gewicht> <eenheid> <BCC> ETX EOT. Set the same protocol and speed on the scale. Data bits / parity: 8N1 (Aclas, Adam Equipment, DIGI, Dini Argeo, Excell Precision, Gram, Kern & Sohn, Minebea Intec, Ohaus, Precisa, Sartorius, Star Micronics, UWE, Wedderburn, Wintec) or 7E1 (A&D, Avery Berkel, Avery Weigh-Tronix, Balanzas Marques, Baxtran, Brecknell, CAS, Datalogic, Mettler Toledo 8217, Rice Lake, Zebra); Dialog 06 is always 7O1. Request also reads NCI (Avery Weigh-Tronix, Brecknell, Rice Lake BP-R): onWthe scale answersLF 1.234KG CR LF S00 CR ETX; the status line (S+ 2 or 3 bytes) says whether it is moving (byte 1 bit 0), underloaded (byte 2 bit 0) or overloaded (byte 2 bit 1);^^^^^= overload,_____= underload. - Dialog 06 (Checkout-Dialog 06, the European protocol for a calibrated scale on a till): the till sends the price per kilo (and the product's tare) to the scale; the scale weighs, calculates the amount itself and shows price per kilo, weight and amount on its own (calibrated) display. The till takes over the weight and amount; the weighing window shows "calculated by the scale". Always 9600 baud, 7 data bits, odd parity, 1 stop bit (the speed in the setting is then ignored). Sequence:
EOT STX 01 ESC <kiloprijs 6> ESC ETX(with tare: record03with 4 digits of grams) → ACK;ENQ→STX 02 ESC 3 ESC <gram 5> ESC <kiloprijs 6> ESC <bedrag 6> ETX; NAK →EOT STX 08 ETX→STX 09 ESC <code> ETX(22 = not ready yet, then retry after 100 ms; 20 = moving; 21 = lift first; 30/31 = too light; 32 = too heavy; 11 = invalid price). Check codes: many Dialog 06 scales occasionally (e.g. every 30 weighings) request the check codes of the till software (record 11 → record 10). The scale manufacturer only gives those codes, and how they are calculated, to the till supplier. Enter them under Check codes (pairs of 4 hexadecimal characters, e.g.74AE 1B2C); the till sends them when the scale asks for them. If the scale calculates with a changing number (Z) so fixed codes don't match, the till reports this; in that case ask the supplier to set up the scale without this check, or use Toledo. - The scales are connected to the PC or device where the till server runs; all tills and tablets weigh via the till server and choose in the weighing window which scale they use. Test weighs once.
- Network works everywhere.
- Also type in the weight by hand: on = the weight may also be typed in when there is a scale; without an OS6X it is always possible.
Scan labels (tick box at the scale: Aclas TS6X, another PC or AI scale, the LS series or the LH15X; scale + label printer, one per venue):
- IP address: only needed for Naar TS6X sturen. Weighing and scanning labels work without it. If the POS runs on the TS6X itself, leave it empty: the POS then sends to itself (127.0.0.1). If the same scale also weighs at the till, both tick boxes are on the same scale (Search sets it up that way).
- Scan labels: scan labels on the order screen. Set how the barcode looks, just like on the TS6X: starts with (20–29, default
28), number of digits for the PLU (4, 5 or 6) and then the weight in grams or the price in cents, plus the check digit (EAN-13). An example is shown below the setting. - PLU numbers: under Settings → Products a weighable product gets a price per kilo, optionally a tare and a PLU number (unique). You choose the PLU number from a list (No PLU, next free, Other number…); when you tick Price per kilo the next free number is already filled in. Only needed for the labels and PLUs of the TS6X: without a TS6X it can stay No PLU.
- Sending directly works on Windows and Linux; on Android and macOS use the PLU file. At the first installation, check the field names of the PLU file and the codes in
aclas-plu.ps1against the SDK manual of the supplied scale (one place to adjust:ACLAS_PLU_KOLOMMENinpackages/shared/src/weegschaal.ts).
Management portal: the report to the portal has the function Scale (A&D, Aclas, Adam Equipment, Avery Berkel, Avery Weigh-Tronix, Balanzas Marques, Baxtran, Bizerba, Brecknell, CAS, Datalogic, Dibal, DIGI, Dini Argeo, Excell Precision, Gram, Ishida, Kern & Sohn, Mettler Toledo, Minebea Intec, Ohaus, Precia Molen, Precisa, Rice Lake, Rongta, Sartorius, Star Micronics, T-Scale, UWE, Wedderburn, Wintec, Zebra) with on/off and which scales per model (e.g. TS6X (op dit apparaat), 2x OS6X, PS1CX, Ariva-S, DS-781, LS6RX, 5 producten per kilo); no IP addresses, COM ports or Bluetooth addresses.
Weights and measures law: a scale you sell with must be calibrated (class III, like the OS6X). With Toledo/continuous the till calculates with the weight the scale provides; with Dialog 06 the calibrated scale calculates the price itself.
Code: packages/shared/src/weegschaal.ts (protocols, labels, PLU file), apps/pos-server/src/lib/weegschaal.ts and routes/weegschaal.ts; screens WeegschaalInstellingen.tsx and WeegDialoog.tsx.
Thuisbezorgd.nl / Takeaway.com
Orders from Thuisbezorgd.nl come straight into the till, without an intermediary (no Deliverect, HubRise or similar): Just Eat Takeaway JET Connect talks to the Pin Voordeel management portal, and the till collects its messages from there.
In Belgium the platform is called Takeaway.com: the same company (Just Eat Takeaway) and the same integration. For a Belgian business, the screens, notifications, kitchen ticket and management portal show Takeaway.com everywhere instead of Thuisbezorgd.nl. Below, Thuisbezorgd stands for both.
Why via the portal? The till only needs PORTAAL_URL and PORTAAL_SLEUTEL (see Management portal) and only makes outgoing requests.
Setup (Settings → Delivery platforms → Thuisbezorgd.nl / Takeaway.com, permission Set up business, payments and printers; previously this was under Settings → Business):
- Turn on Use Thuisbezorgd (takes effect immediately, separate from Save).
- Register with Thuisbezorgd. The business then chooses OptimumPOS / Pin Voordeel as its POS at Thuisbezorgd (Partner Hub or account manager). JET then starts an onboarding session; the portal finds the registered till (by postcode and name, otherwise Pin Voordeel links the session manually in the portal), sends the configuration and asks the till for the menu. The integration then goes live.
- Tick the products that can be ordered via Thuisbezorgd (per group or individually), optionally with a description for Thuisbezorgd. The menu (price, options as modifiers, allergens, VAT) is included automatically; PLU = id of the product/option. After a change in the catalogue the till updates the menu within 30 seconds; only "sold out"/"available again" goes via the availability API.
- Thuisbezorgd opening hours: separately for delivery and collection (e.g.
16:00-22:00, several blocks separated by a comma). They are saved with the Save opening hours button below and are sent to Thuisbezorgd as service times as soon as the integration is ready. - Temporarily closed / Open again (in NL/BE open again by 07:00 the next morning at the latest).
Orders. An order becomes a normal order without a table (bezorgen or afhalen, group name TB <ordernummer>) with the prices the customer paid, plus delivery/service charges as a separate line and Thuisbezorgd discounts as a discount line; if the total still doesn't match, a line "Verschil Thuisbezorgd" is added. The kitchen ticket goes to the kitchen/bar immediately (can be turned off). The till confirms within seconds to the portal, which reports it to JET; if that fails within 3 minutes or the till is offline, JET receives "failed" and the business falls back on the Orderpad.
Thuisbezorgd button in the top bar (with the number of active orders): list, customer and address, ready/delivery time and the timeline (track & trace): received, courier on the way to the restaurant, courier at the restaurant, on the way to the customer, delivered (from JET), plus own steps (in preparation, ready, on the way/delivered when delivering yourself, picked up). JET Connect does not offer the till a live map of the courier; the customer sees that in the Thuisbezorgd app. A new order, a cancellation and "courier at the restaurant" trigger an orange bar and a sound. Complete (paid online) checks out with payment method online; if the customer pays at the door, just check out as usual. A cancellation from Thuisbezorgd voids the order and prints a "GEANNULEERD" (cancelled) kitchen ticket.
Code: apps/pos-server/src/lib/thuisbezorgd.ts, routes/thuisbezorgd.ts; screens ThuisbezorgdInstellingen.tsx and Thuisbezorgd.tsx. Portal side: horecapos-portaal/src/thuisbezorgd.mjs (see the portal's README).
Count in the management portal. The number of Thuisbezorgd orders per day is included in the report to the management portal (verkoopTelling in lib/portaal.ts): received and not cancelled, on the day received. A Thuisbezorgd order checked out in the till (including Complete (paid online)) is not counted again there under takeaway/delivery. The Thuisbezorgd data is stored in the till database and is therefore simply included in the till's backups.
Webshop and online ordering
Each business can get its own webshop: an ordering site (and app) in its own branding for takeaway, delivery, ordering at the table with a QR code and reservations, with online payment (MultiSafepay or Buckaroo) or payment on collection/delivery. The webshop is a separate project, horecapos-webshop (Node.js, see the README there), and runs on the same server as the management portal.
Turning on and setting up is done in webshop management: the Manage webshop button in the customer portal (owner) or at the installation in the management portal (Pin Voordeel). There you find on/off, the web address (<zaak>.<webshopdomein> or your own domain), branding (colours, logo, header image, font), opening hours and time slots for takeaway and delivery, delivery area (postcodes, radius or an area on the map, with charges and minimum), payment, discount codes, texts, languages, QR codes for the tables, reservations and the app (installable as a PWA; an Android app via a Trusted Web Activity), and push notifications (optional, off by default): the guest turns on a notification on the page of their order and gets a push notification when the order is ready or on its way; those who want can also get an occasional offer, which the business sends from webshop management (Push notifications tab). Works on Android and computers (Chrome, Edge, Firefox, Samsung Internet), in the Android app, and on iPhone and iPad (iOS 16.4 or later) if the guest adds the webshop to their home screen. No text message or email is sent and no name or number is stored. Details in the webshop README.
Menu. The till sends the menu automatically: all active products (not sold per kilo), per product group, with price, choice options, allergens, sold out and the product photo, plus the tables and the business details, and which marketing channels are on (for the "receive offers" checkbox at checkout, see Text and email marketing). This happens at startup, as soon as the webshop is turned on, within 30 seconds of a change in the catalogue and within a few seconds of a change under Settings → Business, such as marketing or the loyalty card (or with Send menu now). You can keep a product out of the webshop in webshop management (hide), or in the database with artikel.webshop = false.
Orders. Takeaway and delivery become a regular order without a table (group name WEB <bestelnummer>) with the prices the guest saw, plus delivery charge and transaction costs as separate lines and a discount code as a discount line; if the total still does not match, a "Webshop difference" line is added. The guest's tip does not count as revenue: it is added to the payment as a tip with Complete (paid online). Ordering at the table (QR code) goes to that table's open bill (paid online: as a separate group at that table). The kitchen ticket goes straight to kitchen/bar (can be turned off in the Webshop window). The till confirms within seconds with the receipt number; the guest then gets "received" and an email. If the till is offline, the webshop does not accept orders (the guest sees this immediately) and emails the business if an order is left waiting too long. Reservations from the webshop go to Reservations (only if reservations are turned on in the till). If a maximum per time slot is set (Delivery and time slots), webshop orders with a time in that slot count too.
Belgium (black box). A webshop order goes straight to the black box as an order (signOrder), before the work ticket, just like Send order at the POS. If that fails, it does not reach the POS and the webshop resends it later. Anything not yet tested with the black box is switched off in the webshop menu (gift cards, discount codes, on account, charge to room, menus, options with a surcharge, happy hour and tips) and is rejected if an old webshop sends it anyway. Complete checks tips, on account and charge to room just like the POS.
Charge to room (hotel integration, Settings → Hotel → Self-service → In the webshop): the menu gets kamer: { maxBedrag }; the webshop sends betaling.wijze = "kamer" with kamer and achternaam. The POS checks the guest with the hotel software (not at the table, not with a gift card) and stores it with the order; Complete (charge to room) settles to the room and posts the receipt to the hotel bill. Collective invoice for on account: the receipt then remains as an open item.
Webshop button in the top bar (with the number of active orders): list, customer and address, requested time or "as soon as possible", payment method and the timeline. The guest sees the steps In preparation, Ready and On the way live in the webshop (and by email, if the business wants). Checked out in the till = Completed; Cancel voids only the lines of that webshop order, prints a "CANCELLED" kitchen ticket, and the webshop refunds an order paid online. Arrived, no-show or cancelled for a reservation is also sent back to the webshop. A new order or reservation shows an orange bar and plays a sound.
Code: apps/pos-server/src/lib/webshop.ts, routes/webshop.ts; screen Webshop.tsx. Portal side: horecapos-portaal/src/webshop.mjs.
Till and webshop in sync (each part can be switched on separately, off by default; an older webshop ignores the new fields). What is turned on in the till also works in the webshop:
- Happy hour: the webshop charges the same price as the till at that moment (struck-through normal price and the name of the happy hour), also with a season.
- Dayparts and order types (if they are switched on): the webshop only shows what can be sold now, and for pick-up and delivery the price and products for that choice (at the table: dine-in). The menu gets
prijzen(afhalen,bezorgen) andnietBijper product, and the listdagdelen. - Menus: the guest chooses the dishes (fixed and choice, with their options); in the till it appears as a menu line with the dishes below it and the menu price split (VAT per dish is correct). Dishes that only belong in a menu are sent as
menuArtikelen. An old webshop without choices: the menu appears as a regular product on the receipt, as before. - Out of stock = sold out, including choice options with an ingredient that has run out.
- Allergens: off in the till = not in the webshop.
- Loyalty card: the guest can collect points at checkout (by phone number or email); the till links the customer to the order, and the points are added at checkout (redeeming happens in the restaurant). The webshop shows the balance.
- Gift cards (Settings → Business → Gift cards → Sell gift cards in the webshop, balance cards only): the guest buys a card and pays online; the till creates the card, which is active immediately, and the code goes back to the webshop via the portal (status and email). If Gift card as payment method is also on, the guest can choose "with a gift card in the restaurant" for takeaway.
- Discount codes (Settings → Discount codes, with the switch under Business): per code at the till and/or in the webshop; usage counts for both together.
- Pause and busy: the Webshop button in the top bar: Pause webshop (with a text for the guest) and Busy (extra minutes). Reaches the webshop within a few seconds.
- Online reservations with the till's rules (Settings → Business → Reservations): maximum people, days ahead, time slot, minimum notice and the times per weekday.
- Delivery and time slots: see The webshop follows the till under Delivery and time slots.
- All-you-can-eat at the table (Settings → Business → All-you-can-eat → Also when ordering at the table via the QR code): if a package is running at the table, the guest sees the dishes that belong to it as Included for € 0, with the rounds, the maximum per person, the waiting time and the time limit. They simply pay for everything else; everything goes on the table's bill. If the status at the table has just changed, the till refuses the order and the guest orders again.
- On account (Settings → Invoices → Payment on account → Also in the webshop): see In the webshop under Payment on account.
- Online on the waiting list (Settings → Business → Waiting list): see Online on the waiting list under Waiting list for walk-ins.
- Upsell: "Anything else?" (optional, off by default; Settings → Business → Checkout → Upsell in the webshop): choose the product groups (e.g. drinks, sauces, desserts) and how many suggestions. The webshop then shows, at the basket and at checkout, products from those groups that are not yet in the basket (only what is on sale now, not sold out and without required choices); the guest adds them with one tap. No groups chosen = off, as before. The kiosk has its own upsell (see Self-service kiosk).
For this, the menu for the webshop has versie: 2 with the fields menuArtikelen, allergenenAan, happyhours, menus, klantenkaart, cadeaubon, kortingscodes, pauze, drukteMin, volgt, bezetting, reserveren.online, ayce, opRekening, wachtlijst and upsell. The confirmation to the portal also has cadeaubonnen (codes), klant (points) and plek (waiting list).
Count in the management portal. Takeaway and delivery via the webshop are counted separately (webshop, webshopGeannuleerd in verkoopTelling), on the day received, and not again under takeaway/delivery. Ordering at the table is simply counted under table.
Card payments and terminals
Settings → Payments (administrator only):
- Terminals: for each terminal a name, the terminal ID and its own API key from PinPortal (Customer → Edit customer → Other → API Keys). After saving, only the end of the key remains visible; it is never sent back to the browser. Use Test connection to check the key and terminal.
- Test mode: simulates a terminal (succeeds after about 7 s; an amount ending in 13 cents is declined). Handy for testing without a card terminal.
If there is at least one terminal with an API key (or test mode is on), Checkout → Card / Bancontact starts the payment automatically on the terminal, for the amount calculated by the server.
While the integration is on, the server only accepts "card" with a successful terminal payment for exactly that order and that amount. The requests are sent as a regular form, just as in the official PHP SDK, with the backup API (api-backup.pinvandaag.com) if the main API does not respond. Every API response is shown with [pin] in the server window, handy when troubleshooting. A successful payment that has not yet been processed (e.g. tablet crashed) is found again the next time that order is checked out.
Tips (card, cash and gift card)
The checkout screen shows a row of tip buttons for each payment method: None, 5%, 10%, 15% (rounded up to 10 cents), Rounding (to the next whole euro) and Other amount. With card the customer pays amount + tip in one go on the terminal; with cash the tip is included in the change and the cash drawer. The receipt shows the card amount with "of which tip" below it; the TOTAL and VAT stay the same, because tips are not revenue. The X/Z report shows the tips per payment method and as "Total tips".
The administrator sets up the tip buttons under Settings → Business → Tip: on/off, which percentages (at most 4, e.g. "5, 10, 15"), whether the "Rounding" button is included and for which payment methods (card, cash, gift card) tips are possible. "None" and "Other amount" are always included.
"Make it …" is always there, for every payment method, even when the tip buttons are off (no setting): the customer rounds the bill up themselves and the difference is the tip. There are buttons with the next whole euro and the next round amounts (e.g. € 28,00 → 29, 30, 40; € 44,00 → 45, 50, 60) and Other total to type in the total yourself. Tap the chosen button again = no rounding. At most € 500 tip (same limit as the till server).
No internet
The till works on the local network and does not need internet; only card payments via the integration do. If the business has no internet, the top bar shows No internet · card manually (checked every minute). The checkout screen then shows, also after a failed start on the terminal, the Already paid on the terminal button: take the card payment on the terminal itself and record it this way.
Floor plans and tables
Settings → Floor plans (administrator only):
- Add floor plans (e.g. Dining room, Terrace, Conservatory), rename, delete and reorder them with ◀ ▶.
- Add tables with the buttons above the grid (round, square, long, high table) and drag them into place with the mouse or your finger. The blue corner of a selected table makes it bigger or smaller.
- Set the name/number, number of seats (the chairs around the table count) and shape per table; duplicate or delete.
- With the keyboard: arrow keys move (Shift = bigger step), Delete removes.
- Changes only apply after Save; "Undo" puts everything back.
- A table or floor plan with an open order cannot be removed. Deleted tables are kept in old orders.
Copy configuration to a second venue
Settings → Import/export (administrator only). Once you have fully set up one business, export the configuration to a .json file and import it into the till of the second business. You can choose per section:
- Products: groups, products, prices (also per order type), VAT, options, menus, happy hours (with season), dayparts, allergens, ingredients/recipes, stamp cards, the all-you-can-eat packages and the product photos.
- Floor plans: areas and tables.
- Other settings: all business options, printers (without IP address), permissions per role and accounting.
Never included: name, address, postcode, town, phone, email, VAT number and receipt footer of the business, the email address for the Z report, card terminals and their keys, staff and PINs, and all revenue, receipts, customers and stock quantities.
Importing is heavily protected: a large red warning, a checkbox "I understand...", the administrator's own PIN again, no open orders, the same country (VAT rates) and an automatic backup beforehand. The import happens in a single transaction: if anything goes wrong, nothing changes. Existing products, groups, ingredients and tables are not erased but removed from the till (as with Delete), so old receipts and reports stay correct.
Import from another till
Switch without retyping everything. Always available (no switch): Settings → Import/export (administrator only) contains the section Import from another till.
- What: products (name, price incl. VAT, VAT, category, code/PLU, stock) or loyalty card customers (name, phone, email, points, address, postcode, town; first name and last name are merged).
- File: an export from your previous till (Dobizzz/DoPos, Lightspeed, MplusKASSA, unTill, Tebi ...) or your own list: CSV (; , tab or |; UTF-8 or Dutch Excel) or Excel (.xlsx), the first sheet, with the column names in the first row. Save an old .xls file as .xlsx or CSV first.
- Preview: the till recognises the columns by their name (Omschrijving, Verkoopprijs incl. BTW, BTW %, Omzetgroep, Artikelnummer, GSM, Spaarpunten ...) and shows the first 10 rows. If a column is wrong, choose it yourself. Nothing changes until Import.
- Products: prices as 3,50, € 3,50 or 1.234,50; VAT as 21, 9%, 0,09, high or low (unknown or empty: the rate you choose, by default the highest). Categories that don't exist yet are created (no category: "Imported").
- Stock (column Voorraad, Stock, Aantal ...): if Track stock is on (Settings → Business), the product tracks stock and the stock becomes that quantity (a count in the stock history, reason "Imported"). Empty: the stock stays as it is.
- Sample file (CSV): a list to fill in yourself (Naam;Productgroep;Prijs;Btw;Voorraad;Code), for example in Excel.
- Customers: points are added as a correction "Imported from another till" (visible in the history). Consent for text or email is not transferred (GDPR): ask for it again. Turn on the loyalty card first.
- Existing products (same code, or without a code the same name) and customers (same phone or email) are skipped, or updated if you tick that option (for products: name, price, VAT, category and stock). Duplicate rows in the file are taken once.
- Afterwards: how many are new, updated and skipped, with for each row what was wrong (e.g. no price). At most 5000 rows at a time. The log shows it as "Configuration imported".
Languages (42, including Turkish, Arabic, Darija, Berber, Polish, Bulgarian, Hungarian, Russian, Serbian, Albanian, Persian, Tigrinya, Amharic, Somali, Papiamento, Sranan Tongo, Hindi, Urdu, Indonesian, Vietnamese, Syriac-Aramaic, Chinese and Ukrainian)
Next to the © button at the bottom right, every screen has a language button (e.g. NL and the flag). Tap it for the menu: the languages are in alphabetical order, with the name in the language itself before the flag: Bahasa Indonesia (Indonesian), Čeština (Czech), Darija (Moroccan Arabic in Latin script), Deutsch, English, Español, Français, Hrvatski (Croatian), Italiano, Kurdî (Kurmancî), Latviešu (Latvian), Lietuvių (Lithuanian), Magyar (Hungarian), Nederlands, Papiamentu (Papiamento), Polski, Português, Română, Shqip (Albanian), Slovenčina (Slovak), Soomaali (Somali), Sranantongo, Srpski (Serbian, in Latin script), Tarifit (Riffian Berber), Tiếng Việt (Vietnamese), Türkçe, then in Cyrillic script Български (Bulgarian), Русский (Russian) and Українська (Ukrainian), then the languages in Arabic script: اردو (Urdu), الدارجة (Darija), العربية (Arabic), دری (Dari), فارسی (Persian, Farsi), پښتو (Pashto) and کوردی (سۆرانی) (Kurdish Sorani), then in Syriac script ܣܘܪܝܝܐ (Syriac-Aramaic, Suryoyo), in Devanagari हिन्दी (Hindi), in Ge'ez script ትግርኛ (Tigrinya) and አማርኛ (Amharic), in Tifinagh ⵜⴰⵎⴰⵣⵉⵖⵜ (Tamazight, Berber), and finally 中文(简体)(Chinese, simplified script). All screens, buttons, messages and error messages from the till server are translated.
- Per staff member: the chosen language is saved with the logged-in staff member (
gebruiker.taal). If someone logs in with a different language, the till switches immediately. The device itself remembers the last language used, so the PIN screen is already in that language. If you choose a language (on the PIN screen or while logged in) and log in (again) within 10 minutes, that choice takes priority and becomes that staff member's language. Switching reloads the screen; you stay logged in and the open bill stays open. - First time on a device: if a tablet or PC has no language set yet, the POS starts in the language chosen during installation. If no language was chosen, it uses the language of the device itself (browser or operating system, also in the Android app), and if that is not one of them, Dutch. After that, each device remembers its own choice.
- Eastern Europe: Polish, Czech, Slovak, Hungarian, Romanian, Bulgarian, Croatian (also for Bosnian), Lithuanian, Latvian, Ukrainian and Russian: the languages of most labour migrants from Central and Eastern Europe in the Netherlands and Belgium.
- Balkans: Serbian (in Latin script, as most Serbs in the Netherlands and Belgium write it; also for Montenegrin) and Albanian (Albania, Kosovo and North Macedonia).
- Horn of Africa: Tigrinya (Eritrea) and Amharic (Ethiopia), both in Ge'ez script, and Somali (in Latin script).
- Iran: Persian (Farsi). A device set to Afghan Persian (fa-AF) gets Dari, all others get Farsi.
- Caribbean Netherlands and Suriname: Papiamento (Papiamentu, Curaçao and Bonaire spelling; also for Aruba) and Sranan Tongo.
- Asia: Hindi (Devanagari; also for Sarnami Hindustani), Urdu (right to left), Indonesian and Vietnamese (Latin script, also on the receipt).
- Moroccan: Darija (Moroccan Arabic, the spoken language) in Arabic and in Latin script (the way many Dutch Moroccans write it in chat apps), alongside Modern Standard Arabic. Berber: Tarifit (Riffian, in Latin script; most Dutch Moroccans come from the Rif) and Standard Moroccan Tamazight in Tifinagh script.
- Right to left: Arabic (Modern Standard Arabic), Urdu, Darija in Arabic script, Dari and Pashto (Afghanistan), Persian (Farsi, Iran), Kurdish Sorani (Iraq/Iran) and Syriac-Aramaic (Suryoyo, in Syriac script). Amounts, codes and the number keys stay left to right. Kurdish Kurmancî (Turkey/Syria) is in Latin script.
- Kitchen ticket (kitchen/bar): by default in the language of the staff member who places the order. Per printer, a fixed language (e.g. the cook's) can also be set under Settings → Printers → Kitchen ticket language, in Latin script: Nederlands, Čeština, Darija, Deutsch, English, Español, Français, Hrvatski, Italiano, Kurdî, Latviešu, Lietuvių, Magyar, Papiamentu, Polski, Português, Română, Shqip, Slovenčina, Soomaali, Sranantongo, Srpski, Tarifit, Tiếng Việt, Bahasa Indonesia or Türkçe. Bulgarian, Russian and Ukrainian are printed on the kitchen ticket in Latin transcription (the receipt printer has no Cyrillic). Arabic, Syriac, Devanagari, Ge'ez and Tifinagh script and Chinese cannot be printed on a receipt printer: Darija is then printed in Latin script, Tamazight as Tarifit and the rest in Dutch. The fixed texts (TABLE, Course, HOLD until called, CALL COURSE, PRINTED LATER, Takeaway, Counter) are translated; product names and notes stay as they were entered. Printers that were set to Dutch follow the staff member.
- Receipt (for all customers): Dutch by default, separate from the language of the screens. You choose another language under Settings → Business → Receipt language (just below the text at the bottom of the receipt), only languages in Latin script. This also applies to the pro forma, return receipt, copy, gift voucher and the receipt by email. The amounts, VAT codes, the business's VAT number and the fiscal lines (Belgium) stay the same; a custom text at the bottom of the receipt stays exactly as the business types it.
- Products, groups and options are named as the business enters them; they are not translated.
- You can also set the language per staff member under Settings → Staff.
- Introduction and manual are also available in all these languages. The © button opens them in the till's language; at the top you can pick another language with the flags (this changes nothing in the till).
For developers: every visible text is in the code as vt('Nederlandse tekst') (apps/pos-web/lib/i18n.ts); the Dutch text is the key. The translations are in apps/pos-web/lib/vertalingen/<taal>.ts. If a translation is missing, the till shows the Dutch; the i18n test (pos-web) checks that every text is translated in every language and that the {0} placeholders match. Messages from the till server stay in Dutch and are translated in the browser (also with {0}, e.g. a product name in the message).
Setting up printers
A new till has no printers. Log in as administrator (demo: 1111) and choose Settings in the top bar.
- Printers: add as many printers as the business has (e.g. till, kitchen, bar, pizza), each with a connection (usually the network: IP address and port 9100) and paper width. Use Test print to check that it works. At the top you choose which printer prints the receipt and pro forma (and opens the cash drawer). Per printer you also choose the kitchen ticket language (see Languages); the receipt stays in Dutch.
- Connection per printer:
- Network (IP address): IP address and port (usually 9100). This is how it always worked, and it keeps working this way: existing printers are automatically set to network.
- USB: on Linux the device, for example
/dev/usb/lp0. On Android the USB printer attached to the device (OTG cable; empty = the first USB printer). On Windows and macOS, choose System printer. - Serial (COM / ttyUSB): a COM port (Windows),
/dev/ttyUSB0or/dev/ttyS0(Linux, Android) or/dev/cu.…(macOS), with the speed (usually 9600, 19200 or 38400 baud). Also for a Bluetooth printer that Windows or Linux pairs as a COM port or/dev/rfcomm0. - Bluetooth: in the HorecaPOS app on Android, with the Bluetooth address of the paired printer (e.g. a mobile receipt printer). Pair the printer first in the Android Bluetooth settings.
- System printer (Windows / CUPS): the printer as Windows or CUPS (Linux, macOS) knows it, with its own driver or as Generic / Text Only. The ticket is sent raw (RAW) to the printer, without formatting by the driver.
- Built-in (Sunmi, iMin ...): the printer inside an Android POS terminal itself.
- Search shows the printers and ports the till can see. Pick one and the address is filled in.
- Protocol: ESC/POS (almost all receipt printers, including Star printers in ESC/POS mode) or Star (Star Line Mode). With Star the till converts the ticket itself; the ticket looks the same.
- Order screen with its own printer: an Android order screen with the HorecaPOS app (e.g. a handheld with a mobile Bluetooth printer, or a Sunmi as order screen) can print by itself. Register it on the device itself (Settings → Printers → Order screens with their own printer) and choose Connected to for the printer. The order screen fetches its tickets from the till; keep the app open there. If that fails (app closed, out of Wi-Fi range), a kitchen ticket goes into the print queue, just like with a network printer that is switched off. Unregister device puts the printers back on the till itself.
- Printer per category / product: choose per product group which printer the kitchen ticket goes to. Per product you can override this with its own printer or "no kitchen ticket".
Identical products are combined when printing: twice 1x Cola becomes 2x Cola, on the kitchen ticket and on the receipt. Only products with the same options and note are combined.
The Linux installer adds the till user to the lp and dialout groups, so the till is allowed to use USB and serial printers.
Need help?
Optimum POS · 085 560 00 60 · support@optimumpos.nl · Mon–Fri 9:00–20:00, Sat–Sun 14:00–20:00