curl --request GET \
--url https://studio.weaverse.io/api/v1/content/projects/{projectId}/pages/{type}/{handle} \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://studio.weaverse.io/api/v1/content/projects/{projectId}/pages/{type}/{handle}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://studio.weaverse.io/api/v1/content/projects/{projectId}/pages/{type}/{handle}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"object": "page",
"id": "clz2r7t5w0002mnop9012qrst",
"type": "PRODUCT",
"handle": "blue-shirt",
"locale": "en-us",
"items": [
{
"id": "019a3c2e-5b7d-7f10-8a2b-3c4d5e6f7a81",
"type": "main",
"data": {},
"children": [
{
"id": "019a3c2e-5b7d-7f10-8a2b-3c4d5e6f7a82"
},
{
"id": "019a3c2e-5b7d-7f10-8a2b-3c4d5e6f7a83"
}
]
},
{
"id": "019a3c2e-5b7d-7f10-8a2b-3c4d5e6f7a82",
"type": "hero-banner",
"data": {
"title": "Summer Collection",
"subtitle": "New arrivals for the season",
"buttonText": "Shop Now",
"buttonLink": "/collections/summer"
},
"children": null
},
{
"id": "019a3c2e-5b7d-7f10-8a2b-3c4d5e6f7a83",
"type": "product-details",
"data": {
"showPrice": true,
"showVariants": true,
"layout": "two-column"
},
"children": null
}
],
"updatedAt": "2026-10-18T14:22:05.000Z",
"meta": {
"inherited": false,
"sourceProjectId": "clz1k8m2n0000abcd1234efgh",
"depth": 0
},
"seo": null
}{
"object": "error",
"code": "UNAUTHORIZED",
"message": "<string>",
"status": 123,
"details": "<unknown>"
}{
"object": "error",
"code": "UNAUTHORIZED",
"message": "<string>",
"status": 123,
"details": "<unknown>"
}{
"object": "error",
"code": "UNAUTHORIZED",
"message": "<string>",
"status": 123,
"details": "<unknown>"
}{
"object": "error",
"code": "UNAUTHORIZED",
"message": "<string>",
"status": 123,
"details": "<unknown>"
}Get page content
Returns a page’s full content: its component items, revision and inheritance metadata. This is the primary endpoint for rendering Weaverse pages in external applications.
Use the exact type, handle and locale from GET /projects/{projectId}/pages. Custom page handles may include / (for example pages/gift-shop, fetched at /projects/{projectId}/pages/CUSTOM/pages/gift-shop). Singleton types (INDEX, ALL_PRODUCTS, COLLECTION_LIST, CART, CUSTOMER, NOT_FOUND, PASSWORD, SEARCH) accept an empty handle; CUSTOM and the per-resource types require one. An unknown type returns 400.
Always pass locale on localized projects. Content is stored per locale: a page edited while a market such as en-us is selected in Studio is saved on the en-us assignment, not the base locale (""). Without locale the base locale is requested first and may resolve to a different, unedited assignment. This is the most common reason a published change looks missing from the API.
Resolution order, evaluated at each project level:
- The requested handle’s market match, when the project uses market-first resolution
- The requested handle with the exact locale
- The requested handle with the empty locale (
"") - The requested handle with the legacy
en-uslocale - For a non-
CUSTOMrequest with a non-empty handle, the type’s shared default template (empty handle), in the same market, exact-locale, empty-locale, thenen-usorder
If the project has no match, the same sequence runs for its parent and then grandparent project (meta.inherited, meta.depth, meta.sourceProjectId tell you where the content came from). Nothing found returns 404 PAGE_NOT_FOUND.
items is a flat list. Rebuild the tree from each item’s children references, starting at the root item. With format=portable-text (or Accept: application/portable-text+json), items is replaced by a content array of Portable Text blocks. includeDefaults=true fills settings the merchant never customized with their schema defaults.
Required scope: content:read
curl --request GET \
--url https://studio.weaverse.io/api/v1/content/projects/{projectId}/pages/{type}/{handle} \
--header 'Authorization: Bearer <token>'const options = {method: 'GET', headers: {Authorization: 'Bearer <token>'}};
fetch('https://studio.weaverse.io/api/v1/content/projects/{projectId}/pages/{type}/{handle}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://studio.weaverse.io/api/v1/content/projects/{projectId}/pages/{type}/{handle}"
headers = {"Authorization": "Bearer <token>"}
response = requests.get(url, headers=headers)
print(response.text){
"object": "page",
"id": "clz2r7t5w0002mnop9012qrst",
"type": "PRODUCT",
"handle": "blue-shirt",
"locale": "en-us",
"items": [
{
"id": "019a3c2e-5b7d-7f10-8a2b-3c4d5e6f7a81",
"type": "main",
"data": {},
"children": [
{
"id": "019a3c2e-5b7d-7f10-8a2b-3c4d5e6f7a82"
},
{
"id": "019a3c2e-5b7d-7f10-8a2b-3c4d5e6f7a83"
}
]
},
{
"id": "019a3c2e-5b7d-7f10-8a2b-3c4d5e6f7a82",
"type": "hero-banner",
"data": {
"title": "Summer Collection",
"subtitle": "New arrivals for the season",
"buttonText": "Shop Now",
"buttonLink": "/collections/summer"
},
"children": null
},
{
"id": "019a3c2e-5b7d-7f10-8a2b-3c4d5e6f7a83",
"type": "product-details",
"data": {
"showPrice": true,
"showVariants": true,
"layout": "two-column"
},
"children": null
}
],
"updatedAt": "2026-10-18T14:22:05.000Z",
"meta": {
"inherited": false,
"sourceProjectId": "clz1k8m2n0000abcd1234efgh",
"depth": 0
},
"seo": null
}{
"object": "error",
"code": "UNAUTHORIZED",
"message": "<string>",
"status": 123,
"details": "<unknown>"
}{
"object": "error",
"code": "UNAUTHORIZED",
"message": "<string>",
"status": 123,
"details": "<unknown>"
}{
"object": "error",
"code": "UNAUTHORIZED",
"message": "<string>",
"status": 123,
"details": "<unknown>"
}{
"object": "error",
"code": "UNAUTHORIZED",
"message": "<string>",
"status": 123,
"details": "<unknown>"
}Authorizations
Bearer token: a shop API key (WEAVERSE_API_KEY), a scoped API key or a delegated MCP OAuth token; translation-unit routes also accept a project-bound translation agent token. Each operation lists the scope it requires; the scope table is in the API description.
Path Parameters
Page type (e.g. PRODUCT, INDEX)
Page handle. This is the final greedy path component and may include /; pass the exact handle from the list endpoint, e.g. blue-shirt, track-order, or pages/gift-shop. Leave empty to target a singleton type's single default page — the home page (INDEX), the /products and /collections index pages (ALL_PRODUCTS, COLLECTION_LIST), CART, CUSTOMER, NOT_FOUND, PASSWORD, SEARCH. A handle is required for CUSTOM pages and for per-resource templated types (PRODUCT, COLLECTION, PAGE, BLOG, ARTICLE), whose empty handle is the shared default template.
Query Parameters
Requested locale. Falls back through locale chain if not found.
Output format for rich-text fields.
weaverse(default): rich text returned as HTML strings — original behavior, no migration needed.portable-text: rich text returned as structured Portable Text blocks for multi-channel rendering and AI consumption.
Equivalent to setting Accept: application/portable-text+json on the request. The query parameter takes precedence over the header when both are provided. An invalid value returns 400 INVALID_PARAMS.
weaverse, portable-text Opt-in inclusion of _weaverse: { id, schemaVersion } on each Portable Text custom block so consumers can round-trip back to the original Weaverse item id. Only meaningful when format=portable-text; silently ignored otherwise. Not applicable on /theme-settings (free-form leaves have no item id to round-trip).
Only the literal string true enables this; any other value (e.g. 1, yes, false) is silently treated as false rather than returning 400 — this asymmetry vs format exists because meta was added later and is purely additive.
Opt-in server-side default resolution. When true, each item's data is completed with the component schema defaultValue for every setting the merchant never customized (the studio strips values equal to their default on save). Stored values always win; only missing keys are filled. Items whose component type has no stored schema are returned unchanged. resolved=true is an accepted alias. Only the literal string true enables this; any other value is treated as false.
Note: component schemas are keyed by type only (not per theme version) — if two themes register the same section type, the most recently synced schema's defaults apply.
Response
Page with item tree
page Show child attributes
Show child attributes
Show child attributes
Show child attributes
The page's SEO metadata (title, description, keywords, canonicalUrl, openGraph, twitter, ...), or null when the page has none.
Was this page helpful?