Resolve the effective branding for your tenant
One read returns the branding your dashboard, hosted sign-in page, and white-label surfaces should render with. The resolver walks a three-step chain — your own settings first, your reseller parent second, the platform default theme last — and answers it in one envelope so no surface needs a second round-trip. Two auth paths reach the same resolver. With a tenant API key you passX-API-Key and resolve your own tenant; an unsigned render — the white-labelled sign-in page before anyone logs in — passes X-Tenant-Host instead, with no key. Both calls below hit GET /api/v1/branding/effective and return the same envelope shape.
null, which signals “fall back to the platform default theme.”
Resolution chain
- Tenant override wins. Fields you set directly — under Settings → Branding in the dashboard, or via the organization branding API — are self-authoritative.
- Reseller parent fills the gaps. For a subaccount with
inherits_from_parent: true, any unset field is pulled from the parent organization.inherited_from_organization_idnames the org that supplied values, andinherited_fieldsmaps each inherited field to that org, so the dashboard can badge “Inherited from Acme HQ.” - Null means platform default. A field still
nullafter both steps renders with the unbranded default theme — the merger never invents a value.
help_logo_url, help_primary_color, help_secondary_color, help_header_links, help_show_powered_by) are returned on the same record; they control the public help center and join the chain exactly like the dashboard fields.
When branding cannot be resolved — a transient database blip, or a subdomain that is still provisioning — the read still returns 200 with every field nulled, so the shell your authenticating user is waiting on never fails to render.
The response carries
Cache-Control: private, max-age=60. Cache it for a minute per client rather than polling on every render.Custom domains before a session exists
The same resolution powers your white-labelled sign-in page. The page passes its domain inX-Tenant-Host — no API key — and receives the resolved branding of the tenant that registered that domain, so custom.acme.example.com shows your logo and palette before anyone signs in.
X-API-Key — the header that identifies the tenant is X-Tenant-Host, and the response’s custom_domain names the registered domain it resolved to. The unsigned path is IP-rate-limited at a lower ceiling than authenticated calls; the resolution chain above is unchanged.
Unsigned resolution — response example
WhenX-Tenant-Host resolves to an active tenant domain, the resolver returns the full effective branding envelope. For a subaccount mirroring a parent reseller, inherited_from_organization_id points to the providing parent organization and inherits_from_parent is true:
Unknown or unprovisioned host — 200 with nulls
When the domain passed inX-Tenant-Host is not registered to an active tenant, or when branding cannot be resolved during a database blip, the endpoint returns HTTP 200 with every field nulled rather than failing. The authenticating user’s browser shell falls back cleanly to the platform default theme:
Rate-limit on the unsigned path — 429 envelope
BecauseX-Tenant-Host is unauthenticated and resolves domains before a session exists, it is rate-limited by caller IP (RATE_LIMIT_PUBLIC_UNAUTH: 10 requests per minute). Exceeding this limit returns HTTP 429: