Build a shop or website with the API
The Builder API lets you assemble a complete online shop and website over plain REST — no dashboard clicking. Everything acts only on the business your key belongs to. This is also exactly what an AI agent like Claude needs to build a site for a merchant end-to-end.
The flow
- 1
Create a key with the builder scopes
In your LUXPOS dashboard, mint an lpk_live_ key with site:write, shop:write and products:write (plus the matching :read scopes). All three ride on the Shop entitlement — if your plan does not include the shop, the scopes are simply not offered.
- 2
Set up the shop
PATCH /public/shop is an upsert: the first call creates the shop, later calls update it. Name defaults to your business name.
- 3
Add products
Create catalog items with POST /public/products (and categories, stock, images). These are the products your storefront and product-grid blocks render.
- 4
Build pages
Compose pages from visual blocks, or drop to raw HTML with renderMode='CODE'. Ask GET /public/site/block-types for the exact config shape of every block.
- 5
Apply a theme (optional)
POST /public/site/apply-theme maps a theme's design tokens + source code onto your site and clones its pages.
- 6
Publish
Set the site live (PATCH /public/site { isEnabled: true }) and the shop live (PATCH /public/shop { status: 'ACTIVE' }).
1 · Create the shop
One PATCH creates and configures the shop. Send an Idempotency-Key so a retry never creates a duplicate.
curl -X PATCH https://api.luxpos.lu/api/v1/public/shop \
-H "Authorization: Bearer lpk_live_xxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: shop-setup-1" \
-d '{
"name": "Corner Roastery",
"mode": "B2C",
"currency": "EUR",
"offersShipping": true,
"shippingFlatRate": 4.90,
"showPricesToGuests": true
}'2 · Add products
Products live in the shared catalog and are managed with the products:write scope. Mark them isForSale so the storefront lists them.
curl -X POST https://api.luxpos.lu/api/v1/public/products \
-H "Authorization: Bearer lpk_live_xxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: prod-ethiopia-1" \
-d '{
"name": "Ethiopia Yirgacheffe 250g",
"sellingPrice": 12.50,
"vatPercent": 3,
"isForSale": true,
"images": ["https://cdn.example.com/coffee.jpg"]
}'See the Writing data guide for categories, stock and image upload.
3 · Build pages from blocks
A page is an ordered array of blocks, each { type, order, config }. Fetch the catalog first so you know every type and its config keys:
curl https://api.luxpos.lu/api/v1/public/site/block-types \
-H "Authorization: Bearer lpk_live_xxx"Then create a page. This one shows a shop hero over a product grid:
curl -X POST https://api.luxpos.lu/api/v1/public/site/pages \
-H "Authorization: Bearer lpk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"title": "Shop",
"slug": "shop",
"showInNav": true,
"blocks": [
{ "type": "shop-hero", "order": 0,
"config": { "title": "Freshly roasted", "ctaText": "Shop now", "ctaLink": "/products" } },
{ "type": "product-grid", "order": 1,
"config": { "title": "Our coffees", "columns": 3, "showPrices": true, "showAddToCart": true } }
]
}'4 · …or write a page in raw HTML
Set renderMode: "CODE" and pass customHtml to render your own full-page markup instead of blocks. It can reference the CSS/JS you set on the site with PATCH /public/site. This code is owner-authored and injected as-is (Shopify-style), so keep it trusted.
curl -X PATCH https://api.luxpos.lu/api/v1/public/site/pages/PAGE_ID \
-H "Authorization: Bearer lpk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"renderMode": "CODE",
"customHtml": "<section class=\"hero\"><h1>About us</h1><p>Since 2019.</p></section>"
}'Global source code lives on the site itself — inject fonts and meta into <head>, add CSS, and run JS before </body>:
curl -X PATCH https://api.luxpos.lu/api/v1/public/site \
-H "Authorization: Bearer lpk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"primaryColor": "#0A0A0A",
"fontFamily": "Inter",
"customHeadHtml": "<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">",
"customCss": ".hero { padding: 6rem 1rem; text-align: center; }"
}'5 · Apply a theme, then publish
Prefer a head start? List themes (each ships tokens + editable source code) and apply one — it maps the design onto your site and clones its pages. Then flip the site and shop live.
# apply the "vitrine" storefront theme
curl -X POST https://api.luxpos.lu/api/v1/public/site/apply-theme \
-H "Authorization: Bearer lpk_live_xxx" \
-H "Content-Type: application/json" \
-d '{ "themeKey": "vitrine" }'
# publish the website
curl -X PATCH https://api.luxpos.lu/api/v1/public/site \
-H "Authorization: Bearer lpk_live_xxx" \
-H "Content-Type: application/json" \
-d '{ "isEnabled": true }'
# publish the shop
curl -X PATCH https://api.luxpos.lu/api/v1/public/shop \
-H "Authorization: Bearer lpk_live_xxx" \
-H "Content-Type: application/json" \
-d '{ "status": "ACTIVE" }'Driving it with Claude (or any LLM)
The whole API is plain REST with a Bearer token, so an LLM can operate it directly — as tool calls, or by generating the curl commands above. Give the model these three facts and it can build a merchant a full site from a brief:
- • Base URL:
https://api.luxpos.lu/api/v1 - • Auth header:
Authorization: Bearer lpk_live_… - • It should call
GET /public/site/block-typesfirst to learn the exact block config shapes before composing pages.
A reliable prompt pattern:
You have a LUXPOS API key with scopes: shop:write, products:write, site:write.
Base URL: https://api.luxpos.lu/api/v1. Authenticate every request with
"Authorization: Bearer $LUXPOS_KEY".
Build a storefront for a coffee roaster:
1. GET /public/site/block-types to learn the available blocks.
2. PATCH /public/shop to create the shop (B2C, EUR, flat shipping).
3. POST /public/products for each of the 6 coffees I list below.
4. Build a home page (shop-hero + product-grid) and an about page.
5. Apply the "vitrine" theme, set brand color #0A0A0A.
6. Publish the site and the shop.
Send an Idempotency-Key on every POST/PATCH so retries are safe.Because ownership is derived from the key, the model can never touch another business's data — the worst a bad generation can do is create pages/products in your own draft site, which you can delete or unpublish.