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

# Formulários (WhatsApp Flows)

> Formulário nativo que abre dentro da conversa do WhatsApp: crie pelo painel, envie por template ou pela API e receba cada resposta no webhook com chaves estáveis.

## O que é

Um formulário é uma tela de perguntas que abre **por cima da conversa**, dentro do próprio WhatsApp, quando o cliente toca no botão da sua mensagem. Ele preenche ali, toca em Enviar, e a resposta volta para você já separada campo a campo.

Não é link, não é site, não é bot perguntando uma coisa por vez. É um recurso nativo do WhatsApp (a Meta chama de Flow) que a Arara cria, publica e lê para você.

O formulário da Arara é **uma tela só e estática**: de 1 a 10 perguntas, todas visíveis de uma vez, tudo declarado na criação. Não tem etapas, não tem pergunta que aparece dependendo da resposta anterior e não tem nada vindo do seu servidor enquanto o cliente preenche. Os tipos de campo são nove, texto, texto longo, e-mail, telefone, número, escolha única, múltipla escolha, data e aceite. Não há upload de arquivo, imagem nem link dentro do formulário.

## Por que usar

* **Ninguém sai da conversa.** Sem link externo, sem página que demora a carregar, sem "abrir no navegador".
* **A resposta chega estruturada.** Você lê `fields.email`, não uma frase para interpretar.
* **A chave do campo é sua e não muda.** O que você leu uma vez vale para sempre.
* **Serve para cadastro, pesquisa, NPS, agendamento, opt-in.** De 1 a 10 perguntas por formulário.

<Note>
  Disponível do plano Voo para cima. Abaixo disso, criar ou enviar formulário responde `403 PLAN_FEATURE_LOCKED`.
</Note>

<Warning>
  **Você cria pelo painel ou pela API.** Os caminhos `/v1/flows/**` aceitam chave de API: leitura pede a permissão `READ`, criar, publicar e remover pedem `TEMPLATES_WRITE`. O envio é por `POST /v1/messages` e cada resposta chega no webhook `message.flow_reply`.
</Warning>

## Como aparece no WhatsApp

À esquerda, a mensagem com o botão. À direita, o formulário depois que o cliente toca nele.

<img className="block dark:hidden" src="https://mintcdn.com/arara/1O3fcKz8iJHdQsj0/images/formulario-conversa-light.svg?fit=max&auto=format&n=1O3fcKz8iJHdQsj0&q=85&s=f0771909542c8521f397e386096eb0d1" alt="Mensagem com botão Responder e, ao lado, o formulário aberto dentro do WhatsApp" width="640" height="360" data-path="images/formulario-conversa-light.svg" />

<img className="hidden dark:block" src="https://mintcdn.com/arara/1O3fcKz8iJHdQsj0/images/formulario-conversa-dark.svg?fit=max&auto=format&n=1O3fcKz8iJHdQsj0&q=85&s=d554708bed3f0803ed63d2f589bb6460" alt="Mensagem com botão Responder e, ao lado, o formulário aberto dentro do WhatsApp" width="640" height="360" data-path="images/formulario-conversa-dark.svg" />

Quando o cliente toca em Enviar, a conversa recebe uma mensagem de resposta e o seu webhook recebe o evento `message.flow_reply` com os campos preenchidos.

## Como faço

<Steps>
  <Step title="Crie o formulário no painel">
    Na aba **Formulários**, em Nova, você escreve as perguntas, escolhe o tipo de cada uma e confere a prévia. A Arara monta o Flow JSON, sobe para Meta e publica.

    Vale gastar um minuto na prévia: a criação já publica, e publicado não se edita.

    Depois de criado, o formulário aparece na lista com o **id**, é esse id que você usa no envio pela API e o que o botão de template aponta.

    Os limites de quem preenche o construtor: de 1 a 10 perguntas, título até 30 caracteres, introdução até 300, de 2 a 20 opções em escolha única e múltipla, com até 30 caracteres cada. Pergunta que não couber no rótulo do WhatsApp aparece como texto acima do campo, com um rótulo curto no campo, você não precisa encurtar.
  </Step>

  <Step title="Mande num template (ou direto na conversa)">
    **Com template**, use o botão `FLOW` com o `id` do formulário. Um botão de formulário por template, podendo conviver com outros botões.

    ```bash theme={null}
    curl -X POST https://api.ararahq.com/v1/templates \
      -H "Authorization: Bearer $ARARA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "captar_contato",
        "category": "MARKETING",
        "language": "pt_BR",
        "body": "Oi {{nome}}, conta para gente o que você procura?",
        "samples": { "nome": "João" },
        "buttons": [
          { "type": "FLOW", "text": "Responder", "flowId": "0b7e6a52-3c1d-4f7a-9a55-2f4f6f1f9c10" }
        ]
      }'
    ```

    Depois de aprovado, envie como qualquer outro template.

    **Sem template**, com a janela de 24h aberta, o formulário vai como mensagem interativa. Não passa por aprovação da Meta, então é o jeito mais rápido de testar: crie e mande para você mesmo.

    ```bash theme={null}
    curl -X POST https://api.ararahq.com/v1/messages \
      -H "Authorization: Bearer $ARARA_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "receiver": "5588999990000",
        "interactive": {
          "type": "flow",
          "flowId": "0b7e6a52-3c1d-4f7a-9a55-2f4f6f1f9c10",
          "body": "Pode responder rapidinho por aqui?",
          "buttonText": "Responder"
        }
      }'
    ```

    `body` é obrigatório. `buttonText` é opcional: padrão `Responder`, até 20 caracteres. Fora da janela de 24h a API recusa, e aí o caminho é o template. No dashboard, é o link **Formulário** ao lado de **Template**, na caixa de Conversas.

    O `flowId` vem da lista de formulários no painel ou de `GET /v1/flows`.
  </Step>

  <Step title="Leia a resposta">
    Cada envio chega no seu webhook como [`message.flow_reply`](/webhooks/events#message-flow_reply). Leia de `data.fields`:

    ```json theme={null}
    {
      "event": "message.flow_reply",
      "data": {
        "id": "wamid.HBgM...",
        "from": "5588999990000",
        "to": "5588911110000",
        "flow_id": "0b7e6a52-3c1d-4f7a-9a55-2f4f6f1f9c10",
        "flow_name": "Captar contato",
        "source_message_id": "c0a8012e-7d2b-4a3f-8e11-9b1f4c2d7a66",
        "fields": {
          "nome": "Ana Exemplo",
          "email": "ana@exemplo.com",
          "interesse": "Falar com vendas",
          "obs": ""
        },
        "answers": [
          { "key": "nome", "label": "Seu nome", "value": "Ana Exemplo" }
        ]
      }
    }
    ```

    Os valores já vêm legíveis: a opção escolhida chega com o texto da opção, múltipla escolha separada por vírgula, aceite como `Sim` ou `Não`, data como `dd/MM/yyyy`. Pergunta opcional sem resposta chega como string vazia, nunca ausente.

    `source_message_id` é o id da mensagem da Arara que levou o botão. Use para ligar a resposta ao envio, ao contato e à campanha.

    **A conversa não mostra o que foi respondido.** No inbox entra só uma mensagem do cliente com o texto "Formulário respondido", as respostas em si só existem em dois lugares: no webhook e no detalhe do formulário, numa lista de 50 por página em que você expande cada envio.
  </Step>
</Steps>

## O que pode dar errado

### Publicar é automático, e publicado não se edita

`POST /v1/flows` já publica. Não existe rascunho para revisar antes, nem pré-visualização no WhatsApp de formulário não publicado: quando a chamada volta `201`, ele está no ar. **Confira as perguntas, as opções e as chaves antes de criar**, é o que mais gera retrabalho aqui.

A Meta não deixa mudar um formulário que já está no ar. Não existe endpoint de edição na Arara porque não existe do outro lado. Para mudar uma pergunta, crie outro formulário e desative o antigo com `POST /v1/flows/{id}/deprecate`. Desativar mantém as respostas já recebidas e impede que o botão abra para quem recebeu a mensagem antes.

`DELETE /v1/flows/{id}` só funciona em formulário que nunca foi publicado (`DRAFT`); publicado responde `409 FLOW_NOT_DRAFT`.

### Formulário vive por número, não por conta

O formulário nasce preso ao número (à conta WhatsApp) em que foi criado. É a mesma armadilha do template:

* Se o botão de um template apontar para um formulário criado em outro número, o envio é recusado com a frase "foi criado em outro número. Recrie o formulário neste número".
* Se aquele número sair da sua conta, as ações sobre esse formulário respondem `409 FLOW_NUMBER_GONE`.
* Trocou de número ou de conexão? **Recrie o formulário**, não adianta reapontar.

O nome também é único por número, não por organização: `409 FLOW_NAME_TAKEN` quando repete.

E não existe atalho: template tem "Recriar neste número", formulário **não tem**. Não dá para duplicar nem reaproveitar. Trocou de número, você reescreve as perguntas à mão. Some isso a "publicado não se edita" e a conclusão prática é uma só: confira na prévia antes de publicar.

### A resposta casa pelo token do envio

O WhatsApp não diz qual formulário foi respondido. Ele devolve só o `flow_token` que saiu no envio, e a Arara manda ali o id do formulário mais o id da mensagem. É assim que `flow_id` e `source_message_id` aparecem no webhook.

Consequências práticas:

* O token vem do aparelho do cliente, então a Arara sempre confere se aquele formulário é da organização dona do número que recebeu. Token que não casa é ignorado, sem evento.
* Resposta que chega duas vezes (o WhatsApp reentrega) é gravada uma vez só, pelo id da mensagem do provedor.
* Se a gravação da resposta falhar, a mensagem "Formulário respondido" ainda entra na conversa, só que sem resposta guardada e sem evento. Conversa com essa mensagem e nenhum envio na lista do formulário é exatamente esse caso.

### A publicação falha sem o formulário sumir

Criar são três chamadas na Meta. Se o JSON for recusado, nada é gravado e você recebe `400 INVALID_FLOW` com o motivo. Se só a publicação falhar, o formulário fica em **rascunho** com o erro da Meta anotado. Ele aparece assim na lista e você manda publicar de novo pelo painel, sem reescrever as perguntas.

### Chave de campo é decisão de uma vez só

Sem `key`, a chave nasce do texto da pergunta (`Seu melhor e-mail` vira `seu_melhor_e_mail`). Como o formulário publicado não se edita, essa chave vai viver com você. Defina a sua sempre que o handler do outro lado já existir.

## Referência

### Limites de cada campo

| Campo | Regra |
| - | - |
| `name` | Até 120 caracteres, único por número. Só você vê. |
| `category` | `SIGN_UP`, `LEAD_GENERATION`, `SURVEY`, `APPOINTMENT_BOOKING`, `CONTACT_US` ou `OTHER`. |
| `title` | Até 30 caracteres. Aparece no topo do formulário. |
| `intro` | Opcional, até 300 caracteres. |
| `submitLabel` | Até 30 caracteres. Padrão `Enviar`. |
| `fields` | De 1 a 10 perguntas. |
| `fields[].type` | `TEXT`, `LONG_TEXT`, `EMAIL`, `PHONE`, `NUMBER`, `SELECT`, `MULTI_SELECT`, `DATE`, `OPT_IN`. |
| `fields[].label` | Até 80 caracteres no request. Pergunta que não couber no rótulo do WhatsApp aparece como texto acima do campo, com um rótulo curto no campo, você não precisa encurtar nada. |
| `fields[].options` | Só em `SELECT` e `MULTI_SELECT`: de 2 a 20 opções, até 30 caracteres cada. |
| `fields[].required` | Padrão `true`. |
| `fields[].key` | Minúsculas, números e `_`, começando por letra, até 40 caracteres. É o nome do campo no webhook. |

### Endpoints

```bash theme={null}
GET    /v1/flows?page=0&size=20
GET    /v1/flows/{id}
GET    /v1/flows/{id}/responses?page=0&size=50
POST   /v1/flows
POST   /v1/flows/{id}/publish
POST   /v1/flows/{id}/deprecate
DELETE /v1/flows/{id}
POST   /v1/flows/{id}/test
GET    /v1/flows/{id}/responses.csv
```

Listas seguem o formato `{ data, pagination }`.

### Erros

| Status | `error.code` | Quando |
| - | - | - |
| 400 | `INVALID_FLOW` | Pergunta em branco, opções de menos, chave inválida ou JSON recusado pela Meta. |
| 403 | `PLAN_FEATURE_LOCKED` | Plano abaixo do Voo. |
| 404 | `FLOW_NOT_FOUND` | Formulário inexistente ou de outra organização. |
| 409 | `FLOW_NAME_TAKEN` | Já existe formulário com esse nome no número. |
| 409 | `FLOW_NUMBER_REQUIRED` | Nenhum número conectado. |
| 409 | `FLOW_NUMBER_GONE` | O número em que o formulário foi criado saiu da conta. |
| 409 | `FLOW_NOT_DRAFT` / `FLOW_NOT_PUBLISHED` | Ação que não cabe no estado atual. |

## Próximos passos

<CardGroup cols={2}>
  <Card title="Mensagens" icon="message" href="/api-reference/messages">
    Enviar o formulário por POST /v1/messages.
  </Card>

  <Card title="Webhooks" icon="webhook" href="/webhooks/events">
    Evento message.flow\_reply.
  </Card>

  <Card title="Templates" icon="file-lines" href="/concepts/templates">
    Botão de formulário em template.
  </Card>
</CardGroup>


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