4. Configuration
4.1 Platform-Wide Configuration — WhatsAppCloudApi Section
Bound from appsettings.json's WhatsAppCloudApi section into WhatsAppCloudApiOptions via
services.AddWhatsAppIntegration(config) (Shumoul.Infrastructure/Extensions/ServiceCollectionExtensions.cs).
| Key | Type | Default | Purpose |
|---|---|---|---|
WhatsAppCloudApi:VerifyToken | string | (empty) | Shared secret Meta echoes back during the webhook GET verification handshake |
WhatsAppCloudApi:AppSecret | string | (empty) | Meta App secret — HMAC-SHA256 key for X-Hub-Signature-256 webhook signature validation |
WhatsAppCloudApi:SignatureValidationEnabled | bool | true | Gate for webhook signature enforcement — never disable in production |
WhatsAppCloudApi:LogRawPayload | bool | false | Debug-only — logs raw webhook JSON; must stay false in production (payloads can contain customer message content) |
WhatsAppCloudApi:AccessToken | string | (empty) | Meta Cloud API long-lived access token for the platform's own WhatsApp Business number |
WhatsAppCloudApi:PhoneNumberId | string | (empty) | Meta registered phone number ID for the platform's own number |
WhatsAppCloudApi:BusinessAccountId | string | (empty) | Meta business account ID |
WhatsAppCloudApi:GraphApiVersion | string | v25.0 | Graph API version segment used in every outbound URL — centralized as of Phase 1 Runtime Consolidation |
WhatsAppCloudApi:BaseUrl | string | https://graph.facebook.com | Graph API base URL |
Environment variable form (double-underscore, ASP.NET Core convention — this is the form actually used in this codebase, not colon-separated):
WhatsAppCloudApi__VerifyToken
WhatsAppCloudApi__AppSecret
WhatsAppCloudApi__AccessToken
WhatsAppCloudApi__PhoneNumberId
WhatsAppCloudApi__BusinessAccountId
No secret values are reproduced here or anywhere in this guide.
4.2 SecretsManifest Relationship
Shumoul.Application/Secrets/SecretsManifest.cs declares the platform's canonical list of externally-sourced
secrets, consumed by SecretsHealthCheck at startup. It lists exactly five WhatsApp-related entries:
| Environment Variable | Required | Production-Required | Rotation Supported | Description |
|---|---|---|---|---|
WhatsAppCloudApi__VerifyToken | No | Yes | Yes | Meta webhook verify token |
WhatsAppCloudApi__AppSecret | No | Yes | No | Meta App secret for webhook HMAC-SHA256 validation |
WhatsAppCloudApi__AccessToken | No | Yes | Yes | Meta Cloud API long-lived access token |
WhatsAppCloudApi__PhoneNumberId | No | Yes | No | Meta registered phone number ID |
WhatsAppCloudApi__BusinessAccountId | No | Yes | No | Meta business account ID |
"Production-Required" means the health check flags a missing value as a startup warning in Production, even
though the value is not strictly Required at the framework level (WhatsApp can be entirely disabled for a
deployment that doesn't use it).
4.3 Tenant-Scoped Credentials — WhatsAppOperationalSettings
Read per-tenant via IAppSettingService.GetAppSetting<WhatsAppOperationalSettings>() — never hardcoded, never
shared across tenants:
| Property | Default | Purpose |
|---|---|---|
EnableWhatsApp | true | Master switch for the tenant |
EnableWhatsAppOtp | true | Enables OTP delivery via WhatsApp |
EnableWhatsAppNotifications | true | Enables Notification Framework WhatsApp channel dispatch |
EnableWhatsAppTemplates | true | Gate for template-based sends |
EnableWhatsAppActivationForFreeSubscriptions | false | Whether free-tier tenants get an activation WhatsApp message |
WhatsAppTenantActivationTemplateNameAr / ...En | welcome_activation_ar / welcome_activation_en | Activation template names |
WhatsAppTenantActivationDefaultLanguageCode | ar | Fallback language for activation messages |
WhatsAppTenantOtpTemplateNameAr / ...En | otp_verification_ar / otp_verification_en | OTP template names |
WhatsAppTenantOtpLanguageDefault | ar | Fallback language for OTP messages |
WhatsAppTenantOtpIncludeUrlButton | true | Whether the OTP template includes a URL button component reusing the OTP code |
EnableSending | false | Master switch for the tenant's own Meta Business number (Communication module) |
PhoneNumberId / BusinessAccountId / AccessToken / AppSecret / VerifyToken | (empty) | The tenant's own Meta credentials, used only by the Communication module's TenantWhatsAppSender |
DefaultLanguage | ar | Default template language for tenant document sends |
DefaultTemplatePrefix | send_document | Prefix used when resolving a document-type-specific template name |
TemplateLanguageStrategy | ByRecipientLanguage | WhatsAppTemplateLanguageStrategy enum — see §16 Appendix |
WebhookEnabled | false | Whether this tenant's own number has webhook delivery configured |
Important nuance: the OTP and Activation message services actually resolve their template names from a
different, platform-level settings class, SaaSNotificationSettings (bound via IOptions<T>, not
tenant-scoped) — not from WhatsAppOperationalSettings. The two classes have similarly-named properties for
different purposes: WhatsAppOperationalSettings governs the tenant's own WhatsApp Business number (used
by the Communication module only); SaaSNotificationSettings governs the platform's WhatsApp number used
for OTP/activation to every tenant's end customers.
4.4 Graph API Version — One Source of Truth
As of the Phase 1 Runtime Consolidation, every outbound Meta call in the solution reads
GraphApiVersion/BaseUrl from the same IOptions<WhatsAppCloudApiOptions> — including
TenantWhatsAppSender, which previously hardcoded v19.0. There is exactly one place to change the Graph
API version platform-wide: the WhatsAppCloudApi:GraphApiVersion configuration key.
