So senden Sie WhatsApp-Nachrichten mit der Cloud API
21. Mai 2026
·
20 Min. Lesezeit
Sections: API fundamentals · Text message · Template with variables · Image & document · Interactive buttons · Location · Bulk sending with rate limiting · Error handling & retry · Full class wrappers (Node / Python / PHP)
API fundamentals: the one endpoint everything goes through
Every outbound WhatsApp message — regardless of type — goes through one HTTP POST endpoint. The message type and content are in the JSON body. That's it. No WebSockets, no streaming, no long-polling.
API Endpoint
POST https://graph.facebook.com/v21.0/{PHONE_NUMBER_ID}/messages
Authorization: Bearer {ACCESS_TOKEN}
Content-Type: application/json
// PHONE_NUMBER_ID — numeric ID for your WhatsApp number (NOT the phone number itself)// Find it: Meta Developer Dashboard → WhatsApp → Phone Numbers// ACCESS_TOKEN — permanent System User token// Find it: Meta Business Settings → System Users → Generate Token
Three values you need before any code runs:
Phone Number ID — a numeric ID for your WhatsApp Business number (looks like 123456789012345). Different from your actual phone number.
Access Token — a permanent System User token with whatsapp_business_messaging permission. Never use a temporary user token in production.
Recipient phone number — in E.164 format: country code + number, no spaces, no dashes, no plus sign in the JSON value (e.g. 15550001234 for a US number, or with + is also accepted: +15550001234).
A successful send returns HTTP 200 with a body like:
Success Response
{
"messaging_product": "whatsapp",
"contacts": [{ "input": "+15550001234", "wa_id": "15550001234" }],
"messages": [{ "id": "wamid.HBgL..." }] // store this for delivery status tracking
}
Message types: session vs template
Before picking a message type, you need to know whether you're inside a service window. The session window (24h after a customer messages you, or 72h after a Click-to-WhatsApp ad click) determines which message types are free and unrestricted.
💬
text
Plain text. Markdown-like WhatsApp formatting supported. Up to 4,096 chars.
Free in window
📋
template
Pre-approved format with variable slots. Required to initiate contact outside window.
Approval required
🖼️
image
JPEG or PNG. Max 5MB. URL or media ID. Optional caption.
Free in window
📄
document
PDF, DOCX, XLSX. Max 100MB. URL or media ID. Filename shown.
Free in window
🎬
video
MP4 or 3GPP. Max 16MB. URL or media ID. Optional caption.
Free in window
🔘
interactive
Button replies (max 3) or list messages (max 10 items). Customer taps to reply.
Free in window
📍
location
Send lat/lng with optional name and address. Renders on map in WhatsApp.
Free in window
🎵
audio
MP3 or AAC. Max 16MB. URL or media ID. No caption supported.
Free in window
Send a text message
The simplest send. Works inside the 24-hour service window at no Meta charge (within the 1,000 free service conversations/month quota). Outside the window, use a template instead.
Node.js (native fetch)
sendText.js
async functionsendText(to, message) {
const url = `https://graph.facebook.com/v21.0/${process.env.WA_PHONE_ID}/messages`;
const res = awaitfetch(url, {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.WA_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
messaging_product: 'whatsapp',
recipient_type: 'individual',
to,
type: 'text',
text: { body: message, preview_url: false },
}),
});
if (!res.ok) throw newError(`WhatsApp error: ${await res.text()}`);
return (await res.json()).messages[0].id; // wamid — store for status tracking
}
// Usageconst messageId = awaitsendText('+15550001234', 'Hello from WhatsApp Cloud API! 👋');
Templates are required for the first message in a new conversation, or any message sent outside the 24-hour service window. Templates are defined in WhatsApp Manager, approved by Meta, and can include {{1}}{{2}} variable placeholders. Your API call fills those variables at send time.
Template approval timing: Simple utility templates (order confirmations, shipping updates) typically approve in 1–24 hours. Marketing templates take 1–5 business days. You can check approval status via the message_template_status_update webhook subscription or in WhatsApp Manager. Templates with rejected status cannot be sent — sending a non-APPROVED template returns a 400 error.
Media messages reference a file either by URL (the file must be publicly accessible via HTTPS) or by a Media ID (obtained after uploading the file to Meta's media endpoint). URL is simpler for most use cases — the Cloud API fetches and caches it. Media IDs are better for frequently reused assets like product images or branded PDFs.
Node.js
sendMedia.js
// Send image by public URLasync functionsendImage(to, imageUrl, caption = '') {
returnsendMedia(to, 'image', { link: imageUrl, caption });
}
// Send document by public URLasync functionsendDocument(to, docUrl, filename, caption = '') {
returnsendMedia(to, 'document', { link: docUrl, filename, caption });
}
// Generic media sender — works for image, video, audio, documentasync functionsendMedia(to, type, mediaObj) {
const res = awaitfetch(
`https://graph.facebook.com/v21.0/${process.env.WA_PHONE_ID}/messages`,
{
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.WA_TOKEN}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
messaging_product: 'whatsapp',
to,
type,
[type]: mediaObj, // { link, caption } OR { id, caption }
}),
}
);
if (!res.ok) throw newError(`Media send failed: ${await res.text()}`);
return (await res.json()).messages[0].id;
}
// UsageawaitsendImage('+15550001234', 'https://yourdomain.com/promo.jpg', 'Check out our new product! 🚀');
awaitsendDocument('+15550001234', 'https://yourdomain.com/invoice.pdf', 'invoice-2026.pdf');
Interactive button messages let customers reply with a tap instead of typing. Maximum 3 buttons per message. Button titles are limited to 20 characters. When a customer taps a button, your webhook receives an interactive type message with the button's id value in msg.interactive.button_reply.id.
Location messages render as a map pin in WhatsApp with an optional name and address below it. Customers can tap to open in their maps app. No URL or media ID needed — just coordinates.
The WhatsApp Cloud API allows 80 messages per second per phone number by default. At that rate, sending 10,000 messages takes about 2 minutes. Without rate limiting, a naive loop exhausts the limit almost immediately and you start getting 429 errors mid-campaign. The right pattern: add a fixed delay between sends and implement exponential backoff on 429s.
Sending messages is only half the picture. When your customer replies, the WhatsApp Cloud API fires a webhook to your server — but you need a publicly reachable HTTPS endpoint to receive it, plus HMAC-SHA256 signature verification, nested payload extraction, and retry handling.
SocialHook handles the entire inbound layer. Connect your WhatsApp number to SocialHook, paste your server's URL as the destination, and every customer reply arrives as a normalized JSON event — verified, extracted from Meta's nested envelope, and forwarded to your endpoint in under 50ms. The same flat format works for Facebook Messenger and Instagram DMs too.
The complete setup: your server uses the WhatsAppClient above for outbound, SocialHook delivers inbound events to your webhook handler. Two directions, one flat $50/month. See the full inbound webhook guide or start with the 5-minute quickstart.
FAQ
Common questions
How do I send a WhatsApp message using the Cloud API?
POST to https://graph.facebook.com/v21.0/{PHONE_NUMBER_ID}/messages with your Authorization: Bearer {ACCESS_TOKEN} header and a JSON body with messaging_product: "whatsapp", to: "+E.164_number", type: "text", and text: { body: "message" }. Full code for Node.js, Python, and PHP is in the text message section above.
What is the WhatsApp Phone Number ID and where do I find it?
The Phone Number ID is a numeric identifier for your specific WhatsApp Business number on the Cloud API — it's different from the actual phone number. Find it in the Meta Developer Dashboard → WhatsApp → Phone Numbers. It looks like a 15-16 digit number. Use it in the URL: graph.facebook.com/v21.0/{PHONE_NUMBER_ID}/messages. One phone number has one ID that never changes.
What is the difference between a session message and a template message?
A session message (text, image, buttons, location, document) can only be sent within the 24-hour service window that opens when a customer messages you first. These are free within the monthly quota. A template message is a Meta-approved format required for initiating new conversations or sending outside the service window. Templates must be approved (1–24 hours for utility, up to 5 days for marketing) before you can send them.
What happens when I get a 429 from the WhatsApp Cloud API?
You've hit the rate limit (80 msg/s default). Implement exponential backoff: wait 1000 * 2^attempt + random(500) ms before retrying, capped at 60 seconds. Add jitter (the random component) to prevent synchronized retries from multiple workers. For bulk campaigns, add a fixed 15–20ms delay between sends to stay safely below the limit rather than hitting it and retrying.
How do I send a WhatsApp template with variables in Python?
Set "type": "template" and include a components array with a body component containing parameters — one object per variable in your template. Each parameter is {"type": "text", "text": "variable_value"}. They map sequentially to {{1}}, {{2}}, {{3}} in your template. Full Python code is in the template message section above.
How do I receive WhatsApp message replies from customers?
Customer replies arrive via webhook — Meta fires an HTTP POST to your registered endpoint when any message event occurs. You need a publicly reachable HTTPS URL, HMAC-SHA256 signature verification, and nested payload parsing. SocialHook handles all of this automatically and delivers clean JSON to your endpoint in under 50ms. See the complete setup in our inbound webhook guide.
Your outbound code is ready. Connect SocialHook for inbound — every customer reply arrives as clean JSON at your webhook endpoint. No HMAC boilerplate, no nested payload parsing, no retry infrastructure to build.
Aufhören, Meta APIs zu verwalten. Anfangen zu bauen.
Verbinde dein erstes Facebook-, Instagram- oder WhatsApp-Konto in unter 2 Minuten. Dein Webhook erhält sein erstes Payload, bevor dein Kaffee kalt wird.