VB.NET Send WhatsApp Message via Cloud API (2026)
You can send WhatsApp messages from VB.NET using the official WhatsApp Cloud API and a simple HttpClient request. No third-party library required. This guide covers setup, sending text messages, template messages, handling responses, batch sending, and a Twilio alternative with complete code examples.
Inhaltsverzeichnis
What you need
Before writing any code, you need three things from Meta:
- Meta Business Account with a registered app at developers.facebook.com
- Phone Number ID from the WhatsApp section in your app dashboard
- Access Token (temporary for testing, permanent via System User for production)
Meta provides a free test phone number and five test recipient numbers. You can send real messages during development without any cost.
How the WhatsApp Cloud API works
The WhatsApp Cloud API is a REST API hosted by Meta. Your VB.NET application sends an HTTP POST request with a JSON body to Meta’s servers. Meta then delivers the message to the recipient’s WhatsApp app. The flow is:
- Your app sends a POST request to
https://graph.facebook.com/v20.0/{phone_number_id}/messages - Meta validates your token, phone number, and message format
- Meta delivers the message via WhatsApp servers
- You receive a JSON response with the message ID or an error
There is one important rule: you can only send template messages to users who have not messaged you in the last 24 hours. Free-form text messages are only allowed within a 24-hour conversation window. For most notification use cases (order confirmations, alerts, reminders), template messages are what you need.
Sending a text message
This is the simplest example. It sends a plain text message to a single recipient inside an active conversation window:
Imports System.Net.Http
Imports System.Text
Private Async Function SendWhatsAppMessage(recipientPhone As String, message As String) As Task(Of Boolean)
Dim phoneNumberId As String = "YOUR_PHONE_NUMBER_ID"
Dim accessToken As String = "YOUR_ACCESS_TOKEN"
Dim url As String = $"https://graph.facebook.com/v20.0/{phoneNumberId}/messages"
Dim json As String = "{" &
"""messaging_product"": ""whatsapp""," &
"""to"": """ & recipientPhone & """," &
"""type"": ""text""," &
"""text"": {""body"": """ & message & """}" &
"}"
Using client As New HttpClient()
client.DefaultRequestHeaders.Add("Authorization", "Bearer " & accessToken)
Dim content As New StringContent(json, Encoding.UTF8, "application/json")
Dim response = Await client.PostAsync(url, content)
Return response.IsSuccessStatusCode
End Using
End Function
Call it from a button click or any event handler:
Private Async Sub btnSend_Click(sender As Object, e As EventArgs) Handles btnSend.Click
Dim success = Await SendWhatsAppMessage("491234567890", "Your order has been shipped.")
If success Then
lblStatus.Text = "Message sent."
Else
lblStatus.Text = "Failed to send message."
End If
End Sub
The phone number must include the country code without a plus sign or leading zeros. For a German number like +49 123 4567890, use 491234567890.
Sending a template message
Template messages are pre-approved message formats that you create in your Meta Business dashboard. They are required for sending the first message to a user or for messages outside the 24-hour window:
Private Async Function SendTemplateMessage(recipientPhone As String, templateName As String) As Task(Of Boolean)
Dim phoneNumberId As String = "YOUR_PHONE_NUMBER_ID"
Dim accessToken As String = "YOUR_ACCESS_TOKEN"
Dim url As String = $"https://graph.facebook.com/v20.0/{phoneNumberId}/messages"
Dim json As String = "{" &
"""messaging_product"": ""whatsapp""," &
"""to"": """ & recipientPhone & """," &
"""type"": ""template""," &
"""template"": {" &
"""name"": """ & templateName & """," &
"""language"": {""code"": ""en_US""}" &
"}" &
"}"
Using client As New HttpClient()
client.DefaultRequestHeaders.Add("Authorization", "Bearer " & accessToken)
Dim content As New StringContent(json, Encoding.UTF8, "application/json")
Dim response = Await client.PostAsync(url, content)
Return response.IsSuccessStatusCode
End Using
End Function
Meta provides a default template called hello_world for testing. Create your own templates in the WhatsApp Manager section of your Meta Business dashboard. Templates can include variables like {{1}} that you fill with dynamic content at send time.
Template message with variables
Most real templates include placeholders for customer names, order numbers, or dates. Here is how to send a template with variable parameters:
Private Async Function SendOrderConfirmation(phone As String, customerName As String, orderId As String) As Task(Of Boolean)
Dim phoneNumberId As String = "YOUR_PHONE_NUMBER_ID"
Dim accessToken As String = "YOUR_ACCESS_TOKEN"
Dim url As String = $"https://graph.facebook.com/v20.0/{phoneNumberId}/messages"
' Template "order_confirmation" with two body parameters
Dim json As String = "{" &
"""messaging_product"": ""whatsapp""," &
"""to"": """ & phone & """," &
"""type"": ""template""," &
"""template"": {" &
"""name"": ""order_confirmation""," &
"""language"": {""code"": ""en_US""}," &
"""components"": [{" &
"""type"": ""body""," &
"""parameters"": [" &
"{""type"": ""text"", ""text"": """ & customerName & """}," &
"{""type"": ""text"", ""text"": """ & orderId & """}" &
"]" &
"}]" &
"}" &
"}"
Using client As New HttpClient()
client.DefaultRequestHeaders.Add("Authorization", "Bearer " & accessToken)
Dim content As New StringContent(json, Encoding.UTF8, "application/json")
Dim response = Await client.PostAsync(url, content)
Return response.IsSuccessStatusCode
End Using
End Function
The parameters fill the {{1}}, {{2}} placeholders in your template in order. Make sure the number of parameters matches what the template expects.
Reading the API response
A successful response returns a JSON object with the message ID. An error returns a structured error object. Here is how to read both:
Private Async Function SendAndLog(recipientPhone As String, message As String) As Task
Dim phoneNumberId As String = "YOUR_PHONE_NUMBER_ID"
Dim accessToken As String = "YOUR_ACCESS_TOKEN"
Dim url As String = $"https://graph.facebook.com/v20.0/{phoneNumberId}/messages"
Dim json As String = "{" &
"""messaging_product"": ""whatsapp""," &
"""to"": """ & recipientPhone & """," &
"""type"": ""text""," &
"""text"": {""body"": """ & message & """}" &
"}"
Using client As New HttpClient()
client.DefaultRequestHeaders.Add("Authorization", "Bearer " & accessToken)
Dim content As New StringContent(json, Encoding.UTF8, "application/json")
Dim response = Await client.PostAsync(url, content)
Dim body = Await response.Content.ReadAsStringAsync()
If response.IsSuccessStatusCode Then
' body contains: {"messaging_product":"whatsapp","contacts":[...],"messages":[{"id":"wamid.xxx"}]}
Console.WriteLine("Sent. Response: " & body)
Else
' body contains: {"error":{"message":"...","type":"...","code":100,...}}
Console.WriteLine("Error " & response.StatusCode.ToString() & ": " & body)
End If
End Using
End Function
For production applications, log the response body to a file for debugging. See the VB.NET write text file guide for file logging patterns.
Sending to multiple recipients
The WhatsApp API accepts one recipient per request. To send to multiple numbers, loop through a VB.NET List of phone numbers:
Private Async Function SendToMultiple(phones As List(Of String), message As String) As Task
Dim successCount As Integer = 0
Dim failCount As Integer = 0
For Each phone In phones
Dim success = Await SendWhatsAppMessage(phone, message)
If success Then
successCount += 1
Else
failCount += 1
End If
' Respect rate limits: max 80 messages per second for Business API
Await Task.Delay(50)
Next
Console.WriteLine($"Sent: {successCount}, Failed: {failCount}")
End Function
The Task.Delay(50) adds a small pause between requests to stay within the API rate limit. For large batches (thousands of messages), consider queuing messages and processing them in the background.
Storing credentials safely
Never hardcode your access token in source code. For desktop applications, store credentials in an external config file or environment variables:
' Read from App.config or environment variable
Dim accessToken As String = Environment.GetEnvironmentVariable("WHATSAPP_TOKEN")
Dim phoneNumberId As String = Environment.GetEnvironmentVariable("WHATSAPP_PHONE_ID")
If String.IsNullOrEmpty(accessToken) OrElse String.IsNullOrEmpty(phoneNumberId) Then
MessageBox.Show("WhatsApp credentials not configured.", "Configuration Error",
MessageBoxButtons.OK, MessageBoxIcon.Error)
Return
End If
Set environment variables on the machine running your app, or use My.Settings with user-scoped settings for per-user configuration.
Using Twilio as an alternative
If you prefer a simpler SDK over raw HTTP requests, Twilio offers a WhatsApp integration with a .NET NuGet package. Install Twilio via NuGet, then:
Imports Twilio
Imports Twilio.Rest.Api.V2010.Account
' Initialize once at app startup
TwilioClient.Init("YOUR_ACCOUNT_SID", "YOUR_AUTH_TOKEN")
' Send a message
Dim msg = MessageResource.Create(
body:="Your order has been shipped.",
from:=New Twilio.Types.PhoneNumber("whatsapp:+14155238886"),
[to]:=New Twilio.Types.PhoneNumber("whatsapp:+491234567890")
)
Console.WriteLine("Message SID: " & msg.Sid)
Twilio costs money per message but handles rate limiting, retries, and delivery tracking for you. The direct Meta API is free (you only pay for conversations after the free tier), but you handle everything yourself.
Common mistakes
Sending free-form text outside the 24-hour window
The API returns error code 131047 if you try to send a text message to someone who has not messaged you in the last 24 hours. Use a template message instead. Template messages work anytime and are the standard approach for notifications.
Wrong phone number format
The API expects the full international number without a plus sign, spaces, or dashes. 491234567890 is correct. +49 123 456 7890, 01234567890, or 0049-123-4567890 will fail. Strip all formatting before sending:
Dim cleanPhone = phone.Replace("+", "").Replace(" ", "").Replace("-", "")
Hardcoding the access token
Temporary tokens expire after 24 hours. If you hardcode one and forget to update it, your app silently stops sending. Use a permanent System User token for production and store it in environment variables or a secure config file, never in source code.
FAQ
Meta offers 1,000 free service conversations per month. Beyond that, you pay per conversation (not per message). Template messages for notifications cost a small fee per conversation, varying by country. Development and testing with the sandbox number is free.
Technically you could automate WhatsApp Web with Selenium, but this violates WhatsApp’s terms of service and can get your number banned. The official Cloud API or a provider like Twilio are the only reliable and compliant options.
A text message is free-form content you can only send during an active 24-hour conversation window. A template message is a pre-approved format registered in your Meta dashboard that can be sent anytime, including to users who have not contacted you first.
You need a phone number that is not already registered with WhatsApp or WhatsApp Business App. Meta provides a free test number for development. For production, register a dedicated business number in the Meta Business dashboard.
Yes, but it requires a webhook. Meta sends incoming messages to a public HTTPS endpoint you configure. For a desktop VB.NET app, you would need a server component (ASP.NET or a cloud function) that receives the webhook and forwards messages to your app.
Wrapping up
Sending WhatsApp messages from VB.NET comes down to a single HttpClient.PostAsync call to Meta’s Cloud API. Use template messages for notifications, store your token securely, and clean phone numbers before sending. For simpler integration at higher cost, Twilio wraps the same functionality in a NuGet package. For logging API responses to a file, see the VB.NET write text file guide.