curl --request PATCH \
--url https://studio.weaverse.io/api/v1/content/projects/{projectId}/theme-settings \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"theme": {
"colorPrimary": "#1e40af",
"pageWidth": 1440
}
}
'const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({theme: {colorPrimary: '#1e40af', pageWidth: 1440}})
};
fetch('https://studio.weaverse.io/api/v1/content/projects/{projectId}/theme-settings', 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}/theme-settings"
payload = { "theme": {
"colorPrimary": "#1e40af",
"pageWidth": 1440
} }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text){
"object": "theme_settings_update",
"projectId": "clz1k8m2n0000abcd1234efgh",
"updatedKeys": [
"colorPrimary",
"pageWidth"
],
"theme": {
"colorBackground": "#ffffff",
"colorText": "#1a1a1a",
"colorPrimary": "#1e40af",
"headingFont": "Inter",
"bodyFont": "Inter",
"pageWidth": 1440
}
}{
"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>"
}{
"object": "error",
"code": "UNAUTHORIZED",
"message": "<string>",
"status": 123,
"details": "<unknown>"
}{
"object": "error",
"code": "STALE_PROJECT",
"message": "Theme settings changed since your last read (expectedRevision mismatch). Re-read the settings and reapply your patch.",
"status": 409
}{
"object": "error",
"code": "UNAUTHORIZED",
"message": "<string>",
"status": 123,
"details": "<unknown>"
}Update theme settings
Shallow-merges theme over the project’s own theme settings. Send only the top-level keys you want to change; theme must contain at least one key.
Nested objects are replaced wholesale. Fetch the current settings first when you need to preserve sibling values inside a nested object.
- Writes the project’s own config only; a parent project’s theme is never changed through a child project.
updatedKeyslists the top-level keys whose stored value actually changed. It is empty for a no-op patch, in which case no cache invalidation happens.- When values change, a theme version snapshot (restorable from Studio) is attempted before the write. Snapshots are deduplicated and best-effort, so do not assume every update has one.
- After a change, caches are invalidated like a Studio save so the edit goes live through api.weaverse.io. Propagation time is not guaranteed; read the settings again to verify.
- Clients or proxies that strip
PATCHbodies may sendPOSTto the same URL.
Concurrency: pass the revision from your GET as expectedRevision. If the settings changed since, the request returns 409 STALE_PROJECT and writes nothing; re-read and reapply. Delegated (MCP OAuth) tokens must send it (428 PRECONDITION_REQUIRED otherwise); it is optional for API keys.
Required scope: content:write
curl --request PATCH \
--url https://studio.weaverse.io/api/v1/content/projects/{projectId}/theme-settings \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"theme": {
"colorPrimary": "#1e40af",
"pageWidth": 1440
}
}
'const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({theme: {colorPrimary: '#1e40af', pageWidth: 1440}})
};
fetch('https://studio.weaverse.io/api/v1/content/projects/{projectId}/theme-settings', 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}/theme-settings"
payload = { "theme": {
"colorPrimary": "#1e40af",
"pageWidth": 1440
} }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text){
"object": "theme_settings_update",
"projectId": "clz1k8m2n0000abcd1234efgh",
"updatedKeys": [
"colorPrimary",
"pageWidth"
],
"theme": {
"colorBackground": "#ffffff",
"colorText": "#1a1a1a",
"colorPrimary": "#1e40af",
"headingFont": "Inter",
"bodyFont": "Inter",
"pageWidth": 1440
}
}{
"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>"
}{
"object": "error",
"code": "UNAUTHORIZED",
"message": "<string>",
"status": 123,
"details": "<unknown>"
}{
"object": "error",
"code": "STALE_PROJECT",
"message": "Theme settings changed since your last read (expectedRevision mismatch). Re-read the settings and reapply your patch.",
"status": 409
}{
"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
Top-level theme settings keys to merge. Must be a non-empty object.
Optimistic-concurrency token: the revision value from the GET read this patch was based on (null when GET returned null for a project whose revision was never set; compared null-safely). Required for delegated (MCP OAuth) tokens — omitted → 428 PRECONDITION_REQUIRED; optional for API keys. When the settings changed since (e.g. a concurrent studio save), the request is rejected with 409 STALE_PROJECT before anything is written. Re-read and reapply instead of retrying the same patch.
Response
Merge result with the full stored theme
Was this page helpful?