LoyversePOS DataStream (Loyverse)
Written by AI, not reviewed by a human. Please apply the written-by-ai-not-reviewed label. The contract below comes from Loyverse's published OpenAPI specification — no live Loyverse account has been exercised.
Integrates Loyverse as a NexSigns DataStream source.
Source name |
|
Vendor API | Loyverse REST API v1.0, host |
Docs | developer.loyverse.com/docs — and the far more useful machine-readable spec at |
Status | CODE COMPLETE, UNVERIFIED LIVE |
This is the easiest of the six to onboard. One access token the merchant creates themselves, sent as a plain bearer. No OAuth dance, no token exchange, no expiry, no rotation, one host, no regions and no sandbox. It is also the only source of the fourteen whose native model already matches what we want — an item owns a variants[] array — so there is no size folding at all.
Configuration
{
"DataSource": "LoyversePOS",
"Version": "1.0",
"AccessToken": "<Replace Loyverse Access Token>",
"StoreID": "<Replace Loyverse Store ID>",
"UseInventory": false,
"IncludeCompositeItems": true,
"IncludeUnavailableItems": true
}Field | Meaning |
|---|---|
| A personal access token the merchant creates in Loyverse Back Office → Settings → Access tokens. A full-account credential — logged only as |
| The setting that matters. See below. |
| Pulls the separate inventory collection. Off by default; see Availability. |
| A composite item is a recipe made of other items (a gift basket, a combo). It is sellable and priced, so it is kept by default; the switch exists because some accounts use composites purely as internal production records. |
| Applied after normalization. |
A helper endpoint lists the account's stores so a customer can find their StoreID:
GET /api/nexsigns/DataStreams/GetLoyversePOSAvailableStoreList?DataStreamGUID=...StoreID is not optional in practice
A Loyverse account has one catalog and many stores. Each variant carries a per-store price override and a per-store available_for_sale flag. Leaving StoreID blank prices the board off the account-wide default — so a wrong or missing store ID silently misprices every item on the board, with nothing on screen to show it happened.
Because that failure is invisible, a StoreID that does not belong to the account is rejected at save time and again at sync time, rather than being quietly ignored.
API contract
Call | Purpose |
|---|---|
| Proves the token works; supplies business name, currency code and the currency's decimal places. |
| Validates |
| The board's categories. |
| Items with their nested |
| Optional, scoped to the configured store. |
Paging is cursor-based with limit capped at 250 (the default of 50 would be five times the calls for the same catalog). Unlike an offset scheme there is no "short page" heuristic to get wrong — Loyverse states plainly that an absent or empty cursor is the end of the collection. A server echoing the same cursor back is treated as the end rather than being allowed to spin.
Loyverse is the only source of the fourteen that reports its own minor-unit precision (currency.decimal_places on the merchant profile). So unlike CloverPOS and SquarePOS this integration carries no zero-decimal ISO currency table — it reads the merchant's answer instead of guessing from a currency code.
Prices are decimal major units. No division anywhere.
How the catalog is normalized
{
"source": "LoyversePOS", "schema_version": 1,
"store_id": "...", "store_name": "...", "business_name": "...",
"currency": "USD", "currency_decimal_places": 2,
"categories": [ { "id", "name", "sort_order" } ],
"items": [ { "id", "name", "description", "category_ids": [], "image",
"thumbnail", "reference_id", "handle", "option_names",
"track_stock", "sold_by_weight", "is_composite", "sold_out",
"variations": [ { "id", "name", "sku", "barcode",
"reference_id", "pricing_type",
"price_amount", "cost", "in_stock",
"sold_out", "is_default" } ] } ]
}The one real join: price
There is no size folding to do — Loyverse already owns variants. The sync's only substantive work is resolving each variant's price for the configured store: start from the variant's account-wide default_price, then let the configured store's override win. available_for_sale lives on the same override row, which is why availability and price are resolved together in one pass rather than two.
Variant labels and ordering
An item carries option names ("Size", "Color"); each variant carries the option values. The label is the values joined — "Large", or "Large / Green" for a two-option item. An item with no options has exactly one nameless variant and the picker hides the Variation row entirely.
Variants sort alphabetically, which means Large sorts before Small. Loyverse exposes no ordinal on a variant at all — option order on the item is the closest thing and it does not order the values within an option — so alphabetical is the only stable signal available, and stability matters because the change-detection hash runs over this document. This affects the dropdown order only, never the price; the customer picks a default explicitly in the design.
Other projection rules
Categories carry no sort order of any kind — only a colour — so they are ordered by name. There is no operator arrangement being discarded here; there is none to discard.
Only categories a kept item actually references are projected; anything else would render as an empty group in the picker.
VARIABLE("open price") variants have no catalog amount by design — the cashier types it at the till — so the price binding renders blank rather than an error token. Same treatment as Clover'sVARIABLE, Square'sVARIABLE_PRICINGand OLO'sOPEN.thumbnaildeliberately mirrorsimage— Loyverse serves one image per item and no derived sizes — so a design carried over from ToastPOS keeps working.Items are sorted by name; Loyverse returns them newest-first, which moves the moment anyone adds an item.
Availability
Two independent signals, deliberately treated differently:
available_for_saleis always honoured, regardless ofUseInventory. It is an explicit operator switch — un-stocking a variant at this store — and an explicit flag is safe to trust.Stock level is opt-in. With
UseInventoryon, a variant is marked sold out only when it is both stock-tracked (track_stock) and at or below zero. Off by default because an untracked item legitimately reports nothing, and treating that as out-of-stock would black out a board.
Data fields available in the Smart Menu Editor
Name, Variation Name, Price, Description, Image URL, Thumbnail URL, SKU, Barcode, Reference ID, Option Names, Cost, Stock On Hand, Inventory Status, Item ID, Store Name, Business Name, Currency.
No calories — Loyverse has no nutrition concept. A calories binding resolves to a blank, not an error token.
Multi-store designs
Within one Loyverse account the item id is stable across every store, because there is one catalog. So a design authored against store A resolves perfectly against store B and the fallback key never fires. The picker still records SKU / barcode / name for the genuinely cross-account case — a second franchisee, or a re-created account.
Each store gets its own DataStream with the same Name and a different StoreID; the existing name-based dereference handles resolving one design against whichever store's data is loaded.
Troubleshooting
Symptom | Likely cause |
|---|---|
HTTP 401 / 403 | The token is wrong, or it has been revoked in Loyverse Back Office. Issue a new one under Settings → Access tokens. |
"Store ID … does not belong to this Loyverse account" | Exactly what it says. Use the store-list endpoint. The sync refuses to continue rather than silently using account-default prices. |
Prices look wrong for one store but right for another |
|
Everything reads out of stock |
|
Size dropdown reads Large, Medium, Small | Expected — see the ordering note above. Pick the default explicitly in the design. |
Paging exceeded the budget | The catalog is larger than 30 pages of 250. Raise it in the code or split the board. |
Known gaps
Composite item components are not decomposed — a composite appears as one priced item.
Modifiers (
/modifiers) are not projected; only native variants become sizes.Discounts and taxes are not projected.
Category order is alphabetical because Loyverse has no ordinal.
No webhook — hourly polling only. Loyverse does publish webhooks, which would make stock and menu updates immediate; that is the most valuable follow-up for this source.
Verification status
Done: builds clean (0 errors); the editor partial parsed with the real Razor engine (0 parser errors) and verified pure ASCII; the contract taken from Loyverse's own OpenAPI document rather than the rendered docs.
Not done: no live Loyverse call; no offline assertion harness; no end-to-end walkthrough.
Because onboarding is so simple — one self-service token — Loyverse is the cheapest of the six to validate first. A free Loyverse account with a handful of items and two stores would confirm the price-override join, the availability flags and the cursor paging in an afternoon.