Configure newsroom themes
Distinguish theme definitions from newsroom presets, validate editable settings, and review a theme before activating it.
A theme defines the hosted newsroom's presentation. A preset holds that theme's settings for a particular newsroom. The account's theme catalog, a newsroom's available presets, and its active preset answer different questions.
These APIs configure Prezly-hosted themes. They do not edit this developer documentation's theme or deploy a custom React newsroom. For your own site, start with Story rendering and the JavaScript SDK.
Personal tokens need sites:read for catalog/preset reads and sites:write to save or apply settings. The owner also needs the relevant newsroom permissions, and theme visibility/editable settings depend on the account and newsroom. Load PREZLY_API_TOKEN using Your first API request.
Discover definitions and newsroom presets
The account-wide GET /themes response contains themes, each a theme definition with its id, name, features, and other descriptive fields. Use Get Theme to inspect one available definition. Do not assume a theme ID from another account is available here.
For the intended newsroom:
curl --fail-with-body --silent --show-error 'https://api.prezly.com/v2/newsrooms/YOUR_NEWSROOM_UUID/themes' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Accept: application/json'Here themes contains presets, not just theme definitions. Each preset nests its definition under theme, so the ID used in a subsequent URL is preset.theme.id. The list is not a paginated collection.
A preset also exposes settings, editable_settings, is_active, and, when available, preview_url. The editable settings are a JSON Schema filtered for this newsroom's feature access. A list of theme names or a global catalog response is not a settings schema.
List theme catalog → · List newsroom presets →
Inspect the active and candidate presets
curl --fail-with-body --silent --show-error 'https://api.prezly.com/v2/newsrooms/YOUR_NEWSROOM_UUID/themes/active' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Accept: application/json'The response uses an outer theme envelope containing the preset; its definition is nested again as theme.theme. A 404 can mean that no theme is active. Handle that state deliberately rather than assuming every newsroom has an active preset.
Then read the candidate preset, replacing YOUR_THEME_ID with an ID available to this newsroom:
curl --fail-with-body --silent --show-error 'https://api.prezly.com/v2/newsrooms/YOUR_NEWSROOM_UUID/themes/YOUR_THEME_ID' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Accept: application/json'Compare the candidate's editable schema and effective settings with the existing design. Use its preview URL when provided, and review representative stories, images, rich content, language navigation, contact cards, galleries, and subscription forms. The existence of a preview URL alone does not establish that every content feature is supported.
Read active preset → · Read candidate preset →
Prepare a reviewed settings document
Do not invent universal keys such as a color or logo setting: each theme's schema is its contract. Save a snapshot of the candidate's current editable settings and schema with this Node.js 22+ preparation script. Replace both identifiers, save as prepare-theme.mjs, and run node prepare-theme.mjs:
import { writeFile } from 'node:fs/promises';
const token = process.env.PREZLY_API_TOKEN;
if (!token) throw new Error('Set PREZLY_API_TOKEN before running this script.');
const newsroomId = 'YOUR_NEWSROOM_UUID';
const themeId = 'YOUR_THEME_ID';
const url = `https://api.prezly.com/v2/newsrooms/${encodeURIComponent(newsroomId)}/themes/${encodeURIComponent(themeId)}`;
const response = await fetch(url, {
headers: { Authorization: `Bearer ${token}`, Accept: 'application/json' },
signal: AbortSignal.timeout(15_000),
});
if (!response.ok) throw new Error(`Prezly returned HTTP ${response.status}.`);
const { theme: preset } = await response.json();
if (preset.theme.id !== themeId) throw new Error('Unexpected theme preset.');
await writeFile('theme-settings.json', `${JSON.stringify({ settings: preset.settings }, null, 2)}\n`);
await writeFile('theme-settings.schema.json', `${JSON.stringify(preset.editable_settings, null, 2)}\n`);
console.log('Prepared local files; no theme was saved or activated.');Review and edit theme-settings.json using the returned schema. Retain a separate snapshot of the currently active theme ID and settings if you need a recovery plan. The server validates supplied settings against the newsroom-specific editable schema.
Settings are not a recursive PATCH. When settings is supplied, it becomes the saved override document on top of theme defaults; omitted previous overrides can revert to defaults. Nested objects are not guaranteed to merge field by field. Omitting settings or sending settings: null retains the preset's effective settings. Sending {"settings":{}} chooses defaults rather than preserving all current customization.
Save a preset or activate it
Use PATCH to save settings without selecting a different active theme:
curl --fail-with-body --silent --show-error --request PATCH 'https://api.prezly.com/v2/newsrooms/YOUR_NEWSROOM_UUID/themes/YOUR_THEME_ID' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-binary @theme-settings.jsonSave newsroom theme settings returns 200 OK with theme. Saving an inactive preset does not activate it; saving the currently active preset can change the live design. It is not a separate draft layer for the active theme.
After reviewing the settings and preview, POST to select that theme:
curl --fail-with-body --silent --show-error --request POST 'https://api.prezly.com/v2/newsrooms/YOUR_NEWSROOM_UUID/themes/YOUR_THEME_ID' \
--header "Authorization: Bearer $PREZLY_API_TOKEN" \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--data-binary @theme-settings.jsonThe response contains the applied preset under theme; inspect is_active and re-read /themes/active. Applying also requests hosted routing/network updates. Verify the public website separately, including mobile layouts and the content reviewed in preview.
The current apply validator accepts optional key_features to request compatibility checks. Those checks run when a non-empty feature list is supplied; do not assume the request above performs an exhaustive content audit. Review relevant warnings and account restrictions before changing a live design.
If the response is lost, inspect the active preset and saved settings before retrying. Returning to a previous design means deliberately applying its available theme and reviewed settings again, not merely changing a local name or assuming a browser preview saved it.