Online shop
Storefront API
The endpoints the BaxPay storefront itself uses, open to any front end: a custom site, a mobile app or a kiosk. They need no API key and only expose what the shop already shows the public.
All paths are under https://api.baxpay.com/v1. Each shop is addressed by its slug (the
{slug} in https://{slug}.baxpay.com). Prices are always computed on the server from the
merchant's catalog: what the client sends is never trusted.
A checkout in four calls
Read the catalog
GET /shop/{slug}/catalog lists products, variants, add-ons and categories.Price the cart
POST /shop/{slug}/quote returns the priced lines, delivery and pickup options and any discount.Check out
POST /shop/{slug}/checkout creates the order and returns a payUrl.Send the customer to pay
payUrl. After paying, the customer lands on the shop's order page; read it with GET /shop/{slug}/orders/{token}.Resolve a shop
/shop/resolve?host=shop.example.comFinds a shop from a host name ({slug}.baxpay.com or a verified custom domain). Without ?host=,
the request's Host header is used. Returns the shop's public face:
curl "https://api.baxpay.com/v1/shop/resolve?host=maison-lumiere.baxpay.com"{
"success": true,
"data": {
"slug": "maison-lumiere",
"displayName": "…",
"language": "fr",
"currency": "EUR",
"productsEnabled": true,
"theme": {},
"settings": {}
}
}slugstringdisplayNamestringlogoUrl, iconUrlstring | nullthemeobjectsettingsobjectlanguagestringfr, en, de…). Use it as the default locale.currencystringEUR.Read the catalog
/shop/{slug}/catalog/shop/{slug}/products/{productId}one product + up to 4 relatedOnly active products sold ONLINE or BOTH are listed (up to 500).
curl https://api.baxpay.com/v1/shop/maison-lumiere/catalog{
"success": true,
"data": {
"slug": "maison-lumiere",
"displayName": "…",
"categories": [],
"products": [{ "id": "…", "name": "…", "currency": "EUR", "priceType": "FIXED" }]
}
}One product comes with its shop and up to 4 related products:
curl https://api.baxpay.com/v1/shop/maison-lumiere/products/6f0e2c4a-…{
"success": true,
"data": {
"slug": "maison-lumiere",
"displayName": "…",
"product": { "id": "6f0e2c4a-…", "name": "…", "unitAmount": 12.5, "priceType": "FIXED", "booking": null },
"related": []
}
}Each product looks like this (shown with variants and add-ons):
{
"id": "…",
"name": "Lampe Arc",
"description": "Brass and linen, 160 cm.",
"unitAmount": 189,
"currency": "EUR",
"priceType": "FIXED",
"quantityStep": 1,
"categoryId": "…",
"supplyType": "GOODS",
"imageUrl": "https://cdn.baxpay.com/…",
"trackInventory": true,
"stockHint": "low",
"variants": [{ "id": "…", "name": "Black", "sku": "ARC-BLK", "unitAmount": 199, "imageUrl": null }],
"modifierGroups": [
{ "id": "…", "name": "Bulb", "minSelect": 0, "maxSelect": 1,
"modifiers": [{ "id": "…", "name": "Warm LED", "priceDelta": 9 }] }
],
"booking": null
}unitAmountnumberunitAmount overrides it.priceTypeFIXED | VARIABLEVARIABLE (a gift card, a donation): the customer sets the price, sent as unitAmount in the cart.stockHintstringin_stock, low (5 or fewer), out or unlimited (stock not tracked), at the shop's stock location.supplyTypeGOODS | SERVICESbookingobject | nullPrice a cart
/shop/{slug}/quotecurl -X POST https://api.baxpay.com/v1/shop/maison-lumiere/quote \
-H "Content-Type: application/json" \
-d '{ "items": [{ "productId": "6f0e2c4a-…", "quantity": 2 }], "country": "FR", "discountCode": "WELCOME10" }'{
"success": true,
"data": {
"subtotalMinor": 2500,
"hasGoods": true,
"lines": [{ "productId": "6f0e2c4a-…", "quantity": 2, "unitMinor": 1250, "lineMinor": 2500, "supplyType": "GOODS" }],
"discount": null,
"discountError": { "reason": "NOT_FOUND" },
"options": [{ "id": "standard", "kind": "SHIPPING", "priceMinor": 590 }]
}
}The request body in full:
{
"items": [
{ "productId": "…", "variantId": "…", "quantity": 1, "modifierIds": ["…"] }
],
"country": "FR",
"discountCode": "WELCOME10",
"email": "[email protected]"
}itemsarrayrequiredproductId, optional variantId, quantity, modifierIds (add-ons), unitAmount for VARIABLE products, and booking for bookable services.countrystringdiscountCodestringemailstring{
"subtotalMinor": 18900,
"hasGoods": true,
"lines": [
{ "productId": "…", "name": "Lampe Arc", "quantity": 1, "unitMinor": 18900, "lineMinor": 18900,
"supplyType": "GOODS", "imageUrl": "https://…", "vatRate": 20 }
],
"discount": { "code": "WELCOME10", "kind": "PERCENT", "discountMinor": 1890, "freeShipping": false },
"discountError": null,
"countries": ["BE", "FR"],
"options": [
{ "id": "standard", "kind": "SHIPPING", "label": "Standard delivery", "priceMinor": 0, "detail": "2-4" },
{ "id": "pickup-1", "kind": "PICKUP", "label": "Workshop", "priceMinor": 0, "detail": "12 rue des Lampes, Paris" }
],
"requirePhone": false,
"allowNote": true
}Amounts in the quote and order are in minor units (cents). options[].detail is the delivery
time in days for shipping, or the address for pickup. A cart of services only gets one option of
kind NONE. Free-over thresholds use the subtotal after the discount.
discountError is null or { reason, minSubtotalMinor? }, where reason is one of NOT_FOUND,
NOT_STARTED, EXPIRED, USED_UP, ALREADY_USED, MIN_SUBTOTAL or NOT_ELIGIBLE.
Check out
/shop/{slug}/checkoutcurl -X POST https://api.baxpay.com/v1/shop/maison-lumiere/checkout \
-H "Content-Type: application/json" \
-d '{
"items": [{ "productId": "6f0e2c4a-…", "quantity": 1 }],
"customer": { "name": "Camille Martin", "email": "[email protected]" },
"fulfilmentOptionId": "standard",
"address": { "line1": "12 rue des Lampes", "postalCode": "75011", "city": "Paris", "country": "FR" },
"locale": "fr"
}'{
"success": true,
"data": { "orderNumber": 1001, "orderToken": "kW3c…", "payUrl": "https://pay.baxpay.com/plk_…", "totalMinor": 1840, "currency": "EUR" }
}All the fields:
{
"items": [{ "productId": "…", "quantity": 1 }],
"customer": { "name": "Camille Martin", "email": "[email protected]", "phone": "+33 6 12 34 56 78" },
"fulfilmentOptionId": "standard",
"address": { "line1": "12 rue des Lampes", "postalCode": "75011", "city": "Paris", "country": "FR" },
"note": "Please ring twice.",
"locale": "fr",
"discountCode": "WELCOME10"
}itemsarrayrequiredcustomerobjectrequiredname (2–100 characters), email, and phone (required when the quote said requirePhone).fulfilmentOptionIdstringoptions[].id from the quote. Required when the cart has goods.addressobjectline1, postalCode, city, country (one the rate serves; French postal codes have 5 digits), optional line2.notestringlocalestringdiscountCodestring{
"orderNumber": 1042,
"orderToken": "kW3c…",
"payUrl": "https://pay.baxpay.com/plk_…",
"totalMinor": 17010,
"currency": "EUR"
}Redirect the customer to payUrl. The link stays open for a while and holds the stock; an unpaid
order stays PENDING_PAYMENT. Once paid, the customer is sent back to the shop's order page
(https://{shop}/order/{orderToken}) and receives the order confirmation by email.
Show the order
/shop/{slug}/orders/{token}curl https://api.baxpay.com/v1/shop/maison-lumiere/orders/kW3c…{
"success": true,
"data": { "number": 1001, "status": "PENDING_PAYMENT", "totalMinor": 1840, "currency": "EUR", "payUrl": "https://pay.baxpay.com/plk_…", "bookings": [] }
}The customer may also drop an unpaid order: POST /shop/{slug}/orders/{token}/cancel.
Returns what the customer may see: number, status (PENDING_PAYMENT, PAID,
READY_FOR_PICKUP, SHIPPED, COMPLETED, CANCELLED), items, subtotalMinor,
discountMinor, discountCode, shippingMinor, totalMinor, currency, the delivery choice
and pickup point, the dates of each step, trackingNumber / trackingUrl, the order's
bookings, and payUrl while it is still unpaid.
Errors
| Status | When | Body |
|---|---|---|
400 | Empty or invalid cart, not enough stock, invalid customer or address, no delivery option chosen | { "message": "Only 2 × Lampe Arc left." } |
400 | Refused discount code at checkout | { "message": "…", "reason": "EXPIRED" } |
403 | Online shop not available on the platform | { "message": "…" } |
404 | Unknown or unpublished shop, product or order | { "message": "…" } |
409 | A booked time was taken meanwhile | { "message": "…", "reason": "SLOT_TAKEN" } |
429 | Too many requests | — |
curl -X POST https://api.baxpay.com/v1/shop/maison-lumiere/quote \
-H "Content-Type: application/json" \
-d '{ "items": [] }'message is a string, or an array of strings for validation errors (as above). It's in English and
safe to show; use reason when you show your own text. See Errors for the shape.
Related
- Online shop — orders, domains, roles
- Bookings — slots and booking pages
- Payment links — the page behind
payUrl