Skip to content

Shopcaisse Integration Setup

Looking for guided setup? Start Emily in the backoffice for step-by-step guided setup.

Purpose

The Shopcaisse integration (Shopcaisse is also marketed as EasyShop) connects Upvendo to the Shopcaisse POS. It is an in-house, read-only inbound integration: Upvendo pulls the existing product catalog out of Shopcaisse, and after a customer pays in an Upvendo channel (Kiosk, Online Ordering, QR Ordering), Upvendo pushes the order back into Shopcaisse. Shopcaisse remains the source of truth for the catalog and the in-store POS.

Production status: The provider is marked test_only in Upvendo's POS provider config (config/pos-providers.php) — it is enabled for testing/onboarding, not a fully GA self-serve connector. Consult the Upvendo team before using it in production.


Key Concepts

In-house, location-specific channel

ShopCaisse is one of Upvendo's in-house, location-scoped channels (alongside Hendrickx and Vanhoutte). A merchant can have only one in-house channel active at a time — attempting to add ShopCaisse when another in-house channel (Hendrickx, Vanhoutte, Square, MplusKassa, Lightspeed) already exists for the merchant/location is rejected with "Another in-house channel is already enabled for this merchant".

Authentication: a single JWT bearer token

Authentication is a single JWT bearer token ("AppToken") generated from a Shopcaisse External Application, created under Shopcaisse's Public API feature — see Prerequisites Checklist → Obtain the Shopcaisse Bearer Token for the exact path. Upvendo validates it by calling GET /v1/authentication and reading the bundle.permissions it returns. The token must grant at minimum:

  • store.*.orders.write — to push orders to Shopcaisse
  • company.*.items.read — to read the product catalog

If either is missing, the connect/validate call fails with "Missing required permissions: store.*.orders.write and company.*.items.read". The optional company.*.items.write permission additionally enables pushing simple items back to Shopcaisse (see Business Rules).

The token also encodes a resources list of the form company.{id}, store.{id}, pos.{id}. Upvendo parses these to discover the company, store(s) and POS the token can act on.

API environment is decided by the token

Shopcaisse has two API hosts:

  • Production: https://api.shop-caisse.com
  • Staging: https://api-staging.shop-caisse.com

Which host is used is resolved from the JWT's namespace claim (prod → production host, staging → staging host); the token only authenticates against its own environment. The stored is_sandbox flag is just a fallback when the namespace can't be decoded.

Connection model: merchant-level "paste once" (current UI)

The current backoffice connect flow is merchant-level: the merchant pastes one JWT and Upvendo creates one Upvendo Location per Shopcaisse store the token covers. This is stored as a single merchant-level integration record (with an empty location_id) carrying a store_location_map that maps each Shopcaisse store → its Upvendo Location. A merchant-level catalog sync then runs automatically for every mapped location.

A legacy per-Location model also exists in the code (one record per location, with a single selected store). When both exist, the per-Location record takes precedence; otherwise the merchant-level record governs the location. Documents and order routing resolve through this two-step precedence.

One-way catalog sync (Shopcaisse → Upvendo)

The catalog must exist in Shopcaisse first. The sync (ShopCaisseService) pulls, for each mapped location's company/store:

  • Items from GET /v1/companies/{companyId}/items — Shopcaisse SIMPLE, MENU (combo) and PACK types become Upvendo items (product_type simple/combo/pack); MODIFIER-type products are held back to build modifiers.
  • Menus / combo composition from GET /v1/companies/{companyId}/menus — supplies MENU/PACK step composition and drives a ComboDefinition.
  • Modifier groups from GET /v1/companies/{companyId}/modifiergroups — become Upvendo modifier groups + modifiers.
  • Product family (inline family on each item) → a location-scoped Upvendo category.
  • VAT (vatOnSite / vatTakeAway) → an Upvendo TaxRateCustom (country defaults to BE).
  • Item images (primary/COVER image) → uploaded to Cloudflare Images.
  • Seating plan from GET /v1/stores/{storeId}/seating-plan → a "ShopCaisse Tables" section (+ QR codes).
  • Stock from GET /v1/stores/{storeId}/stocks → Upvendo inventory (only for items Shopcaisse flags manageStock=true). Shopcaisse has no stock webhook, so stock is pulled during each catalog sync.
  • Menu availabilityGET /v1/companies/{companyId}/menus is also used to activate items in the menu and deactivate items not in it (operator-set Unavailable/Hidden statuses are never overwritten).
  • Customers (CRM) from GET /v1/stores/{storeId}/customers → matched onto Upvendo's global Customer plus the merchant-scoped CustomerMerchant (see Customer sync below).

The sync runs as a queued job (SyncShopCaisseCatalogJob, one per location, unique-locked, 3 retries) and the UI polls for completion.

Customer (CRM) sync (Shopcaisse → Upvendo)

Every catalog sync also pulls Shopcaisse's CRM customers for the mapped store and merges them into Upvendo's customer records (ShopCaisseService::syncCustomersShopCaisseCustomerSyncService):

  • Source: GET /v1/stores/{storeId}/customers (paginated). A customer record is skipped if Shopcaisse marks it deleted: true / active: false, or if it has no stable identity — Upvendo requires the Shopcaisse id and at least one of email or phone; an id with neither is dropped.
  • Matching order: an incoming customer is matched to an existing Upvendo CustomerMerchant (for that merchant) by, in order: (1) a previously-recorded Shopcaisse customer_id in external_data.shopcaisse.customer_ids, (2) email, (3) phone (only tried if the record has no email at all). If nothing matches, a new global Customer and merchant CustomerMerchant are created.
  • Write behavior: the merchant-scoped CustomerMerchant fields (first/last name, email, phone, date of birth, company) are overwritten from Shopcaisse whenever Shopcaisse supplies a non-empty value; empty upstream fields never blank existing Upvendo data. The global Customer record is filled only for blank fields (additive-only — Shopcaisse never overwrites existing global account data, since that record can be shared across merchants).
  • Provenance: each sync writes external_data.shopcaisse on the CustomerMerchant: customer_ids (all Shopcaisse ids ever matched to this person), stores (per-store customer_id, customer_group_id, last_synced_at, source snapshot), and a top-level last_synced_at.
  • Scope/frequency: this is pull-only — Upvendo never pushes customer changes to Shopcaisse — and runs automatically on every catalog sync (Connect, Sync Now, and the company.items webhook re-sync), not as a separate action. Per-record failures are logged and skipped without failing the rest of the sync; a summary (created/updated/skipped/failed) is written to the sync Logs.

Order forwarding (Upvendo → Shopcaisse)

After payment is confirmed, ProcessOrderJob calls ShopCaisseService::createOrder, which POSTs to /v1/stores/{storeId}/orders. There is a local idempotency guard: once a Shopcaisse order id is stored on the transaction, a retry/requeue will not re-POST (Shopcaisse does not dedup on the payload's orderId).

Webhooks (Shopcaisse → Upvendo)

Upvendo exposes POST /api/webhook/shopcaisse. Each request is verified by HMAC-SHA256 over the raw body, keyed by the integration's applicationId, in the x-server-authorization-hmac-sha256 header. The webhook URL is registered on the Shopcaisse External Application. Handled events:

  • company.items — triggers a catalog re-sync for the affected location(s).
  • store.orders — order lifecycle updates; the status is mirrored onto the matched Upvendo transaction.
  • store.sales — sale finalization; appended to the transaction's history.

Other events are logged and ignored.

Data Mapping

ShopcaisseUpvendoNotes
StoreLocationOne Upvendo Location per Shopcaisse store (via store_location_map)
Company(catalog scope)Items/modifiers/menus are read per company
Product familyCategoryLocation-scoped; created from the item's inline family
Item (SIMPLE)Item (simple)Name, price, PLU/reference, VAT
Item (MENU)Item (combo) + ComboDefinitionSteps/choices from /menus
Item (PACK)Item (pack) + ComboDefinition
Item (MODIFIER)ModifierHeld back, then attached to modifier groups
Modifier groupModifier groupDefault visibility: Kiosk, Online Ordering, QR Ordering
VAT code(s)TaxRateCustomvatOnSite/vatTakeAway; combined as {onSite}_{takeAway} when they differ
Item imageCloudflare image + ContentPrimary/COVER image only
Seating plan"ShopCaisse Tables" section
StockInventoryOnly manageStock=true items
Customer (CRM)Customer + CustomerMerchantMatched by Shopcaisse customer_id, then email, then phone; pull-only, additive to the global Customer record

Which price gets imported: the store's price list

A ShopCaisse item is company-scoped, and its prices live in priceCollections — one entry per price list. A company can hold several lists, and different stores of the same company can each own their own. So "the item's price" is not a single number: it depends on which list you read.

Upvendo resolves the store's governing (default) price list once per sync run and reads the price from that collection. The order of priceCollections on an item is arbitrary, so the list id has to be explicit — reading "the first collection" would give different prices on different syncs.

  • How the default is chosen. GET /v1/companies/{id}/prices returns {id, ownerStoreId, name} and carries no isDefault flag (verified live 2026-08-06). So the default is the first list whose ownerStoreId matches this store. That is the best signal ShopCaisse offers.
  • Pull and push target the same list. An Upvendo price edit is pushed back to the store's default list, the same one the import reads — the two paths share one resolver so they cannot drift apart.
  • A price-list fetch failure never fails a catalog sync. It degrades to "no default", callers fall through their existing fallback chains, and the failure is logged.
  • Other stores' lists are ignored. When an item carries two or more price collections within this store's lists and they disagree, Upvendo logs the divergence. Lists belonging to other stores of the same company are skipped — otherwise every multi-store company would log a misleading "multiple POS price lists" entry on every sync.

If a merchant reports the wrong price on a synced item, this is the usual cause: the item is priced differently on a second list, and Upvendo took the store's default. Fixing it means changing the price on the store's own list in ShopCaisse.

Catalog ownership and field locking

Because the catalog is owned by Shopcaisse, Upvendo blocks certain catalog actions for ShopCaisse-connected locations (driven by catalog_capabilities in config/pos-providers.php):

  • Blocked creates/deletes: modifier groups, modifiers, categories (create + delete).
  • Allowed: simple item create (pushed to Shopcaisse when VAT resolves and the token has company.*.items.write).

Synced items also have certain fields locked from editing in Upvendo (Item::getUneditableFields for the ShopCaisse label): name, kitchen_name, modifier_group_ids, plu, tax_rate_code. Price is editable — editing an item's price (or description) in Upvendo pushes the change back to Shopcaisse (bi-directional, simple-item only).


Actions

Connect Shopcaisse (paste-once)

Route: /shopcaisse (Settings tab)

  1. Complete the prerequisites (see checklist below).
  2. Open the ShopCaisse connect dialog and paste your Shopcaisse bearer token (the JWT from your Shopcaisse External Application).
  3. Submit. Upvendo authenticates the token, fetches every store it covers, and creates one Upvendo Location per store, recording the store → location map. It then dispatches a catalog sync for each mapped location.
  4. You're taken to the Locations tab, which lists the mapped stores/locations and any warnings (e.g. business hours not configured in Shopcaisse).

The connect form asks only for the token — there is no manual store-picker step in the current UI; locations are created automatically from the token's stores.

Sync Now

Route: /shopcaisse (Status tab)

Click Sync Now to re-run the catalog sync for every mapped location. The status flips to in progress and the page polls until each location's sync finishes. The Status tab shows connection status, last-sync time, and a product count; the Logs section shows per-sync info/error entries.

Test Connection

Route: /shopcaisse (Status tab)

Test Connection authenticates the stored token and fetches stores, reporting "Connection test successful (N store(s) found)" or a failure. A 401/403 marks the token as expired.

Review Imported Menu Items

After a sync:

  1. Go to Menus → Items (/menus/items).
  2. Review the items pulled from Shopcaisse. Name, PLU, tax rate and modifier-group links are locked (managed in Shopcaisse); price and description are editable and push back to Shopcaisse.
  3. Items not present in Shopcaisse's catalog do not appear unless you create a simple item in Upvendo (which is pushed to Shopcaisse).

Disconnecting

Disconnecting the ShopCaisse integration is disabled in the backoffice — the delete endpoint returns "Disconnecting ShopCaisse integration is disabled. Please contact administrator." To disconnect, contact Upvendo support/an administrator.

Webhook registration

To receive change notifications, register Upvendo's webhook URL (https://<your-Upvendo-API-host>/api/webhook/shopcaisse) on your Shopcaisse External Application. Upvendo verifies each delivery's HMAC signature.


Business Rules

  • The catalog must exist in Shopcaisse first; it is pulled into Upvendo one-way. Creating modifier groups, modifiers or categories in Upvendo is blocked for ShopCaisse locations.
  • A simple item created in Upvendo can be pushed to Shopcaisse, but only if its VAT rate resolves to a Shopcaisse VAT code and the token grants company.*.items.write. Combos, packs, variants, modifier groups and images cannot be pushed.
  • Editing a synced item's price or description in Upvendo pushes the change back to Shopcaisse. Name, PLU, tax rate and modifier-group links are locked.
  • Orders are forwarded to Shopcaisse only after payment is confirmed, by ProcessOrderJob. A duplicate-POST guard prevents re-creating the same order on retry.
  • Order payment amounts and item prices are sent as decimal (major-unit) values with decimalDigits: 2 — Shopcaisse multiplies by 10^decimalDigits internally. (Sending cents caused a verified 100× overpayment, fixed.)
  • Order type is sent as Shopcaisse's documented enum: EAT_IN, PICKUP or DELIVERY. Scheduled pickup/delivery time is sent as a Unix timestamp in seconds (with deliveryIsAsap: false).
  • Only one in-house channel may be active per merchant/location.
  • The token's namespace claim decides the API environment (prod vs staging), not a manually chosen setting.
  • The JWT does not expire traditionally but can be revoked in Shopcaisse; a 401/403 marks it expired in Upvendo and a new token must be entered.
  • One Shopcaisse store maps to exactly one Upvendo Location. Re-pointing a location at a different store is rejected (would orphan synced data).
  • Stock is pulled during catalog sync (no stock webhook). Only items Shopcaisse flags manageStock=true get an Upvendo inventory record.
  • Newly imported items are seeded onto the default sales channels — Kiosk, Online Ordering and QR Ordering — the same default the Kassanet, MplusKassa, Lightspeed and Square imports use. This happens on create only: an existing item's channels are operator-owned and a later sync never touches them. Items imported before this behaviour shipped landed with no channels and were invisible everywhere until ticked by hand; a backfill command (items:backfill-platforms) repairs those, and it only touches rows whose channel list is empty, so a deliberately narrowed item is never overwritten.
  • Customers are pulled from Shopcaisse (CRM) on every catalog sync — Connect, Sync Now, and the company.items webhook re-sync. A Shopcaisse customer with no id, or with neither an email nor a phone number, is skipped and never imported. Matching prefers a previously-recorded Shopcaisse customer id, then email, then phone.
  • Customer sync is pull-only: Upvendo never pushes customer edits back to Shopcaisse, and the global Customer record is only filled in where blank (Shopcaisse never overwrites existing Upvendo customer data). Customer sync is best-effort, like stock sync: per-record failures are logged and skipped, and a failure fetching the customer list itself (e.g. a Shopcaisse API error) is caught and swallowed too — the catalog sync still completes and reports success. The only signal is a "Customer sync failed: …" error entry in the integration's Logs (see Troubleshooting).

Prerequisites Checklist

Before integrating with Shopcaisse, complete these steps.

1. Branding Profile Setup (Required)

  1. Go to Settings → Brand (/settings/brand).
  2. Configure your branding (logo, etc.). A default branding profile is required to connect (and to auto-create Locations from Shopcaisse stores).

Payment and billing profiles are optional at connect time — you can set them up later. (Only a branding profile is enforced by ThirdPartyIntegrationHelper::checkRequiredProfiles for ShopCaisse.)

  1. Go to Settings → Payments (/settings/payments).
  2. Set up payment providers so customers can pay before orders are pushed:
    • A terminal provider for Kiosk payments.
    • Stripe for Online Ordering payments.
  1. Go to Settings → Billing (/settings/billing).
  2. Complete your billing information.

4. Shopcaisse Account Setup (Required)

On the Shopcaisse side, before generating a token:

  • The Public API feature must be active on the Shopcaisse side (a paid add-on) so you can create an External Application and obtain a JWT bearer token.
  • An Order Management Module must be active on the POS device(s) that will receive orders, or Shopcaisse rejects order creation with an "…does not have an Order Management Module license…" error.
  • The Shopcaisse POS device must be set up, logged in and online so it can accept incoming orders.
  • The menu must be fully configured in Shopcaisse (items, modifiers, VAT codes) — Upvendo reads it from there.

Exact Shopcaisse-side subscription tiers, pricing, and the iPad "Discovery Mode" gate are configured in Shopcaisse and are not verified from Upvendo's code — confirm current requirements with Shopcaisse / the reseller.

5. Obtain the Shopcaisse Bearer Token (Required)

  1. Log in to your Shopcaisse backoffice (bo.shopcaisse.com).
  2. Go to Features (/app/modules) → IntegrationsConnectors & API, and make sure the Public API feature is Active. It is a paid add-on (shown as "from €19,99/month excl. tax"), so a merchant on a plan without it must subscribe first.
  3. Click Configure on the Public API card. This opens Your External Applications — the list of applications for the selected company/store.
  4. Open the application for Upvendo (or create one with +). Its fields are Application name, Application description, Application webhook, Application resources, Application permissions, and Application token.
  5. Set Application webhook to Upvendo's …/api/webhook/shopcaisse endpoint.
  6. Under Application resources, grant the Company and the Store(s) you want to connect.
  7. Under Application permissions, tick at minimum:
    • Company items (read)company.*.items.read, catalog read
    • Store orders (write)store.*.orders.write, order create
    • Optionally Company items (write)company.*.items.write, to push simple items created in Upvendo
  8. Click Copy API token and paste the JWT into the Upvendo connect dialog.

Provenance: steps 2–8 were walked in a live Shopcaisse backoffice on 2026-08-02 and the labels above are quoted from those screens. Note that the Configure panel is an embedded legacy view (bo.shopcaisse.com/v2/settings/apps in an iframe), not part of the v3 back office around it — so its wording is versioned separately from the rest of the UI and can drift independently. Re-check if a merchant reports the labels don't match.


Order Flow

Orders are created in Upvendo and pushed to Shopcaisse after payment is confirmed (ProcessOrderJob → ShopCaisseService::createOrder → POST /v1/stores/{storeId}/orders).

Kiosk Flow

text
Customer submits order on Kiosk
            |
Payment terminal prompts for payment
            |
Customer pays the prompted amount
            |
Upvendo confirms payment, then ProcessOrderJob runs
            |
Order pushed to Shopcaisse (POST /v1/stores/{storeId}/orders)

Online Ordering Flow

text
Customer submits order online
            |
Payment processed via Stripe
            |
Upvendo confirms payment, then ProcessOrderJob runs
            |
Order pushed to Shopcaisse (POST /v1/stores/{storeId}/orders)

Once pushed, Shopcaisse emits store.orders (lifecycle) and store.sales (finalization) webhooks; Upvendo records the status onto the matching transaction.

The specific in-Shopcaisse / on-iPad order lifecycle states and the storefront ordering UX are not verified from Upvendo's backend code here.


FAQs

Q: Where do I get the Shopcaisse integration token? Is it from the Shopcaisse dashboard? A: Yes — the token is generated on the Shopcaisse side, not in Upvendo. In your Shopcaisse backoffice (bo.shopcaisse.com), go to FeaturesIntegrationsConnectors & API and click Configure on the Public API card (a paid add-on — it must be Active). That opens Your External Applications. Open or create the application for Upvendo, set its Application webhook to Upvendo's …/api/webhook/shopcaisse endpoint, grant it your Company and Store(s) under Application resources, tick at least Company items (read) and Store orders (write) under Application permissions, then click Copy API token and paste the JWT into Upvendo's ShopCaisse connect dialog. Full steps are in Prerequisites Checklist → Obtain the Shopcaisse Bearer Token.

Q: How do I connect — do I pick a store? A: You paste the JWT token only. Upvendo reads every store the token covers and creates one Upvendo Location per store automatically (merchant-level connect), then syncs each one's catalog. There is no manual store-picker step in the current UI.

Q: Can I create menu items in Upvendo and push them to Shopcaisse? A: Only simple items. A plain item you create in Upvendo can be pushed back to Shopcaisse if it has a resolvable Shopcaisse VAT code and the token grants company.*.items.write. Combos, packs, variants, modifier groups, modifiers, categories and images cannot be created from Upvendo — build those in Shopcaisse and sync them in.

Q: Can I edit prices on synced items? A: Yes. Price (and description) are editable on ShopCaisse-synced items and are pushed back to Shopcaisse. Name, PLU, tax rate and modifier-group links are locked.

Q: How do I disconnect the integration? A: You can't self-serve — disconnecting is disabled in the backoffice and returns an error directing you to contact an administrator.

Q: What permissions does the bearer token need? A: At minimum company.*.items.read (read catalog) and store.*.orders.write (push orders). company.*.items.write is optional and enables pushing simple items.

Q: What happens if the bearer token is revoked or expires? A: Test/sync calls fail with 401/403; Upvendo flags the token as expired. Re-enter a valid token to recover.

Q: Which API environment is used? A: It's derived from the token itself (the JWT namespace claim) — prod uses api.shop-caisse.com, staging uses api-staging.shop-caisse.com. Use the token matching the environment you intend to connect to.

Q: Does the integration support stock/inventory? A: Yes, partially. Stock is pulled from Shopcaisse during each catalog sync (there's no stock webhook), and only items Shopcaisse marks manageStock=true get an Upvendo inventory record.

Q: Does ShopCaisse sync customer/CRM data? A: Yes. Every catalog sync (Connect, Sync Now, and the company.items webhook) also pulls Shopcaisse's CRM customers for the mapped store (GET /v1/stores/{storeId}/customers) and merges them into Upvendo's Customer/CustomerMerchant records. It's pull-only — Upvendo never pushes customer edits back to Shopcaisse — and matching prefers a previously-matched Shopcaisse customer id, then email, then phone. Customers with no email or phone in Shopcaisse are skipped.

Q: Will syncing Shopcaisse customers overwrite my existing Upvendo customer data? A: The merchant-scoped CustomerMerchant record (name, email, phone, DOB, company) is updated from Shopcaisse whenever Shopcaisse has a non-empty value for that field. The global Customer record (shared across merchants) is only filled in where currently blank — it's never overwritten by Shopcaisse.

Q: Can the same Shopcaisse store map to multiple Upvendo locations? A: No. Each store maps to exactly one Upvendo Location, and a location's store binding is permanent (re-pointing is rejected).

Q: Why don't my prices appear to be in cents on Shopcaisse? A: Upvendo sends money as decimal euros with decimalDigits: 2; Shopcaisse converts internally. (Sending cents previously caused a 100× mismatch, now fixed.)

Q: Is this integration production-ready? A: It is marked test_only in Upvendo's POS provider config. Consult the Upvendo team before using it in production.


Troubleshooting

Connect fails with "Missing required permissions"

  • The token must grant both store.*.orders.write and company.*.items.read. Regenerate the Shopcaisse application token with those permissions.

Orders or items not syncing

  • Verify the token is valid and not expired (run Test Connection).
  • Check the Logs on the Status tab for sync errors.
  • Confirm the token covers the company/store for the affected location.

"401 Unauthorized" / "403 Forbidden"

  • The token was likely revoked or lacks permissions. Upvendo marks it expired. Generate a new token in Shopcaisse and re-enter it.

Catalog sync returns 0 items

  • Verify the Shopcaisse company has items configured and the token has company.*.items.read.
  • Ensure you used a token for the correct environment (its namespace must match the host).
  • Review the Logs for the specific error.

Orders not appearing in Shopcaisse

  • Orders are pushed only after payment is confirmed — verify the transaction was paid.
  • The token needs store.*.orders.write.
  • The Shopcaisse POS device must have the Order Management Module active and be online.
  • Review the Logs for order push errors; a temporary API failure is retried (with the duplicate-POST guard preventing duplicates).

Prices differ between Shopcaisse and Upvendo

  • Prices are imported at sync time; re-run Sync Now to pull updated prices.
  • Note prices are editable in Upvendo and push back to Shopcaisse — an Upvendo edit becomes the new price on both sides.
  • Check which price list the item is priced on. Upvendo reads the price from the store's default list (the first list whose ownerStoreId is this store — ShopCaisse exposes no isDefault flag). If the item is priced differently on a second list, Upvendo shows the store-default one. Correct it on the store's own list in ShopCaisse, not on another list of the same company.

Imported items do not show up on the kiosk or storefront

  • Check the item's sales channels. Items imported before channel seeding shipped were created with an empty channel list, so they exist in Upvendo but are sellable nowhere. Newly imported items now default to Kiosk, Online Ordering and QR Ordering.
  • Re-running Sync Now does not fix this — an existing item's channels are operator-owned and sync deliberately leaves them alone. Either tick the channels on the item, or ask Upvendo support to run the items:backfill-platforms repair, which only fills in items whose channel list is still empty.

An order failed and the location shows the POS as disconnected

  • A ShopCaisse integration the merchant switched off is not a disconnected POS. An intentionally inactive integration no longer flags the location's POS as failed — the order carries a re-queue flag and a lifecycle breadcrumb to the scheduled retry instead. Re-activate the integration and the queued orders go through.
  • A missing integration on a ShopCaisse location is broken wiring, and that still surfaces as disconnected.

Items missing or wrongly active/inactive after sync

  • Menu availability is derived from Shopcaisse's /menus — items in the menu are activated, items not in it are deactivated (operator-set Unavailable/Hidden statuses are preserved).
  • Items skipped due to errors are recorded individually in the Logs.

Customers not appearing / not updating in Upvendo

  • Customer sync runs automatically on every catalog sync — it is not a separate manual action. Re-run Sync Now to re-pull customers.
  • A Shopcaisse customer with no email and no phone number is skipped and will not be imported (Upvendo requires at least one contact key to match identities safely).
  • A Shopcaisse customer marked deleted or inactive is also skipped.
  • Check the Logs on the Status tab for a "Customer sync: N created, N updated, N skipped, N failed" entry; per-record failures are logged individually and don't block the rest of the sync.
  • If the customer list itself can't be fetched from Shopcaisse (e.g. API error), the catalog sync still succeeds — customer sync is best-effort and the whole step is swallowed. Look for a "Customer sync failed: …" error entry in the Logs on the Status tab; the sync's own status will read success, so the log line is the only signal. Check Test Connection and the token's permissions.

Webhook notifications not arriving

  • Confirm the webhook URL on the Shopcaisse application points to Upvendo's /api/webhook/shopcaisse.
  • A signature mismatch returns 403 — the HMAC is keyed by the application id; ensure the right application/token is connected.

Assistant Guidance

When helping users with the ShopCaisse integration:

  • This is test_only in Upvendo's provider config — flag it as not fully GA and point merchants to the Upvendo team before they rely on it in production.
  • The connect flow is merchant-level and paste-once: never suggest a store picker or a per-location connect step. One JWT creates one Upvendo Location per Shopcaisse store automatically.
  • The catalog is one-way (Shopcaisse → Upvendo). Never tell a merchant they can create modifier groups, modifiers, categories, combos, packs, variants or images in Upvendo for a ShopCaisse location — only a simple item can be created and pushed back, and only if VAT resolves and the token has company.*.items.write.
  • Customer/CRM sync is automatic and pull-only, bundled into every catalog sync (Connect, Sync Now, company.items webhook) — there is no separate "sync customers" action or toggle to point users to.
  • Disconnecting is disabled in the backoffice; always direct merchants to contact Upvendo support/an administrator rather than describing a self-serve delete.
  • If a merchant reports stale prices, items, stock, or customers, the fix is always the same: run Sync Now (or wait for the company.items webhook) — Shopcaisse is the source of truth and Upvendo only pulls.
  • Don't suggest the merchant can pick prod vs staging manually — the environment is derived from the pasted JWT's namespace claim.