> ## Documentation Index
> Fetch the complete documentation index at: https://developers.telnyx.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quickstart: Send Your First WhatsApp Message

> Complete end-to-end guide to send your first WhatsApp message via Telnyx API, from setup to delivery confirmation.

# 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

<Note>
  WhatsApp Business Platform requires business verification through Meta's process. Personal WhatsApp accounts cannot send template messages via the API.
</Note>

<Steps>
  <Step title="Set up your Telnyx account">
    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.
  </Step>

  <Step title="Connect WhatsApp Business Account">
    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

    <Warning>
      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.
    </Warning>

    <Note>
      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.
    </Note>
  </Step>

  <Step title="Create your first message template">
    WhatsApp requires pre-approved templates for outbound marketing and notifications:

    <Warning>
      Set a display name for the phone number before submitting templates. Templates submitted from numbers without an approved display name are rejected by Meta.
    </Warning>

    <Warning>
      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.
    </Warning>

    <Tip>
      Complete the business profile (website, description, industry category) before submitting templates. Incomplete profiles increase rejection rates, especially for new WhatsApp Business Accounts.
    </Tip>

    Create a message template using the API:

    <CodeGroup>
      ```bash cURL theme={null}
      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 theme={null}
      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 theme={null}
      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 theme={null}
      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']]
            }
          }
        ]
      )
      ```
    </CodeGroup>

    Meta typically reviews templates within 24-48 hours. You'll receive an email when approved.

    <Tip>
      Start with simple templates for faster approval. Avoid promotional language or special characters in your first template.
    </Tip>
  </Step>

  <Step title="Send your first WhatsApp message">
    Once your template is approved, send your first message:

    <CodeGroup>
      ```bash cURL theme={null}
      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 theme={null}
      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 theme={null}
      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 theme={null}
      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 theme={null}
      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 theme={null}
      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());
              }
          }
      }
      ```
    </CodeGroup>

    <Note>
      The messaging profile is automatically resolved from your WhatsApp-enabled phone number specified in the `from` field.
    </Note>
  </Step>

  <Step title="Set up webhook notifications">
    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.

    <Expandable title="Example webhook payload">
      ```json theme={null}
      {
        "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"
          }
        }
      }
      ```
    </Expandable>
  </Step>

  <Step title="Handle webhook events">
    Implement webhook handling to track message status and respond to inbound messages:

    <CodeGroup>
      ```python Python theme={null}
      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 theme={null}
      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');
      });
      ```
    </CodeGroup>
  </Step>
</Steps>

## 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 theme={null}
{
  "data": {
    "id": "msg_123abc",
    "to": [
      {
        "phone_number": "+15557654321",
        "status": "queued",
        "carrier": "WhatsApp"
      }
    ]
  }
}
```

## Common Issues

<AccordionGroup>
  <Accordion title="Template not approved">
    **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
  </Accordion>

  <Accordion title="Phone number not verified">
    **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
  </Accordion>

  <Accordion title="Outside 24-hour window">
    **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
  </Accordion>

  <Accordion title="Invalid recipient">
    **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
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Send Messages" href="/docs/messaging/whatsapp/send-messages" icon="paper-plane">
    Send templates, text, media, and interactive messages
  </Card>

  <Card title="Embedded Signup" href="/docs/messaging/whatsapp/embedded-signup" icon="right-to-bracket">
    Set up your WhatsApp Business Account and verify your number
  </Card>

  <Card title="Receiving Webhooks" href="/docs/messaging/messages/receiving-webhooks" icon="webhook">
    Handle inbound messages and delivery status callbacks
  </Card>
</CardGroup>
