Publish a new branding revision
Publishes a new immutable branding revision for the project. Branding revisions cannot be updated or deleted; every edit publishes a new revision, and flow responses resolve the latest revision per project.
The liquid_template is validated lexically on save (size, encoding,
banned patterns such as <script> tags, inline event handlers, and the
| raw filter). Authoritative LiquidJS validation runs at authoring
time via zitadel plan / zitadel apply.
oauth2 branding.writeAuthorizationBearer <token>Scope: branding.write
project_id*stringThe unique identifier of the project
^[a-zA-Z0-9_-]+$application/json- body
Branding configuration, used in two places with one shape: as the request
body of POST /branding, which publishes it as a new immutable revision,
and as a read-only projection on flow responses, which carries the
project's latest revision. Locally it is the .zitadel/branding/ descriptor
that zitadel apply publishes.
Every field is optional. An omitted key uses Zitadel's maintained default, so a revision carrying one colour is as valid as one carrying the whole object.
$schema?stringEditor affordance: path or URL of this file's JSON meta-schema, so an editor validates and autocompletes it. The CLI strips it before upload; the platform ignores it.
layout?stringLayout preset the revision declares, centered or split. It is
validated on publish and handed to the template as branding.layout.
The bundled default template does not read it, so changing it alone
changes nothing on screen, and it is not an appearance control.
Not a design catalog: the ejectable designs (centered, minimal)
ship as templates and both carry centered; switch designs with
zitadel branding eject --design <name> instead of editing this field.
split is carried by revisions published from the earlier split
designs.
"centered""centered""split"liquid_template?stringThe LiquidJS template for rendering this step. The orchestrator renders it into its Shadow DOM with the capability dictionaries as context.
length <= 131072logo_url?stringFallback mark, used only when neither theme.light.logo_url nor
theme.dark.logo_url is set. Prefer the per-side marks — one file
cannot serve both surfaces.
^([hH][tT][tT][pP][sS]://(?:\[[0-9A-Fa-f:.]+\]|[^/:?#@]+)(?::0*(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?(?:[/?#]|$)|[hH][tT][tT][pP]://([lL][oO][cC][aA][lL][hH][oO][sS][tT]|127\.(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){2}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])|\[::1\])(?::0*(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?([/?#]|$))urilength <= 2048hero_url?stringHero image URL, for templates that reference branding.hero_url. The
bundled default template does not use it.
^([hH][tT][tT][pP][sS]://(?:\[[0-9A-Fa-f:.]+\]|[^/:?#@]+)(?::0*(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?(?:[/?#]|$)|[hH][tT][tT][pP]://([lL][oO][cC][aA][lL][hH][oO][sS][tT]|127\.(?:(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])\.){2}(?:25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])|\[::1\])(?::0*(?:[0-9]|[1-9][0-9]{1,3}|[1-5][0-9]{4}|6[0-4][0-9]{3}|65[0-4][0-9]{2}|655[0-2][0-9]|6553[0-5]))?([/?#]|$))urilength <= 2048theme?The theme sides this project publishes, and which of them may run.
Publishing one side makes it the only theme that resolves, even under auto
or an operating-system preference for the other. Publishing both lets auto
follow the operating system, each side using its own logo and palette.
The element-level theme property overrides mode. When one side is
published it cannot select the other. Publishing neither side leaves
mode, the theme property and the operating system to pick one, painted
with the maintained defaults.
typography?The typeface the login surface renders in. One face covers both body and headings; separate heading and mono faces are not modelled yet.
shape?Corner rounding, spacing and logo size. Shared across theme sides.
The branding revision was created successfully.
application/json- response
A stored branding revision. branding echoes the canonical stored
configuration so clients (e.g. the CLI sync engine) can reconcile local
files with the server's stored state.
id*stringThe unique identifier of this branding revision.
created_at*stringWhen this revision was published.
date-timebranding*Branding configuration, used in two places with one shape: as the request
body of POST /branding, which publishes it as a new immutable revision,
and as a read-only projection on flow responses, which carries the
project's latest revision. Locally it is the .zitadel/branding/ descriptor
that zitadel apply publishes.
Every field is optional. An omitted key uses Zitadel's maintained default, so a revision carrying one colour is as valid as one carrying the whole object.
import { createZitadelClient } from "@zitadel/api/client";const client = createZitadelClient({ baseUrl: process.env.ZITADEL_URL ?? "http://localhost:8080", token: process.env.ZITADEL_PROJECT_SECRET!, // server-side only});const branding = await client.createBranding({}, { project_id: "proj_01KWH1P4MYS7F0N9WD3P2E4YM5" });{ "id": "string", "created_at": "2019-08-24T14:15:22Z", "branding": { "$schema": "string", "layout": "centered", "liquid_template": "string", "logo_url": "http://example.com", "hero_url": "http://example.com", "theme": { "mode": "light", "light": { "logo_url": "http://example.com", "palette": { "primary": "#4F46E5", "on_primary": "#4F46E5", "background": "#4F46E5", "surface": "#4F46E5", "muted": "#4F46E5", "border": "#4F46E5", "text": "#4F46E5", "text_muted": "#4F46E5", "link": "#4F46E5", "success": "#4F46E5", "warning": "#4F46E5", "error": "#4F46E5" } }, "dark": { "logo_url": "http://example.com", "palette": { "primary": "#4F46E5", "on_primary": "#4F46E5", "background": "#4F46E5", "surface": "#4F46E5", "muted": "#4F46E5", "border": "#4F46E5", "text": "#4F46E5", "text_muted": "#4F46E5", "link": "#4F46E5", "success": "#4F46E5", "warning": "#4F46E5", "error": "#4F46E5" } } }, "typography": { "font_family": "string", "font_url": "http://example.com", "scale": 0.75 }, "shape": { "radius": "none", "density": "compact", "logo_scale": 0.5 } }}Was this helpful?