Appearance
MplusKassa Onboarding Flow
Overview
MplusKassa (Mpluskassa) is a merchant-scoped in-house POS system commonly used in the Netherlands and Belgium. One connection covers the whole merchant account; MplusKassa branches are imported as Upvendo locations. MplusKassa does not include payment processing — to take customer payments you connect a separate payment provider (Stripe and/or Viva Wallet).
MplusKassa owns the catalog. Products, articles, modifiers, prices, VAT and stock are pulled one way, from MplusKassa into Upvendo (read-only), and the synced fields are locked against editing in Upvendo. Build your menu in MplusKassa first, then sync. (See the MplusKassa integration doc for the full sync behaviour.)
Prerequisite enforced at connect: the only profile the backend requires before MplusKassa can be connected is a Branding Profile (ThirdPartyIntegrationHelper::checkRequiredProfiles). Payment and billing profiles are optional at connect time and can be set up later — though you will need a payment provider before you can accept customer payments. A branding profile is required because imported locations are assigned the merchant's default branding profile.
One in-house POS per merchant. MplusKassa is an in-house, merchant-scoped channel and is mutually exclusive with any other in-house channel for the merchant. If the merchant already has another in-house channel (Hendrickx, Vanhoutte, Shopcaisse, Square, or Lightspeed K-Series) connected, the connect request is rejected with 400 "Another in-house channel is already enabled for this merchant" (ThirdPartyIntegrationHelper::checkForInhouseChannel).
Locations. MplusKassa branches are imported as Upvendo locations (on connect and on each sync). Merchants don't create these locations manually, but MplusKassa only supplies the branch name — all other location details (address, coordinates, business hours, delivery zones, contact info, a consumer-friendly name) must be completed in Upvendo under Settings → Locations before enabling online ordering or kiosk.
Integration Type
- Scope: Merchant-scoped (one connection covers all branches)
- Payment Processing: NOT included (requires Stripe and/or Viva Wallet)
- Branding Profile: Required at connect (assigned to imported locations)
- Payment Profile: Optional at connect (required before accepting customer payments)
- Billing Profile: Optional at connect
- Menu Sync: Pull-only — MplusKassa → Upvendo (read-only; synced fields locked in Upvendo)
- Order Sync: Push-only — Upvendo → MplusKassa (orders forwarded after they reach a syncable status)
- Inventory Sync: Pull-only — MplusKassa → Upvendo (
amountFreeper article per branch) - Location Import: Pull from MplusKassa (branches imported as locations; only branch name provided)
The KB previously described this as a "bidirectional" menu/order sync. That is not how the integration behaves: the catalog is pulled one way (MplusKassa → Upvendo) and orders are pushed one way (Upvendo → MplusKassa). See the corrected integration doc.
Discovery Flow (JSON - for deterministic parsing)
discovery_questions
[
{
"id": "channels",
"text": "What channels do you want to set up with MplusKassa?",
"text_i18n": {
"nl": "Welke kanalen wil je instellen met MplusKassa?",
"fr": "Quels canaux souhaitez-vous configurer avec MplusKassa ?",
"de": "Welche Kanäle möchten Sie mit MplusKassa einrichten?",
"es": "¿Qué canales quieres configurar con MplusKassa?",
"it": "Quali canali vuoi configurare con MplusKassa?",
"pt": "Que canais quer configurar com o MplusKassa?"
},
"options": [
"Kiosk only",
"Online ordering only",
"Both"
],
"labels": {
"nl": {
"Kiosk only": "Alleen kiosk",
"Online ordering only": "Alleen online bestellen",
"Both": "Beide"
},
"fr": {
"Kiosk only": "Kiosque uniquement",
"Online ordering only": "Commande en ligne uniquement",
"Both": "Les deux"
},
"de": {
"Kiosk only": "Nur Kiosk",
"Online ordering only": "Nur Online-Bestellung",
"Both": "Beides"
},
"es": {
"Kiosk only": "Solo quiosco",
"Online ordering only": "Solo pedidos en línea",
"Both": "Ambos"
},
"it": {
"Kiosk only": "Solo chiosco",
"Online ordering only": "Solo ordini online",
"Both": "Entrambi"
},
"pt": {
"Kiosk only": "Apenas quiosque",
"Online ordering only": "Apenas pedidos online",
"Both": "Ambos"
}
}
},
{
"id": "menu_ready",
"text": "Do you already have your menu set up in MplusKassa?",
"text_i18n": {
"nl": "Heb je je menu al ingesteld in MplusKassa?",
"fr": "Votre menu est-il déjà configuré dans MplusKassa ?",
"de": "Ist Ihr Menü bereits in MplusKassa eingerichtet?",
"es": "¿Ya tienes tu menú configurado en MplusKassa?",
"it": "Hai già configurato il tuo menu in MplusKassa?",
"pt": "Já tem o seu menu configurado no MplusKassa?"
},
"options": [
"Yes, my menu is in MplusKassa",
"No, I need to create it"
],
"labels": {
"nl": {
"Yes, my menu is in MplusKassa": "Ja, mijn menu staat in MplusKassa",
"No, I need to create it": "Nee, ik moet het nog aanmaken"
},
"fr": {
"Yes, my menu is in MplusKassa": "Oui, mon menu est dans MplusKassa",
"No, I need to create it": "Non, je dois le créer"
},
"de": {
"Yes, my menu is in MplusKassa": "Ja, mein Menü ist in MplusKassa",
"No, I need to create it": "Nein, ich muss es erst erstellen"
},
"es": {
"Yes, my menu is in MplusKassa": "Sí, mi menú está en MplusKassa",
"No, I need to create it": "No, necesito crearlo"
},
"it": {
"Yes, my menu is in MplusKassa": "Sì, il mio menu è in MplusKassa",
"No, I need to create it": "No, devo crearlo"
},
"pt": {
"Yes, my menu is in MplusKassa": "Sim, o meu menu está no MplusKassa",
"No, I need to create it": "Não, preciso de o criar"
}
},
"abort_if": "No, I need to create it",
"abort_message": "MplusKassa owns the catalog and Upvendo only pulls it in read-only. Please create your products and articles in MplusKassa first, then come back to connect and sync.",
"abort_message_i18n": {
"nl": "MplusKassa beheert de catalogus en Upvendo haalt die alleen read-only op. Maak je producten en artikelen eerst aan in MplusKassa en kom daarna terug om te verbinden en te synchroniseren.",
"fr": "MplusKassa détient le catalogue et Upvendo ne le récupère qu'en lecture seule. Créez d'abord vos produits et articles dans MplusKassa, puis revenez pour connecter et synchroniser.",
"de": "MplusKassa besitzt den Katalog und Upvendo ruft ihn nur schreibgeschützt ab. Legen Sie Ihre Produkte und Artikel zuerst in MplusKassa an und kehren Sie dann zurück, um zu verbinden und zu synchronisieren.",
"es": "MplusKassa es dueño del catálogo y Upvendo solo lo obtiene en modo de solo lectura. Crea primero tus productos y artículos en MplusKassa y luego vuelve para conectar y sincronizar.",
"it": "MplusKassa possiede il catalogo e Upvendo lo recupera solo in sola lettura. Crea prima i tuoi prodotti e articoli in MplusKassa e poi torna per collegare e sincronizzare.",
"pt": "O MplusKassa é dono do catálogo e o Upvendo apenas o obtém em modo de leitura. Crie primeiro os seus produtos e artigos no MplusKassa e depois volte para ligar e sincronizar."
}
}
]setup_steps
{
"Kiosk only": [
{"id": "branding_profile", "title": "Set up Store Branding", "route": "/settings/brand", "note": "Required before connecting MplusKassa; assigned to imported locations."},
{"id": "connect_pos", "title": "Connect MplusKassa", "route": "/mpluskassa"},
{"id": "sync_locations", "title": "Sync Locations", "route": "/mpluskassa"},
{"id": "complete_location", "title": "Complete Location Details", "route": "/settings/locations", "note": "MplusKassa supplies only the branch name; add address, coordinates, hours, etc."},
{"id": "menu_for_kiosk", "title": "Build Menu for Kiosk", "route": "/menus/menu-builder"},
{"id": "in_house_settings", "title": "Set up In-House Settings", "route": "/in-house/settings"},
{"id": "device_profile", "title": "Create Device Profile", "route": "/device-management/profiles"},
{"id": "kiosk_device", "title": "Set up Kiosk & Activate Payment", "route": "/device-management/devices"},
{"id": "payment_profile", "title": "Set up Payment Profile", "route": "/settings/payments", "optional_for_go_live": true, "note": "Optional at connect, but required to accept customer payments (Stripe / Viva Wallet)."},
{"id": "billing_profile", "title": "Set up Billing Profile", "route": "/settings/billing", "optional_for_go_live": true, "note": "Optional - can be set up later."},
{"id": "test_kiosk", "title": "Activate Kiosk & Test Order", "optional_for_go_live": true}
],
"Online ordering only": [
{"id": "branding_profile", "title": "Set up Store Branding", "route": "/settings/brand", "note": "Required before connecting MplusKassa; assigned to imported locations."},
{"id": "connect_pos", "title": "Connect MplusKassa", "route": "/mpluskassa"},
{"id": "sync_locations", "title": "Sync Locations", "route": "/mpluskassa"},
{"id": "complete_location", "title": "Complete Location Details", "route": "/settings/locations", "note": "MplusKassa supplies only the branch name; add address, coordinates, hours, etc."},
{"id": "menu_for_online_ordering", "title": "Build Menu for Online Ordering", "route": "/menus/menu-builder"},
{"id": "online_settings", "title": "Set up Online Settings", "route": "/online-settings"},
{"id": "configure_online_ordering", "title": "Set up Online Ordering", "route": "/online/online-ordering"},
{"id": "payment_profile", "title": "Set up Payment Profile", "route": "/settings/payments", "optional_for_go_live": true, "note": "Optional at connect, but required to accept customer payments (Stripe / Viva Wallet)."},
{"id": "billing_profile", "title": "Set up Billing Profile", "route": "/settings/billing", "optional_for_go_live": true, "note": "Optional - can be set up later."},
{"id": "test_online_ordering", "title": "Open Online Ordering URL & Test Order", "route": "/online/online-ordering", "optional_for_go_live": true}
],
"Both": [
{"id": "branding_profile", "title": "Set up Store Branding", "route": "/settings/brand", "note": "Required before connecting MplusKassa; assigned to imported locations."},
{"id": "connect_pos", "title": "Connect MplusKassa", "route": "/mpluskassa"},
{"id": "sync_locations", "title": "Sync Locations", "route": "/mpluskassa"},
{"id": "complete_location", "title": "Complete Location Details", "route": "/settings/locations", "note": "MplusKassa supplies only the branch name; add address, coordinates, hours, etc."},
{"id": "menu_for_kiosk", "title": "Build Menu for Kiosk", "route": "/menus/menu-builder"},
{"id": "menu_for_online_ordering", "title": "Build Menu for Online Ordering", "route": "/menus/menu-builder"},
{"id": "in_house_settings", "title": "Set up In-House Settings", "route": "/in-house/settings"},
{"id": "device_profile", "title": "Create Device Profile", "route": "/device-management/profiles"},
{"id": "kiosk_device", "title": "Set up Kiosk & Activate Payment", "route": "/device-management/devices"},
{"id": "online_settings", "title": "Set up Online Settings", "route": "/online-settings"},
{"id": "configure_online_ordering", "title": "Set up Online Ordering", "route": "/online/online-ordering"},
{"id": "payment_profile", "title": "Set up Payment Profile", "route": "/settings/payments", "optional_for_go_live": true, "note": "Optional at connect, but required to accept customer payments (Stripe / Viva Wallet)."},
{"id": "billing_profile", "title": "Set up Billing Profile", "route": "/settings/billing", "optional_for_go_live": true, "note": "Optional - can be set up later."},
{"id": "test_kiosk", "title": "Activate Kiosk & Test Order", "optional_for_go_live": true},
{"id": "test_online_ordering", "title": "Open Online Ordering URL & Test Order", "route": "/online/online-ordering", "optional_for_go_live": true}
]
}Prerequisites
Enforced by ThirdPartyIntegrationHelper::checkIntegrationPrerequisites when you submit the connect form:
- Branding Profile (required).
checkRequiredProfilesaborts with400 "Missing required profiles: branding profile…"if the merchant has no branding profile. The default branding profile is assigned to imported locations. Set it up at Settings → Brand (/settings/brand). - No other in-house channel (required).
checkForInhouseChannelaborts with400 "Another in-house channel is already enabled for this merchant"if any other in-house channel (Hendrickx, Vanhoutte, Shopcaisse, Square, Lightspeed K-Series) is already connected for the merchant.
Optional (can be done later, not blocked at connect):
- Payment Profile (
/settings/payments) — required before you can accept customer payments. MplusKassa has no payment processing, so connect Stripe (e.g. for online ordering, iDEAL) and/or Viva Wallet (e.g. for kiosk terminals). - Billing Profile (
/settings/billing).
Connect MplusKassa
Route: /mpluskassa (back office). The connect form posts to POST /back-office/mpluskassa (MplusKassaIntegrationController::initiate, validated by InitiateMplusKassaRequest).
Connect form fields
Shown before the integration is connected:
| Field | Payload key | Required | Notes |
|---|---|---|---|
| API ident | ident | Yes (UI) | Your MplusKassa API ident (from your Mplus partner portal / account manager). |
| API secret | secret | Yes (UI) | Your MplusKassa API secret (masked input). |
| API URL (optional) | api_url | No | Custom endpoint (e.g. a VPN URL). Defaults to the standard MplusKassa cloud endpoint when omitted. |
| API port | api_port | No | Used to build the endpoint URL (default cloud host https://api.mpluskassa.nl:{port}). |
ident and secret are marked nullable in the backend request but are validated as required by the front-end form and the backend aborts (422 "MplusKassa ident and secret are required") if they are still empty on an initial connection. On submit Upvendo auto-tests the connection and, if the test passes, dispatches the first sync automatically.
Note: the connect step is labelled "Connect MplusKassa and Sync Now" because connecting auto-tests and (on success) kicks off the initial sync; there is no separate manual button to start that first sync.
Post-connect configuration
Shown only after the integration is connected (sent on the same POST /back-office/mpluskassa endpoint as a settings update):
| Field | Payload key | Required | Notes |
|---|---|---|---|
| Branch (Filiaal) | branch_number | No | The MplusKassa branch this configuration targets. |
| Online Ordering Workplace | online_workplace_number | No | Where Online Ordering orders are injected. |
| Table QR Workplace | qr_workplace_number | No | Where Table QR orders are injected (clearable; falls back to the online workplace when unset). |
| Auto Sync Time | sync_time | No | Daily catalog/inventory sync time. Whole or half hour only (HH:00 or HH:30, validated by regex `^([01]?[0-9] |
The backend
InitiateMplusKassaRequestalso acceptsworkplace_number(a generic workplace), but the back-office form exposes only branch, online workplace and Table QR workplace selectors. Per-location / per-device workplace mappings are managed on the integration's Location Mapping tab (not the connect form).
After connecting
- Sync Locations —
POST /back-office/mpluskassa/locations/sync(syncLocations→syncLocationsOnly) creates/updates Upvendo locations from MplusKassa branches without pulling the catalog. - Sync Now — clicking "Sync Now" (Status tab) opens a sync-mode dialog ("Start MplusKassa Sync") before anything runs. You pick one of two modes, then the dialog dispatches
POST /back-office/mpluskassa/start-syncwithsync_typeset accordingly:- Incremental Sync (
sync_type: "incremental", the pre-selected default) — only fetches products that changed since the last sync. Faster; recommended for routine updates. - Full Sync (
sync_type: "full") — re-pulls the entire catalog from MplusKassa from scratch (resets the sync marker) and deactivates items that no longer exist there. Slower; use when data looks out of sync. sync_typeis optional/sometimeson the backend (StartSyncMplusKassaRequest) and must beincrementalorfullwhen present; omitting it (or any other value) behaves as incremental. The request is refused with409 "A sync is already in progress. Please wait for it to complete."if a sync is already running.
- Incremental Sync (
- Test Connection / Re-probe / Status — the integration page also exposes a connection test, a capabilities probe (loyalty/vouchers), and sync statistics.
Complete Location Setup
After branches import, go to Settings → Locations (/settings/locations) to complete the fields the POS does not provide. MplusKassa supplies only the branch name; you must add the address, latitude/longitude coordinates, business hours, delivery zones and contact details before enabling online ordering or kiosk. Imported locations are assigned the merchant's default branding profile (and the default billing profile's Stripe customer ID if one exists).
The specific "Incomplete / Partial / Ready" location-status indicators and exact per-field readiness thresholds described in a previous version of this doc could not be verified against the back-office code and have been removed.
Disconnect
Disconnecting MplusKassa is administratively disabled. The back office surfaces a disconnect option, but the request (POST /back-office/mpluskassa/disable) is rejected with 400 "Disconnecting MplusKassa integration is disabled. Please contact administrator."
Netherlands / Belgium Notes
Payment methods
MplusKassa has no payment processing, so customer payments go through your connected provider:
- iDEAL — popular in the Netherlands (via Stripe)
- Card — Visa, Mastercard
- Bancontact — for Belgian customers
(Specific provider/method availability is configured under Payment Profiles, not on the MplusKassa page.)
VAT (BTW)
VAT is not configured by a tax-mapping screen in Upvendo. Each MplusKassa article carries its own VAT code/percentage, and Upvendo auto-creates a matching tax rate (MPLUS_VAT_{code}) with the inclusive tax method when the article is imported. The integration derives country, timezone and language from the MplusKassa branch.
Troubleshooting
"Another in-house channel is already enabled" on connect
MplusKassa is mutually exclusive with every other in-house channel (Hendrickx, Vanhoutte, Shopcaisse, Square, Lightspeed K-Series). Remove the other in-house integration before connecting MplusKassa.
"Missing required profiles: branding profile" on connect
Set up a Branding Profile at Settings → Brand first — it is the one profile the backend requires before MplusKassa can be connected.
Locations not appearing
- Confirm the connection test passed on the MplusKassa page.
- Run Sync Locations (
/mpluskassa) to create locations from branches, then complete their details in Settings → Locations. - If a branch was added in MplusKassa after the initial connection, run a sync to detect it.
Menu / prices won't change in Upvendo
MplusKassa owns the catalog. Item name, description, price, PLU, modifier groups, allergens and dietary preferences (and category name/description) are locked in Upvendo. Make the change in MplusKassa, then sync.
"A sync is already in progress"
A sync is already running — wait for it to finish before triggering another (the start-sync endpoint returns 409 while one is in progress).
Incremental vs. Full sync — which one do I need?
Clicking Sync Now always opens the "Start MplusKassa Sync" dialog and asks you to choose a mode:
- Incremental Sync (default, pre-selected) — pulls only products changed since the last sync. Use this for routine updates; it's faster.
- Full Sync — re-pulls the entire catalog from MplusKassa from scratch and deactivates Upvendo items that no longer exist in MplusKassa. Use this if items look stale, duplicated, or out of sync after a bulk change in MplusKassa (e.g. deleted/renamed articles not reflecting in Upvendo).
This incremental/full choice applies to the manual "Sync Now" trigger; the scheduled daily sync (driven by Auto Sync Time, read as your local time) and background change-detection run on their own separate logic.
Payments failing
Connect a payment provider (Stripe / Viva Wallet) under Settings → Payments and assign a payment profile to the location — MplusKassa does not process payments itself.