Platforms
Connect a WhatsApp Business number, send templates and replies, run broadcasts, flows, groups and calls, and know the 24-hour window and tier rules.
WhatsApp in Pozy runs on Meta's WhatsApp Business Platform. You connect a WhatsApp Business number to a profile, then message customers from the Inbox API, send broadcasts, and use templates, flows, groups and calling. The platform id is whatsapp.
This page is the summary. The WhatsApp section has a page for each feature.
#What you can do
| Feature | Supported | Where |
|---|---|---|
| Text, media, documents, audio and voice notes | Yes | Sending messages |
| Templates (marketing, utility, authentication) | Yes | Templates |
| Interactive messages (lists, buttons, CTA links, flows) | Yes | Flows |
| Broadcasts, scheduled | Yes | Broadcasts |
| Group chats | Yes, on Cloud API only numbers | Groups |
| Voice calling, inbound and outbound | Yes, on Cloud API only numbers | Calling |
| AI business agent | Yes | Business agent |
| Free test number | Yes | Sandbox |
| Click-to-WhatsApp ads | Yes | Meta Ads |
| Scheduling a single message | No | Schedule a broadcast instead |
| Post analytics, comments | No | Delivery and read status per message only |
#Two rules that shape every send
The 24-hour window. For 24 hours after a customer's last message you can send them anything. Outside that window, the first message must be an approved template. A free-form message outside the window fails with Meta's error 131047.
The messaging tier. A new number starts on Meta's lowest tier: 250 unique contacts in 24 hours for business-initiated conversations. Meta raises the tier as you build history and keep quality up. Quality and tier changes arrive as the whatsapp.account.quality_updated webhook.
#Connect
You need a WhatsApp Business Account inside a Meta Business account. A personal WhatsApp account cannot be connected. If the business has no WhatsApp Business Account yet, Meta creates one during signup. There are three ways in:
| Route | When to use it | How |
|---|---|---|
| Meta's Embedded Signup | The business connects its own number in the browser | Get OAuth connect URL with platform whatsapp |
| System User token | You already manage the WhatsApp Business Account in Meta and want a headless connect | Connect WhatsApp via credentials with accessToken, wabaId and phoneNumberId |
| A number bought through Pozy | You want a new number that can also carry calls and SMS | WhatsApp phone numbers |
curl "https://api.pozy.ai/v1/connect/whatsapp?profileId=66a1f0c2a4b9d3e8f1a2b3c4&redirect_url=https://app.example.com/connected&onboarding=api" \
-H "Authorization: Bearer $POZY_API_KEY"const res = await fetch("https://api.pozy.ai/v1/connect/whatsapp?profileId=66a1f0c2a4b9d3e8f1a2b3c4&redirect_url=https:%2F%2Fapp.example.com%2Fconnected&onboarding=api", {
headers: { Authorization: `Bearer ${process.env.POZY_API_KEY}` },
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
// Send the user's browser to data.authUrlimport os, requests
resp = requests.get(
"https://api.pozy.ai/v1/connect/whatsapp",
headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
params={"profileId": "66a1f0c2a4b9d3e8f1a2b3c4", "redirect_url": "https://app.example.com/connected", "onboarding": "api"},
)
print(resp.json()["authUrl"])The user lands back on redirect_url with the new accountId, which every WhatsApp call takes from then on.
#Cloud API only or coexistence
onboarding decides whether the number keeps working in the WhatsApp Business app on the phone:
onboarding |
What happens | Trade-off |
|---|---|---|
business_app (the default when you leave it out) |
Coexistence. The number stays in the WhatsApp Business app and also works on the API. The user scans a QR code Meta shows during signup | Throughput fixed at 20 messages per second. No group chats, no calling. Meta has no API to leave coexistence later |
api |
Cloud API only. The number is used through the API | Full throughput, groups and calling available |
A profile can hold several WhatsApp numbers, each its own account. One number can be live on one profile only. If the user picks a number that conflicts, they come back to your redirect_url with an error such as one_whatsapp_per_profile, whatsapp_number_pinned_to_profile or whatsapp_number_already_connected. See Connect WhatsApp for each fix and for the full signup walkthrough.
#Sending messages
A new conversation starts with a template through Create conversation. Replies inside the 24-hour window use Send message.
curl -X POST https://api.pozy.ai/v1/inbox/conversations \
-H "Authorization: Bearer $POZY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"participantId": "+13105551234",
"templateName": "order_shipped",
"templateLanguage": "en_US",
"templateParams": ["Maria", "A-10423"]
}'const res = await fetch("https://api.pozy.ai/v1/inbox/conversations", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.POZY_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
accountId: "66b2e19d8c3f5a7e9d0b1c2d",
participantId: "+13105551234",
templateName: "order_shipped",
templateLanguage: "en_US",
templateParams: ["Maria", "A-10423"],
}),
});
const data = await res.json();
if (!res.ok) throw new Error(data.error);
console.log(data.data.conversationId);resp = requests.post(
"https://api.pozy.ai/v1/inbox/conversations",
headers={"Authorization": f"Bearer {os.environ['POZY_API_KEY']}"},
json={
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"participantId": "+13105551234",
"templateName": "order_shipped",
"templateLanguage": "en_US",
"templateParams": ["Maria", "A-10423"],
},
)
print(resp.json()["data"]["conversationId"])Once the customer replies, send free-form messages to that conversationId:
{
"accountId": "66b2e19d8c3f5a7e9d0b1c2d",
"message": "Your parcel is with the courier. Tracking link below.",
"attachmentUrl": "https://pozy.ai/media/label.pdf",
"attachmentType": "file"
}What a message can carry:
| Type | How |
|---|---|
| Text | message. Links get a preview unless linkPreview: false |
| Image, video, audio, document | attachmentUrl and attachmentType (image, video, audio, file) |
| Voice note | An OGG (Opus, mono) audio attachment with voiceNote: true |
| Template | template with name, language and components, or the templateName fields on create |
| Interactive | interactive with a type such as list, cta_url, flow, location_request_message, voice_call, product, carousel |
Send an Idempotency-Key header so a retry never sends twice. See Idempotency.
#Media requirements
| Type | Formats | Max size |
|---|---|---|
| Images | JPEG, PNG | 5 MB |
| Videos | MP4, 3GPP (H.264 video, AAC audio) | 16 MB |
| Documents | PDF, DOC, DOCX, XLS, XLSX, PPT, PPTX, TXT | 100 MB |
| Audio | MP3, OGG (Opus), AMR, AAC | 16 MB |
Every URL must be public with no login and return the file, not a web page. Use Media to host files.
#Limits
| Limit | Value |
|---|---|
| Free-form messages | Only inside the 24-hour customer service window |
| New number tier | 250 unique contacts in 24 hours, raised by Meta over time |
| Messages to one recipient | About 10 a minute before Meta throttles that recipient |
| Coexistence throughput | 20 messages per second |
| Recipients | Must be on WhatsApp, written in E.164 (for example +13105551234) |
#Analytics
WhatsApp has no post analytics. Delivery is tracked per message and per broadcast recipient through the message.delivered, message.read and message.failed webhooks. Conversation volume and response times are in Inbox analytics.
#Inbox
WhatsApp conversations live in the same Inbox as every other channel. Contacts, custom fields and automations such as workflows and sequences work on WhatsApp. There are no comments.
#Pricing
WhatsApp has two billers:
- Pozy bills the connected account, outbound messages past the monthly free allowance, numbers you buy through Pozy, and the carrier leg of outbound calls.
- Meta bills template delivery and its per-minute calling fee straight to the WhatsApp Business Account. Meta needs a payment method on that account, or it stops delivering templates once the free tier runs out.
See WhatsApp pricing and Pricing.
#Errors you may see
| Error | Cause | Fix |
|---|---|---|
| 131047 "Re-engagement message" | The 24-hour window closed | Send an approved template |
| 132001 "Template not found" | Name or language does not match | Use the exact name and language code (en is not en_US) |
| 131021 "Invalid phone number" | Malformed number or not on WhatsApp | Use E.164 with the country code |
| 131026 "Message undeliverable" | The recipient cannot receive it, or Meta is holding back marketing messages to them | Check the number. If other messages deliver, send it as a utility template |
| 131056 "Too many messages sent to this recipient" | More than about 10 a minute to one person | Pace sends per recipient |
| 131052 "Media download failed" | WhatsApp could not fetch the media URL | Serve the file from a public URL |
| 131031 "Account locked" | Meta suspended the WhatsApp Business Account | Contact Meta support |
(#200) permission error on every send |
The number has a two-step PIN that was not registered | Register the number with its PIN |
A message that was accepted and later fails arrives as message.failed with the same Meta code. Errors covers Pozy's error format.
#Endpoints
| Endpoint | What it does |
|---|---|
GET /v1/connect/{platform} |
Get OAuth connect URL |
POST /v1/connect/whatsapp/credentials |
Connect WhatsApp via credentials |
GET /v1/connect/whatsapp/select-phone-number |
List numbers for selection |
POST /v1/connect/whatsapp/select-phone-number |
Complete number selection |
POST /v1/inbox/conversations |
Create conversation |
POST /v1/inbox/conversations/{conversationId}/messages |
Send message |
GET /v1/whatsapp/templates |
List templates |
POST /v1/whatsapp/templates |
Create template |
POST /v1/broadcasts |
Create broadcast draft |
POST /v1/broadcasts/{broadcastId}/send |
Send broadcast now |
GET /v1/whatsapp/business-profile |
Get business profile |
POST /v1/whatsapp/business-profile |
Update business profile |
POST /v1/accounts/{accountId}/whatsapp/register |
Register a connected WhatsApp number on the Cloud API |
The full list is in the API reference.
#Webhook events
| Event | When it fires |
|---|---|
message.received |
Message received. |
conversation.started |
Conversation started. |
message.sent |
Message sent. |
message.edited |
Message edited. |
message.deleted |
Message deleted. |
message.delivered |
Message delivered. |
message.read |
Message read. |
message.played |
Message played. |
message.failed |
Message delivery failed. |
whatsapp.template.status_updated |
WhatsApp template status updated. |
whatsapp.template.category_updated |
WhatsApp template category updated. |
whatsapp.account.quality_updated |
WhatsApp quality rating or messaging limit changed. |
whatsapp.account.status_updated |
WhatsApp Business Account restricted or reinstated. |
whatsapp.account.alert_received |
WhatsApp account alert received. |
whatsapp.account.name_status_updated |
WhatsApp display-name review outcome. |