# Telnyx Messaging: WhatsApp — Full Documentation > Complete page content for WhatsApp (Messaging section) of the Telnyx developer docs (https://developers.telnyx.com). > Root index: https://developers.telnyx.com/llms.txt · Lightweight index for this subsection: https://telnyx-openapi-ng.s3.us-east-1.amazonaws.com/llms/messaging/whatsapp.txt ## Getting Started ### Quickstart > Source: https://developers.telnyx.com/docs/messaging/whatsapp/quickstart.md # Send Your First WhatsApp Message Get started with WhatsApp Business messaging via Telnyx in minutes. This guide covers account setup, template creation, and sending your first message with delivery confirmation. ## Prerequisites Before sending WhatsApp messages, ensure you have: - **Telnyx Account** — [Sign up](https://telnyx.com/sign-up) and verify your account - **Meta Business Manager Account** — Required for WhatsApp Business Platform access - **WhatsApp Business Account (WABA)** — Connected via Telnyx's Embedded Signup - **Verified phone number** — Added to your WABA and verified with Meta WhatsApp Business Platform requires business verification through Meta's process. Personal WhatsApp accounts cannot send template messages via the API. 1. Create a [Telnyx account](https://telnyx.com/sign-up) and verify your email 2. Navigate to the [Portal](https://portal.telnyx.com) and complete account verification 3. Add billing information to enable message sending 4. Generate an API key from **Developer Center → API Keys → Create API Key** Store your API key securely — you'll need it for all API requests. Complete the WhatsApp Embedded Signup to connect your Meta Business Manager: 1. Navigate to **Messaging → WhatsApp** in the Telnyx Portal 2. Click **Connect WhatsApp Business Account** 3. Sign in with your Facebook Business Manager credentials 4. Select the Business Manager account to connect 5. Follow Meta's prompts to create or select a WhatsApp Business Account 6. Verify your business phone number when prompted Use a Telnyx number with an active messaging profile that you haven't used with personal WhatsApp. The embedded signup flow currently requires Telnyx-owned numbers — bring-your-own-number is not yet supported through the portal. If you're registering a landline number, choose **phone call verification** instead of SMS when prompted. SMS delivery to landline numbers can be unreliable — call verification is more consistent. WhatsApp requires pre-approved templates for outbound marketing and notifications: Set a display name for the phone number before submitting templates. Templates submitted from numbers without an approved display name are rejected by Meta. When a template contains parameters (e.g., `\{\{1\}\}`), provide sample values in the `example` field. Meta reviewers use these to evaluate the template. Without sample values, templates are typically rejected. Complete the business profile (website, description, industry category) before submitting templates. Incomplete profiles increase rejection rates, especially for new WhatsApp Business Accounts. Create a message template using the API: ```bash cURL curl -X POST "https://api.telnyx.com/v2/whatsapp/message_templates" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "welcome_message", "category": "MARKETING", "language": "en_US", "waba_id": "YOUR_WABA_ID", "components": [ { "type": "BODY", "text": "Hello {{1}}! Welcome to our WhatsApp updates.", "example": { "body_text": [["John"]] } } ] }' ``` ```javascript JavaScript import Telnyx from 'telnyx'; const client = new Telnyx({apiKey: 'YOUR_API_KEY'}); const template = await client.whatsapp.templates.create({ name: 'welcome_message', category: 'MARKETING', language: 'en_US', waba_id: 'YOUR_WABA_ID', components: [ { type: 'BODY', text: 'Hello {{1}}! Welcome to our WhatsApp updates.', example: { body_text: [['John']] } } ] }); ``` ```python Python from telnyx import Telnyx client = Telnyx(api_key='YOUR_API_KEY') template = client.whatsapp.templates.create( name='welcome_message', category='MARKETING', language='en_US', waba_id='YOUR_WABA_ID', components=[ { 'type': 'BODY', 'text': 'Hello {{1}}! Welcome to our WhatsApp updates.', 'example': { 'body_text': [['John']] } } ] ) ``` ```ruby Ruby require 'telnyx' telnyx.whatsapp.templates.create( name: 'welcome_message', category: 'MARKETING', language: 'en_US', waba_id: 'YOUR_WABA_ID', components: [ { type: 'BODY', text: 'Hello {{1}}! Welcome to our WhatsApp updates.', example: { body_text: [['John']] } } ] ) ``` Meta typically reviews templates within 24-48 hours. You'll receive an email when approved. Start with simple templates for faster approval. Avoid promotional language or special characters in your first template. Once your template is approved, send your first message: ```bash cURL curl -X POST "https://api.telnyx.com/v2/messages/whatsapp" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "template", "template": { "name": "welcome_message", "language": { "policy": "deterministic", "code": "en_US" }, "components": [ { "type": "body", "parameters": [ { "type": "text", "text": "John" } ] } ] } } }' ``` ```python Python from telnyx import Telnyx client = Telnyx(api_key='YOUR_API_KEY') response = client.messages.send_whatsapp( from_="+15551234567", to="+15557654321", whatsapp_message={ "type": "template", "template": { "name": "welcome_message", "language": { "policy": "deterministic", "code": "en_US" }, "components": [ { "type": "body", "parameters": [ { "type": "text", "text": "John" } ] } ] } } ) print(f"Message ID: {response.data.id}") print(f"Status: {response.data.to[0].status}") ``` ```javascript Node.js import Telnyx from 'telnyx'; const client = new Telnyx({apiKey: 'YOUR_API_KEY'}); const message = await client.messages.sendWhatsapp({ from: '+15551234567', to: '+15557654321', whatsapp_message: { type: 'template', template: { name: 'welcome_message', language: { policy: 'deterministic', code: 'en_US' }, components: [ { type: 'body', parameters: [ { type: 'text', text: 'John' } ] } ] } } }); console.log(`Message ID: ${message.data.id}`); console.log(`Status: ${message.data.to[0].status}`); ``` ```ruby Ruby require 'telnyx' response = telnyx.messages.send_whatsapp( from: '+15551234567', to: '+15557654321', whatsapp_message: { type: 'template', template: { name: 'welcome_message', language: { policy: 'deterministic', code: 'en_US' }, components: [ { type: 'body', parameters: [ { type: 'text', text: 'John' } ] } ] } } ) puts "Message ID: #{response.data.id}" puts "Status: #{response.data.to[0].status}" ``` ```go Go package main import ( "context" "fmt" "github.com/team-telnyx/telnyx-go/v2" ) func main() { client := telnyx.NewAPIClient(telnyx.NewConfiguration()) client.GetConfig().AddDefaultHeader("Authorization", "Bearer YOUR_API_KEY") parameters := []telnyx.TemplateParameter{ { Type: telnyx.PtrString("text"), Text: telnyx.PtrString("John"), }, } components := []telnyx.TemplateComponent{ { Type: telnyx.PtrString("body"), Parameters: parameters, }, } template := telnyx.WhatsAppTemplate{ Name: telnyx.PtrString("welcome_message"), Language: &telnyx.TemplateLanguage{ Policy: telnyx.PtrString("deterministic"), Code: telnyx.PtrString("en_US"), }, Components: components, } whatsappMessage := telnyx.WhatsAppMessageContent{ Type: telnyx.PtrString("template"), Template: &template, } params := telnyx.MessageSendWhatsappParams{ From: "+15551234567", To: "+15557654321", WhatsappMessage: whatsappMessage, } response, err := client.Messages.SendWhatsapp(context.TODO(), params) if err != nil { panic(err) } fmt.Printf("Message ID: %s\n", response.Data.Id) fmt.Printf("Status: %s\n", response.Data.To[0].Status) } ``` ```java Java import com.telnyx.sdk.ApiClient; import com.telnyx.sdk.ApiException; import com.telnyx.sdk.Configuration; import com.telnyx.sdk.auth.HttpBearerAuth; import com.telnyx.sdk.api.MessagesApi; import com.telnyx.sdk.model.*; import java.util.Arrays; public class WhatsAppQuickstart { public static void main(String[] args) { ApiClient defaultClient = Configuration.getDefaultApiClient(); HttpBearerAuth bearerAuth = (HttpBearerAuth) defaultClient.getAuthentication("bearerAuth"); bearerAuth.setBearerToken("YOUR_API_KEY"); MessagesApi apiInstance = new MessagesApi(defaultClient); TemplateParameter parameter = new TemplateParameter() .type("text") .text("John"); TemplateComponent component = new TemplateComponent() .type("body") .parameters(Arrays.asList(parameter)); TemplateLanguage language = new TemplateLanguage() .policy("deterministic") .code("en_US"); WhatsAppTemplate template = new WhatsAppTemplate() .name("welcome_message") .language(language) .components(Arrays.asList(component)); WhatsAppMessageContent whatsappMessage = new WhatsAppMessageContent() .type("template") .template(template); MessageSendWhatsappRequest request = new MessageSendWhatsappRequest() .from("+15551234567") .to("+15557654321") .whatsappMessage(whatsappMessage); try { var result = apiInstance.sendWhatsapp(request); System.out.println("Message ID: " + result.getData().getId()); System.out.println("Status: " + result.getData().getTo().get(0).getStatus()); } catch (ApiException e) { System.err.println("Exception: " + e.getResponseBody()); } } } ``` The messaging profile is automatically resolved from your WhatsApp-enabled phone number specified in the `from` field. Configure webhooks to receive real-time delivery status updates: 1. In the Telnyx Portal, navigate to **Messaging → Messaging Profiles** 2. Select your messaging profile 3. Set **Webhook URL** to your endpoint (e.g., `https://yourapp.com/webhooks/telnyx`) 4. Enable **Failover URL** for redundancy (optional) 5. Save the configuration Your webhook endpoint will receive delivery reports and inbound message notifications. ```json { "data": { "event_type": "message.sent", "id": "msg_123abc", "occurred_at": "2023-01-01T12:00:00.000Z", "payload": { "id": "msg_123abc", "type": "whatsapp", "to": "+15557654321", "from": "+15551234567", "text": "Hello John! Welcome to our WhatsApp updates.", "direction": "outbound", "parts": 1, "tags": [], "messaging_profile_id": "your_messaging_profile_id", "billing_type": "whatsapp_marketing", "valid_until": "2023-01-01T12:30:00.000Z" } } } ``` Implement webhook handling to track message status and respond to inbound messages: ```python Python from flask import Flask, request, jsonify import hmac import hashlib app = Flask(__name__) @app.route('/webhooks/telnyx', methods=['POST']) def handle_webhook(): webhook_data = request.json event_type = webhook_data['data']['event_type'] payload = webhook_data['data']['payload'] if event_type == 'message.sent': print(f"WhatsApp message sent: {payload['id']}") print(f"Status: {payload.get('to', [{}])[0].get('status', 'unknown')}") elif event_type == 'message.received': print(f"WhatsApp message received: {payload['text']}") print(f"From: {payload['from']}") # Auto-reply during 24-hour window reply_to_customer(payload['from'], payload['to']) return '', 200 def reply_to_customer(customer_number, business_number): from telnyx import Telnyx client = Telnyx(api_key="YOUR_API_KEY") # Send free-form message (no template required in 24hr window) client.messages.send_whatsapp( from_=business_number, to=customer_number, whatsapp_message={ "type": "text", "text": { "body": "Thanks for your message! We'll get back to you soon.", "preview_url": False } } ) if __name__ == '__main__': app.run(debug=True) ``` ```javascript Node.js const express = require('express'); import Telnyx from 'telnyx'; const client = new Telnyx({apiKey: 'YOUR_API_KEY'}); const app = express(); app.use(express.json()); app.post('/webhooks/telnyx', async (req, res) => { const { data } = req.body; const { event_type, payload } = data; if (event_type === 'message.sent') { console.log(`WhatsApp message sent: ${payload.id}`); console.log(`Status: ${payload.to[0]?.status || 'unknown'}`); } else if (event_type === 'message.received') { console.log(`WhatsApp message received: ${payload.text}`); console.log(`From: ${payload.from}`); // Auto-reply during 24-hour window await replyToCustomer(payload.from, payload.to); } res.status(200).send(); }); async function replyToCustomer(customerNumber, businessNumber) { try { await client.messages.sendWhatsapp({ from: businessNumber, to: customerNumber, whatsapp_message: { type: 'text', text: { body: "Thanks for your message! We'll get back to you soon.", preview_url: false } } }); } catch (error) { console.error('Error sending reply:', error); } } app.listen(3000, () => { console.log('Webhook server listening on port 3000'); }); ``` ## Verify Message Delivery Check message delivery through multiple channels: ### Portal Dashboard 1. Navigate to **Messaging → Message Logs** in the Telnyx Portal 2. Filter by **Channel: WhatsApp** and **Date Range** 3. View delivery status, timestamps, and any error codes 4. Click individual messages for detailed delivery information ### Webhook Events Monitor these key webhook events: - `message.sent` — Message successfully submitted to WhatsApp - `message.delivered` — Message delivered to recipient's device - `message.read` — Recipient opened and read the message (when enabled by recipient) - `message.failed` — Message delivery failed (with error details) ### API Response The initial API response includes: ```json { "data": { "id": "msg_123abc", "to": [ { "phone_number": "+15557654321", "status": "queued", "carrier": "WhatsApp" } ] } } ``` ## Common Issues **Symptoms:** API returns a `40008` error indicating the template was not found or not approved **Solutions:** - Verify template status in Portal under **Messaging → WhatsApp → Send Messages** - Ensure template name matches exactly (case-sensitive) - Wait for Meta's approval (typically 24-48 hours for first templates) - Review Meta's template guidelines for approval requirements **Symptoms:** API returns a `40008` error indicating the sender phone number is not registered with WhatsApp **Solutions:** - Complete phone number verification in the Telnyx Portal - Ensure number is added to your WhatsApp Business Account - Verify the number through Meta's verification process - Check that the number hasn't been used with personal WhatsApp **Symptoms:** Free-form (session) message fails with a `40008` error. WhatsApp requires a template to initiate conversations outside the 24-hour window **Solutions:** - Use approved message templates for outbound messaging - Only send free-form messages within 24 hours of customer's last message - Check conversation window status via webhook events - Consider switching to template-based messaging for customer re-engagement **Symptoms:** Message status webhook returns `undeliverable` with Meta API error details in the response **Solutions:** - Verify recipient has WhatsApp installed and active - Ensure phone number format includes country code (+1...) - Check that recipient hasn't blocked your business number - Confirm recipient's WhatsApp account is not banned or restricted ## Next Steps Send templates, text, media, and interactive messages Set up your WhatsApp Business Account and verify your number Handle inbound messages and delivery status callbacks --- ### Embedded Signup > Source: https://developers.telnyx.com/docs/messaging/whatsapp/embedded-signup.md # WhatsApp Embedded Signup WhatsApp Embedded Signup enables businesses to connect their Facebook Business Manager account to Telnyx and provision WhatsApp Business Account (WABA) resources through a streamlined browser-based workflow. ## Prerequisites Before starting the embedded signup process: **Required account status:** - Active Telnyx account with messaging enabled - Valid payment method configured - Account in good standing with no billing issues **Portal access:** - Log in to [Telnyx Portal](https://portal.telnyx.com) - Navigate to **Messaging** → **WhatsApp** - Ensure you have admin permissions for your organization **Business Manager requirements:** - Facebook Business Manager account ([business.facebook.com](https://business.facebook.com)) - Admin access to the Business Manager account - Business verification completed (recommended for production use) **Important limitations:** - Each phone number can only be associated with one Business Manager - Business Manager must have appropriate permissions for WhatsApp Business API - Account must comply with Facebook Business policies Ensure your Facebook Business Manager is fully set up and verified before starting embedded signup. Incomplete Business Manager setup can cause signup failures that require manual intervention. ## Signup Flow Overview The embedded signup process follows a multi-step finite state machine (FSM) that progresses through these states: ```mermaid graph LR A[initiated] --> B[facebook_auth] B --> C[waba_created] C --> D[phone_registered] D --> E[verified] B --> F[failed] C --> F D --> F E --> G[active] style A fill:#e1f5fe style E fill:#c8e6c9 style F fill:#ffcdd2 style G fill:#4caf50,color:#fff ``` Each state represents a checkpoint in the signup process with specific completion criteria and potential failure points. ## Step-by-Step Signup Process **From Telnyx Portal:** 1. Navigate to **Messaging** → **WhatsApp** → **Getting Started** 2. Click **Connect WhatsApp Business** 3. Review the permissions and requirements displayed 4. Click **Begin Setup** to start the embedded signup flow **What happens:** - Telnyx creates a signup session with state `initiated` - Portal generates a secure OAuth URL for Facebook authorization - Session tracking begins for completion monitoring **Verification:** Signup session monitoring is handled automatically by the portal. API-based signup tracking may not be available in all configurations. ```bash # Check signup session status via API curl -X GET "https://api.telnyx.com/v2/whatsapp/signup/{signup_id}/status" \ -H "Authorization: Bearer YOUR_API_KEY" # Response { "data": { "id": "signup_123abc", "state": "initiated", "created_at": "2024-01-15T10:30:00Z" } } ``` **Facebook authorization flow:** 1. Browser redirects to Facebook Business Manager OAuth consent screen 2. Review the requested permissions: - **WhatsApp Business Management** — Create and manage WABA - **Business Asset Management** — Associate phone numbers and templates - **Webhook Management** — Configure message and status webhooks 3. Click **Continue** to grant permissions 4. Select target Business Manager if you have multiple **What happens:** - Facebook validates your Business Manager admin status - OAuth token is generated and securely transmitted to Telnyx - Signup state advances to `facebook_auth` **Common issues:** - **Permission denied:** Ensure you have admin access to Business Manager - **Business not verified:** Some features require verified Business Manager - **Already connected:** Phone number may be connected to another provider **Verification:** The Portal will show "Connected to Facebook" with Business Manager details when successful. **WABA provisioning:** Telnyx automatically creates your WhatsApp Business Account using the connected Business Manager: 1. WABA is created under your Business Manager 2. Telnyx is granted the necessary permissions as a solution partner 3. Initial configuration is applied (timezone, business category) 4. Webhook endpoints are pre-configured for Telnyx integration **What happens:** - Facebook creates the WABA resource - Telnyx receives WABA credentials and configuration details - Signup state advances to `waba_created` - WABA settings are synced to Telnyx systems **WABA configuration:** - **Business category:** Inherited from Business Manager - **Webhooks:** Configured via your messaging profile webhook settings **Verification:** ```bash # List WABAs for your account curl -X GET "https://api.telnyx.com/v2/whatsapp/business_accounts" \ -H "Authorization: Bearer YOUR_API_KEY" # Response { "data": [ { "id": "waba_456def", "name": "Your Business Name", "status": "APPROVED", "waba_id": "2019979452207634" } ] } ``` **Number selection and registration:** 1. Portal displays available phone numbers from your Telnyx inventory 2. Select the phone number to register for WhatsApp 3. Choose the WABA to associate with the number 4. Confirm the registration request **Phone number requirements:** - Must be a Telnyx number with an active messaging profile assigned - Cannot be currently registered with another WhatsApp provider - Can be used alongside SMS/voice on the same number — WhatsApp uses a separate API path The embedded signup flow currently requires a Telnyx-owned number with a messaging profile. Bring-your-own-number (non-Telnyx numbers) is not yet supported through the portal signup flow. If you need to register an external number, contact support for assistance. **What happens:** - Phone number is submitted to Facebook for WhatsApp registration - Facebook begins the verification process - Signup state advances to `phone_registered` - Number status changes to "pending verification" **Registration details:** - **Number format:** E.164 format (+1234567890) - **Verification method:** Automatically determined by Facebook - **Processing time:** Usually 1-5 minutes for verification **Verification:** ```bash # Check phone number registration status curl -X GET "https://api.telnyx.com/v2/whatsapp/phone_numbers" \ -H "Authorization: Bearer YOUR_API_KEY" # Response { "data": [ { "phone_number": "+15551234567", "business_account_id": "waba_456def", "status": "pending_verification", "registered_at": "2024-01-15T11:15:00Z" } ] } ``` **Facebook verification process:** Facebook automatically verifies phone numbers using multiple methods: 1. **Carrier validation:** Facebook verifies number ownership with telecom provider 2. **SMS verification:** Test SMS may be sent to validate delivery capability 3. **API validation:** Facebook tests webhook delivery and response handling **Verification timeline:** - **Typical duration:** 1-15 minutes - **Complex cases:** Up to 24 hours for carrier validation - **Failed attempts:** May require manual review or different number **What happens:** - Facebook completes all verification checks - Number status updates to "verified" in Facebook systems - Signup state advances to `verified` - Number becomes available for sending messages **Verification methods Facebook may use:** Automated voice call to verify number is operational and accessible. **Duration:** 30 seconds **Requirements:** Number must accept incoming calls Test SMS sent to verify message delivery capability. **Message:** "Facebook verification code: [CODE]" **Requirements:** Number must receive SMS messages Direct verification with mobile carrier for number ownership. **Duration:** Instant to 24 hours **Requirements:** Carrier must support Facebook verification API **Verification completion:** ```bash # Final verification status curl -X GET "https://api.telnyx.com/v2/whatsapp/phone_numbers/+15551234567" \ -H "Authorization: Bearer YOUR_API_KEY" # Response { "data": { "phone_number": "+15551234567", "business_account_id": "waba_456def", "status": "verified", "verified_at": "2024-01-15T11:20:00Z", "enabled": true, "calling_enabled": false } } ``` ## Signup Completion When verification succeeds, your WhatsApp integration is ready: ### Account Status - **WABA Status:** Active and ready for messaging - **Phone Number:** Verified and enabled for sending/receiving - **Webhooks:** Configured and receiving events - **Templates:** Ready for submission and approval ### Next Steps After Signup Send templates, text, media, and interactive messages Send your first WhatsApp message end-to-end Handle inbound messages and delivery status callbacks ## Troubleshooting Common Issues **Error:** "You don't have permission to complete this action" **Causes:** - Not admin of Business Manager account - Business Manager doesn't have WhatsApp permissions - Account suspended or restricted **Solutions:** 1. Verify admin access in Business Manager 2. Contact Facebook Business Support if account restricted 3. Use different Business Manager account 4. Check account verification status **Error:** "Unable to create WhatsApp Business Account" **Causes:** - Business Manager doesn't meet Facebook requirements - Too many existing WABAs on Business Manager - Business policy violations **Solutions:** 1. Complete Business Manager verification 2. Review and resolve any policy violations 3. Remove unused WABAs from Business Manager 4. Contact Telnyx support with signup session ID **Error:** "This phone number is already connected to WhatsApp Business API" **Causes:** - Number registered with another Business Service Provider - Number previously registered but not properly disconnected - Number registered to different WABA **Solutions:** 1. Disconnect number from previous provider 2. Contact previous provider to release number 3. Use different phone number for registration 4. Contact Facebook Business Support for assistance **Error:** "Phone number verification failed" or timeout **Causes:** - Number doesn't support voice calls or SMS - Carrier blocking verification attempts - Number routing issues **Solutions:** 1. Verify number accepts incoming calls and SMS 2. Try different phone number if possible 3. Contact carrier to check for blocks 4. Wait and retry verification process 5. Contact Telnyx support with verification details **Error:** Webhooks not receiving events after successful signup **Causes:** - Webhook URL not properly configured - Firewall blocking webhook delivery - Invalid webhook signature verification **Solutions:** 1. Verify webhook URL accessibility from Facebook servers 2. Check webhook signature verification implementation 3. Review webhook configuration in Portal 4. Test webhook endpoint with manual POST requests 5. Check logs for delivery attempts and errors **Symptom:** Embedded signup popup fails to load, shows a blank page, or gets stuck during the Facebook OAuth step. **Causes:** - Ad blockers (uBlock Origin, Adblock Plus, etc.) blocking Facebook/Meta domains - Privacy extensions (Privacy Badger, Ghostery) blocking third-party scripts - Browser security settings blocking cross-origin popups **Solutions:** 1. Temporarily disable ad blockers and privacy extensions for the signup flow 2. Add `facebook.com` and `meta.com` domains to your extension's allowlist 3. Try using a different browser profile without extensions 4. Use Chrome Incognito mode (extensions are typically disabled by default) 5. Ensure popup blockers allow popups from the Telnyx Portal domain **Note:** The WhatsApp embedded signup flow is powered by Meta/Facebook. The OAuth consent screen and business verification steps are hosted on Facebook's servers, which means browser extensions that block Facebook domains will prevent the signup from completing. ## API Integration ### Signup Session Monitoring Monitor signup progress programmatically using the Signup API: ```bash cURL curl -X GET "https://api.telnyx.com/v2/whatsapp/signup/{signup_id}/status" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ### Webhook Events Receive real-time signup progress updates: ```json { "data": { "event_type": "whatsapp.signup.state_updated", "payload": { "signup_id": "signup_123abc", "state": "verified", "previous_state": "phone_registered", "waba_id": "waba_456def", "phone_number": "+15551234567", "occurred_at": "2024-01-15T11:20:00Z" } } } ``` --- ### Tech Provider Embedded Signup > Source: https://developers.telnyx.com/docs/messaging/whatsapp/embedded-signup/tech-provider.md WhatsApp Tech Provider Embedded Signup lets ISVs and SaaS platforms embed Meta's WhatsApp onboarding flow directly into their own portal. Your end-customers can create and register a WhatsApp Business Account (WABA), claim a phone number, and begin messaging — all without leaving your application. Unlike the [standard embedded signup flow](/docs/messaging/whatsapp/embedded-signup), which is designed for direct Telnyx customers, the Tech Provider flow is built for partners who manage multiple end-customers and need programmatic control over WABA provisioning. ## Overview As a Tech Provider, you build the onboarding experience into your own product. The end-customer clicks a button in your portal, completes Meta's embedded signup flow, and your backend receives the resulting WABA ID and phone number ID. You then register the WABA with Telnyx so that it can use Telnyx's messaging infrastructure. ```mermaid sequenceDiagram participant EndCustomer as End Customer participant PartnerPortal as Your Portal participant Meta as Meta participant Telnyx as Telnyx API EndCustomer->>PartnerPortal: Clicks "Connect WhatsApp" PartnerPortal->>Meta: Launches embedded signup (FB.login) Meta->>EndCustomer: Shows signup & business verification EndCustomer->>Meta: Completes signup Meta-->>PartnerPortal: Returns WABA ID + Phone Number ID PartnerPortal->>Telnyx: POST /whatsapp/business_accounts/tech_provider Telnyx-->>PartnerPortal: 200 OK — WABA registered Telnyx->>PartnerPortal: Credit line applied, number ready PartnerPortal->>EndCustomer: WhatsApp connected ✅ ``` ### Tech Provider vs. Direct Customer | | Tech Provider | Direct Customer | |---|---|---| | **Who uses this?** | ISVs, SaaS platforms, resellers | Individual businesses | | **Onboarding** | Embedded in your portal | Via Telnyx portal or API | | **WABA ownership** | Your end-customers own their WABAs | You own your WABA | | **API calls** | You call Telnyx on behalf of customers | You call Telnyx directly | | **Scale** | Many WABAs under one integration | One WABA per integration | ## Prerequisites Before you begin, make sure you have: - A [Meta Business Account](https://business.facebook.com/) with admin access - A **Meta Tech Provider App** that has been approved by Meta with the following permissions: - `whatsapp_business_messaging` - `whatsapp_business_management` - The Tech Provider onboarding process completed in [Meta App Dashboard](https://developers.facebook.com/apps/) - A [Telnyx account](https://telnyx.com/sign-up) with an API key All links to Meta documentation in this guide require that you are logged in to a Meta Business account. If you don't have one, create one at [business.facebook.com](https://business.facebook.com/) before proceeding. ## Step 1: Create and configure your Meta Tech Provider App Go to [Meta App Dashboard](https://developers.facebook.com/apps/) and create a new app. Select **Business** as the app type. In your app's dashboard, add the **WhatsApp** product. This will generate the permissions you need. Under **App Review > Permissions and Features**, request the following permissions: | Permission | Purpose | |---|---| | `whatsapp_business_messaging` | Send and receive WhatsApp messages on behalf of your customers | | `whatsapp_business_management` | Manage WhatsApp Business Accounts and phone numbers | Both permissions require **Advanced Access** for production use. Follow Meta's [Tech Provider onboarding guide](https://developers.facebook.com/docs/development/create-an-app/business-onboarding) to complete the Tech Provider registration process. This includes business verification and agreeing to Meta's Tech Provider terms. Submit your app for Meta's App Review. Meta will evaluate your use case and grant (or deny) the requested permissions. This process typically takes several business days. While waiting for App Review approval, you can test in **Development Mode** with your own test users. Production use requires **Live Mode** and Advanced Access permissions. ## Step 2: Link your Meta App to Telnyx Once your Meta App is configured, you need to link it to Telnyx so that WABAs created through your embedded signup flow are registered on Telnyx's infrastructure. In the [Meta App Dashboard](https://developers.facebook.com/apps/), change your app mode from **Development** to **Live**. This is required for Telnyx to initiate the partner invitation. Reach out to your Telnyx representative or contact [support](https://support.telnyx.com) and provide: - Your **Meta App ID** (found in your app's dashboard) - Your **business name** as registered with Meta Within 1–2 business days, you'll receive an email from Meta containing a partner invitation link. Click the link and accept the invitation to link your app with Telnyx. After accepting the invitation, you can switch your app back to **Development** mode for testing. The link persists regardless of the app mode. You must switch your app to **Live mode** before Telnyx can send the partner invitation. The invitation will fail if your app is in Development mode. After accepting the invite, you can switch back to Development mode for testing. ## Step 3: Implement the frontend embedded signup Meta's embedded signup flow is triggered from your web application using the Facebook JavaScript SDK. Your frontend launches the signup dialog, the end-customer completes it, and you receive the resulting credentials. Add the Facebook SDK to your web application: ```html window.fbAsyncInit = function () { FB.init({ appId: 'YOUR_APP_ID', autoLogAppEvents: true, xfbml: true, version: 'v19.0', }); }; ``` Call `FB.login()` with the `config_id` of your WhatsApp Business Configuration. This opens Meta's embedded signup dialog for your end-customer. ```javascript function launchWhatsAppSignup() { // The response_type must include 'code' and 'setup_token' FB.login( function (response) { if (response.authResponse) { const code = response.authResponse.code; // Send the code to your backend to exchange for credentials sendCodeToBackend(code); } else { console.error('User cancelled login or did not fully authorize.'); } }, { config_id: 'YOUR_CONFIG_ID', response_type: 'code', override_default_response_type: true, extras: { setup: {}, featureType: '', sessionInfoVersion: '3', }, } ); } ``` After the user completes the signup, Meta returns an authorization code. Exchange this code using Meta's API to obtain the WABA ID and phone number ID. ```bash curl -X GET \ "https://graph.facebook.com/v19.0/oauth/access_token?\ client_id=YOUR_APP_ID\ &client_secret=YOUR_APP_SECRET\ &code=AUTHORIZATION_CODE" ``` The response contains access token information. Use this access token to retrieve the WABA ID and phone number ID from the signed request or the response payload: ```json { "access_token": "EAAJc...", "token_type": "bearer", "expires_in": 5183814 } ``` From the embedded signup response, extract the two critical identifiers: | Field | Description | |---|---| | `waba_id` | The WhatsApp Business Account ID (e.g., `123456789012345`) | | `phone_number_id` | The phone number ID within that WABA (e.g., `987654321098765`) | Refer to Meta's [embedded signup documentation](https://developers.facebook.com/documentation/business-messaging/whatsapp/embedded-signup/implementation) for full details on parsing the response. You only need the **frontend (web) portion** of Meta's guide — the backend registration is handled by Telnyx in the next step. ## Step 4: Register the WABA with Telnyx Once you have the `waba_id` and `phone_number_id` from the embedded signup flow, send them to Telnyx to register the WABA and activate messaging. ### Request ```bash curl -X POST https://api.telnyx.com/v2/whatsapp/business_accounts/tech_provider \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "waba_id": "123456789012345", "phone_number_id": "987654321098765", "app_id": "123456789012345", "customer_id": "acme-corp-42" }' ``` ### Request body parameters | Parameter | Type | Required | Description | |---|---|---|---| | `waba_id` | string | Yes | The WABA ID returned by Meta's embedded signup flow | | `phone_number_id` | string | Yes | The phone number ID returned by Meta's embedded signup flow | | `app_id` | string | Yes | Your Meta App ID | | `customer_id` | string | No | An optional identifier you assign to track this customer (e.g., your internal customer ID) | This endpoint requires authentication with a Telnyx API key via the `Authorization: Bearer` header. Use an API key from your Telnyx account — you can create one in the [API Keys](https://portal.telnyx.com/#/app/api-keys) page. ### Response A successful response confirms that the WABA has been registered with Telnyx: ```json { "data": { "waba_id": "123456789012345", "phone_number_id": "987654321098765", "status": "registered", "customer_id": "acme-corp-42" } } ``` ### What happens after registration When the Telnyx API returns a successful response: 1. **Credit line is applied** — The WABA is associated with your Telnyx billing account 2. **WABA is registered** — The WhatsApp Business Account is linked to Telnyx's messaging infrastructure 3. **Number is ready for messaging** — The phone number can send and receive WhatsApp messages through Telnyx ## Troubleshooting - Verify that your app was in **Live mode** when you contacted Telnyx - Check your spam and junk folders - Ensure the email associated with your Meta Business account is correct - Confirm with your Telnyx representative that they initiated the invitation - The invitation typically arrives within 1–2 business days - Review Meta's rejection reasons carefully in the App Review section of your dashboard - Common reasons include: insufficient permissions justification, unclear use case description, or missing screencast - Update your submission with clearer documentation and resubmit - Ensure your app is functional and testable during the review period - Confirm the Facebook SDK is loaded before calling `FB.login()` - Check that your `config_id` is correct and matches a WhatsApp Business Configuration in your app - Ensure your app has the `whatsapp_business_messaging` and `whatsapp_business_management` permissions - Open your browser's developer console for error messages from the SDK - Verify you are using a valid Telnyx API key - Ensure the `Authorization: Bearer YOUR_API_KEY` header is included in your request - Check that your API key has not expired or been revoked - Ensure the `response_type` parameter includes `code` - Check that `override_default_response_type` is set to `true` - Verify the user completed all steps in the Meta signup flow (business verification, phone number selection) - Inspect the full response object in your `FB.login()` callback for debug information - Verify the phone number entered by the end-customer is correct and can receive SMS - Check that the phone number is not already registered with another WhatsApp account - Try requesting the verification code via phone call instead of SMS - Ensure the end-customer's phone carrier is not blocking Meta's verification messages ## Next steps Send your first WhatsApp message with Telnyx Direct customer embedded signup flow Explore WhatsApp API endpoints Send messages across all channels --- ## Sending Messages ### Send Messages > Source: https://developers.telnyx.com/docs/messaging/whatsapp/send-messages.md Send WhatsApp messages using `POST /v2/messages/whatsapp`. All message types use the same endpoint — the `whatsapp_message` object determines the message type. ``` POST https://api.telnyx.com/v2/messages/whatsapp ``` ### Request Structure Every request requires these fields: | Field | Type | Required | Description | |-------|------|----------|-------------| | `from` | string | Yes | Your WhatsApp-enabled phone number (E.164) | | `to` | string | Yes | Recipient phone number (E.164) | | `whatsapp_message` | object | Yes | Message content — structure varies by type | | `webhook_url` | string | No | URL for delivery status callbacks | The messaging profile is automatically resolved from the `from` number. You do not need to pass `messaging_profile_id`. The `whatsapp_message` object must include a `type` field and the corresponding content object. Supported types: `text`, `template`, `image`, `video`, `document`, `audio`, `sticker`, `location`, `contacts`, `interactive`, `reaction`. --- ## Template Messages Template messages are required to start conversations outside the 24-hour window. Templates must be pre-approved by Meta. Error code `40008` indicates the template could not be used for sending. Possible causes include: the template is still pending review, was rejected by Meta, has been paused due to quality issues, or was disabled. Check template status in the Telnyx Portal or via `GET /v2/whatsapp/message_templates`. Text, media, and interactive messages can only be sent within a 24-hour conversation window. The window opens when the recipient sends a message to the business number. Outside this window, use an approved template message to initiate the conversation. For comprehensive template creation guidance, see the [Manage Templates guide](/docs/messaging/whatsapp/manage-templates). ```bash cURL curl -X POST https://api.telnyx.com/v2/messages/whatsapp \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "template", "template": { "name": "order_confirmation", "language": { "policy": "deterministic", "code": "en_US" }, "components": [ { "type": "body", "parameters": [ {"type": "text", "text": "John"}, {"type": "text", "text": "ORD-12345"} ] } ] } } }' ``` ```python Python from telnyx import Telnyx client = Telnyx(api_key="YOUR_API_KEY") client.messages.send_whatsapp( from_="+15551234567", to="+15557654321", whatsapp_message={ "type": "template", "template": { "name": "order_confirmation", "language": {"policy": "deterministic", "code": "en_US"}, "components": [ { "type": "body", "parameters": [ {"type": "text", "text": "John"}, {"type": "text", "text": "ORD-12345"} ] } ] } } ) ``` ```javascript Node.js import Telnyx from 'telnyx'; const client = new Telnyx({apiKey: 'YOUR_API_KEY'}); const message = await client.messages.sendWhatsapp({ from: '+15551234567', to: '+15557654321', whatsapp_message: { type: 'template', template: { name: 'order_confirmation', language: { policy: 'deterministic', code: 'en_US' }, components: [ { type: 'body', parameters: [ { type: 'text', text: 'John' }, { type: 'text', text: 'ORD-12345' } ] } ] } } }); ``` ### Sending by Template ID Instead of specifying `name` and `language`, you can reference a template by its Telnyx UUID (`template_id`). The name and language are resolved automatically from the database. ```bash cURL curl -X POST https://api.telnyx.com/v2/messages/whatsapp \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "template", "template": { "template_id": "019cd44b-3a1c-781b-956e-bd33e9fd2ac6", "components": [ { "type": "body", "parameters": [ {"type": "text", "text": "John"}, {"type": "text", "text": "ORD-12345"} ] } ] } } }' ``` You can find a template's UUID by listing templates via `GET /v2/whatsapp/message_templates`. The `id` field in the response is the `template_id` you can use when sending. ### Template Components Templates use `components` to pass dynamic content into header, body, and button slots: | Component `type` | `sub_type` | Use | |-------------------|-----------|-----| | `header` | — | Media or text for template header | | `body` | — | Variable substitution in body text | | `button` | `quick_reply` | Quick reply button payload | | `button` | `url` | Dynamic URL suffix for CTA buttons | ### Media Header Template To send a template with an image header: ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "template", "template": { "name": "promo_with_image", "language": {"policy": "deterministic", "code": "en_US"}, "components": [ { "type": "header", "parameters": [ {"type": "image", "image": {"link": "https://example.com/promo.jpg"}} ] }, { "type": "body", "parameters": [ {"type": "text", "text": "20%"} ] } ] } } } ``` Header parameters also support `document` and `video` types with the same `{link, caption, filename}` structure. --- ## Text Messages Send plain text within the 24-hour conversation window. Body must be 1–4096 bytes. ```bash cURL curl -X POST https://api.telnyx.com/v2/messages/whatsapp \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "text", "text": { "body": "Thanks for reaching out! How can we help?", "preview_url": false } } }' ``` ```python Python from telnyx import Telnyx client = Telnyx(api_key="YOUR_API_KEY") client.messages.send_whatsapp( from_="+15551234567", to="+15557654321", whatsapp_message={ "type": "text", "text": { "body": "Thanks for reaching out! How can we help?", "preview_url": False } } ) ``` ```javascript Node.js import Telnyx from 'telnyx'; const client = new Telnyx({apiKey: 'YOUR_API_KEY'}); const message = await client.messages.sendWhatsapp({ from: '+15551234567', to: '+15557654321', whatsapp_message: { type: 'text', text: { body: 'Thanks for reaching out! How can we help?', preview_url: false } } }); ``` Set `preview_url: true` to render link previews when the message body contains a URL. --- ## Media Messages Send images, videos, documents, audio, and stickers. Each media object requires exactly one of `link` (URL) or `id` (Meta media ID). Captions are optional and limited to 1024 bytes. ### Image ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "image", "image": { "link": "https://example.com/receipt.png", "caption": "Your receipt for order #12345" } } } ``` ### Document ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "document", "document": { "link": "https://example.com/invoice.pdf", "filename": "invoice_12345.pdf", "caption": "Invoice for March 2026" } } } ``` ### Video ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "video", "video": { "link": "https://example.com/tutorial.mp4", "caption": "Setup walkthrough" } } } ``` ### Audio ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "audio", "audio": { "link": "https://example.com/voicenote.ogg" } } } ``` ### Sticker ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "sticker", "sticker": { "link": "https://example.com/sticker.webp" } } } ``` Stickers do not support captions. Audio does not support captions. Only one media type per message. --- ## Location Messages Share a location pin. Latitude and longitude are passed as **strings** (decimal format). ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "location", "location": { "latitude": "40.7128", "longitude": "-74.0060", "name": "Telnyx HQ", "address": "311 W 43rd St, New York, NY" } } } ``` Latitude must be between -90 and 90. Longitude must be between -180 and 180. --- ## Contact Messages Share one or more contact cards (1–257 contacts per message). ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "contacts", "contacts": [ { "name": { "formatted_name": "Jane Smith", "first_name": "Jane", "last_name": "Smith" }, "phones": [ {"phone": "+15559876543", "type": "WORK"} ], "emails": [ {"email": "jane@example.com", "type": "WORK"} ] } ] } } ``` --- ## Interactive Messages Interactive messages let recipients tap buttons, select from lists, or open URLs. Supported `interactive.type` values: | Type | Description | |------|-------------| | `button` | Up to 3 quick reply buttons | | `cta_url` | Call-to-action URL button | | `list` | Selectable list with sections and rows | | `location_request_message` | Request the recipient's location | | `carousel` | Scrollable cards with media and buttons | ### Quick Reply Buttons ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "interactive", "interactive": { "type": "button", "body": {"text": "Would you like to schedule a callback?"}, "action": { "buttons": [ {"type": "reply", "reply": {"id": "yes_callback", "title": "Yes, call me"}}, {"type": "reply", "reply": {"id": "no_thanks", "title": "No thanks"}} ] } } } } ``` When a recipient taps a button, you receive an inbound webhook with the button's `id` in the payload. ### CTA URL Button ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "interactive", "interactive": { "type": "cta_url", "body": {"text": "Track your shipment"}, "action": { "name": "cta_url", "parameters": { "display_text": "Track Order", "url": "https://example.com/track/12345" } } } } } ``` ### List Messages ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "interactive", "interactive": { "type": "list", "body": {"text": "Select a support topic:"}, "action": { "button": "Choose topic", "sections": [ { "title": "Account", "rows": [ {"id": "billing", "title": "Billing", "description": "Payment and invoice questions"}, {"id": "access", "title": "Account Access", "description": "Login and permissions"} ] }, { "title": "Technical", "rows": [ {"id": "api", "title": "API Issues", "description": "Integration and endpoint help"}, {"id": "webhooks", "title": "Webhooks", "description": "Delivery and configuration"} ] } ] } } } } ``` ### Location Request ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "interactive", "interactive": { "type": "location_request_message", "body": {"text": "Share your location so we can find the nearest store."}, "action": {"name": "send_location"} } } } ``` --- ## Reactions React to a received message with an emoji. ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "reaction", "reaction": { "message_id": "wamid.ABGGFlA5FpafAgo6tHcNmNjXhvRm", "emoji": "👍" } } } ``` --- ## Reply Context Reply to a specific message by including `context.message_id`: ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "text", "context": { "message_id": "wamid.ABGGFlA5FpafAgo6tHcNmNjXhvRm" }, "text": { "body": "Thanks for your order! It will ship tomorrow." } } } ``` --- ## Callback Tracking Use `biz_opaque_callback_data` to attach tracking data that will be returned in delivery webhooks: ```json { "from": "+15551234567", "to": "+15557654321", "whatsapp_message": { "type": "text", "biz_opaque_callback_data": "order_12345_confirmation", "text": { "body": "Your order has been confirmed." } } } ``` --- ## API Response All message types return the same response structure: ```json { "data": { "record_type": "message", "direction": "outbound", "id": "3fa85f64-5717-4562-b3fc-2c963f66afa6", "type": "WHATSAPP", "from": {"phone_number": "+15551234567"}, "to": [{"phone_number": "+15557654321", "status": "queued"}], "webhook_url": "https://example.com/webhooks" } } ``` --- ## Validation Rules | Constraint | Limit | |-----------|-------| | Text body | 1–4096 bytes | | Media caption | Max 1024 bytes | | Header text | Max 1024 bytes | | Contacts per message | 1–257 | | Location latitude | -90 to 90 (string) | | Location longitude | -180 to 180 (string) | | Media per message | Exactly 1 | | Media source | Exactly one of `link` or `id` | --- ## Error Handling Common WhatsApp errors return error code `40008`. This is a catch-all code covering template issues (pending, rejected, paused, disabled) and delivery failures. For general API errors, see the [Error Codes Reference](/development/api-fundamentals/api-errors). Template, text, media, and interactive messages all use the same endpoint. The `type` field inside `whatsapp_message` determines which content object is required. --- ## Next Steps Send your first WhatsApp message end-to-end Set up your WhatsApp Business Account and verify your number Handle inbound messages and delivery status callbacks --- ### Manage Templates > Source: https://developers.telnyx.com/docs/messaging/whatsapp/manage-templates.md # Manage WhatsApp Message Templates WhatsApp requires pre-approved message templates for business-initiated conversations. Use the Telnyx Management API to create, review, and manage templates programmatically. For template best practices and approval tips, see the [Approval Tips](/docs/messaging/whatsapp/manage-templates#approval-tips) guide. ## Template Lifecycle ```mermaid graph LR A[Create] --> B[PENDING] B --> C[APPROVED] B --> D[REJECTED] C --> E[PAUSED] E --> C C --> F[DISABLED] ``` Templates must be approved by Meta before they can be used. Review typically takes 24-48 hours. ## List Templates Retrieve all templates for your WhatsApp Business Account. ```bash cURL curl -X GET "https://api.telnyx.com/v2/whatsapp/message_templates" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ```python Python from telnyx import Telnyx client = Telnyx(api_key="YOUR_API_KEY") templates = client.whatsapp.templates.list() for template in templates.data: print(f"{template.name} ({template.category}) - {template.status}") ``` ```javascript Node.js import Telnyx from 'telnyx'; const client = new Telnyx({apiKey: 'YOUR_API_KEY'}); const { data } = await client.whatsapp.templates.list(); data.forEach(t => console.log(`${t.name} (${t.category}) - ${t.status}`)); ``` ### Filter by Status ```bash # List only approved templates curl -X GET "https://api.telnyx.com/v2/whatsapp/message_templates?filter[status]=APPROVED" \ -H "Authorization: Bearer YOUR_API_KEY" # Search by name curl -X GET "https://api.telnyx.com/v2/whatsapp/message_templates?filter[search]=welcome" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ### Response ```json { "data": [ { "id": "019cd44b-3a1c-781b-956e-bd33e9fd2ac6", "record_type": "whatsapp_message_template", "name": "welcome_message", "category": "MARKETING", "language": "en_US", "status": "APPROVED", "components": [ { "type": "BODY", "text": "Hello {{1}}! Welcome to our WhatsApp updates.", "example": { "body_text": [["John"]] } } ], "quality_rating": "HIGH", "created_at": "2026-03-15T12:00:00.000Z", "updated_at": "2026-03-15T14:30:00.000Z" } ], "meta": { "page_number": 1, "page_size": 20, "total_pages": 1, "total_results": 1 } } ``` ## Create a Template Submit a new template for Meta review. Set a display name for the phone number before submitting templates. Templates submitted from numbers without an approved display name are rejected by Meta. Always include sample values in the `example` field when your template contains parameters (`\{\{1\}\}`, `\{\{2\}\}`). Templates without examples are typically rejected. ### Authentication Template Authentication templates include an OTP code with a copy-code button. ```bash cURL curl -X POST "https://api.telnyx.com/v2/whatsapp/message_templates" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "login_verification", "category": "AUTHENTICATION", "language": "en_US", "components": [ { "type": "BODY", "text": "Your verification code is {{1}}. Do not share this code.", "example": { "body_text": [["123456"]] } }, { "type": "BUTTONS", "buttons": [ { "type": "OTP", "otp_type": "COPY_CODE", "text": "Copy Code" } ] } ] }' ``` ```python Python from telnyx import Telnyx client = Telnyx(api_key="YOUR_API_KEY") template = client.whatsapp.templates.create( name="login_verification", category="AUTHENTICATION", language="en_US", waba_id="YOUR_WABA_ID", components=[ { "type": "BODY", "text": "Your verification code is {{1}}. Do not share this code.", "example": {"body_text": [["123456"]]} }, { "type": "BUTTONS", "buttons": [{"type": "OTP", "otp_type": "COPY_CODE", "text": "Copy Code"}] } ] ) print(f"Template ID: {template.id}, Status: {template.status}") ``` ```javascript Node.js import Telnyx from 'telnyx'; const client = new Telnyx({apiKey: 'YOUR_API_KEY'}); const template = await client.whatsapp.templates.create({ name: 'login_verification', category: 'AUTHENTICATION', language: 'en_US', waba_id: 'YOUR_WABA_ID', components: [ { type: 'BODY', text: 'Your verification code is {{1}}. Do not share this code.', example: { body_text: [['123456']] } }, { type: 'BUTTONS', buttons: [{ type: 'OTP', otp_type: 'COPY_CODE', text: 'Copy Code' }] } ] }); console.log(`Template ID: ${template.data.id}`); ``` ### Marketing Template Marketing templates support rich media headers, body text with parameters, and call-to-action buttons. ```bash curl -X POST "https://api.telnyx.com/v2/whatsapp/message_templates" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "spring_promotion", "category": "MARKETING", "language": "en_US", "components": [ { "type": "HEADER", "format": "TEXT", "text": "Spring Sale!" }, { "type": "BODY", "text": "Hi {{1}}, enjoy {{2}}% off your next order with code {{3}}. Offer ends soon!", "example": { "body_text": [["Sarah", "25", "SPRING25"]] } }, { "type": "FOOTER", "text": "Reply STOP to opt out" }, { "type": "BUTTONS", "buttons": [ { "type": "URL", "text": "Shop Now", "url": "https://example.com/shop?promo={{1}}", "example": ["SPRING25"] } ] } ] }' ``` ### Utility Template Utility templates are for transactional updates like order confirmations, shipping notifications, and account alerts. ```bash curl -X POST "https://api.telnyx.com/v2/whatsapp/message_templates" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "order_shipped", "category": "UTILITY", "language": "en_US", "components": [ { "type": "BODY", "text": "Your order {{1}} has shipped! Expected delivery: {{2}}. Track your package here.", "example": { "body_text": [["ORD-12345", "March 20, 2026"]] } } ] }' ``` ## Get a Template Retrieve details of a specific template by ID. ```bash curl -X GET "https://api.telnyx.com/v2/whatsapp/message_templates/{template_id}" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ## Update a Template Edit a template's content. Only templates in `APPROVED` or `REJECTED` status can be updated. Updated templates are re-submitted for Meta review. Editing an approved template resets its status to `PENDING` while Meta reviews the changes. Your template will be temporarily unavailable for sending. ```bash curl -X PATCH "https://api.telnyx.com/v2/whatsapp/message_templates/{template_id}" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "components": [ { "type": "BODY", "text": "Your order {{1}} has shipped! Estimated arrival: {{2}}.", "example": { "body_text": [["ORD-12345", "March 22, 2026"]] } } ] }' ``` Edit and resubmit rejected templates rather than creating new ones. Meta enforces a 30-day restriction on reusing template names. ## Delete a Template Remove a template permanently. This action cannot be undone. ```bash curl -X DELETE "https://api.telnyx.com/v2/whatsapp/message_templates/{template_id}" \ -H "Authorization: Bearer YOUR_API_KEY" ``` ## Template Categories | Category | Use Case | Requires Opt-in | Pricing Tier | |----------|----------|-----------------|-------------| | **AUTHENTICATION** | OTP codes, login verification | No | Lowest | | **UTILITY** | Order updates, shipping, account alerts | Yes | Medium | | **MARKETING** | Promotions, newsletters, product launches | Yes | Highest | Choose the most specific category. Meta may reclassify templates that don't match their declared category, which can affect pricing and delivery. ### Authentication Rules - Must contain a one-time code or password - Must include a copy-code or one-tap button - Cannot include URLs or media (except the OTP button) - Limited to one code parameter ### Naming Rules - Lowercase letters, numbers, and underscores only - Maximum 512 characters - Must be unique within your WABA for each language - Avoid words like `test`, `sample`, `demo` — Meta flags these for extra review ### Approval Tips - **Always include sample values** — Templates with parameters but no `example` field are almost always rejected - **Set a display name first** — Templates submitted from numbers without an approved display name get rejected - **Complete your business profile** — Add website, description, and category before submitting. Incomplete profiles increase rejection rates - **Edit rejected templates, don't recreate** — Meta enforces a 30-day restriction on reusing template names - **Match category to content** — Meta may reclassify miscategorized templates, affecting pricing and delivery For detailed best practices and troubleshooting, see our [WhatsApp Message Templates Guide](https://support.telnyx.com/en/articles/13986483) on the support center. ## Multi-Language Templates Create the same template in multiple languages. Each language variant is reviewed independently. ```bash # English version curl -X POST "https://api.telnyx.com/v2/whatsapp/message_templates" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "order_confirmation", "category": "UTILITY", "language": "en_US", "components": [ { "type": "BODY", "text": "Order {{1}} confirmed. Delivery by {{2}}.", "example": {"body_text": [["ORD-789", "March 20"]]} } ] }' # Spanish version curl -X POST "https://api.telnyx.com/v2/whatsapp/message_templates" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "order_confirmation", "category": "UTILITY", "language": "es", "components": [ { "type": "BODY", "text": "Pedido {{1}} confirmado. Entrega estimada: {{2}}.", "example": {"body_text": [["ORD-789", "20 de marzo"]]} } ] }' ``` ## Error Handling | Error Code | Description | Resolution | |-----------|-------------|------------| | `40008` | Template operation failed (catch-all) | Check template status and Meta error details | | `10004` | Missing required parameter | Ensure all required fields are included | | `10032` | Invalid enumerated value | Check category and language codes | Common issues: - **Rejected templates**: Review [Template Best Practices](/docs/messaging/whatsapp/message-templates/index) for approval tips - **Duplicate name**: Template names must be unique per language within a WABA - **Invalid parameters**: Ensure `example` values match parameter count in template body ## Next Steps - [Send Messages](/docs/messaging/whatsapp/send-messages/index) — Use approved templates to send messages - [Approval Tips](/docs/messaging/whatsapp/manage-templates#approval-tips) — Tips for getting templates approved - [Quickstart](/docs/messaging/whatsapp/quickstart/index) — End-to-end setup guide --- ## API Reference (WhatsApp) ### Whatsapp Business Accounts - [List Whatsapp Business Accounts](https://developers.telnyx.com/api-reference/whatsapp-business-accounts/list-whatsapp-business-accounts.md) - [Get a single Whatsapp Business Account](https://developers.telnyx.com/api-reference/whatsapp-business-accounts/get-a-single-whatsapp-business-account.md) - [Delete a Whatsapp Business Account](https://developers.telnyx.com/api-reference/whatsapp-business-accounts/delete-a-whatsapp-business-account.md) - [List phone numbers for a WABA](https://developers.telnyx.com/api-reference/whatsapp-business-accounts/list-phone-numbers-for-a-waba.md) - [Get WABA settings](https://developers.telnyx.com/api-reference/whatsapp-business-accounts/get-waba-settings.md) - [Update WABA settings](https://developers.telnyx.com/api-reference/whatsapp-business-accounts/update-waba-settings.md) ### Whatsapp Phone Numbers - [Initialize Whatsapp phone number verification](https://developers.telnyx.com/api-reference/whatsapp-phone-numbers/initialize-whatsapp-phone-number-verification.md) - [List Whatsapp phone numbers](https://developers.telnyx.com/api-reference/whatsapp-phone-numbers/list-whatsapp-phone-numbers.md) - [Delete a Whatsapp phone number](https://developers.telnyx.com/api-reference/whatsapp-phone-numbers/delete-a-whatsapp-phone-number.md) - [Get calling settings for a phone number](https://developers.telnyx.com/api-reference/whatsapp-phone-numbers/get-calling-settings-for-a-phone-number.md) - [Enable or disable Whatsapp calling for a phone number](https://developers.telnyx.com/api-reference/whatsapp-phone-numbers/enable-or-disable-whatsapp-calling-for-a-phone-number.md) - [Get phone number business profile](https://developers.telnyx.com/api-reference/whatsapp-phone-numbers/get-phone-number-business-profile.md) - [Update phone number business profile](https://developers.telnyx.com/api-reference/whatsapp-phone-numbers/update-phone-number-business-profile.md) - [Get Whatsapp profile photo](https://developers.telnyx.com/api-reference/whatsapp-phone-numbers/get-whatsapp-profile-photo.md) - [Upload Whatsapp profile photo](https://developers.telnyx.com/api-reference/whatsapp-phone-numbers/upload-whatsapp-profile-photo.md) - [Delete Whatsapp profile photo](https://developers.telnyx.com/api-reference/whatsapp-phone-numbers/delete-whatsapp-profile-photo.md) - [Resend verification code](https://developers.telnyx.com/api-reference/whatsapp-phone-numbers/resend-verification-code.md) - [Submit verification code for a phone number](https://developers.telnyx.com/api-reference/whatsapp-phone-numbers/submit-verification-code-for-a-phone-number.md) ### Whatsapp Message Templates - [List Whatsapp message templates](https://developers.telnyx.com/api-reference/whatsapp-message-templates/list-whatsapp-message-templates.md) - [Create a Whatsapp message template](https://developers.telnyx.com/api-reference/whatsapp-message-templates/create-a-whatsapp-message-template.md) - [Get a Whatsapp message template by ID](https://developers.telnyx.com/api-reference/whatsapp-message-templates/get-a-whatsapp-message-template-by-id.md) - [Update a Whatsapp message template](https://developers.telnyx.com/api-reference/whatsapp-message-templates/update-a-whatsapp-message-template.md) - [Delete a Whatsapp message template](https://developers.telnyx.com/api-reference/whatsapp-message-templates/delete-a-whatsapp-message-template.md)