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 authentication: a shop API key (WEAVERSE_API_KEY), a scoped API key, a delegated MCP OAuth token, or (translation-unit routes only) a project-bound translation agent token. Scopes: content:read — Read projects, pages, theme settings, versions, drafts and translation units. content:write — Save drafts and make non-destructive edits (page items, metadata, SEO, assignments, languages, glossary). Never publishes or deletes. content:publish — Publish drafts, schedule/reschedule/cancel publications, restore versions, publish global sections. content:delete — Delete pages, global sections, languages, static keys, override reverts; required with project:manage for project deletion. project:manage — Create/copy/delete projects, settings, variants, hierarchy, backups, restore-as-new, previews, hostname policy. translations:read — Read translation units only (no general content access). translations:write — Apply translation units only; never mutates page content. A legacy unscoped API key keeps read/write/translation baseline access and every pre-scope endpoint, but never gains publish/delete/project-manage implicitly.
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?