Setup and Deployment
WApi can be brought into service within hours on a typical Windows or Linux server. Below is the reference
configuration for a Windows + Caddy + SQL Server setup.
Prerequisites
- .NET 10 SDK (for building) + .NET 10 ASP.NET Core Runtime (for running)
- SQL Server 2019+ (LocalDB, on-prem, Docker or Azure SQL)
- Reverse proxy (recommended: Caddy, for automatic TLS)
- Node.js 22 LTS for real WhatsApp sending (for the sidecar; adding it to the system PATH is not required)
1 · Publish the API as a Windows Service
# 1. Build + publish (framework-dependent; the .NET 10 runtime must be on the server)
dotnet publish src/WApi.Api -c Release -o C:\.MyApps\Wapi\Api
# 2. Write the production appsettings next to the binaries (ConnectionStrings, Security:MasterKey, ...)
# Lock the file down with restricted access:
icacls C:\.MyApps\Wapi\Api\appsettings.Production.json /inheritance:r `
/grant:r "NT AUTHORITY\SYSTEM:R" "BUILTIN\Administrators:F"
# 3. Create the service
sc.exe create WApi.Api binPath= "\"C:\.MyApps\Wapi\Api\WApi.Api.exe\" `
--contentRoot \"C:\.MyApps\Wapi\Api\" --urls \"http://127.0.0.1:2785\"" `
start= auto obj= LocalSystem DisplayName= "WApi — WhatsApp API Gateway"
# 4. Set the production environment as a registry env-var
New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\WApi.Api `
-Name Environment -PropertyType MultiString `
-Value @("ASPNETCORE_ENVIRONMENT=Production","DOTNET_ENVIRONMENT=Production") -Force
Start-Service WApi.Api
2 · TLS and reverse proxy with Caddy
wapi.example.com {
encode zstd gzip
header {
Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
X-Content-Type-Options "nosniff"
Referrer-Policy "strict-origin-when-cross-origin"
}
# For SignalR long-lived connections
@signalr path /api/events*
handle @signalr {
reverse_proxy 127.0.0.1:2785 {
flush_interval -1
stream_close_delay 5m
transport http { keepalive 60s }
}
}
reverse_proxy 127.0.0.1:2785
}
3 · node-bridge sidecar for real WhatsApp
In a production setup, the nodebridge/ folder runs as a separate Windows Service (e.g. with WinSW),
brings up Baileys and listens on loopback at 127.0.0.1:2787. WApi.Api reaches it with a shared
WAPI_BRIDGE_TOKEN bearer. appsettings.Production.json:
{
"Engine": { "Type": "node-bridge" },
"NodeBridge": {
"BaseUrl": "http://127.0.0.1:2787",
"Token": "",
"TimeoutSeconds": 60
}
}
The sidecar keeps a separate auth state folder for each session using Baileys' useMultiFileAuthState mechanism.
When the service restarts, the credentials are loaded from this folder; no rescan is needed.
4 · Whole stack in one command with Docker
To bring up SQL Server + API + Dashboard with a single compose file:
docker compose up --build
# API: http://localhost:2785/api/docs
# Dashboard: http://localhost:2886