Skip to content

Lightspeed K-Series Onboarding Flow

Overview

Lightspeed Restaurant K-Series is a merchant-scoped POS integration that connects via OAuth 2.0. One OAuth authorization covers the whole Lightspeed account, but data is wired up per location: you create your Upvendo locations manually, then map each one to a Lightspeed business location.

Key points:

  • OAuth connection — you log in to your Lightspeed account to authorize Upvendo. There are no API keys to manage, and the integration does not use PKCE (CSRF protection comes from an HMAC-signed state parameter).

  • Locations are not auto-imported — you create locations in Upvendo manually and link each one to a Lightspeed business location ID in the integration's Locations tab.

  • Menu is pulled from Lightspeed, but items push back — Upvendo imports your menu, items, modifiers, categories, tax rates, allergens, and stock from Lightspeed K-Series, which is the source of truth for structure. It is not strictly one-way, though: an item created or edited in Upvendo on a K-Series-mapped location is pushed to Lightspeed (PushItemToLightspeedKSeriesJob, dispatched from ItemRepository). Categories are the exception — K-Series categories are its accounting groups, so they cannot be created or deleted from Upvendo (config/pos-providers.php sets category_create and category_delete to false).

  • Separate payment provider required — Lightspeed handles in-house POS payments only. Kiosk and Online Ordering still need Stripe or Viva Wallet for customer-facing payments.

  • Lightspeed K-Series only in development/testing — the production PRODUCTION_POS_PROVIDERS list is Upvendo POS, Hendrickx and Vanhoutte; Lightspeed K-Series is listed only in development/testing.

    POS_PROVIDERS / PRODUCTION_POS_PROVIDERS now begin with the first-party upvendo entry, but neither is a live provider list: they are read only by POSSelectionGrid.vue, which renders inside EmilyGuidedSetupDialog — a component imported and registered in App.vue but absent from its template and referenced nowhere else as a tag, so it never renders (Emily's modal registry maps guided-setup to a different component, emilyModalRegistry.ts:139). The list a merchant actually sees comes from GET /back-office/merchant/reseller-providers. The first-party provider is server-gated regardless: staged test_only (config/pos-providers.php:51-52), so in production only merchants flagged is_test are offered it.

For the full integration reference (OAuth internals, scopes, token lifecycle, webhooks, order flow), see the Lightspeed K-Series Integration doc.


Integration Type

  • Scope: Merchant-scoped (one OAuth connection for the entire account), wired per location via mappings
  • Menu Sync: Structure imported from Lightspeed; Upvendo-created items push back to K-Series (categories are pull-only)
  • Location Import: Manual — create locations in Upvendo, then map each to a Lightspeed business location
  • Order Flow: Completed, paid Upvendo orders are pushed to Lightspeed K-Series via API (payment is embedded in the order payload)

Discovery Flow (JSON - for deterministic parsing)

How this is used: The Upvendo proxy parses the discovery_questions and setup_steps fenced blocks below verbatim and runs a deterministic discovery flow (no LLM involved). Question ids, abort_if/abort_message, the channels option labels, and the step ids are load-bearing — they must stay aligned with the proxy parser (upvendo-backend-proxy/src/emily/merchant/onboarding-state.js) and the frontend completion mapping (upvendo-backoffice/src/utils/emily/setupStepMappings.ts). The proxy keeps only each step's id, title, and route (and required: false when present) when it serves steps to the frontend; any note field is for documentation only and is not delivered to the UI.

discovery_questions
[
  {
    "id": "channels",
    "text": "Which channels do you want to set up with Lightspeed K-Series?",
    "text_i18n": {
      "nl": "Welke kanalen wil je instellen met Lightspeed K-Series?",
      "fr": "Quels canaux souhaitez-vous configurer avec Lightspeed K-Series ?",
      "de": "Welche Kanäle möchten Sie mit Lightspeed K-Series einrichten?",
      "es": "¿Qué canales quieres configurar con Lightspeed K-Series?",
      "it": "Quali canali vuoi configurare con Lightspeed K-Series?",
      "pt": "Que canais quer configurar com o Lightspeed K-Series?"
    },
    "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": "lightspeed_account",
    "text": "Do you have an active Lightspeed Restaurant K-Series account?",
    "text_i18n": {
      "nl": "Heb je een actief Lightspeed Restaurant K-Series-account?",
      "fr": "Avez-vous un compte Lightspeed Restaurant K-Series actif ?",
      "de": "Haben Sie ein aktives Lightspeed Restaurant K-Series-Konto?",
      "es": "¿Tienes una cuenta activa de Lightspeed Restaurant K-Series?",
      "it": "Hai un account Lightspeed Restaurant K-Series attivo?",
      "pt": "Tem uma conta ativa do Lightspeed Restaurant K-Series?"
    },
    "options": [
      "Yes, I have an account",
      "No, I need to set one up"
    ],
    "labels": {
      "nl": {
        "Yes, I have an account": "Ja, ik heb een account",
        "No, I need to set one up": "Nee, ik moet er een aanmaken"
      },
      "fr": {
        "Yes, I have an account": "Oui, j'ai un compte",
        "No, I need to set one up": "Non, je dois en créer un"
      },
      "de": {
        "Yes, I have an account": "Ja, ich habe ein Konto",
        "No, I need to set one up": "Nein, ich muss eines einrichten"
      },
      "es": {
        "Yes, I have an account": "Sí, tengo una cuenta",
        "No, I need to set one up": "No, necesito crear una"
      },
      "it": {
        "Yes, I have an account": "Sì, ho un account",
        "No, I need to set one up": "No, devo crearne uno"
      },
      "pt": {
        "Yes, I have an account": "Sim, tenho uma conta",
        "No, I need to set one up": "Não, preciso de criar uma"
      }
    },
    "abort_if": "No, I need to set one up",
    "abort_message": "You'll need an active Lightspeed Restaurant K-Series account before connecting. Please contact Lightspeed at lightspeedhq.com to get an account set up, then come back here to continue.",
    "abort_message_i18n": {
      "nl": "Je hebt een actief Lightspeed Restaurant K-Series-account nodig voordat je kunt verbinden. Neem contact op met Lightspeed via lightspeedhq.com om een account aan te maken en kom daarna terug om verder te gaan.",
      "fr": "Vous aurez besoin d'un compte Lightspeed Restaurant K-Series actif avant de vous connecter. Contactez Lightspeed sur lightspeedhq.com pour créer un compte, puis revenez ici pour continuer.",
      "de": "Sie benötigen ein aktives Lightspeed Restaurant K-Series-Konto, bevor Sie eine Verbindung herstellen können. Wenden Sie sich an Lightspeed unter lightspeedhq.com, um ein Konto einzurichten, und kehren Sie dann hierher zurück, um fortzufahren.",
      "es": "Necesitarás una cuenta activa de Lightspeed Restaurant K-Series antes de conectar. Ponte en contacto con Lightspeed en lightspeedhq.com para crear una cuenta y luego vuelve aquí para continuar.",
      "it": "Prima di collegarti ti serve un account Lightspeed Restaurant K-Series attivo. Contatta Lightspeed su lightspeedhq.com per creare un account, poi torna qui per continuare.",
      "pt": "Vai precisar de uma conta ativa do Lightspeed Restaurant K-Series antes de ligar. Contacte a Lightspeed em lightspeedhq.com para criar uma conta e depois volte aqui para continuar."
    }
  },
  {
    "id": "menu_ready",
    "text": "Do you already have your menu set up in Lightspeed K-Series?",
    "text_i18n": {
      "nl": "Heb je je menu al ingesteld in Lightspeed K-Series?",
      "fr": "Votre menu est-il déjà configuré dans Lightspeed K-Series ?",
      "de": "Ist Ihr Menü bereits in Lightspeed K-Series eingerichtet?",
      "es": "¿Ya tienes tu menú configurado en Lightspeed K-Series?",
      "it": "Hai già configurato il tuo menu in Lightspeed K-Series?",
      "pt": "Já tem o seu menu configurado no Lightspeed K-Series?"
    },
    "options": [
      "Yes, my menu is in Lightspeed",
      "No, I need to create it"
    ],
    "labels": {
      "nl": {
        "Yes, my menu is in Lightspeed": "Ja, mijn menu staat in Lightspeed",
        "No, I need to create it": "Nee, ik moet het nog aanmaken"
      },
      "fr": {
        "Yes, my menu is in Lightspeed": "Oui, mon menu est dans Lightspeed",
        "No, I need to create it": "Non, je dois le créer"
      },
      "de": {
        "Yes, my menu is in Lightspeed": "Ja, mein Menü ist in Lightspeed",
        "No, I need to create it": "Nein, ich muss es erst erstellen"
      },
      "es": {
        "Yes, my menu is in Lightspeed": "Sí, mi menú está en Lightspeed",
        "No, I need to create it": "No, necesito crearlo"
      },
      "it": {
        "Yes, my menu is in Lightspeed": "Sì, il mio menu è in Lightspeed",
        "No, I need to create it": "No, devo crearlo"
      },
      "pt": {
        "Yes, my menu is in Lightspeed": "Sim, o meu menu está no Lightspeed",
        "No, I need to create it": "Não, preciso de o criar"
      }
    },
    "abort_if": "No, I need to create it",
    "abort_message": "Lightspeed requires your menu to be set up in the POS first. Please create your menu items in Lightspeed K-Series, then come back to continue the setup.",
    "abort_message_i18n": {
      "nl": "Lightspeed vereist dat je menu eerst in de kassa staat. Maak je menu-items aan in Lightspeed K-Series en kom daarna terug om de installatie te voltooien.",
      "fr": "Lightspeed nécessite que votre menu soit d'abord configuré dans le système de caisse. Créez vos articles dans Lightspeed K-Series, puis revenez pour poursuivre la configuration.",
      "de": "Lightspeed erfordert, dass Ihr Menü zuerst im Kassensystem eingerichtet ist. Legen Sie Ihre Menüartikel in Lightspeed K-Series an und kehren Sie dann zurück, um die Einrichtung fortzusetzen.",
      "es": "Lightspeed requiere que tu menú esté configurado primero en el TPV. Crea tus artículos en Lightspeed K-Series y luego vuelve para continuar la configuración.",
      "it": "Lightspeed richiede che il menu sia prima configurato nel POS. Crea i tuoi articoli in Lightspeed K-Series e poi torna per continuare la configurazione.",
      "pt": "O Lightspeed exige que o seu menu esteja primeiro configurado no POS. Crie os seus artigos no Lightspeed K-Series e depois volte para continuar a configuração."
    }
  }
]
setup_steps
{
  "Kiosk only": [
    {
      "id": "branding_profile",
      "title": "Set up Store Branding",
      "route": "/settings/brand"
    },
    {
      "id": "create_location",
      "title": "Create Location",
      "route": "/settings/locations",
      "note": "Create your location manually. Lightspeed does not auto-import locations."
    },
    {
      "id": "connect_pos",
      "title": "Connect Lightspeed K-Series",
      "route": "/lightspeed",
      "note": "Click 'Connect with Lightspeed' on the Settings tab. You will be redirected to log in to your Lightspeed account and authorize Upvendo. After authorization you are returned to the Locations tab, where you map each Upvendo location to a Lightspeed business location."
    },
    {
      "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": "lightspeed_order_profiles",
      "title": "Set up Order Profiles & Tax",
      "route": "/lightspeed",
      "action": "order_profiles_guidance",
      "note": "Create the dedicated take-away / delivery order profiles in the Lightspeed Back Office (name/code are your choice — e.g. upvtakeout / upvdelivery; what matters is Takeaway mode = Pick up / Delivery and Order completion = Complete manually in POS), map them on the Locations tab via the mapping's Order profiles dialog, and attach the tax rules. US & Canada: tax is calculated automatically from the store address, so the new profiles bill correctly with no per-profile setup — a live account already has this configured with Lightspeed. Only Lightspeed can change tax rates. (The tax method — exclusive vs inclusive — imports automatically; there is no dine-in vs take-away rate split.) EU: send Lightspeed support a one-time request to attach the reduced-rate VAT rule (template in the 'Order profiles & VAT setup' section). The built-in dine-in / take-away profiles already bill the correct tax, so custom profiles are mainly needed to keep prepaid orders on the Orders screen. Auto-completes once the profiles are mapped in Upvendo.",
      "optional_for_go_live": true
    },
    {
      "id": "payment_profile",
      "title": "Set up Payment Profile",
      "route": "/settings/payments",
      "optional_for_go_live": true
    },
    {
      "id": "billing_profile",
      "title": "Set up Billing Profile",
      "route": "/settings/billing",
      "optional_for_go_live": true
    },
    {
      "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"
    },
    {
      "id": "create_location",
      "title": "Create Location",
      "route": "/settings/locations",
      "note": "Create your location manually. Lightspeed does not auto-import locations."
    },
    {
      "id": "connect_pos",
      "title": "Connect Lightspeed K-Series",
      "route": "/lightspeed",
      "note": "Click 'Connect with Lightspeed' on the Settings tab. You will be redirected to log in to your Lightspeed account and authorize Upvendo. After authorization you are returned to the Locations tab, where you map each Upvendo location to a Lightspeed business location."
    },
    {
      "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": "lightspeed_order_profiles",
      "title": "Set up Order Profiles & Tax",
      "route": "/lightspeed",
      "action": "order_profiles_guidance",
      "note": "Create the dedicated take-away / delivery order profiles in the Lightspeed Back Office (name/code are your choice — e.g. upvtakeout / upvdelivery; what matters is Takeaway mode = Pick up / Delivery and Order completion = Complete manually in POS), map them on the Locations tab via the mapping's Order profiles dialog, and attach the tax rules. US & Canada: tax is calculated automatically from the store address, so the new profiles bill correctly with no per-profile setup — a live account already has this configured with Lightspeed. Only Lightspeed can change tax rates. (The tax method — exclusive vs inclusive — imports automatically; there is no dine-in vs take-away rate split.) EU: send Lightspeed support a one-time request to attach the reduced-rate VAT rule (template in the 'Order profiles & VAT setup' section). The built-in dine-in / take-away profiles already bill the correct tax, so custom profiles are mainly needed to keep prepaid orders on the Orders screen. Auto-completes once the profiles are mapped in Upvendo.",
      "optional_for_go_live": true
    },
    {
      "id": "payment_profile",
      "title": "Set up Payment Profile",
      "route": "/settings/payments",
      "optional_for_go_live": true
    },
    {
      "id": "billing_profile",
      "title": "Set up Billing Profile",
      "route": "/settings/billing",
      "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
    }
  ],
  "Both": [
    {
      "id": "branding_profile",
      "title": "Set up Store Branding",
      "route": "/settings/brand"
    },
    {
      "id": "create_location",
      "title": "Create Location",
      "route": "/settings/locations",
      "note": "Create your location manually. Lightspeed does not auto-import locations."
    },
    {
      "id": "connect_pos",
      "title": "Connect Lightspeed K-Series",
      "route": "/lightspeed",
      "note": "Click 'Connect with Lightspeed' on the Settings tab. You will be redirected to log in to your Lightspeed account and authorize Upvendo. After authorization you are returned to the Locations tab, where you map each Upvendo location to a Lightspeed business location."
    },
    {
      "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": "lightspeed_order_profiles",
      "title": "Set up Order Profiles & Tax",
      "route": "/lightspeed",
      "action": "order_profiles_guidance",
      "note": "Create the dedicated take-away / delivery order profiles in the Lightspeed Back Office (name/code are your choice — e.g. upvtakeout / upvdelivery; what matters is Takeaway mode = Pick up / Delivery and Order completion = Complete manually in POS), map them on the Locations tab via the mapping's Order profiles dialog, and attach the tax rules. US & Canada: tax is calculated automatically from the store address, so the new profiles bill correctly with no per-profile setup — a live account already has this configured with Lightspeed. Only Lightspeed can change tax rates. (The tax method — exclusive vs inclusive — imports automatically; there is no dine-in vs take-away rate split.) EU: send Lightspeed support a one-time request to attach the reduced-rate VAT rule (template in the 'Order profiles & VAT setup' section). The built-in dine-in / take-away profiles already bill the correct tax, so custom profiles are mainly needed to keep prepaid orders on the Orders screen. Auto-completes once the profiles are mapped in Upvendo.",
      "optional_for_go_live": true
    },
    {
      "id": "payment_profile",
      "title": "Set up Payment Profile",
      "route": "/settings/payments",
      "optional_for_go_live": true
    },
    {
      "id": "billing_profile",
      "title": "Set up Billing Profile",
      "route": "/settings/billing",
      "optional_for_go_live": true
    },
    {
      "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
    }
  ]
}

Step IDs and completion detection: Each step's completion is auto-detected by the backoffice from the GET /api/back-office/setup-status endpoint. The step ids above map to status flags in setupStepMappings.ts — for example connect_pos is marked complete only when both pos_connected and has_integration_test are true, which for Lightspeed K-Series both become true the moment you finish the OAuth connect: the callback fetches your business from /o/op/data/businesses, and that successful authenticated call is itself recorded as the integration test, so there is no "Test Connection" button to click for this step (the same applies to a re-auth). If the businesses fetch fails, no test is recorded and the step stays open. (Verified: upvendo-backend/app/Services/BackOffice/LightspeedKSeriesIntegrationService.php lines 336-354 and 414-421; upvendo-backoffice/src/utils/emily/setupStepMappings.ts line 53.) create_location maps to has_location; menu_for_kiosk/menu_for_online_ordering to has_menu_for_kiosk/has_menu_for_online_ordering; in_house_settings, device_profile, kiosk_device, online_settings, configure_online_ordering, test_kiosk, and test_online_ordering to their respective flags. There is no separate "Select Location from Topbar" or "Sync Menu" step in the Lightspeed flow (the frontend fallback BASE_SETUP_STEPS.lightspeed omits both, and the menu is imported per mapping rather than synced via a dedicated step).


Conditional Logic

If lightspeed_account = "No, I need to set one up"

The discovery flow aborts with the abort_message:

"You'll need an active Lightspeed Restaurant K-Series account before connecting. Please contact Lightspeed at lightspeedhq.com to get an account set up, then come back here to continue." Onboarding pauses here until the merchant confirms they have an account.

If menu_ready = "No, I need to create it"

The discovery flow aborts with the abort_message:

"Lightspeed requires your menu to be set up in the POS first. Please create your menu items in Lightspeed K-Series, then come back to continue the setup."

Lightspeed-side menu creation and obtaining a Lightspeed account are out of scope for Upvendo and are not verified here — they happen in the Lightspeed back office.


Connecting (OAuth)

Route: /lightspeedSettings tab

  1. Create your Upvendo location(s) first at /settings/locations — Lightspeed does not auto-import locations.
  2. On the Settings tab, click Connect with Lightspeed.
  3. You are redirected to the Lightspeed (Keycloak) login. Log in with a Lightspeed Restaurant K-Series account that has sufficient permissions, and authorize Upvendo.
  4. Lightspeed redirects back to the callback (/api/oauth/lightspeed/callback, also aliased at /api/lightspeed/callback). Upvendo verifies the HMAC-signed state, exchanges the code for tokens, fetches your business from /o/op/data/businesses, and stores the access token, refresh token, and business ID/name. That successful business fetch also counts as your connection test, so the Connect Lightspeed K-Series onboarding step ticks itself — you do not need to click Test Connection. (Verified: upvendo-backend/app/Services/BackOffice/LightspeedKSeriesIntegrationService.php lines 336-354 and 414-421.)
  5. You land on the Locations tab (/lightspeed?tab=locations).
  6. Map each Upvendo location to one Lightspeed business location. Creating a mapping links the webhook for that business location and starts the initial menu sync.

Order profiles & VAT setup

Why this matters: the K-Series order profile on each pushed order controls which POS tab the order appears in (Dine-in vs Pickup/Delivery) and, together with the payment state, whether the order stays visible on the POS Orders screen for the kitchen (or completes straight to Receipts); the VAT rule attached to the profile controls which VAT rate is billed. Important: with Upvendo's standard full-payment push, a fully-paid order closes straight to Receipts in K-Series regardless of the profile's completion setting — keeping prepaid take-away/delivery orders on the Orders/production queue requires enabling the merchant-level, default-OFF "create unpaid + settle later" option (see below). Even without that, the order still reaches the kitchen as a production ticket and bills the correct VAT. This is a one-time setup of roughly 15 minutes (plus a short wait on Lightspeed for the tax step in the EU).

Step 1 — Create the order profiles in Lightspeed (± 5 min)

In the Lightspeed Back OfficeOrder profilesAdd order profile, create profiles like the ones below. The name and code are your choice — the upv… codes are just an example convention, not required Upvendo values. What Upvendo actually needs is a take-away profile with Takeaway mode = Pick up and a delivery profile with Takeaway mode = Delivery, both set to Order completion = Complete manually in POS, and with a reduced-rate VAT rule attached (Step 3). The built-in dine-in / take-away profiles already bill the correct VAT, so a custom dine-in profile is optional — its main value is keeping prepaid take-away/delivery orders on the Orders screen.

Name (example)Code (example)Takeaway modeOrder completion
Upvendo Dine-inupvdineinOffComplete manually in POS
Upvendo TakeoutupvtakeoutPick upComplete manually in POS
Upvendo DeliveryupvdeliveryDeliveryComplete manually in POS

Two settings are load-bearing — double-check them:

  • Takeaway mode decides which POS tab the order lands in (Pick up / Delivery → the Pickup/Delivery tab; Off → Dine-in).
  • Order completion = "Complete manually in POS" is what allows a take-away/delivery order to stay open on the Orders screen until staff complete it — but this only takes effect when the order reaches K-Series unpaid. With Upvendo's standard full-payment push, a fully-paid order closes straight to Receipts in K-Series regardless of this setting. To actually keep prepaid take-away/delivery orders on the Orders screen you must enable the merchant-level, default-OFF "create unpaid + settle later" option (Upvendo pushes the order unpaid and settles the payment afterwards). (Known K-Series behaviour: fully-paid dine-in orders complete to Receipts regardless — the kitchen still receives the production ticket when the order is created.)

Step 2 — Map the profiles in Upvendo (± 2 min)

In the Upvendo back office: LightspeedLocations tab → your location's ⋯ menuOrder profiles → select Dine-in = Upvendo Dine-in, Takeout = Upvendo Takeout, Delivery = Upvendo DeliverySave. From that moment every pushed order carries the matching profile. (Any order type left empty falls back to the K-Series built-in profile.)

Step 3 — Have the VAT rules attached to the new profiles

New custom profiles bill the standard rate until tax rules are attached to them. Who does that depends on your region:

  • EU (Belgium, Netherlands, Germany, France, …): tax rules cannot be edited by merchants in the K-Series Back Office — Lightspeed configures them. Send Lightspeed support a short request (template below). It is a one-time change per location.
  • US & Canada (tax-exclusive): tax is computed automatically from the store address (destination-based), so the new Upvendo order profiles inherit the correct rate with no per-profile assignment — and for a live account this is already configured with Lightspeed. Only Lightspeed staff can change tax rates. The tax method is imported automatically (taxIncluded = false → tax-exclusive), and there is no dine-in vs take-away rate split.

Copy-paste email to Lightspeed support (k-series.support@lightspeedhq.com, or your Lightspeed contact) — fill in the bracketed parts, and confirm the exact rates with your accountant first, since reduced take-away rates differ per country:

Subject: Tax rules for custom order profiles — [Business name] (Business ID [xxxxx])

Hi K-Series Support,

We use the Upvendo integration for online ordering / kiosk and have created dedicated order profiles for it in our Back Office. Could you please attach the correct tax rules to these profiles, the same way our built-in "Take away" profile is configured?

  • Business: [Business name] — Business ID [xxxxx]
  • Business Location ID: [xxxxxxxxxxxx]
  • upvtakeout (Pick up) and upvdelivery (Delivery): please apply our country's reduced take-away rates (same rules as the built-in Take away profile — e.g. food [x]%, non-alcoholic drinks [x]%).
  • upvdinein (eat-in): the standard on-site rates.

Thank you!

Belgium reference (verified in production use): take-away/delivery bill 6% on food and non-alcoholic drinks and 21% on alcohol; dine-in bills 12% food / 21% drinks / 21% alcohol. Other countries follow the same mechanism with their own rates — always confirm the target rates with your accountant before sending the email.

Step 4 — Verify before going live (± 5 min)

  1. Place one small take-away test order through your ordering channel.
  2. Check the receipt (POS, or Lightspeed Back Office reports): the food line must show the reduced rate. If it shows the standard rate, the tax rules from Step 3 are not attached yet — wait for Lightspeed's confirmation and re-test.
  3. If you have enabled the "create unpaid + settle later" option, check the order appeared on the POS Orders screen (Pickup tab) rather than going straight to Receipts. With the standard full-payment push (the default), a fully-paid order closes to Receipts — that is expected; the kitchen still receives the production ticket.

Skipping Steps 3–4 does not block ordering — orders still flow and totals are correct — but take-away/delivery would be billed at the standard rate instead of the reduced one until the rules are attached.


Reconnecting / Token Expiry

Access tokens are refreshed automatically (proactively within a 5-minute buffer, plus a one-shot reactive refresh on a 401). If the refresh token is revoked or expires, the integration is flagged needs_reauth and a Reconnect banner appears.

To reconnect:

  1. Go to Lightspeed (/lightspeed) → Settings tab (a warning banner also appears when needs_reauth).
  2. Click Reconnect — this re-runs the full OAuth flow.
  3. Existing location mappings are preserved and the webhook is healed/re-linked automatically. A successful re-auth clears the needs_reauth status.

Troubleshooting

"I was redirected back but it shows an error"

  • The authorization may have been denied — try connecting again and confirm the authorization screen.
  • Ensure you are logged in to the correct Lightspeed account (a Restaurant K-Series account). L-Series and R-Series are not compatible.

"Connection test fails after connecting"

  • Go to the Status tab and click Test Connection (it calls /o/op/data/businesses).
  • If you see a needs_reauth banner, click Reconnect on the Settings tab to re-authorize.
  • Check the Lightspeed account is active and not suspended.

"Where do I find my business location ID?"

  • After a successful connection, the business ID is shown on the Status tab.
  • Your Lightspeed business locations are listed in the Locations tab, where you map each one to an Upvendo location.

"My location shows a 'Degraded' badge after syncing"

  • The menu did sync — the item count in the message is real. What did not happen is the modifier refresh: Lightspeed returned incomplete modifier / production-instruction data, so Upvendo left those groups alone rather than refreshing or deleting them. Nothing was lost. (Verified: upvendo-backend/app/Services/BackOffice/LightspeedKSeriesIntegrationService.php lines 4417-4433, 4452-4457, and 5778-5794.)
  • Click Sync now on that location's row in the Locations tab. The cause is usually transient and the next run clears the badge.
  • Full explanation, triggers, and escalation path: Lightspeed K-Series Integration → Troubleshooting.

"The Connect Lightspeed K-Series step won't tick"

  • This step does not need a Test Connection click — it completes automatically when the OAuth connect succeeds. If it stays open, the business fetch after authorization failed.
  • Reconnect from /lightspeedSettings tab, then check the Status tab and the integration logs for the error.