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' });