Skip to main content

Patterns

Multi-tenant branding for emails and PDFs

Logo, primary colour and footer per tenant and sub-tenant

Branding (`branding`) customises the logo, primary colour and texts (footer, signature) applied to transactional emails and emitted PDFs, per tenant AND per sub-tenant. The `brand_email_enabled` toggle enables/disables branding on emails; `computed_email_footer` exposes the actually-rendered footer (computed fallback when empty). Email logo upload uses a dedicated multipart endpoint (`uploadLogo`/`uploadLogoFile`), stored separately from the invoice logo (invoice templates). Key pattern: an HTML/PDF preview with NON-persisted overrides (`preview(overrides)`) lets you test a colour or footer before saving. Colours can be auto-derived from the email logo (`POST /invoice-templates/derive-colors-from-email-logo`). The `branding.subTenants.*` sub-path applies the same contract to a sub-tenant (anti-IDOR by scope).

Key facts

  • Branding per tenant AND per sub-tenant (anti-IDOR scope)
  • `brand_email_enabled` toggle + `computed_email_footer` (read-only)
  • Email logo stored separately from invoice logo (templates)
  • HTML/PDF preview with non-persisted overrides: `preview(overrides)`
  • Colours derivable from logo: `derive-colors-from-email-logo`
  • Endpoints: `/api/v1/branding/tenant/*` and `/branding/sub-tenants/{id}/*`

Code example

import { ScellApiClient } from '@scell/sdk'; // v3.5.0

const client = new ScellApiClient({ apiKey: process.env.SCELL_API_KEY! });

// 1. Lire la configuration de marque du tenant
const branding = await client.branding.tenant.get();
console.log('Footer rendu :', branding.computed_email_footer);

// 2. Uploader un logo email (presigned S3, séparé du logo facture)
const { url, public_url } = await client.branding.tenant.uploadLogo('image/png');
// PUT le binaire vers `url` côté client, puis :
await client.branding.tenant.update({ brand_logo_url: public_url, brand_primary_color: '#0066FF' });

// 3. Aperçu HTML AVANT de sauvegarder (overrides non persistés)
const draftHtml = await client.branding.tenant.preview({
  brand_primary_color: '#10B981',
  brand_email_footer: 'Brouillon — Ma SAS, SIRET 12345678901234',
});

// 4. Désactiver le branding sur les emails transactionnels
await client.branding.tenant.update({ brand_email_enabled: false });

// 5. Brander un sub-tenant (même contrat, scope isolé)
await client.branding.subTenants.update('sub-tenant-uuid', { brand_primary_color: '#2E7D32' });

See also

Your cookie preferences

We use cookies to improve your experience. Essential cookies are always active. Cookie policy.