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

# Enviar Lista

> Envia menu interativo com seções e opções selecionáveis

**Auth:** `TokenAccount` ou `TokenInstance` • **Rate-limit:** `Global` (100/min) • **Idempotente:** não

## Descrição

Envia uma **lista interativa** com até **10 seções** e **10 rows** por seção (limite total de **100 rows** somando todas as seções). O destinatário toca o botão (`buttonText`) para abrir o menu e escolher uma das opções, e o WhatsApp retorna o `id` da row selecionada como uma mensagem de resposta. Ideal para menus, catálogos curtos, FAQs guiadas e atendimento estruturado.

## Exemplos

### Lista simples (1 seção)

Menu enxuto com uma única seção "Pratos" e duas rows. O destinatário toca em "Ver opções" para abrir o menu e selecionar uma das opções, que volta como resposta carregando o `id` (`p1` ou `p2`).

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://ryzeapi.cloud/api/message/list/$Instance_Name" \
    -H "token: $Token_Instance" \
    -H "Content-Type: application/json" \
    -d '{
      "number":      "5511999999999",
      "contentText": "Selecione um item do cardápio:",
      "buttonText":  "Ver opções",
      "sections": [
        {
          "title": "Pratos",
          "rows": [
            { "id": "p1", "title": "Lasanha", "description": "Bolonhesa, 4 fatias" },
            { "id": "p2", "title": "Risoto",  "description": "Funghi" }
          ]
        }
      ]
    }'
  ```

  ```javascript JavaScript theme={null}
  await fetch(`https://ryzeapi.cloud/api/message/list/${process.env.Instance_Name}`, {
    method: "POST",
    headers: {
      "token":        process.env.Token_Instance,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      number:      "5511999999999",
      contentText: "Selecione um item do cardápio:",
      buttonText:  "Ver opções",
      sections: [
        {
          title: "Pratos",
          rows: [
            { id: "p1", title: "Lasanha", description: "Bolonhesa, 4 fatias" },
            { id: "p2", title: "Risoto",  description: "Funghi" }
          ]
        }
      ]
    })
  });
  ```

  ```python Python theme={null}
  import os, requests

  requests.post(
      f"https://ryzeapi.cloud/api/message/list/{os.environ['Instance_Name']}",
      headers={
          "token":        os.environ["Token_Instance"],
          "Content-Type": "application/json"
      },
      json={
          "number":      "5511999999999",
          "contentText": "Selecione um item do cardápio:",
          "buttonText":  "Ver opções",
          "sections": [
              {
                  "title": "Pratos",
                  "rows": [
                      {"id": "p1", "title": "Lasanha", "description": "Bolonhesa, 4 fatias"},
                      {"id": "p2", "title": "Risoto",  "description": "Funghi"}
                  ]
              }
          ]
      }
  )
  ```

  ```go Go theme={null}
  package main

  import (
      "net/http"
      "os"
      "strings"
  )

  func main() {
      body := strings.NewReader(`{
          "number":      "5511999999999",
          "contentText": "Selecione um item do cardápio:",
          "buttonText":  "Ver opções",
          "sections": [
              {
                  "title": "Pratos",
                  "rows": [
                      { "id": "p1", "title": "Lasanha", "description": "Bolonhesa, 4 fatias" },
                      { "id": "p2", "title": "Risoto",  "description": "Funghi" }
                  ]
              }
          ]
      }`)
      req, _ := http.NewRequest("POST", "https://ryzeapi.cloud/api/message/list/"+os.Getenv("Instance_Name"), body)
      req.Header.Set("token", os.Getenv("Token_Instance"))
      req.Header.Set("Content-Type", "application/json")
      http.DefaultClient.Do(req)
  }
  ```
</CodeGroup>

### Menu multi-seção (categorias)

Lista com múltiplas categorias agrupadas em seções. Cada seção é renderizada com um cabeçalho próprio dentro do menu, separando visualmente os grupos.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://ryzeapi.cloud/api/message/list/$Instance_Name" \
    -H "token: $Token_Instance" \
    -H "Content-Type: application/json" \
    -d '{
      "number":      "5511999999999",
      "contentText": "Cardápio completo. Escolha uma opção:",
      "buttonText":  "Abrir menu",
      "sections": [
        {
          "title": "Pratos principais",
          "rows": [
            { "id": "p1", "title": "Lasanha",  "description": "Bolonhesa, 4 fatias" },
            { "id": "p2", "title": "Risoto",   "description": "Funghi" },
            { "id": "p3", "title": "Salmão",   "description": "Grelhado com legumes" }
          ]
        },
        {
          "title": "Bebidas",
          "rows": [
            { "id": "b1", "title": "Suco natural" },
            { "id": "b2", "title": "Refrigerante" }
          ]
        },
        {
          "title": "Sobremesas",
          "rows": [
            { "id": "s1", "title": "Pudim" },
            { "id": "s2", "title": "Sorvete", "description": "3 sabores" }
          ]
        }
      ]
    }'
  ```

  ```javascript JavaScript theme={null}
  await fetch(`https://ryzeapi.cloud/api/message/list/${process.env.Instance_Name}`, {
    method: "POST",
    headers: {
      "token":        process.env.Token_Instance,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      number:      "5511999999999",
      contentText: "Cardápio completo. Escolha uma opção:",
      buttonText:  "Abrir menu",
      sections: [
        {
          title: "Pratos principais",
          rows: [
            { id: "p1", title: "Lasanha", description: "Bolonhesa, 4 fatias" },
            { id: "p2", title: "Risoto",  description: "Funghi" },
            { id: "p3", title: "Salmão",  description: "Grelhado com legumes" }
          ]
        },
        {
          title: "Bebidas",
          rows: [
            { id: "b1", title: "Suco natural" },
            { id: "b2", title: "Refrigerante" }
          ]
        },
        {
          title: "Sobremesas",
          rows: [
            { id: "s1", title: "Pudim" },
            { id: "s2", title: "Sorvete", description: "3 sabores" }
          ]
        }
      ]
    })
  });
  ```

  ```python Python theme={null}
  import os, requests

  requests.post(
      f"https://ryzeapi.cloud/api/message/list/{os.environ['Instance_Name']}",
      headers={
          "token":        os.environ["Token_Instance"],
          "Content-Type": "application/json"
      },
      json={
          "number":      "5511999999999",
          "contentText": "Cardápio completo. Escolha uma opção:",
          "buttonText":  "Abrir menu",
          "sections": [
              {
                  "title": "Pratos principais",
                  "rows": [
                      {"id": "p1", "title": "Lasanha", "description": "Bolonhesa, 4 fatias"},
                      {"id": "p2", "title": "Risoto",  "description": "Funghi"},
                      {"id": "p3", "title": "Salmão",  "description": "Grelhado com legumes"}
                  ]
              },
              {
                  "title": "Bebidas",
                  "rows": [
                      {"id": "b1", "title": "Suco natural"},
                      {"id": "b2", "title": "Refrigerante"}
                  ]
              },
              {
                  "title": "Sobremesas",
                  "rows": [
                      {"id": "s1", "title": "Pudim"},
                      {"id": "s2", "title": "Sorvete", "description": "3 sabores"}
                  ]
              }
          ]
      }
  )
  ```

  ```go Go theme={null}
  package main

  import (
      "net/http"
      "os"
      "strings"
  )

  func main() {
      body := strings.NewReader(`{
          "number":      "5511999999999",
          "contentText": "Cardápio completo. Escolha uma opção:",
          "buttonText":  "Abrir menu",
          "sections": [
              {
                  "title": "Pratos principais",
                  "rows": [
                      { "id": "p1", "title": "Lasanha", "description": "Bolonhesa, 4 fatias" },
                      { "id": "p2", "title": "Risoto",  "description": "Funghi" },
                      { "id": "p3", "title": "Salmão",  "description": "Grelhado com legumes" }
                  ]
              },
              {
                  "title": "Bebidas",
                  "rows": [
                      { "id": "b1", "title": "Suco natural" },
                      { "id": "b2", "title": "Refrigerante" }
                  ]
              },
              {
                  "title": "Sobremesas",
                  "rows": [
                      { "id": "s1", "title": "Pudim" },
                      { "id": "s2", "title": "Sorvete", "description": "3 sabores" }
                  ]
              }
          ]
      }`)
      req, _ := http.NewRequest("POST", "https://ryzeapi.cloud/api/message/list/"+os.Getenv("Instance_Name"), body)
      req.Header.Set("token", os.Getenv("Token_Instance"))
      req.Header.Set("Content-Type", "application/json")
      http.DefaultClient.Do(req)
  }
  ```
</CodeGroup>

### Lista com cabeçalho e rodapé

Adiciona `headerText` (título acima do corpo) e `footerText` (texto em cinza abaixo do botão), úteis para branding e disclaimers curtos.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST "https://ryzeapi.cloud/api/message/list/$Instance_Name" \
    -H "token: $Token_Instance" \
    -H "Content-Type: application/json" \
    -d '{
      "number":      "5511999999999",
      "headerText":  "Atendimento RyzeAPI",
      "contentText": "Como podemos ajudar você hoje?",
      "footerText":  "Atendimento 24/7",
      "buttonText":  "Ver opções",
      "sections": [
        {
          "title": "Suporte",
          "rows": [
            { "id": "sup_tec",  "title": "Suporte técnico" },
            { "id": "sup_fin",  "title": "Financeiro" },
            { "id": "sup_com",  "title": "Comercial",   "description": "Falar com vendas" }
          ]
        }
      ]
    }'
  ```

  ```javascript JavaScript theme={null}
  await fetch(`https://ryzeapi.cloud/api/message/list/${process.env.Instance_Name}`, {
    method: "POST",
    headers: {
      "token":        process.env.Token_Instance,
      "Content-Type": "application/json"
    },
    body: JSON.stringify({
      number:      "5511999999999",
      headerText:  "Atendimento RyzeAPI",
      contentText: "Como podemos ajudar você hoje?",
      footerText:  "Atendimento 24/7",
      buttonText:  "Ver opções",
      sections: [
        {
          title: "Suporte",
          rows: [
            { id: "sup_tec", title: "Suporte técnico" },
            { id: "sup_fin", title: "Financeiro" },
            { id: "sup_com", title: "Comercial", description: "Falar com vendas" }
          ]
        }
      ]
    })
  });
  ```

  ```python Python theme={null}
  import os, requests

  requests.post(
      f"https://ryzeapi.cloud/api/message/list/{os.environ['Instance_Name']}",
      headers={
          "token":        os.environ["Token_Instance"],
          "Content-Type": "application/json"
      },
      json={
          "number":      "5511999999999",
          "headerText":  "Atendimento RyzeAPI",
          "contentText": "Como podemos ajudar você hoje?",
          "footerText":  "Atendimento 24/7",
          "buttonText":  "Ver opções",
          "sections": [
              {
                  "title": "Suporte",
                  "rows": [
                      {"id": "sup_tec", "title": "Suporte técnico"},
                      {"id": "sup_fin", "title": "Financeiro"},
                      {"id": "sup_com", "title": "Comercial", "description": "Falar com vendas"}
                  ]
              }
          ]
      }
  )
  ```

  ```go Go theme={null}
  package main

  import (
      "net/http"
      "os"
      "strings"
  )

  func main() {
      body := strings.NewReader(`{
          "number":      "5511999999999",
          "headerText":  "Atendimento RyzeAPI",
          "contentText": "Como podemos ajudar você hoje?",
          "footerText":  "Atendimento 24/7",
          "buttonText":  "Ver opções",
          "sections": [
              {
                  "title": "Suporte",
                  "rows": [
                      { "id": "sup_tec", "title": "Suporte técnico" },
                      { "id": "sup_fin", "title": "Financeiro" },
                      { "id": "sup_com", "title": "Comercial", "description": "Falar com vendas" }
                  ]
              }
          ]
      }`)
      req, _ := http.NewRequest("POST", "https://ryzeapi.cloud/api/message/list/"+os.Getenv("Instance_Name"), body)
      req.Header.Set("token", os.Getenv("Token_Instance"))
      req.Header.Set("Content-Type", "application/json")
      http.DefaultClient.Do(req)
  }
  ```
</CodeGroup>

## Resposta de sucesso

O `content` retornado é o `contentText` enviado, e o `messageType` fica fixo em `list`. Guarde o `messageId` para correlacionar com os eventos de seleção que chegam via webhook.

```json 200 OK theme={null}
{
  "success": true,
  "message": "List message sent successfully",
  "status":  "sent",
  "data": {
    "messageId":   "3EB08FCF27E532F1B0F5",
    "direction":   "sent",
    "messageType": "list",
    "content":     "Selecione um item do cardápio:",
    "source":      "api",
    "timestamp":   "2026-04-30T14:30:00Z",
    "chat": {
      "jid":     "5511999999999@s.whatsapp.net",
      "isGroup": false
    },
    "sender": {
      "jid":      "5511777777777@s.whatsapp.net",
      "instance": "minha-instancia"
    }
  }
}
```

<Note>
  Quando o destinatário escolhe uma opção, o WhatsApp envia uma mensagem de resposta contendo o `id` da row selecionada, você captura essa resposta via webhook/websocket de eventos para dar continuidade ao fluxo.
</Note>

## Parâmetros de rota

<ParamField path="instance" type="string" required>
  Nome da instância (ex.: `$Instance_Name`).
</ParamField>

## Headers

<ParamField header="token" type="string" required>
  `TokenAccount` ou `TokenInstance`.
</ParamField>

<ParamField header="Content-Type" type="string" required>
  `application/json`
</ParamField>

## Request body

<ParamField body="number" type="string" required>
  Destino: telefone (`5511999999999`) ou JID (`@s.whatsapp.net`, `@lid`, `@g.us`, `@newsletter`).
</ParamField>

<ParamField body="contentText" type="string" required>
  Corpo principal da mensagem (descrição). Aparece acima do botão que abre a lista.
</ParamField>

<ParamField body="buttonText" type="string" required>
  Texto do botão que abre a lista (ex.: `"Ver opções"`, `"Abrir menu"`). Limitado pelo WhatsApp a poucos caracteres.
</ParamField>

<ParamField body="sections" type="ListSection[]" required>
  Array de **1 a 10 seções**. O total de rows somando todas as seções não pode exceder **100**.

  <Expandable title="ListSection">
    <ParamField body="title" type="string" required>
      Título da seção (cabeçalho do grupo dentro do menu).
    </ParamField>

    <ParamField body="rows" type="ListRow[]" required>
      Array de **1 a 10 rows** por seção.

      <Expandable title="ListRow">
        <ParamField body="id" type="string" required>
          Identificador único da row. É o valor que volta como resposta quando o usuário seleciona essa opção.
        </ParamField>

        <ParamField body="title" type="string" required>
          Título exibido para a opção.
        </ParamField>

        <ParamField body="description" type="string">
          Texto secundário em cinza, abaixo do título.
        </ParamField>
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<ParamField body="headerText" type="string">
  Título exibido acima do `contentText`. Opcional.
</ParamField>

<ParamField body="footerText" type="string">
  Texto em cinza claro abaixo do botão. Opcional, ideal para disclaimers curtos.
</ParamField>

<ParamField body="delay" type="int" default="0">
  Tempo em **segundos** para aguardar antes de enviar. Durante o intervalo, o servidor envia o indicador de "digitando..." ao destinatário e dispara o "paused" antes do envio real.
</ParamField>

<ParamField body="replyTo" type="string">
  ID da mensagem a ser citada (reply). A mensagem original precisa pertencer à mesma instância e ter sido salva no banco.
</ParamField>

<ParamField body="replyPrivate" type="boolean" default="false">
  Quando `true` **e** `replyTo` aponta para uma mensagem originária de um grupo, a resposta é redirecionada para o **privado** do autor original (mantendo a citação).
</ParamField>

<ParamField body="source" type="string" default="api">
  Identificador de origem para rastreabilidade (ex.: `crm`, `bot-suporte`, `n8n`). Salvo no registro da mensagem no banco e propagado para webhooks.
</ParamField>

## Notas

<Note>
  * **Limites do WhatsApp:** máximo de **10 seções**, **10 rows por seção** e **100 rows no total**. Excedeu? O servidor responde com `400` antes de tentar enviar.
  * A row selecionada pelo usuário retorna pelo evento de mensagem como uma resposta carregando o `id` original, capture isso via webhook para mapear a escolha.
  * Listas funcionam bem em DM, grupos e canais, mas a UX pode variar entre WhatsApp Business e WhatsApp pessoal.
  * `description` é opcional por row, mas melhora bastante a legibilidade quando o título sozinho é ambíguo.
</Note>

## Erros

| HTTP | Status interno   | Mensagem                                                     |
| ---- | ---------------- | ------------------------------------------------------------ |
| 400  | ,                | `Instance name is required`                                  |
| 400  | ,                | `Invalid request body: <detalhe>`                            |
| 400  | ,                | `Number is required`                                         |
| 400  | ,                | `ContentText is required`                                    |
| 400  | ,                | `ButtonText is required`                                     |
| 400  | ,                | `At least one section is required`                           |
| 400  | ,                | `Maximum of 10 sections allowed`                             |
| 400  | ,                | `Section N: Title is required`                               |
| 400  | ,                | `Section N: At least one row is required`                    |
| 400  | ,                | `Section N: Maximum of 10 rows allowed`                      |
| 400  | ,                | `Section N, Row M: ID is required`                           |
| 400  | ,                | `Section N, Row M: Title is required`                        |
| 400  | ,                | `Total number of rows across all sections cannot exceed 100` |
| 400  | `invalid_number` | `Invalid phone number format: <detalhe>`                     |
| 404  | ,                | `Instance not found`                                         |
| 500  | `send_failed`    | `Failed to send message: <reason>`                           |
| 503  | `disconnected`   | `Instance is not connected to WhatsApp`                      |

Envelope de erro:

```json theme={null}
{
  "success": false,
  "error": { "message": "ContentText is required" }
}
```
