Appearance
Lightspeed K-Series Onboarding (Reseller)
Overview
Streamlined onboarding flow for resellers (the partner-facing UI calls this role "partner") setting up merchants with Lightspeed Restaurant K-Series POS. The Lightspeed connection is merchant-scoped — one OAuth authorization covers the whole Lightspeed account — but data is wired up per location: each Upvendo location is mapped to one Lightspeed business location, and menu sync and orders run per mapping.
Key points for resellers:
- Payment Profile needed for customer payments — Lightspeed handles in-house POS payments, but Upvendo needs Stripe or Viva Wallet for kiosk/online customer payments. Note: this is not blocked at the connect step (nothing is enforced at OAuth connect except that Upvendo's own Lightspeed API credentials are configured); set it up before going live.
- Locations are NOT auto-imported — create Upvendo locations manually, then map each one to a Lightspeed business location on the Lightspeed Locations tab.
- OAuth connection — the merchant (or reseller acting on their behalf in client mode) logs in to the merchant's Lightspeed K-Series account to authorize. The integration uses OAuth 2.0 (Keycloak); there are no API keys for the merchant to manage, and it does not use PKCE (CSRF protection is an HMAC-signed
state). - Menu structure is pulled from Lightspeed; items push back — items, modifiers, categories, tax rates, and allergens are pulled from K-Series into Upvendo, which is the source of truth for structure. Upvendo pushes completed orders back and pushes item creates/edits to K-Series (
PushItemToLightspeedKSeriesJob). Categories cannot be created or deleted from Upvendo — they are K-Series accounting groups. Sync runs per location mapping. - Disconnect is disabled in production — to remove a live integration, contact an administrator. To stop data for one location, remove that location's mapping on the Locations tab.
Discovery Flow (JSON - for deterministic parsing)
discovery_questions
[
{
"id": "channels",
"text": "Which channels for this merchant?",
"text_i18n": {
"nl": "Welke kanalen voor deze handelaar?",
"fr": "Quels canaux pour ce marchand ?",
"de": "Welche Kanäle für diesen Händler?",
"es": "¿Qué canales para este comercio?",
"it": "Quali canali per questo commerciante?",
"pt": "Que canais para este comerciante?"
},
"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": "payment_provider",
"text": "Which payment provider for this merchant?",
"text_i18n": {
"nl": "Welke betaalprovider voor deze handelaar?",
"fr": "Quel prestataire de paiement pour ce marchand ?",
"de": "Welcher Zahlungsanbieter für diesen Händler?",
"es": "¿Qué proveedor de pago para este comercio?",
"it": "Quale fornitore di pagamenti per questo commerciante?",
"pt": "Que fornecedor de pagamento para este comerciante?"
},
"options": [
"Stripe",
"Viva Wallet"
],
"labels": {
"nl": {
"Stripe": "Stripe",
"Viva Wallet": "Viva Wallet"
},
"fr": {
"Stripe": "Stripe",
"Viva Wallet": "Viva Wallet"
},
"de": {
"Stripe": "Stripe",
"Viva Wallet": "Viva Wallet"
},
"es": {
"Stripe": "Stripe",
"Viva Wallet": "Viva Wallet"
},
"it": {
"Stripe": "Stripe",
"Viva Wallet": "Viva Wallet"
},
"pt": {
"Stripe": "Stripe",
"Viva Wallet": "Viva Wallet"
}
}
},
{
"id": "menu_ready",
"text": "Does the merchant have their menu set up in Lightspeed K-Series?",
"text_i18n": {
"nl": "Heeft de handelaar het menu ingesteld in Lightspeed K-Series?",
"fr": "Le marchand a-t-il configuré son menu dans Lightspeed K-Series ?",
"de": "Hat der Händler sein Menü in Lightspeed K-Series eingerichtet?",
"es": "¿El comercio tiene su menú configurado en Lightspeed K-Series?",
"it": "Il commerciante ha configurato il proprio menu in Lightspeed K-Series?",
"pt": "O comerciante tem o menu configurado no Lightspeed K-Series?"
},
"options": [
"Yes, menu is in Lightspeed",
"No, not yet"
],
"labels": {
"nl": {
"Yes, menu is in Lightspeed": "Ja, menu staat in Lightspeed",
"No, not yet": "Nee, nog niet"
},
"fr": {
"Yes, menu is in Lightspeed": "Oui, le menu est dans Lightspeed",
"No, not yet": "Non, pas encore"
},
"de": {
"Yes, menu is in Lightspeed": "Ja, das Menü ist in Lightspeed",
"No, not yet": "Nein, noch nicht"
},
"es": {
"Yes, menu is in Lightspeed": "Sí, el menú está en Lightspeed",
"No, not yet": "No, todavía no"
},
"it": {
"Yes, menu is in Lightspeed": "Sì, il menu è in Lightspeed",
"No, not yet": "No, non ancora"
},
"pt": {
"Yes, menu is in Lightspeed": "Sim, o menu está no Lightspeed",
"No, not yet": "Não, ainda não"
}
},
"abort_if": "No, not yet",
"abort_message": "The merchant needs their menu structure set up in Lightspeed K-Series first - categories are K-Series accounting groups and cannot be created in Upvendo. Items can be created in Upvendo and are pushed to Lightspeed, but they need somewhere to live. Please have them set up their menu in Lightspeed, then restart the onboarding.",
"abort_message_i18n": {
"nl": "De handelaar moet het menu eerst in Lightspeed K-Series instellen. Lightspeed ondersteunt alleen het ophalen van menu-items uit de kassa — items kunnen niet in Upvendo worden aangemaakt. Laat hen hun menu in Lightspeed aanmaken en start daarna de onboarding opnieuw.",
"fr": "Le marchand doit d'abord configurer son menu dans Lightspeed K-Series. Lightspeed ne prend en charge que la récupération des articles depuis la caisse — les articles ne peuvent pas être créés dans Upvendo. Demandez-lui de créer son menu dans Lightspeed, puis recommencez l'intégration.",
"de": "Der Händler muss sein Menü zuerst in Lightspeed K-Series einrichten. Lightspeed unterstützt nur das Abrufen von Artikeln aus dem Kassensystem — Artikel können nicht in Upvendo erstellt werden. Lassen Sie ihn sein Menü in Lightspeed anlegen und starten Sie dann das Onboarding neu.",
"es": "El comercio debe configurar primero su menú en Lightspeed K-Series. Lightspeed solo admite obtener artículos desde el TPV — los artículos no se pueden crear en Upvendo. Pídele que cree su menú en Lightspeed y luego reinicia el onboarding.",
"it": "Il commerciante deve prima configurare il proprio menu in Lightspeed K-Series. Lightspeed supporta solo il recupero degli articoli dal POS — gli articoli non possono essere creati in Upvendo. Chiedigli di creare il menu in Lightspeed e poi riavvia l'onboarding.",
"pt": "O comerciante precisa de configurar primeiro o menu no Lightspeed K-Series. O Lightspeed só permite obter artigos a partir do POS — os artigos não podem ser criados no Upvendo. Peça-lhe para criar o menu no Lightspeed e depois reinicie o onboarding."
}
}
]setup_steps
{
"Kiosk only": [
{"id": "branding_profile", "title": "Set up Store Branding", "route": "/settings/brand"},
{"id": "payment_profile", "title": "Set up Payment Profile", "route": "/settings/payments", "note": "Stripe or Viva Wallet required for kiosk customer payments. Lightspeed handles POS payments but not customer-facing payments. Not enforced at connect — set up before going live."},
{"id": "create_location", "title": "Create Location", "route": "/settings/locations", "note": "Create the merchant's location(s) manually — Lightspeed does not auto-import locations into Upvendo."},
{"id": "connect_pos", "title": "Connect Lightspeed K-Series", "route": "/lightspeed", "note": "Settings tab → click 'Connect with Lightspeed'. Log in with the merchant's Lightspeed K-Series account and authorize Upvendo. Redirects back to the Locations tab on success."},
{"id": "map_locations", "title": "Map Locations to K-Series", "route": "/lightspeed", "note": "Locations tab → map each Upvendo location to one Lightspeed business location. Creating a mapping links the webhook and starts the initial menu sync for that location."},
{"id": "sync_menu", "title": "Sync Menu", "route": "/lightspeed", "note": "Locations tab → 'Sync now' (per mapping) or 'Sync all'. Pulls items, modifiers, categories, tax rates, and allergens from K-Series. Initial sync also runs automatically when a mapping is created."},
{"id": "in_house_settings", "title": "Set up In-House Settings", "route": "/in-house/settings"},
{"id": "device_profile", "title": "Set up Device Profile", "route": "/device-management/profiles"},
{"id": "kiosk_device", "title": "Configure Kiosk Device", "route": "/device-management/devices"},
{"id": "billing_profile", "title": "Set up Billing Profile", "route": "/settings/billing", "optional_for_go_live": true, "note": "Optional if the reseller invoices the merchant directly (reseller_collects billing model)."},
{"id": "test_connection", "title": "Test Connection & Go Live", "route": "/lightspeed", "note": "Status tab → Test Connection verifies API access (calls /o/op/data/businesses)."}
],
"Online ordering only": [
{"id": "branding_profile", "title": "Set up Store Branding", "route": "/settings/brand"},
{"id": "payment_profile", "title": "Set up Payment Profile", "route": "/settings/payments", "note": "Stripe or Viva Wallet required for online customer payments. Not enforced at connect — set up before going live."},
{"id": "create_location", "title": "Create Location", "route": "/settings/locations", "note": "Create the merchant's location(s) manually — Lightspeed does not auto-import locations into Upvendo."},
{"id": "connect_pos", "title": "Connect Lightspeed K-Series", "route": "/lightspeed", "note": "Settings tab → click 'Connect with Lightspeed'. Log in with the merchant's Lightspeed K-Series account and authorize Upvendo. Redirects back to the Locations tab on success."},
{"id": "map_locations", "title": "Map Locations to K-Series", "route": "/lightspeed", "note": "Locations tab → map each Upvendo location to one Lightspeed business location. Creating a mapping links the webhook and starts the initial menu sync for that location."},
{"id": "sync_menu", "title": "Sync Menu", "route": "/lightspeed", "note": "Locations tab → 'Sync now' (per mapping) or 'Sync all'. Pulls items, modifiers, categories, tax rates, and allergens from K-Series."},
{"id": "online_settings", "title": "Set up Online Settings", "route": "/online-settings"},
{"id": "configure_online_ordering", "title": "Configure Online Ordering", "route": "/online/online-ordering"},
{"id": "billing_profile", "title": "Set up Billing Profile", "route": "/settings/billing", "optional_for_go_live": true, "note": "Optional if the reseller invoices the merchant directly (reseller_collects billing model)."},
{"id": "test_connection", "title": "Test Connection & Go Live", "route": "/lightspeed", "note": "Status tab → Test Connection verifies API access (calls /o/op/data/businesses)."}
],
"Both": [
{"id": "branding_profile", "title": "Set up Store Branding", "route": "/settings/brand"},
{"id": "payment_profile", "title": "Set up Payment Profile", "route": "/settings/payments", "note": "Stripe or Viva Wallet required for both kiosk and online customer payments. Not enforced at connect — set up before going live."},
{"id": "create_location", "title": "Create Location", "route": "/settings/locations", "note": "Create the merchant's location(s) manually — Lightspeed does not auto-import locations into Upvendo."},
{"id": "connect_pos", "title": "Connect Lightspeed K-Series", "route": "/lightspeed", "note": "Settings tab → click 'Connect with Lightspeed'. Log in with the merchant's Lightspeed K-Series account and authorize Upvendo. Redirects back to the Locations tab on success."},
{"id": "map_locations", "title": "Map Locations to K-Series", "route": "/lightspeed", "note": "Locations tab → map each Upvendo location to one Lightspeed business location. Creating a mapping links the webhook and starts the initial menu sync for that location."},
{"id": "sync_menu", "title": "Sync Menu", "route": "/lightspeed", "note": "Locations tab → 'Sync now' (per mapping) or 'Sync all'. Pulls items, modifiers, categories, tax rates, and allergens from K-Series."},
{"id": "in_house_settings", "title": "Set up In-House Settings", "route": "/in-house/settings"},
{"id": "device_profile", "title": "Set up Device Profile", "route": "/device-management/profiles"},
{"id": "kiosk_device", "title": "Configure Kiosk Device", "route": "/device-management/devices"},
{"id": "online_settings", "title": "Set up Online Settings", "route": "/online-settings"},
{"id": "configure_online_ordering", "title": "Configure Online Ordering", "route": "/online/online-ordering"},
{"id": "billing_profile", "title": "Set up Billing Profile", "route": "/settings/billing", "optional_for_go_live": true, "note": "Optional if the reseller invoices the merchant directly (reseller_collects billing model)."},
{"id": "test_connection", "title": "Test Connection & Go Live", "route": "/lightspeed", "note": "Status tab → Test Connection verifies API access (calls /o/op/data/businesses)."}
]
}Notes for Resellers
- Reseller surface: A reseller (UI label "partner") creates and manages merchants through the partner surface — a reseller account carries multiple
vendor_ids, and merchants created this way are stampedonboarding_type = 'reseller'. When managing a merchant, the reseller acts in "client mode" (a merchant-context switch in the backoffice). Note: the exact partner-portal navigation/screens are not verified in these two repos beyond the merchant-creation and client-mode mechanics. - Billing: When the reseller invoices the merchant directly (
reseller_collectsbilling model), the merchant's own billing profile is optional and no free-trial badge is shown. - Connect order: Create Upvendo location(s) → connect Lightspeed via OAuth (Settings tab) → map each Upvendo location to a K-Series business location (Locations tab). Mapping is what kicks off the webhook link and initial menu sync.
- Lightspeed page tabs: Status (default — connection status, Test Connection, integration logs), Locations (per-location mappings, "Sync now" / "Sync all"), Settings ("Connect with Lightspeed" / "Reconnect").
- Menu structure is pull-only (Lightspeed → Upvendo) for categories, which are K-Series accounting groups and cannot be created or deleted from Upvendo. Items are pushable both ways — an item created or edited in Upvendo is pushed to K-Series. The merchant still needs their menu structure in Lightspeed before onboarding.
- Disconnect is disabled in production and staging — the disable endpoint returns "Disconnecting Lightspeed K-Series integration is disabled. Please contact administrator." To remove a live integration, contact an administrator; to stop one location, remove its mapping on the Locations tab.
- Lightspeed product: Only Lightspeed Restaurant K-Series is supported (not L-Series or R-Series).
- Reseller-portal screens, Lightspeed-side account setup, and any process steps performed outside Upvendo are not verified here.