Authentication
The LUXPOS API uses long-lived API keys. Every request must include a valid key in the Authorization header.
How it works
Each API key is tied to a single LUXPOS business account and can only ever access that business's data. Keys carry an explicit set of scopes (default-deny): a key can do nothing it was not granted. Read scopes pull data; write scopes can create and update a small, safe set of resources. Pass the key as a standard Bearer token:
GET /api/v1/public/transactions HTTP/1.1
Host: api.luxpos.lu
Authorization: Bearer lpk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxAPI keys follow the format lpk_live_ for production keys and lpk_test_ for test-mode keys.
Available scopes
When creating a key you select one or more scopes. A request to an endpoint that requires a scope your key does not have returns 403 Forbidden.
Read scopes
business:readRead business info (GET /public/me) and locations / branches (GET /public/locations).
products:readRead product catalogue, categories, prices, and per-location stock (GET /public/products, /public/products/:id/inventory).
transactions:readRead POS transactions and sessions (GET /public/transactions, /public/sessions).
reports:readAggregated revenue reports and breakdowns (GET /public/reports/*).
invoices:readRead sales invoices and their line items (GET /public/invoices).
customers:readRead customer profiles and visit history (GET /public/customers).
staff:readRead staff (id, name, role only — no email/phone).
loyalty:readRead loyalty cards / members and their points/stamps (GET /public/loyalty/cards).
site:readRead the website builder: site config, pages, themes and the block-type catalog (GET /public/site, /public/site/pages, /public/site/themes, /public/site/block-types). Requires the Shop entitlement.
shop:readRead the online shop settings (GET /public/shop). Requires the Shop entitlement.
Write scopes
Grant these only to integrations that must change data. They are enforced independently of read scopes — a key with products:write still cannot read products unless it also has products:read.
products:writeCreate and update products (POST /public/products, PATCH /public/products/:id).
inventory:writeAdjust stock levels with an audit log (POST /public/products/:id/inventory).
customers:writeCreate and update customers (POST /public/customers, PATCH /public/customers/:id).
loyalty:writeEarn and redeem loyalty at the till: add/remove stamps, adjust points, redeem rewards and coupons (POST /public/loyalty/cards/:id/*, /public/loyalty/coupons/:code/redeem).
site:writeBuild the website: update branding + source code, create/update/delete pages (visual blocks or raw HTML), apply themes and publish (PATCH /public/site, POST/PATCH/DELETE /public/site/pages, POST /public/site/apply-theme). Requires the Shop entitlement.
shop:writeUpsert the online shop settings — create it and configure mode, currency, shipping, publishing, and link a builder site (PATCH /public/shop). Requires the Shop entitlement.
Security model: the business a key acts on is always derived from the key itself, never from the request body or URL. A key can never read or mutate another business's products, customers, invoices, locations, or loyalty cards — attempts return 404. LUXPOS never exposes subscription, billing, payout, Stripe, or Apple-IAP data through the public API.
Best practices
Never expose keys in client-side code
API keys must only live in server-side environments (environment variables, secrets managers). If a key is ever accidentally committed or exposed, revoke it immediately from the dashboard.
Rotate every 90 days
Create a new key, update all dependent services, verify they work, then delete the old key. Set a calendar reminder. Short-lived exposure windows minimise blast radius if a key is compromised.
One key per integration
Use a separate key for each integration or application. This makes it easy to revoke access for one system without affecting others, and lets you audit usage per integration in the dashboard.
Request only the scopes you need
Apply the principle of least privilege. If your integration only reads transactions, do not grant
customers:readorstaff:read.