curl --request POST \
--url https://studio.weaverse.io/api/v1/content/versions/{versionId}/restore \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"projectId": "clz7prj0a1b2c3d4e5f6g7h8",
"type": "page",
"confirm": "clz8hst3b5d7f9h1j3l5n7p9"
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
projectId: 'clz7prj0a1b2c3d4e5f6g7h8',
type: 'page',
confirm: 'clz8hst3b5d7f9h1j3l5n7p9'
})
};
fetch('https://studio.weaverse.io/api/v1/content/versions/{versionId}/restore', 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/versions/{versionId}/restore"
payload = {
"projectId": "clz7prj0a1b2c3d4e5f6g7h8",
"type": "page",
"confirm": "clz8hst3b5d7f9h1j3l5n7p9"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"object": "version_restored",
"versionId": "clz8hst3b5d7f9h1j3l5n7p9",
"projectId": "clz7prj0a1b2c3d4e5f6g7h8"
}{
"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>"
}Restore a version to live
Replaces live content with the content of one version. This overwrites what is live now, so it needs both content:publish and content:delete, and confirm must equal the versionId in the path (400 otherwise).
type: "page": the version’s page snapshot is written back to its page, using the assignment recorded on the version. Retired versions (listed by?kind=retired-pagesonGET /projects/{projectId}/versions) can be restored the same way. A legacy version with no recorded assignment restores content only.type: "theme": the version’s theme settings, preview host, default locale and recent colors are written to the project, and the project revision advances.
Conflicts (409 CONFLICT). Another change to the same resource landed while restoring, or the version claims a resource binding the server cannot prove. Nothing is changed; details.handle names the resource. Retry after re-reading.
Cache. If content was restored but edge delivery failed, the response includes cacheDelivery: "degraded". Delivery stays queued and is retried without restoring again.
Required scopes: content:publish and content:delete
curl --request POST \
--url https://studio.weaverse.io/api/v1/content/versions/{versionId}/restore \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"projectId": "clz7prj0a1b2c3d4e5f6g7h8",
"type": "page",
"confirm": "clz8hst3b5d7f9h1j3l5n7p9"
}
'const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
projectId: 'clz7prj0a1b2c3d4e5f6g7h8',
type: 'page',
confirm: 'clz8hst3b5d7f9h1j3l5n7p9'
})
};
fetch('https://studio.weaverse.io/api/v1/content/versions/{versionId}/restore', 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/versions/{versionId}/restore"
payload = {
"projectId": "clz7prj0a1b2c3d4e5f6g7h8",
"type": "page",
"confirm": "clz8hst3b5d7f9h1j3l5n7p9"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text){
"object": "version_restored",
"versionId": "clz8hst3b5d7f9h1j3l5n7p9",
"projectId": "clz7prj0a1b2c3d4e5f6g7h8"
}{
"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
Body
Response
Restored (cacheDelivery=degraded if edge delivery pending)
The response is of type object.
Was this page helpful?