Theme Customizations
Theme customizations are the configurable content blocks that drive the storefront home page and footer — image carousels, category carousels, product carousels, static-content slots, the footer-links columns, and the "services" / "USP" strip. Each block is scoped to a themeCode + channelId pair, with locale-specific options JSON inside its translations.
Endpoints
| Method | Path | Purpose |
|---|---|---|
| GET | /api/shop/theme-customizations | Paginated list — supports ?type= filter |
| GET | /api/shop/theme-customizations/{id} | Single customization by ID |
Use the example switcher above to flip between the unfiltered list, the ?type=footer_links filter, and a single fetch.
Request Headers
| Header | Required | Description |
|---|---|---|
Accept | Yes | application/json |
X-STOREFRONT-KEY | Yes | Storefront API key (pk_storefront_…) |
X-Locale | No | Override request locale — affects which row populates translation. Default: channel locale. |
X-Channel | No | Override channel scope |
Query Parameters (collection only)
| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number (1-based) |
per_page | integer | 10 | Items per page. Max 100 for this endpoint. |
type | string | — | Exact-match filter on the type field (see Supported types) |
Pagination headers (X-Total-Count, X-Page, X-Per-Page, X-Total-Pages) are emitted on the collection. See Pagination.
Supported types
The type filter accepts any of these exact strings:
| Type | Purpose |
|---|---|
image_carousel | Hero / banner image carousel on the home page |
category_carousel | Horizontally-scrolling list of categories |
product_carousel | Horizontally-scrolling list of products |
static_content | Free-form HTML / Markdown block |
footer_links | Footer link columns (privacy, terms, about, customer service, …) |
services_content | "Services" / USP strip (free shipping, 24×7 support, refund policy, …) |
Unsupported values are accepted by the filter but return an empty array (
[]) — the validation isn't strict.
Customization Object Fields
Both endpoints return the same shape — the collection wraps an array of these objects, the single endpoint returns one.
| Field | Type | Description |
|---|---|---|
id | integer | Customization primary key |
themeCode | string | Theme this block belongs to (e.g. default) |
channelId | integer | Channel that owns this block — pair with themeCode |
type | string | One of the supported types |
name | string | Admin-facing name |
sortOrder | integer | Display order within the home page / footer |
status | boolean (0/1) | Whether the block is published — only published rows are returned |
createdAt, updatedAt | string (ISO-8601) | Timestamps |
translation | object | null | Inline translation for the request locale: { id, themeCustomizationId, locale, options } |
translations | array of objects | All locale translations as inline objects (not IRI strings) |
Both
translationandtranslations[]are inlined — there are no IRIs to follow on this resource. Theoptionsfield inside each translation is a JSON string, not a parsed object — you have toJSON.parse(translation.options)on the client.
Shape of the options payload (per type)
The options JSON string varies by type. Common shapes:
type | Parsed options shape |
|---|---|
image_carousel | { "images": [{ "link": "...", "image": "storage/theme/.../*.webp", "title": "..." }, …] } |
category_carousel | { "filters": { "sort": "asc", "limit": "10", "parent_id": "1" } } |
product_carousel | { "filters": { … } } (similar to category) |
footer_links | { "column_1": [{ "url": "...", "title": "...", "sort_order": "3" }, …], "column_2": […], … } |
services_content | { "services": [{ "icon": "...", "title": "...", "description": "..." }, …] } |
static_content | { "html_content": "<p>…</p>" } |
The client must parse the JSON string before using it. The API stores
optionsas a TEXT column and returns it verbatim.
Use Cases
- Render the storefront home page in a single round trip: fetch the unfiltered collection, group by
type, sort bysortOrderper group. - Render the footer in a focused request:
?type=footer_linksreturns just one row whoseoptionscarries the column data. - Build an admin preview of every locale: read all
translations[]entries side-by-side. - Auto-detect new home-page blocks added by store admins by polling the collection — anything with
status=1will appear.
Related Resources
- Channels —
channelIdon each customization points at one of these - Categories — referenced by
category_carouselandproduct_carouselfilters - Introduction → IRIs & HATEOAS

