Obexal Docs

Docs/Administration/Branding and white-label

Branding and sign-in methods

Give the sign-in page your tenant's name, brand color and self-hosted logo, and choose which sign-in methods it offers.

Each tenant brands its own sign-in experience: organization name, brand color and logo, plus the sign-in methods the page offers. Branding is edited in the console (Organization settings, with a live preview of the sign-in page) or over the API with the tenant:manage permission. It applies on accounts.obexal.com and, identically, on your custom domain.

Name and brand color

The tenant name and the branding blob are updated with PATCH /v1/admin/tenant. The brand color lives under the branding.primary key (a hex code) and tints the buttons and accents of the sign-in page:

curl -X PATCH https://accounts.obexal.com/v1/admin/tenant \
  -H "Authorization: Bearer $OBX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Acme SAS","branding":{"primary":"#0e7490"}}'
# 200 {"tenant":{"id":"...","name":"Acme SAS","slug":"acme","branding":{"primary":"#0e7490"},...}}

The console shows a live preview of the sign-in page as you edit the color, before you save.

The logo, self-hosted

The logo is uploaded directly to the platform (self-hosted object storage, no third-party CDN in the sign-in path). Send the raw image bytes:

curl -X PUT https://accounts.obexal.com/v1/admin/tenant/logo \
  -H "Authorization: Bearer $OBX_TOKEN" \
  --data-binary @logo.png
# 200 {"tenant":{...,"branding":{...,"logoUrl":"https://accounts.obexal.com/v1/tenants/acme/logo?v=..."},...}}

The constraints are strict, and deliberate:

RuleWhy
PNG, JPEG or WebP onlyFormat is detected from the bytes, never from your Content-Type header
512 KB maximumLarger uploads are rejected with 413
2000 px maximum per side (PNG/JPEG)Guards against decompression bombs
SVG refusedAn SVG can embed script: an XSS surface when served from the platform origin
One file per tenantUploading again replaces the previous logo in place

On success, branding.logoUrl is set to a versioned URL (?v=<etag>), so browser and proxy caches pick up a new logo immediately. The logo is served publicly at GET /v1/tenants/{slug}/logo with long-lived caching. DELETE /v1/admin/tenant/logo removes the file and clears branding.logoUrl.

Note

If you need a vector logo, host the SVG on your own domain and reference it from your site; the sign-in page logo itself is raster only.

Sign-in methods per tenant

Two flags in the branding blob control what the sign-in page offers. Both are off by default:

KeyEffect when true
branding.allowSelfSignupShows the account creation link; otherwise the directory is invitation only
branding.allowPasswordlessShows the passwordless sign-in option (email code or magic link)
curl -X PATCH https://accounts.obexal.com/v1/admin/tenant \
  -H "Authorization: Bearer $OBX_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"branding":{"primary":"#0e7490","allowPasswordless":true}}'

What is published, and what stays fixed

The sign-in page reads your branding from a public endpoint, by slug or by verified custom domain:

curl https://accounts.obexal.com/v1/tenants/acme/branding
# {"name":"Acme SAS","slug":"acme","branding":{"primary":"#0e7490","logoUrl":"..."},
#  "allowSignup":false,"allowPasswordless":true}

Two honest boundaries:

  • Output allowlist: only known theming keys (primary, primaryHover, primaryFg, bg, surface, fg, muted, border, danger, radius, logoUrl) are published. Anything else you store in the branding blob stays private.
  • Security colors stay fixed: the brand color tints buttons and accents, but the semantic colors of security states (success and warning indicators) are set by the platform and cannot be rebranded. A warning must look like a warning on every tenant.