Appearance
API conventions
Rules shared by all endpoints of the Adore JSON API. The endpoints themselves are in the API reference.
Base URLs
| Prefix | What | Example |
|---|---|---|
/api/v0 | Core (simploSHOP) API: products, variations, carts, orders, … | GET /api/v0/products/71 |
/api/theme | Adore theme API: Adore-only resources (restocks, companies, offers, …) | GET /api/theme/product-variation-expected-restocks |
The shop is resolved from the hostname of the request (e.g. adore.localhost, sk.adore.localhost). The hostname also sets the default language and currency (from the hostname's country). Behind a proxy send the shopfront host in X-SES-Referer-Host. An unknown hostname returns 404 with type ShopNotRecognized.
Headers
| Header | Purpose |
|---|---|
Language-Preference | Locale(s) of multilingual props in the response: cs-CZ, sk-SK, en-US (comma-separated for several). One locale → plain strings; no header → objects keyed by language ID ({"ces": "…", "slk": "…"}). Unknown locale → 400. |
Currency-Preference | Currency of money props, e.g. CZK. One currency → {value, formatted}; no header → object keyed by currency. |
Accept-Preferred-Language | Language the shop runs in for this request (translations of messages, slugs). Enabled in Adore. |
Authorization: Bearer <jwt> | Signed-in customer (shopfront) or admin user. Customers can also use the customer_access_token cookie. |
The shopfront always sends Language-Preference and Currency-Preference.
Authentication and permissions
- Product and variation reads are public: guests and customers see active products accessible to their customer group (hidden products are left out of lists). Admin users with
products:readsee everything, including inactive variations. - Writes need an admin user with the matching permission (
create,update,delete). - Without a session a protected action returns
401 Unauthenticated, with an insufficient one403 Unauthorized.
Response shape
Detail — the object itself:
json
{ "id": 71, "code": "1101310", "stock_state": 50, "_links": [...], "_embedded": { ... } }List — items plus pagination metadata (only when paginated):
json
{
"items": [ { "id": 71, ... }, { "id": 72, ... } ],
"_meta": { "page": 1, "total_pages": 57, "records": 113, "per_page": 2 }
}_links– HATEOAS links (hrefis relative,typeis the HTTP method)._embedded– present only when embeds were requested.- Dates use the format
Y-m-d\TH:i:sO, e.g.2026-11-20T06:00:00+0100. - An empty response (e.g. after
DELETE) is204without a body.
embed – related data in one request
Embeds add related or computed data under _embedded. They are loaded in batches, so embedding into a list does not cost one request per item. Always prefer an embed to a follow-up request.
http
GET /api/v0/products/71?embed=expected_restocks,additional_dataGrammar:
| Syntax | Meaning |
|---|---|
embed=a,b | embeds a and b |
embed=a{x,y} | embed a, only its props x and y |
embed=a{x,_embed{b,c}} | embed a and inside each a item embed b and c |
Example – product with its variations and each variation's restocks:
http
GET /api/v0/products/71?embed=product_variations{id,code,stock_state,_embed{expected_restocks}}- Unknown embed →
400 InvalidResourceParameterslisting the names. - Nesting works only for embeds that return resources (e.g.
product_variations,default_category,brand). additional_data{key}does not narrow the keys – the whole object is always returned.- Embed parameters (
embed=a:param) are not supported.
Product embeds
| Embed | Returns |
|---|---|
expected_restocks | Restocks of the active variations summed per date {items: [{datetime, count}], total_count} (Adore) |
additional_data | {product_variation_type, available_lead_time_days} (Adore) |
stock_states | [{stock_id, state}] per warehouse |
product_variations | all variations (including inactive), supports nested _embed |
active_product_variations_count | number of active variations |
product_availability | availability label |
product_variation_properties | variation properties of the product |
default_product_variation_id, default_product_variation_ids_by_attribute | default variation |
computed_prices, computed_taxed_prices, discounted_price, discounted_taxed_price, discount_percents, discount_taxed_percents, discounted_fixed_amount, customer_price, customer_taxed_price, quantity_prices, prices | prices for the current customer (prices only with price lists) |
default_image_id, default_image_url, default_image, default_image_size, secondary_image_id, secondary_image_url, secondary_image_size, og_image_url | images |
urls, default_category, brand, root_brand, brand_image_url, manufacturer | navigation and brand |
category_ids, tag_ids, tags, properties | classification |
attachments, product_attachments | documents |
rating, product_review_parameters, product_review_parameter_ratings | reviews (*detail only) |
customer_product_wish_list_item_id, customer_product_variations_wish_list_items, customer_account_products, customer_account_products_all, active_customer_groups | customer-specific data |
related_product_gifts, product_related_products_grouped_by_properties | related products |
reservation_expiration_at, amount_unit_translations, export_product_ids, product_pairings, product_fields, product_package_product_ids, product_package_variation_ids | other |
Product variation embeds
| Embed | Returns |
|---|---|
expected_restocks | the variation's restocks {items: [{datetime, count}], total_count} (Adore) |
additional_data | {is_included_in_feed, product_variation_type, available_lead_time_days} (Adore) |
stock_states | [{stock_id, state}] per warehouse |
product_availability | availability label |
properties | [{product_property_id, product_property_attribute_id, attribute_name, property_name}] |
image_url, image, default_image_id, default_image_url, default_image | images (image_url falls back to the product image) |
computed_prices, computed_taxed_prices, discounted_price, discounted_taxed_price, discount_percents, discounted_fixed_amount, customer_price, customer_taxed_price, quantity_prices, prices | prices |
tag_ids, tags, customer_account_products | other |
only / except – choose props
http
GET /api/v0/products?only=id,code,stock_state&embed=expected_restocks- Comma list,
a.bfor nested props,a[b,c]for a group. onlyandexceptcannot be combined.- Fewer props mean less computation – use
onlyin lists. onlydoes not remove_embedded.
filters – list filtering
filters is a base64-encoded JSON array of conditions:
json
[
{ "f": "product_id", "o": "eq", "v": 71 },
{ "f": "is_active", "o": "eq", "v": true }
]js
const filters = btoa(JSON.stringify([{ f: 'product_variation_id', o: 'in', v: [299, 300] }]))
fetch(`/api/theme/product-variation-expected-restocks?filters=${encodeURIComponent(filters)}&paginate=0`)- Conditions are AND-ed.
"f": ["code", "sku"]checks several fields with OR. vis required (it may benullwhere the field allows it).- Operators:
eq, neq, gt, gte, lt, lte, in, nin(numbers, dates, enums),contains, starts_with, ends_with(strings).in/nintake an array. - Additional data are filtered as
additional_data.<key>where the definition allows it (e.g.additional_data.product_variation_type). - Unknown field or bad value →
400 InvalidResourceParameters.
sort, search and pagination
| Parameter | Description |
|---|---|
sort | sort=-stock_state,id – comma list, - for descending; only fields the resource allows |
search | full-text search (products only), max 100 characters; adds sort field relevance |
paginate | 0 = all items, no _meta; lists paginate by default |
page | page number from 1 |
per_page | items per page, default 100 |
filters, sort and search are rejected on detail endpoints.
Errors
json
{
"type": "InvalidResourceParameters",
"message": "…",
"id": "6f1c2f0e-…",
"errors": [{ "field": "name.ces", "message": "…" }]
}| Status | type | When |
|---|---|---|
| 400 | InvalidResourceParameters | bad embed, only, filters, sort, search, pagination |
| 401 | Unauthenticated | a session is required |
| 403 | Unauthorized | the session lacks the permission |
| 404 | NotFound / ShopNotRecognized | missing resource / unknown hostname |
| 422 | ValidationError | invalid body; errors lists the fields (name.ces, price.price.CZK, …) |
| 500 | GeneralError | server error; stack only outside production |