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

# Send interactive menu (buttons, carousel, list, or poll)

> This endpoint provides a unified interface for sending four main types of interactive messages:
- Buttons: For quick, direct actions
- Button carousel: For a horizontal list of buttons with images
- Lists: For menus organized into sections
- Polls: For collecting opinions and voting

**Tracking field support**: This endpoint also supports `track_source` and `track_id` documented in the **"Send Message"** tag.

## Base Payload Structure

All requests follow this base structure:

```json
{
  "number": "5511999999999",
  "type": "button|button_legacy|list|poll|carousel",
  "text": "Texto principal da mensagem",
  "choices": ["opções baseadas no tipo escolhido"],
  "footerText": "Texto do rodapé (opcional para botões e listas)",
  "listButton": "Texto do botão (para listas)",
  "selectableCount": "Número de opções selecionáveis (apenas para enquetes)"
}
```

## Interactive Message Types

### 1. Buttons (type: "button")

Creates interactive buttons with different action functionalities.

#### Specific Fields
- `footerText`: Optional text displayed below the main message
- `choices`: Array of options that will be converted into buttons

#### Button Formats
Each button can be configured using `|` (pipe) or `\n` (line break) as separators:

- **Reply Button**:
  - `"texto|id"` or
  - `"texto\nid"` or
  - `"texto"` (ID will be the same as the text)

- **Copy Button**:
  - `"texto|copy:código"` or
  - `"texto\ncopy:código"`

- **Call Button**:
  - `"texto|call:+5511999999999"` or
  - `"texto\ncall:+5511999999999"`

- **URL Button**:
  - `"texto|https://exemplo.com"` or
  - `"texto|url:https://exemplo.com"`

#### Buttons with image, video, or document
The button header can carry an image, a video, or a document in `file`, via URL or base64, as in
`/send/media`. The type is taken from the file itself; to force it, send `mimetype`: `image`, `video`, `document`, or the file's MIME type (for example, `video/mp4`). The document uses the
name from `docName`; without it, the file name.

Audio is not allowed in the button: WhatsApp does not support audio in the header, and the API responds `400`. Send the audio first,
with `/send/media`. Without `mimetype`, the API detects audio by the URL extension or by the beginning of the base64; for a
URL without an extension, provide the `mimetype`.

```json
{
  "number": "5511999999999",
  "type": "button",
  "text": "Escolha um produto:",
  "file": "https://exemplo.com/produto1.jpg",
  "choices": [
    "Produto A|prod_a",
    "Mais Info|https://exemplo.com/produto-a",
    "Produto B|prod_b",
    "Ligar|call:+5511999999999"
  ],
  "footerText": "Produtos em destaque"
}
```

```json
{
  "number": "5511999999999",
  "type": "button",
  "text": "Tabela de preços de outubro",
  "file": "https://exemplo.com/tabela.pdf",
  "docName": "Tabela de preços.pdf",
  "choices": ["Quero comprar|comprar", "Falar com vendedor|vendedor"]
}
```

If the media fails to download or upload to WhatsApp, the button is sent without it.

#### Buttons in legacy format (type: "button_legacy")

Use `button_legacy` only when you need to send reply buttons in the
previous format. The `choices` format is:

- `"texto|id"`
- `"texto\nid"`
- `"texto|reply:id"`
- `"texto"` — the text itself will be used as the ID

This mode creates only reply buttons. URL, call, and copy actions and
media in `file` remain available in the current `type: "button"` format.

```json
{
  "number": "5511999999999",
  "type": "button_legacy",
  "text": "Deseja continuar?",
  "choices": [
    "Sim|confirmar",
    "Não|reply:cancelar"
  ],
  "footerText": "Escolha uma opção"
}
```

#### Complete Example
```json
{
  "number": "5511999999999",
  "type": "button",
  "text": "Como podemos ajudar?",
  "choices": [
    "Suporte Técnico|suporte",
    "Fazer Pedido|pedido",
    "Nosso Site|https://exemplo.com",
    "Falar Conosco|call:+5511999999999"
  ],
  "footerText": "Escolha uma das opções abaixo"
}
```

#### Limitations and Compatibility
> **Important**: When combining reply buttons with other types (call, url, copy) in the same message, the following notice will be displayed: "This message can't be displayed on WhatsApp Web. Open WhatsApp on your phone to view it."

### 2. Lists (type: "list")

Creates menus organized into sections with selectable items.

#### Specific Fields
- `listButton`: Text of the button that opens the list
- `footerText`: Optional footer text
- `choices`: Array with the list's sections and items

#### Choices Format
- `"[Título da Seção]"`: Starts a new section
- `"texto|id|descrição"`: List item with:
  - texto: Item label
  - id: Unique identifier, optional
  - descrição: Additional, optional descriptive text

#### Complete Example
```json
{
  "number": "5511999999999",
  "type": "list",
  "text": "Catálogo de Produtos",
  "choices": [
    "[Eletrônicos]",
    "Smartphones|phones|Últimos lançamentos",
    "Notebooks|notes|Modelos 2024",
    "[Acessórios]",
    "Fones|fones|Bluetooth e com fio",
    "Capas|cases|Proteção para seu device"
  ],
  "listButton": "Ver Catálogo",
  "footerText": "Preços sujeitos a alteração"
}
```

### 3. Polls (type: "poll")

Creates interactive polls for voting.

#### Specific Fields
- `selectableCount`: Number of options that can be selected (default: 1)
- `choices`: Simple array with the voting options

#### Complete Example
```json
{
  "number": "5511999999999",
  "type": "poll",
  "text": "Qual horário prefere para atendimento?",
  "choices": [
    "Manhã (8h-12h)",
    "Tarde (13h-17h)",
    "Noite (18h-22h)"
  ],
  "selectableCount": 1
}
```

### 4. Carousel (type: "carousel")

Creates a carousel of cards with images and interactive buttons.

#### Specific Fields
- `choices`: Array with carousel elements in the following order:
  - `[Texto do cartão]`: Card text in square brackets
  - `{URL ou base64 da imagem}`: Image in curly braces
  - Card buttons (one per line):
    - `"texto|copy:código"` for a copy button
    - `"texto|https://url"` for a link button
    - `"texto|call:+número"` for a call button

#### Complete Example
```json
{
  "number": "5511999999999",
  "type": "carousel",
  "text": "Conheça nossos produtos",
  "choices": [
    "[Smartphone XYZ\nO mais avançado smartphone da linha]",
    "{https://exemplo.com/produto1.jpg}",
    "Copiar Código|copy:PROD123",
    "Ver no Site|https://exemplo.com/xyz",
    "Fale Conosco|call:+5511999999999",
    "[Notebook ABC\nO notebook ideal para profissionais]",
    "{https://exemplo.com/produto2.jpg}",
    "Copiar Código|copy:NOTE456",
    "Comprar Online|https://exemplo.com/abc",
    "Suporte|call:+5511988888888"
  ]
}
```

> **Note**: We created another endpoint for carousels: `/send/carousel`. It works the same way, but with a different payload format. See which one is easier for you.

## Terms of use

The interactive buttons and lists features may be discontinued at any time without prior notice. We are not responsible for any changes to or unavailability of these features.

### Alternatives and Compatibility

Given the dynamic nature of these features, our endpoint was designed to make it easy to migrate between different message types (buttons, lists, and polls).

We recommend building your flows flexibly, ready to switch between the different types.

If a feature is discontinued, you can easily migrate to another message type just by changing the "type" field in the payload, keeping the same choices structure.




## OpenAPI

````yaml /openapi-en.json post /send/menu
openapi: 3.1.0
info:
  title: WppFy -  WhatsApp API
  version: 1.0.0
  description: >
    API for managing WhatsApp instances and communications.


    ## Important Recommendation: WhatsApp Business

    **It is HIGHLY RECOMMENDED to use WhatsApp Business accounts** instead of
    regular WhatsApp for integration; regular WhatsApp may present
    inconsistencies, disconnections, limitations, and instability when used with
    our API.


    ## Authentication

    - Regular endpoints require a 'token' header with the instance token


    ## Instance States

    Instances can be in the following states:

    - `disconnected`: Disconnected from WhatsApp

    - `connecting`: Connection in progress

    - `connected`: Successfully connected and authenticated
servers:
  - url: https://api.wppfy.com
security:
  - token: []
tags:
  - name: Instance
    description: |
      Operations related to an instance's lifecycle, such as connecting,
      disconnecting, and checking status.
  - name: Proxy
    description: >
      WppFy uses an internal proxy by default.

      You can keep this default, configure your own proxy via `proxy_url`, or
      use your Android phone as a proxy by installing the app from
      https://github.com/WppFy/silver_proxy_apk (direct APK:
      https://github.com/WppFy/silver_proxy_apk/raw/refs/heads/main/silver_proxy.apk).

      If nothing is sent, we keep using the internal proxy. IPs are Brazilian;
      for international clients, consider a proxy in the client's region.
  - name: Profile
    description: |
      Operations related to the WhatsApp instance profile, such as changing
      the profile name and picture.
  - name: Business
    description: |
      ⚠️ **EXPERIMENTAL** - Endpoints not yet fully tested.

      Operations related to the WhatsApp Business business profile.
      Allows querying and updating business profile data such as description,
      address, email, categories, and managing the product catalog.

      **Requirements:**
      - The currently connected account must be a **WhatsApp Business** account
      - Personal WhatsApp accounts do not have a business profile

      **Note:** These endpoints may not work as expected.
      Report any problems found.
  - name: Calls
    description: |
      Operations related to WhatsApp calls.
      Allows making and rejecting calls programmatically.
  - name: Send Message
    description: >
      Endpoints for sending WhatsApp messages with different content types.


      ## Common Optional Fields


      All message sending endpoints support the following optional fields:


      - **`delay`** *(integer)*: Delay in milliseconds before sending
        - During the delay, "Typing..." or "Recording audio..." will appear depending on the type
        - Example: `5000` (5 seconds)

      - **`readchat`** *(boolean)*: Mark chat as read after sending
        - Removes the unread message counter from the chat
        - Example: `true`

      - **`readmessages`** *(boolean)*: Mark last received messages as read
        - Marks the last 10 **received** messages (not sent by you) as read
        - Useful to confirm reading pending messages before replying
        - Different from `readchat` which only removes the unread counter
        - Example: `true`

      - **`replyid`** *(string)*: ID of the message to reply to
        - Creates a reply linked to the original message
        - Support varies by message type
        - Example: `"3A12345678901234567890123456789012"`

      - **`mentions`** *(string)*: Numbers to mention (only for group sending)
        - Specific numbers: `"5511999999999,5511888888888"`
        - Mention all: `"all"`

      - **`forward`** *(boolean)*: Marks the message as forwarded in WhatsApp
        - Adds the "Forwarded" indicator to the message
        - Example: `true`

      - **`track_source`** *(string)*: Message tracking source
        - Identifies the system or source sending the message
        - Useful for integrations (e.g., "chatwoot", "crm", "chatbot")
        - Example: `"chatwoot"`

      - **`track_id`** *(string)*: ID for message tracking
        - Free identifier to track the message in external systems
        - Allows correlating messages between different platforms
        - **Note**: The system accepts duplicate values - there is no uniqueness validation
        - Use the same ID in multiple messages if it makes sense for your integration
        - Example: `"msg_123456789"`

      ### Sending to Groups

      - **`number`** *(string)*: To send a message to a group, use the group ID
      ending with `@g.us`
        - Example: `"120363012345678901@g.us"`
        - **How to get the Group ID:**
          - Use the `chatid` from the webhook received when someone sends a message in the group
          - Use the `GET /group/list` endpoint to list all groups and their IDs

      ## Available Placeholders


      All message sending endpoints support dynamic placeholders for automatic
      personalization:


      ### Name Fields

      - **`{{name}}`**: Consolidated chat name, using the first available
      option:
        1. Lead name (`lead_name`)
        2. Lead full name (`lead_fullName`)
        3. WhatsApp contact name (`wa_contactName`)
        4. WhatsApp profile name (`wa_name`)

      - **`{{first_name}}`**: First valid word of the consolidated name (minimum
      2 characters)


      ### WhatsApp Fields

      - **`{{wa_name}}`**: WhatsApp profile name

      - **`{{wa_contactName}}`**: Contact name as saved in WhatsApp


      ### Lead Fields

      - **`{{lead_name}}`**: Lead name

      - **`{{lead_fullName}}`**: Lead full name

      - **`{{lead_personalid}}`**: Personal ID (SSN, CPF, CNPJ, etc)

      - **`{{lead_email}}`**: Lead email

      - **`{{lead_status}}`**: Current lead status

      - **`{{lead_notes}}`**: Lead notes

      - **`{{lead_assignedAttendant_id}}`**: ID of the assigned attendant


      ### Custom Fields

      Fields added via custom fields are accessible using `{{lead_field01}}` to
      `{{lead_field20}}` or use `{{fieldname}}` defined in
      `/instance/updateFieldsMap`.


      ### Usage Example

      ```

      Hello {{name}}! I saw you work at {{company}}.

      Is your email {{lead_email}} correct?

      ```


      **💡 Tip**: Use `/chat/find` to fetch chat data and see available fields
      before sending messages with placeholders.
  - name: Async Message
    description: >
      Operational controls for the internal asynchronous send queue used when a
      send endpoint receives `async=true`.


      This section is used to:

      - check the current state of the async queue

      - configure the delay between messages sent with `async=true`

      - clear pending backlog and cancel messages not yet completed


      Scope:

      - covers only the internal queue of async direct messages

      - does not change messages already sent successfully
  - name: Message Actions and Search
  - name: Chats
  - name: Contacts
  - name: Blocklist
  - name: Labels
  - name: Groups and Communities
  - name: Newsletters and Channels
    description: >
      Operations for reading and following WhatsApp channels (newsletters).


      Main use cases:

      - list posts already published in a channel

      - edit recent posts in a channel

      - delete recent posts in a channel

      - check post views and reactions

      - integrate channels without needing to persist messages locally


      Notes:

      - `/newsletter/messages` returns the post content

      - `/newsletter/messages/edit` edits the content of recent posts

      - `/newsletter/messages/delete` deletes recent posts

      - views (`viewsCount`) and reactions (`reactionCounts`) come in each post
      of `/newsletter/messages`, not via webhook event

      - `/newsletter/updates` is deprecated: WhatsApp does not respond and the
      API returns 504

      - newsletters use their own routes and must not use `/message/edit` or
      `/message/delete`
  - name: Quick Replies
    description: >
      Management of quick replies to streamline service.


      **⚠️ Important**: This feature is only useful if you use a custom
      frontend/interface

      to register and use the replies. The API only stores the replies, 

      but does not apply them automatically.


      ### How it works:

      - **Create**: Register pre-defined responses with titles and content

      - **List**: Retrieve all registered responses to display in your interface

      - **Use**: Your frontend system can use these responses to speed up typing


      ### Use cases:

      - Custom web service interfaces

      - Mobile apps with reply suggestions

      - CRM systems with message templates

      - Productivity tools for attendants


      **Not a chatbot**: For automatic responses, use Chatbot features.
  - name: CRM
    description: >
      Complete customer relationship management system integrated with the API.


      **💾 Internal Storage**: All lead data is saved directly in the API,

      eliminating the need for external databases. Your application can focus
      only

      on the interface and business logic.


      ### Available Features:

      - **📋 20+ customizable fields**: Name, phone, email, company, notes, etc.

      - **🏷️ Label System**: Organize and categorize your contacts

      - **🔍 Advanced Search**: Filter by any field or label

      - **📊 Complete History**: All interactions are registered automatically


      ### 🎯 Placeholders in messages:

      Use dynamic variables in messages for automatic personalization:


      ```

      Hello {{name}}! I saw you work at {{company}}.

      Is your email {{email}} correct?

      Notes: {{notes}}

      ```


      ### Typical Flow:

      1. **Capture**: Leads arrive via WhatsApp or forms

      2. **Enrichment**: Add data using `/chat/editLead`

      3. **Segmentation**: Organize with labels

      4. **Communication**: Send personalized messages with placeholders

      5. **Follow-up**: History is saved automatically


      **Ideal for**: Sales, marketing, support, lead qualification
  - name: Chatwoot Integration
    description: >
      **🚧 BETA INTEGRATION - Chatwoot integration system for unified service**


      **⚠️ WARNING**: This integration is in BETA phase. Use at your own risk.
      We recommend testing in a non-production environment before use in
      production.


      This category contains resources to configure and manage integration with
      Chatwoot, an open-source customer service platform. The integration allows
      centralizing WhatsApp conversations in Chatwoot.


      ### Available Features:

      - 🔧 **Complete Configuration**: Configure URL, tokens, and Chatwoot
      credentials

      - 📬 **Bidirectional Sync**: New messages between WhatsApp and Chatwoot
      are synced automatically

      - 📱 **Contact Management**: Automatic sync of names and phones

      - 🔄 **LID→PN Update**: Automatic migration from Local ID to Phone Number

      - 🏷️ **Smart Names**: Name system with tilde (~) for automatic update

      - 🚫 **Group Separation**: Option to ignore groups in sync

      - 👤 **Message Signature**: Agent identification in sent messages

      - 🔗 **Automatic Webhook**: URL generated automatically to configure in
      Chatwoot


      ### 🏷️ Smart Name System:

      - **Names with tilde (~)**: Updated automatically when contact modifies
      name in WhatsApp

      - **Specific names**: For fixed name, remove tilde (~) from name in
      Chatwoot

      - **Example**: "~John Doe" = automatic, "John Doe" = fixed

      - **LID→PN Migration**: No conversation duplication during transition

      - **Native responses**: Appear directly in Chatwoot without external
      markings


      ### ⚠️ Known Limitations:

      - **History sync**: Not implemented - only new messages are synced


      ### Use Cases:

      - Centralized service in Chatwoot

      - Support teams with multiple agents

      - CRM integration via Chatwoot

      - Communication channel centralization

      - Automatic contact and name management


      **Ideal for**: Companies with service teams, call centers, technical
      support (in test environment)


      **Requires**: Configured Chatwoot instance, API tokens, and test
      environment


      **🚧 Remember**: BETA integration - features may change without prior
      notice
  - name: Server-Sent Events (SSE)
paths:
  /send/menu:
    post:
      tags:
        - Send Message
      summary: Send interactive menu (buttons, carousel, list, or poll)
      description: >
        This endpoint provides a unified interface for sending four main types
        of interactive messages:

        - Buttons: For quick, direct actions

        - Button carousel: For a horizontal list of buttons with images

        - Lists: For menus organized into sections

        - Polls: For collecting opinions and voting


        **Tracking field support**: This endpoint also supports `track_source`
        and `track_id` documented in the **"Send Message"** tag.


        ## Base Payload Structure


        All requests follow this base structure:


        ```json

        {
          "number": "5511999999999",
          "type": "button|button_legacy|list|poll|carousel",
          "text": "Texto principal da mensagem",
          "choices": ["opções baseadas no tipo escolhido"],
          "footerText": "Texto do rodapé (opcional para botões e listas)",
          "listButton": "Texto do botão (para listas)",
          "selectableCount": "Número de opções selecionáveis (apenas para enquetes)"
        }

        ```


        ## Interactive Message Types


        ### 1. Buttons (type: "button")


        Creates interactive buttons with different action functionalities.


        #### Specific Fields

        - `footerText`: Optional text displayed below the main message

        - `choices`: Array of options that will be converted into buttons


        #### Button Formats

        Each button can be configured using `|` (pipe) or `\n` (line break) as
        separators:


        - **Reply Button**:
          - `"texto|id"` or
          - `"texto\nid"` or
          - `"texto"` (ID will be the same as the text)

        - **Copy Button**:
          - `"texto|copy:código"` or
          - `"texto\ncopy:código"`

        - **Call Button**:
          - `"texto|call:+5511999999999"` or
          - `"texto\ncall:+5511999999999"`

        - **URL Button**:
          - `"texto|https://exemplo.com"` or
          - `"texto|url:https://exemplo.com"`

        #### Buttons with image, video, or document

        The button header can carry an image, a video, or a document in `file`,
        via URL or base64, as in

        `/send/media`. The type is taken from the file itself; to force it, send
        `mimetype`: `image`, `video`, `document`, or the file's MIME type (for
        example, `video/mp4`). The document uses the

        name from `docName`; without it, the file name.


        Audio is not allowed in the button: WhatsApp does not support audio in
        the header, and the API responds `400`. Send the audio first,

        with `/send/media`. Without `mimetype`, the API detects audio by the URL
        extension or by the beginning of the base64; for a

        URL without an extension, provide the `mimetype`.


        ```json

        {
          "number": "5511999999999",
          "type": "button",
          "text": "Escolha um produto:",
          "file": "https://exemplo.com/produto1.jpg",
          "choices": [
            "Produto A|prod_a",
            "Mais Info|https://exemplo.com/produto-a",
            "Produto B|prod_b",
            "Ligar|call:+5511999999999"
          ],
          "footerText": "Produtos em destaque"
        }

        ```


        ```json

        {
          "number": "5511999999999",
          "type": "button",
          "text": "Tabela de preços de outubro",
          "file": "https://exemplo.com/tabela.pdf",
          "docName": "Tabela de preços.pdf",
          "choices": ["Quero comprar|comprar", "Falar com vendedor|vendedor"]
        }

        ```


        If the media fails to download or upload to WhatsApp, the button is sent
        without it.


        #### Buttons in legacy format (type: "button_legacy")


        Use `button_legacy` only when you need to send reply buttons in the

        previous format. The `choices` format is:


        - `"texto|id"`

        - `"texto\nid"`

        - `"texto|reply:id"`

        - `"texto"` — the text itself will be used as the ID


        This mode creates only reply buttons. URL, call, and copy actions and

        media in `file` remain available in the current `type: "button"` format.


        ```json

        {
          "number": "5511999999999",
          "type": "button_legacy",
          "text": "Deseja continuar?",
          "choices": [
            "Sim|confirmar",
            "Não|reply:cancelar"
          ],
          "footerText": "Escolha uma opção"
        }

        ```


        #### Complete Example

        ```json

        {
          "number": "5511999999999",
          "type": "button",
          "text": "Como podemos ajudar?",
          "choices": [
            "Suporte Técnico|suporte",
            "Fazer Pedido|pedido",
            "Nosso Site|https://exemplo.com",
            "Falar Conosco|call:+5511999999999"
          ],
          "footerText": "Escolha uma das opções abaixo"
        }

        ```


        #### Limitations and Compatibility

        > **Important**: When combining reply buttons with other types (call,
        url, copy) in the same message, the following notice will be displayed:
        "This message can't be displayed on WhatsApp Web. Open WhatsApp on your
        phone to view it."


        ### 2. Lists (type: "list")


        Creates menus organized into sections with selectable items.


        #### Specific Fields

        - `listButton`: Text of the button that opens the list

        - `footerText`: Optional footer text

        - `choices`: Array with the list's sections and items


        #### Choices Format

        - `"[Título da Seção]"`: Starts a new section

        - `"texto|id|descrição"`: List item with:
          - texto: Item label
          - id: Unique identifier, optional
          - descrição: Additional, optional descriptive text

        #### Complete Example

        ```json

        {
          "number": "5511999999999",
          "type": "list",
          "text": "Catálogo de Produtos",
          "choices": [
            "[Eletrônicos]",
            "Smartphones|phones|Últimos lançamentos",
            "Notebooks|notes|Modelos 2024",
            "[Acessórios]",
            "Fones|fones|Bluetooth e com fio",
            "Capas|cases|Proteção para seu device"
          ],
          "listButton": "Ver Catálogo",
          "footerText": "Preços sujeitos a alteração"
        }

        ```


        ### 3. Polls (type: "poll")


        Creates interactive polls for voting.


        #### Specific Fields

        - `selectableCount`: Number of options that can be selected (default: 1)

        - `choices`: Simple array with the voting options


        #### Complete Example

        ```json

        {
          "number": "5511999999999",
          "type": "poll",
          "text": "Qual horário prefere para atendimento?",
          "choices": [
            "Manhã (8h-12h)",
            "Tarde (13h-17h)",
            "Noite (18h-22h)"
          ],
          "selectableCount": 1
        }

        ```


        ### 4. Carousel (type: "carousel")


        Creates a carousel of cards with images and interactive buttons.


        #### Specific Fields

        - `choices`: Array with carousel elements in the following order:
          - `[Texto do cartão]`: Card text in square brackets
          - `{URL ou base64 da imagem}`: Image in curly braces
          - Card buttons (one per line):
            - `"texto|copy:código"` for a copy button
            - `"texto|https://url"` for a link button
            - `"texto|call:+número"` for a call button

        #### Complete Example

        ```json

        {
          "number": "5511999999999",
          "type": "carousel",
          "text": "Conheça nossos produtos",
          "choices": [
            "[Smartphone XYZ\nO mais avançado smartphone da linha]",
            "{https://exemplo.com/produto1.jpg}",
            "Copiar Código|copy:PROD123",
            "Ver no Site|https://exemplo.com/xyz",
            "Fale Conosco|call:+5511999999999",
            "[Notebook ABC\nO notebook ideal para profissionais]",
            "{https://exemplo.com/produto2.jpg}",
            "Copiar Código|copy:NOTE456",
            "Comprar Online|https://exemplo.com/abc",
            "Suporte|call:+5511988888888"
          ]
        }

        ```


        > **Note**: We created another endpoint for carousels: `/send/carousel`.
        It works the same way, but with a different payload format. See which
        one is easier for you.


        ## Terms of use


        The interactive buttons and lists features may be discontinued at any
        time without prior notice. We are not responsible for any changes to or
        unavailability of these features.


        ### Alternatives and Compatibility


        Given the dynamic nature of these features, our endpoint was designed to
        make it easy to migrate between different message types (buttons, lists,
        and polls).


        We recommend building your flows flexibly, ready to switch between the
        different types.


        If a feature is discontinued, you can easily migrate to another message
        type just by changing the "type" field in the payload, keeping the same
        choices structure.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                number:
                  type: string
                  description: >-
                    ID of the chat the message will be sent to. Can be a phone
                    number in international format, a group ID (`@g.us`), a user
                    ID (with `@s.whatsapp.net` or `@lid`).
                  example: '5511999999999'
                type:
                  type: string
                  description: >-
                    Menu type. Use button for the current format and
                    button_legacy only for reply buttons in the previous format.
                  enum:
                    - button
                    - button_legacy
                    - list
                    - poll
                    - carousel
                  example: list
                text:
                  type: string
                  description: Main text (accepts placeholders)
                  example: 'Choose an option:'
                footerText:
                  type: string
                  description: Footer text (optional)
                  example: Service menu
                listButton:
                  type: string
                  description: Main button text
                  example: View options
                selectableCount:
                  type: integer
                  description: Maximum number of selectable options (for polls)
                  example: 1
                choices:
                  type: array
                  description: List of options. Use [Title] for sections in lists
                  items:
                    type: string
                  example:
                    - '[Eletrônicos]'
                    - Smartphones|phones|Últimos lançamentos
                    - Notebooks|notes|Modelos 2024
                    - '[Acessórios]'
                    - Fones|fones|Bluetooth e com fio
                    - Capas|cases|Proteção para seu device
                file:
                  type: string
                  description: >-
                    Header media (type: button): image, video or document, by
                    URL or base64, as in `/send/media`. Audio returns `400`.
                  example: https://exemplo.com/produto1.jpg
                mimetype:
                  type: string
                  description: >-
                    Forces the `file` type (optional): `image`, `video`,
                    `document` or the file's MIME type, such as `video/mp4`.
                    Without it, the type comes from the file; any other value
                    returns `400`.
                  example: video/mp4
                docName:
                  type: string
                  description: >-
                    Filename when the `file` is a document. Without it, the
                    file's name.
                  example: Price list.pdf
                replyid:
                  type: string
                  description: ID of the message to reply to
                  example: 3EB0538DA65A59F6D8A251
                mentions:
                  type: string
                  description: Numbers to mention (comma separated)
                  example: 5511999999999,5511888888888
                readchat:
                  type: boolean
                  description: Marks chat as read after sending
                  example: true
                readmessages:
                  type: boolean
                  description: Marks latest received messages as read
                  example: true
                delay:
                  type: integer
                  description: >-
                    Delay in milliseconds before sending; during delay
                    'Typing...' will appear
                  example: 1000
                track_source:
                  type: string
                  description: Message tracking source
                  example: chatwoot
                track_id:
                  type: string
                  description: ID for message tracking (accepts duplicate values)
                  example: msg_123456789
                async:
                  type: boolean
                  description: >-
                    If true, sends the message asynchronously via the internal
                    queue
                  example: false
              required:
                - number
                - type
                - text
                - choices
            examples:
              button:
                summary: Reply buttons
                value:
                  number: '5511999999999'
                  type: button
                  text: Como podemos ajudar?
                  choices:
                    - Suporte|suporte
                    - Fazer pedido|pedido
              list:
                summary: List of options
                value:
                  number: '5511999999999'
                  type: list
                  text: Escolha uma categoria
                  listButton: Ver opções
                  choices:
                    - '[Atendimento]'
                    - Suporte|suporte|Falar com o suporte
                    - Financeiro|financeiro|Falar com o financeiro
              poll:
                summary: Single-choice poll
                value:
                  number: '5511999999999'
                  type: poll
                  text: Qual horário prefere?
                  selectableCount: 1
                  choices:
                    - Manhã
                    - Tarde
      responses:
        '200':
          description: Menu sent successfully
          content:
            application/json:
              schema:
                allOf:
                  - $ref: '#/components/schemas/Message'
                  - type: object
                    properties:
                      response:
                        type: object
                        properties:
                          status:
                            type: string
                            example: success
                          message:
                            type: string
                            example: Menu sent successfully
        '400':
          description: Invalid request
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Missing required fields or invalid menu type
        '401':
          description: Unauthorized
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Invalid token
        '429':
          description: Rate limit exceeded
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Rate limit exceeded
        '500':
          description: Internal server error
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: Failed to send menu
components:
  schemas:
    Message:
      type: object
      description: Represents a message exchanged in the system
      properties:
        id:
          type: string
          format: uuid
          description: Internal unique message ID (format r + 7 random hex characters)
        messageid:
          type: string
          description: Original message ID at the provider
        chatid:
          type: string
          description: Related conversation ID
        sender:
          type: string
          description: Message sender ID
        senderName:
          type: string
          description: Sender's display name
        isGroup:
          type: boolean
          description: Indicates whether it is a group message
          default: false
        fromMe:
          type: boolean
          description: Indicates whether the message was sent by the user
          default: false
        messageType:
          type: string
          description: Message content type
        source:
          type: string
          description: Message source platform
        messageTimestamp:
          type: integer
          description: Original message timestamp in milliseconds
          default: 0
        status:
          type: string
          description: >
            Message lifecycle status.

            Common examples: `Queued`, `Canceled`, `Failed`, `Sent`,
            `Delivered`, `Read`.

            In group messages, it follows the most advanced participant:
            `Delivered` when at least one received it, `Read` when at least one
            read it, and `Played` when at least one listened to it.
        text:
          type: string
          description: Original message text
          default: ''
        quoted:
          type: string
          description: ID of the quoted/replied message
          default: ''
        edited:
          type: string
          description: Message edit history
          default: ''
        reaction:
          type: string
          description: ID of the reacted message
          default: ''
        vote:
          type: string
          description: Poll and list voting data
          default: ''
        convertOptions:
          type: string
          description: Conversion of message options, list, poll and buttons
          default: ''
        buttonOrListid:
          type: string
          description: ID of the selected button or list item
          default: ''
        owner:
          type: string
          description: Message owner
          default: ''
        error:
          type: string
          description: Error message if sending failed
          default: ''
        content:
          description: Raw message content (serialized JSON or text)
          oneOf:
            - type: object
              additionalProperties: true
            - type: string
              description: Raw text when not JSON
        wasSentByApi:
          type: boolean
          description: Indicates whether the message was sent via API
        pinned:
          type: boolean
          description: >-
            Message pinned in the conversation (pin and unpin also arrive in
            `messages_update`, types `Pinned` and `Unpinned`)
        sendFunction:
          type: string
          description: Function used to send the message (when sent via API)
        sendPayload:
          description: >-
            Payload used in the send when available. Base64 media data is
            omitted.
          oneOf:
            - type: object
              additionalProperties: true
            - type: string
              description: Raw text when not JSON
        fileURL:
          type: string
          description: Message file URL or reference
        callPeer:
          type: object
          description: >-
            Known contact associated with a call, when available in
            `messageType: call`.
          properties:
            jid:
              type: string
            name:
              type: string
            imagePreviewUrl:
              type: string
        send_folder_id:
          type: string
          description: Folder associated with the send (when applicable)
        track_source:
          type: string
          description: Tracking source
        track_id:
          type: string
          description: Tracking ID (may repeat)
        ai_metadata:
          type: object
          description: >-
            Record of an AI round. The full one (request to the model, response,
            and `outcome`) is stored once, on the contact's last message that
            the round replied to, even when nothing went out (error, discarded
            response). Each message sent by the AI carries only `agent_id` and
            `turn` (the `id` of that contact message).
          properties:
            agent_id:
              type: string
              description: ID of the responsible AI agent
            turn:
              type: string
              description: >-
                In the message sent by the AI: the `id` of the contact's message
                where the full record of the round is stored.
            flow_id:
              type: string
              description: >-
                Message sent by a flow: the flow's `id`. A message sent by the
                AI includes the `agent_id`.
            request:
              type: object
              description: Request data for the AI API
              properties:
                messages:
                  type: array
                  description: History of messages sent to the API
                tools:
                  type: array
                  description: Tools available to the agent
                options:
                  type: object
                  description: API configuration options
                  properties:
                    model:
                      type: string
                    temperature:
                      type: number
                    maxTokens:
                      type: integer
                    topP:
                      type: number
                    frequencyPenalty:
                      type: number
                    presencePenalty:
                      type: number
            response:
              type: object
              description: AI API response
              properties:
                choices:
                  type: array
                  description: Results returned by the API
                toolResults:
                  type: array
                  description: Tool execution results
                error:
                  type: string
                  description: Error message, if any
            outcome:
              type: object
              description: What the round actually did (only in the full record).
              properties:
                status:
                  type: string
                  enum:
                    - sent
                    - cancelled
                    - error
                    - empty
                  description: >-
                    `sent`: something was sent; `cancelled`: discarded (the
                    conversation was paused, a flow started, or the hourly reply
                    limit was reached); `error`: the provider failed; `empty`:
                    nothing to send.
                texts:
                  type: integer
                  description: Text messages sent.
                audio:
                  type: boolean
                  description: Replied with audio.
                menus:
                  type: integer
                  description: Menus sent.
                files:
                  type: integer
                  description: Files (registered messages) sent.
                handoff:
                  type: string
                  description: '`chamar_humano`: the summary for whoever takes over.'
                lead:
                  type: array
                  items:
                    type: string
                  description: >-
                    `atualizar_lead`: what was written to the CRM (`lead_email =
                    ana@exemplo.com; column = Agendado`).
                detail:
                  type: string
                  description: Why it was discarded, or the error.
        sender_pn:
          description: Sender's resolved PN JID (when available)
          oneOf:
            - type: string
            - type: 'null'
        sender_lid:
          description: Sender's original LID (when available)
          oneOf:
            - type: string
            - type: 'null'
        sender_image_preview_url:
          type: string
          format: uri
          description: >-
            Temporary preview URL of the sender, when known. Hydration in this
            version fills in messages received in groups; the field may be
            omitted. It does not trigger a photo query to WhatsApp during
            listing.
  securitySchemes:
    token:
      name: token
      type: apiKey
      in: header

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.