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

# Send WhatsApp Template

> Send WhatsApp messages using Meta-approved templates

## Overview

Send WhatsApp messages to your contacts using pre-approved templates. Perfect for:

* **Transactional notifications**: Order updates, booking confirmations
* **Customer support**: Appointment reminders, service updates
* **Marketing messages**: Product launches, promotional offers (with opt-in)
* **Authentication**: OTP codes, verification messages

<Tip>
  Before sending messages, make sure to connect a WhatsApp Business Account by visiting the **Channels** section at
  [app.minimo.it/channels](https://app.minimo.it/channels).
</Tip>

## WhatsApp Template Requirements

Unlike emails, WhatsApp messages must use templates **approved by Meta** (Facebook). This ensures:

* User privacy and experience
* Compliance with WhatsApp Business Policy
* Reduced spam and unwanted messages

### Template Approval Process

1. **Create template** in Minimo dashboard
2. **Submit for approval** to Meta
3. **Wait 24-48 hours** for review
4. **Use approved template** via API

<Warning>
  Only templates with `status: "APPROVED"` can be used. Attempting to send with pending or rejected templates will fail.
</Warning>

## Template Categories

WhatsApp templates must be categorized:

| Category         | Description                   | Use Cases                          | 24h Window |
| ---------------- | ----------------------------- | ---------------------------------- | ---------- |
| `UTILITY`        | Account updates, transactions | Order status, booking confirmation | No         |
| `AUTHENTICATION` | OTP codes, verification       | 2FA codes, login verification      | No         |
| `MARKETING`      | Promotional content           | Product launch, special offers     | Yes\*      |

\*Marketing templates require user opt-in and are subject to the 24-hour messaging window.

## Phone Number Format

WhatsApp requires phone numbers in **E.164 format**:

```
+[country code][subscriber number]
```

**Examples**:

* ✅ `+393391234567` (Italy)
* ✅ `+12025551234` (US)
* ✅ `+447700900123` (UK)
* ❌ `3391234567` (missing country code)
* ❌ `+39 339 123 4567` (contains spaces)
* ❌ `+39-339-123-4567` (contains dashes)

<Info>
  Always validate and format phone numbers before sending. Invalid numbers will result in failed messages and count
  against your quality score.
</Info>

## Template Variables

Templates support dynamic content through placeholders. Meta allows two placeholder styles, and the style is fixed when the template is created:

* **Positional**: numbered placeholders like `{{1}}`, `{{2}}`
* **Named**: descriptive placeholders like `{{customer_name}}`, `{{order_id}}`

### Positional Variables

**Template Example** (created in dashboard):

```
Hello {{1}}, your order {{2}} has been confirmed!

Total: {{3}}
Estimated delivery: {{4}}

Track your order: {{5}}
```

**API Request**:

```json theme={null}
{
  "templateName": "order_confirmation",
  "phone": "+393391234567",
  "components": [
    {
      "type": "body",
      "parameters": [
        { "type": "text", "text": "Jane Doe" },
        { "type": "text", "text": "ORD-12345" },
        { "type": "text", "text": "$99.99" },
        { "type": "text", "text": "November 20, 2025" },
        { "type": "text", "text": "https://track.example.com/12345" }
      ]
    }
  ]
}
```

<Note>
  Variable numbering starts at `{{1}}`, not `{{0}}`. Order matters - map parameters in the exact sequence defined in your template.
</Note>

### Named Variables

For templates with named placeholders, add `parameter_name` to each body parameter to state which placeholder the value fills:

**Template Example** (created in dashboard):

```
Hello {{customer_name}}, your order {{order_id}} has been confirmed!
```

**API Request**:

```json theme={null}
{
  "templateName": "order_confirmation_named",
  "phone": "+393391234567",
  "components": [
    {
      "type": "body",
      "parameters": [
        { "type": "text", "text": "Jane Doe", "parameter_name": "customer_name" },
        { "type": "text", "text": "ORD-12345", "parameter_name": "order_id" }
      ]
    }
  ]
}
```

<Note>
  `parameter_name` is recommended but optional. If you omit it, Minimo resolves the names automatically from the approved template definition, matching your parameters **by position**: the first parameter fills the first placeholder appearing in the template body, and so on. When relying on this fallback, the order of your parameters must follow the order in which the placeholders appear in the template.
</Note>

<Warning>
  With explicit `parameter_name` values, every name must match a placeholder defined in the template — a wrong or missing name is rejected by Meta with `(#100) Invalid parameter`.
</Warning>

## WhatsApp Message Components

Templates can have multiple components:

### Header (Optional)

* Text, image, document, or video
* Single dynamic variable supported

### Body (Required)

* Main message content
* Supports multiple variables
* Maximum 1024 characters

### Footer (Optional)

* Additional info (e.g., "Reply STOP to opt-out")
* No variables allowed

### Buttons (Optional)

* Call-to-action buttons
* Quick reply buttons
* URL buttons with dynamic parameters

## Use Cases

<AccordionGroup>
  <Accordion title="Order Confirmation">
    Send instant confirmation when an order is placed:

    ```json theme={null}
    {
      "templateName": "order_confirmation",
      "phone": "+393391234567",
      "components": [
        {
          "type": "body",
          "parameters": [
            {"type": "text", "text": "Mario Rossi"},
            {"type": "text", "text": "ORD-789"},
            {"type": "text", "text": "€149.99"}
          ]
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="Appointment Reminder">
    Remind customers about upcoming appointments:

    ```json theme={null}
    {
      "templateName": "appointment_reminder",
      "phone": "+393391234567",
      "components": [
        {
          "type": "body",
          "parameters": [
            {"type": "text", "text": "Dr. Smith"},
            {"type": "text", "text": "November 15, 2025"},
            {"type": "text", "text": "10:30 AM"},
            {"type": "text", "text": "Via Roma 123, Milano"}
          ]
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="OTP Verification">
    Send one-time passwords securely:

    ```json theme={null}
    {
      "templateName": "otp_code",
      "phone": "+393391234567",
      "components": [
        {
          "type": "body",
          "parameters": [
            {"type": "text", "text": "847592"},
            {"type": "text", "text": "5 minutes"}
          ]
        }
      ]
    }
    ```
  </Accordion>

  <Accordion title="Shipping Update">
    Notify customers about delivery status:

    ```json theme={null}
    {
      "templateName": "shipping_update",
      "phone": "+393391234567",
      "components": [
        {
          "type": "body",
          "parameters": [
            {"type": "text", "text": "ORD-12345"},
            {"type": "text", "text": "Out for delivery"},
            {"type": "text", "text": "https://track.example.com/12345"}
          ]
        }
      ]
    }
    ```
  </Accordion>
</AccordionGroup>

## Best Practices

### Message Quality Score

WhatsApp monitors your message quality. Maintain a high quality score by:

* ✅ Only sending to users who opted in
* ✅ Sending relevant, timely messages
* ✅ Using clear, professional language
* ✅ Respecting the 24-hour window for marketing
* ❌ Avoid spam-like behavior
* ❌ Don't send unsolicited messages
* ❌ Don't exceed rate limits

<Warning>
  Poor quality scores can result in: - Reduced sending limits - Template rejections - Account suspension
</Warning>

### Phone Number Validation

Always validate before sending:

```javascript theme={null}
function isValidE164(phone) {
  // Basic E.164 validation
  return /^\+[1-9]\d{1,14}$/.test(phone);
}

if (!isValidE164(phone)) {
  console.error('Invalid phone number format');
  return;
}
```

### Template Design Guidelines

* **Be concise**: Keep messages short and clear
* **Add context**: Include order numbers, dates, etc.
* **Include branding**: Mention your company name
* **Provide value**: Every message should be useful
* **Call-to-action**: Make next steps obvious

### Rate Limits & Messaging Tiers

WhatsApp enforces tiered messaging limits:

| Tier   | Daily Limit | How to Advance              |
| ------ | ----------- | --------------------------- |
| Tier 1 | 1,000       | Maintain quality score      |
| Tier 2 | 10,000      | Consistent quality + volume |
| Tier 3 | 100,000     | High quality + high volume  |
| Tier 4 | Unlimited   | Enterprise approval         |

Start at Tier 1, advance automatically with good performance.

## Common Errors

| Error                       | Cause                                      | Solution                                                                                                                |
| --------------------------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `template_not_approved`     | Template pending/rejected                  | Check status in dashboard, resubmit if needed                                                                           |
| `invalid_phone_number`      | Phone not in E.164 format                  | Add country code, remove spaces/dashes                                                                                  |
| `template_not_found`        | Wrong template name                        | Verify template name in dashboard                                                                                       |
| `parameter_mismatch`        | Wrong number of variables                  | Match template variable count exactly                                                                                   |
| `(#100) Invalid parameter`  | Wrong `parameter_name` on a named template | Use the exact placeholder names defined in the template, or omit `parameter_name` and send parameters in template order |
| `rate_limit_exceeded`       | Messaging tier limit reached               | Wait for reset or request tier upgrade                                                                                  |
| `recipient_not_on_whatsapp` | Phone number not on WhatsApp               | Verify number is active on WhatsApp                                                                                     |

## Tracking & Analytics

Monitor message delivery and engagement:

* **Delivery status**: Sent, delivered, read
* **Failure reasons**: Why messages didn't deliver
* **Response rate**: How many users reply

Access analytics via the Minimo dashboard.

## 24-Hour Messaging Window

### For Marketing Templates

After a user-initiated conversation, you have a **24-hour window** to send marketing messages without requiring a new opt-in.

**User-initiated means**:

* User sends a message to your WhatsApp number
* User clicks a WhatsApp link
* User interacts with your WhatsApp ad

**Outside the 24-hour window**: Only UTILITY and AUTHENTICATION templates can be sent.

<Info>
  UTILITY templates (order confirmations, booking updates) can be sent anytime, regardless of the 24-hour window.
</Info>

## Compliance & Opt-In

### User Consent Required

* Get explicit opt-in before sending WhatsApp messages
* Keep records of consent
* Honor opt-out requests immediately
* Follow GDPR and local privacy regulations

### Opt-Out Handling

Include opt-out instructions in templates:

```
Don't want to receive these messages? Reply STOP to opt out.
```

## Related Endpoints

* [List WhatsApp Templates](/api-reference/messaging-channels/whatsapp/list-templates) - View all available templates


## OpenAPI

````yaml post /public/v1/templates/whatsapp/send
openapi: 3.1.0
info:
  title: API Documentation
  description: Documentation for transactional and subscribe APIs
  version: 1.0.0
servers:
  - url: https://app.minimo.it
security:
  - bearerAuth: []
paths:
  /public/v1/templates/whatsapp/send:
    servers:
      - url: https://api.minimo.it
    post:
      summary: Send WhatsApp message
      operationId: sendWhatsappMessage
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WhatsappSendMessageRequest'
            examples:
              templateMessage:
                summary: Send template-based message
                value:
                  recipient: '393471234567'
                  type: template
                  template:
                    name: order_confirmation
                    components:
                      - type: BODY
                        parameters:
                          - type: text
                            text: John
                          - type: text
                            text: ORD-12345
              templateMessageNamed:
                summary: Send template with named variables
                value:
                  recipient: '393471234567'
                  type: template
                  template:
                    name: order_confirmation_named
                    components:
                      - type: BODY
                        parameters:
                          - type: text
                            text: John
                            parameter_name: customer_name
                          - type: text
                            text: ORD-12345
                            parameter_name: order_id
              textMessage:
                summary: Send plain text message
                value:
                  recipient: '391234567890'
                  type: text
                  text: Hello! This is a plain message.
      responses:
        '200':
          description: Message sent successfully
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      success:
                        type: boolean
                        example: true
        '400':
          description: Invalid input or missing data
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Missing recipient phone number
        '500':
          description: Internal server error when sending message
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Failed to send the message
      security:
        - bearerAuth: []
components:
  schemas:
    WhatsappSendMessageRequest:
      type: object
      required:
        - recipient
        - type
      properties:
        recipient:
          type: string
          description: Phone number of the recipient including country code
          example: '393471234567'
        type:
          type: string
          enum:
            - text
            - template
          description: Type of message to send
          example: template
        text:
          type: string
          description: Plain text message (used only if type is 'text')
          example: Hello, this is a plain text message.
        template:
          type: object
          required:
            - name
          properties:
            name:
              type: string
              description: Name of the template registered in 360dialog
              example: order_confirmation
            components:
              type: array
              description: List of components with parameters to fill template placeholders
              items:
                type: object
                required:
                  - type
                properties:
                  type:
                    type: string
                    enum:
                      - HEADER
                      - BODY
                      - FOOTER
                      - BUTTONS
                    description: Type of the component
                    example: BODY
                  parameters:
                    type: array
                    description: Parameters to interpolate in the template
                    items:
                      oneOf:
                        - type: object
                          required:
                            - type
                            - text
                          properties:
                            type:
                              const: text
                            text:
                              type: string
                              example: John
                            parameter_name:
                              type: string
                              description: >-
                                For templates with named placeholders (e.g.
                                `{{customer_name}}`), the placeholder this value
                                fills. Optional: when omitted, the server
                                resolves it from the approved template
                                definition by position, so parameters must
                                follow the order in which the placeholders
                                appear in the template body. Ignored for
                                positional templates (`{{1}}`).
                              example: customer_name
                        - type: object
                          required:
                            - type
                            - image
                          properties:
                            type:
                              const: image
                            image:
                              type: object
                              required:
                                - link
                              properties:
                                link:
                                  type: string
                                  format: uri
                                  example: https://example.com/image.jpg
                        - type: object
                          required:
                            - type
                            - video
                          properties:
                            type:
                              const: video
                            video:
                              type: object
                              required:
                                - link
                              properties:
                                link:
                                  type: string
                                  format: uri
                                  example: https://example.com/video.mp4
                        - type: object
                          required:
                            - type
                            - document
                          properties:
                            type:
                              const: document
                            document:
                              type: object
                              required:
                                - link
                              properties:
                                link:
                                  type: string
                                  format: uri
                                  example: https://example.com/doc.pdf
                                filename:
                                  type: string
                                  example: invoice.pdf
                        - type: object
                          required:
                            - type
                            - currency
                          properties:
                            type:
                              const: currency
                            currency:
                              type: object
                              required:
                                - fallback_value
                                - code
                                - amount_1000
                              properties:
                                fallback_value:
                                  type: string
                                  example: €12.50
                                code:
                                  type: string
                                  example: EUR
                                amount_1000:
                                  type: integer
                                  example: 12500
                        - type: object
                          required:
                            - type
                            - date_time
                          properties:
                            type:
                              const: date_time
                            date_time:
                              type: object
                              required:
                                - fallback_value
                              properties:
                                fallback_value:
                                  type: string
                                  example: October 5, 2025 14:00
                        - type: object
                          required:
                            - type
                            - payload
                          properties:
                            type:
                              const: payload
                            payload:
                              type: string
                              example: custom_payload_123
      example:
        recipient: '393471234567'
        type: template
        template:
          name: order_confirmation
          components:
            - type: BODY
              parameters:
                - type: text
                  text: John
                - type: text
                  text: ORD-12345
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: mn-API_CLIENT_ID-API_KEY

````