WhatsApp Configuration
appsettings.json, HTTP client behavior, and how the node registers itself
appsettings.json
The integration services layer reads its HTTP client settings from a WhatsApp section in
application settings:
"WhatsApp": {
"ApiVersion": "v22.0",
"GraphApiBaseUrl": "https://graph.facebook.com",
"TimeoutSeconds": 30,
"MaxMediaUploadSizeBytes": 16777216,
"MaxRateLimitRetries": 3,
"MaxRateLimitDelaySeconds": 60
}
| Key | Type | Default | Description |
|---|---|---|---|
ApiVersion | text | v22.0 | Graph API version segment used to build the base URL. |
GraphApiBaseUrl | text | https://graph.facebook.com | Base host for all Cloud API calls. The effective base URL is {GraphApiBaseUrl}/{ApiVersion}. |
TimeoutSeconds | number | 30 | Per-request HTTP client timeout applied to every WhatsApp typed HttpClient. |
MaxMediaUploadSizeBytes | number | 16777216 (16 MB) | Client-side ceiling matching WhatsApp's own media upload limit. See Media Operations. |
MaxRateLimitRetries | number | 3 | Retry attempts the rate-limit handler makes on HTTP 429 before giving up. |
MaxRateLimitDelaySeconds | number | 60 | Cap applied to the Retry-After delay reported by the Graph API. |
Automatic 429 handling:
WhatsAppRateLimitHandler is attached to every WhatsApp
HttpClient as a DelegatingHandler. On HTTP 429 it reads the Retry-After
header, waits (capped at MaxRateLimitDelaySeconds), and retries the same request — up to
MaxRateLimitRetries times — before surfacing the 429 to the caller. This is transparent; no
workflow configuration is needed to benefit from it.
Registration
WhatsAppDependency.RegisterDefaults(services) (or the extension method
services.AddWhatsAppNodeExecutor()) registers everything the node needs:
WhatsAppRateLimitHandler(transient)- A typed
HttpClientper resource service (message, media, template, profile, phone, QR code, group, commerce), each with the configured timeout and the rate-limit handler attached - The executor itself, scoped
- The
ExecutorRegistryentry forwhatsapp
Host apps must also add an explicit registration call: alongside the standard DI
registration, add
new WhatsAppDependency().RegisterDefaults(services); to your node-plugin
bootstrap so the assembly is force-loaded and discoverable at runtime. Without this line the node type
won't appear in the workflow designer even though the package is referenced.
Project Layout
The node ships as three .NET 9 projects:
| Project | Responsibility |
|---|---|
BizFirst.Integration.WhatsApp.Domain | Sealed result records (message, media, template, profile, phone, QR code, group, commerce) and webhook trigger event records. Zero external dependencies. |
BizFirst.Integration.WhatsApp.Services | One typed HttpClient-backed service per resource, the rate-limit handler, and WhatsAppConfiguration. |
BizFirst.Ai.ExecutionNodes.WhatsApp | The executor: operation routing (_ExecuteInternal_Route_Async), per-operation settings DTOs (Main/Features/<Resource>/<Operation>/), credential resolution, and validation helpers. |