Reference
alter branding
Read and update an app's branding / theming config.
Branding controls how the Connect widget looks for an app (logo, colors, font). These commands read and update it; the visual editor in the dashboard is usually the easier way to author a theme. Branding does not restyle the Wallet — see Wallet.
alter branding get --app <app-id-or-name>alter branding set --app <app-id-or-name> --input <@file|-> [--replace]alter branding reset --app <app-id-or-name> [--yes]All commands are app-scoped — pass --app <id> (or the app’s name), or link a workspace / set ALTER_APP_ID. get needs dashboard_branding:read; set / reset need dashboard_branding:write. Branding is recoverable config — reset restores Alter defaults, and can be undone by setting it again on a plan that includes custom branding (see below).
alter branding getAccepts --output <format> (json, jsonl, or table; default json).
Update branding from a JSON body. Two verbs mirror the dashboard’s branding editor:
- default (PATCH) — a partial merge-update of an existing config; fields you omit are left unchanged. If no branding is configured yet, the command exits
2(usage) with a hint to re-run with--replace. Note this is not the4(NOT_FOUND) the exit-code table lists for a 404: the missing config is a fixable input problem, not an absent resource, so a script branching on4to mean “create it” never fires. --replace(PUT) — create or fully replace branding. Use this for initial setup; it requireslogo_urlplus all three colors (primary,text,background).font_familyis optional.
The input is parsed as JSON locally. Any supplied primary, text, or
background color must use #RRGGBB. A body that supplies logo_url must
also supply all three colors, and a body that supplies all three colors must
also supply logo_url; these correlated checks run before the request.
logo_url accepts either an https:// URL to a hosted image (2,048 characters
max) or a small inline data:image/{png|jpeg|webp};base64,… image, up to
150,000 characters of data URI (about 110 KB decoded).
Accepted inline formats are PNG, JPEG, and WebP; the dashboard’s upload
control emits a downscaled PNG. SVG is not accepted inline (a hosted https://
URL may still point at an SVG file).
A hosted https:// URL must carry no embedded credentials (user:pass@, or a
bare @ in the authority) and no quotes, angle brackets, backticks,
backslashes, whitespace or control characters — percent-encode any of those.
It must resolve to a public network address; loopback, link-local, private and
reserved destinations are rejected.
The CLI applies these rules locally and exits 2 before the request, so a
malformed address fails immediately rather than as a server-side 422.
font_family takes a CSS font stack whose first name selects the web font
to load — a Google Fonts family or a system font; any remaining names are
passed through as the fallback stack. Letters, digits, spaces, hyphens, commas and dots only, 200 characters
max; quotes are rejected, so write Inter, sans-serif rather than
'Inter', sans-serif. Common Google Fonts names are matched regardless of
casing, and fonts are served from Alter’s own origin (no third-party request
is made from an end user’s browser).
Logo preflight
Section titled “Logo preflight”When logo_url is a hosted https:// address, the save fetches it and reports
whether it is actually a displayable image. The verdict comes back on the
response as logo_preflight and is printed to stderr, so it survives
--output table and piping stdout through jq:
| Status | Meaning |
|---|---|
passed | Fetched, and the content type is a displayable image. |
failed | Demonstrably not displayable — the address serves a web page, or the image is not there. The most common cause is pasting a page URL whose image sits behind a # fragment the server never sees. |
inconclusive | Could not be verified — a redirect that is deliberately not followed, a 403 from hotlink protection, or a transient fault. |
skipped | No fetch was needed — an uploaded data URI, or a logo that did not change. |
Ordinary image verdicts never block the save. A wrong logo makes the page look
wrong, and an operator mid-rebrand whose asset is about to be published should
not be locked out. failed is reported loudly and the branding is still stored.
A private or blocked destination is the exception: it is rejected before the
write so a Connect page cannot make an end user’s browser request that user’s
network.
set requires a plan that includes custom branding (Starter and above). On a
plan without it the command exits 7 (forbidden) and prints the plan requirement.
reset is always available, so an organization that downgrades can still
clear custom branding it can no longer edit. The dashboard equivalent is
documented in Setting up your app.
| Flag | Required | Description |
|---|---|---|
--input <path> | yes | JSON branding body from a file (@/path/to/branding.json) or stdin (-). |
--replace | no | Create or fully replace branding (PUT) instead of merge-updating (PATCH). |
--output <format> | no | json (default), jsonl, or table. |
# First-time setup (create):alter branding set --replace --input @branding.json# Later tweak (merge-update an existing config):alter branding set --input @branding.jsonReset branding to Alter defaults. Reversible on a plan that includes custom branding — re-run set to restore a custom theme. reset itself is available on every plan, so a downgraded organization can always clear branding it can no longer edit.
| Flag | Default | Description |
|---|---|---|
--yes | off | Skip the interactive confirmation prompt (for CI). |
alter branding reset --yes