> ## 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.

# Envie sua primeira mensagem

> Da chave de API à primeira mensagem de WhatsApp entregue, com cURL, Node, Python e PHP.

export const DemoWhatsApp = () => {
  const ENDPOINT = 'https://ararahq.com/api/demo-recuperacao';
  const PAGINA_DEMO = 'https://ararahq.com/demo';
  const CENARIO = 'carrinho';
  const DIGITOS_CELULAR = 11;
  const TEMPO_LIMITE_MS = 15000;
  const HTTP_CRIADO = 201;
  const HTTP_INVALIDO = 400;
  const HTTP_LIMITE = 429;
  const [nome, setNome] = useState('');
  const [telefone, setTelefone] = useState('');
  const [aceite, setAceite] = useState(false);
  const [envio, setEnvio] = useState({
    estado: 'parado',
    mensagem: ''
  });
  const soDigitos = valor => {
    const digitos = valor.replace(/\D/g, '');
    const semDdi = digitos.length > DIGITOS_CELULAR && digitos.startsWith('55') ? digitos.slice(2) : digitos;
    return semDdi.slice(0, DIGITOS_CELULAR);
  };
  const mascara = digitos => {
    if (digitos.length <= 2) return digitos.length === 0 ? '' : `(${digitos}`;
    const resto = digitos.slice(2);
    if (resto.length <= 5) return `(${digitos.slice(0, 2)}) ${resto}`;
    return `(${digitos.slice(0, 2)}) ${resto.slice(0, 5)}-${resto.slice(5)}`;
  };
  const digitos = soDigitos(telefone);
  const telefoneOk = digitos.length === DIGITOS_CELULAR && digitos[2] === '9';
  const pronto = nome.trim().length >= 2 && telefoneOk && aceite && envio.estado !== 'enviando';
  const mensagemDe = corpo => corpo && typeof corpo === 'object' && corpo.error && typeof corpo.error.message === 'string' ? corpo.error.message : '';
  const enviar = async evento => {
    evento.preventDefault();
    if (!pronto) return;
    setEnvio({
      estado: 'enviando',
      mensagem: ''
    });
    try {
      const resposta = await fetch(ENDPOINT, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          name: nome.trim(),
          phone: digitos,
          scenario: CENARIO,
          consent: true
        }),
        signal: AbortSignal.timeout(TEMPO_LIMITE_MS)
      });
      if (resposta.status === HTTP_CRIADO) {
        setEnvio({
          estado: 'enviado',
          mensagem: ''
        });
        return;
      }
      const corpo = await resposta.json().catch(() => null);
      if (resposta.status === HTTP_INVALIDO) {
        setEnvio({
          estado: 'invalido',
          mensagem: 'Confira o nome e o número com DDD.'
        });
        return;
      }
      if (resposta.status === HTTP_LIMITE) {
        setEnvio({
          estado: 'limite',
          mensagem: mensagemDe(corpo) || 'Limite de demonstrações atingido. Tente mais tarde.'
        });
        return;
      }
      setEnvio({
        estado: 'erro',
        mensagem: ''
      });
    } catch {
      setEnvio({
        estado: 'erro',
        mensagem: ''
      });
    }
  };
  const campo = 'w-full rounded-lg border border-gray-300 dark:border-gray-700 bg-transparent px-3 py-2 text-sm text-gray-900 dark:text-gray-100 placeholder-gray-400';
  const rotulo = 'mb-1 block text-sm font-medium text-gray-900 dark:text-gray-100';
  if (envio.estado === 'enviado') {
    return <div role="status" className="not-prose my-6 rounded-xl border border-gray-200 dark:border-gray-800 p-5">
        <p className="text-base font-semibold text-gray-900 dark:text-gray-100">Enviado. Olhe o seu WhatsApp.</p>
        <p className="mt-1 text-sm text-gray-600 dark:text-gray-400">
          A mensagem chega em alguns segundos, pelo número de demonstração da Arara. Abaixo está a chamada que acabou
          de rodar.
        </p>
      </div>;
  }
  return <form onSubmit={enviar} className="not-prose my-6 rounded-xl border border-gray-200 dark:border-gray-800 p-5">
      <div className="grid gap-4 sm:grid-cols-2">
        <div>
          <label htmlFor="demo-nome" className={rotulo}>
            Seu nome
          </label>
          <input id="demo-nome" name="nome" type="text" autoComplete="given-name" maxLength={60} value={nome} onChange={evento => setNome(evento.target.value)} className={campo} required />
        </div>
        <div>
          <label htmlFor="demo-telefone" className={rotulo}>
            Seu WhatsApp, com DDD
          </label>
          <input id="demo-telefone" name="telefone" type="tel" inputMode="numeric" autoComplete="tel-national" placeholder="(11) 99999-9999" value={mascara(digitos)} onChange={evento => setTelefone(evento.target.value)} className={campo} required />
        </div>
      </div>

      <label className="mt-4 flex items-start gap-2 text-sm text-gray-700 dark:text-gray-300">
        <input id="demo-aceite" name="aceite" type="checkbox" checked={aceite} onChange={evento => setAceite(evento.target.checked)} className="mt-0.5" required />
        <span>Autorizo a Arara a enviar esta demonstração para este número.</span>
      </label>

      <button type="submit" disabled={!pronto} className="mt-4 rounded-lg bg-primary dark:bg-primary-light px-4 py-2 text-sm font-semibold text-white dark:text-gray-950 disabled:opacity-50">
        {envio.estado === 'enviando' ? 'Enviando...' : 'Receber no meu WhatsApp'}
      </button>

      {envio.estado === 'invalido' || envio.estado === 'limite' ? <p role="alert" className="mt-3 text-sm text-red-600 dark:text-red-400">
          {envio.mensagem}
        </p> : null}

      {envio.estado === 'erro' ? <p role="alert" className="mt-3 text-sm text-red-600 dark:text-red-400">
          Não foi possível enviar daqui agora.{' '}
          <a href={PAGINA_DEMO} target="_blank" rel="noopener noreferrer" className="underline">
            Abra a demonstração em outra aba
          </a>
          .
        </p> : null}

      <p className="mt-3 text-xs text-gray-500 dark:text-gray-400">
        Uma demonstração por número por dia.
      </p>
    </form>;
};

Ao fim desta página você terá enviado uma mensagem de WhatsApp pela API e consultado o status dela.

## Veja chegar no seu WhatsApp

Antes de configurar qualquer coisa, receba uma mensagem enviada pela API. Ela sai do número de demonstração da Arara e não exige conta.

<DemoWhatsApp />

A demonstração roda esta chamada, a mesma que você vai fazer com a sua chave. É um template de carrinho abandonado com [cobrança](/cobrancas):

```bash theme={null}
curl -X POST https://api.ararahq.com/v1/messages \
  -H "Authorization: Bearer $ARARA_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: carrinho-8842" \
  -d '{
    "receiver": "+5511999999999",
    "templateName": "arara_recovery_cart_abandoned_charge_pt_br",
    "templateVariables": ["Ana", "Tênis Runner e mais 3 itens", "R$ 449,50"],
    "charge": {
      "referenceId": "carrinho-8842",
      "items": [
        { "name": "Tênis Runner", "amountCents": 29990 },
        { "name": "Meia cano alto", "amountCents": 2490, "quantity": 2 },
        { "name": "Boné", "amountCents": 7990 }
      ],
      "shippingCents": 1990,
      "paymentLink": "https://sualoja.com.br/checkout/8842"
    }
  }'
```

Para enviar do seu número, com os seus templates, siga os passos abaixo.

## Antes de começar

Todo envio pela API é real e sai do seu número. Para o primeiro envio a sua organização precisa de:

1. **Plano assinado.** Sem assinatura a API recusa o envio com `403 ACCOUNT_NOT_ACTIVATED`. Assine em [Faturamento](https://app.ararahq.com/dashboard/faturamento). Veja os planos em [Preços](/concepts/pricing).
2. **Número conectado.** Conecte em [Números](https://app.ararahq.com/dashboard/numeros). Veja [Números](/numbers).
3. **Um template aprovado pela Meta.** Crie em [Templates](https://app.ararahq.com/dashboard/templates). Veja [Templates](/concepts/templates).
4. **Saldo na carteira.** Recarregue em [Faturamento](https://app.ararahq.com/dashboard/faturamento). Veja [Carteira](/concepts/pricing#carteira).

Criar a conta e gerar a chave de API não exige plano. Você pode conectar o número e criar o template antes de assinar.

## Passo a passo

<Steps>
  <Step title="Pegue sua chave de API">
    Crie uma chave em [Chaves de API](https://app.ararahq.com/dashboard/apikeys). O valor completo aparece uma única vez.

    Guarde em variável de ambiente:

    ```bash theme={null}
    export ARARA_API_KEY=ara_live_...
    ```

    <Warning>
      Nunca coloque a chave no código, no frontend ou em repositório.
    </Warning>
  </Step>

  <Step title="Envie a mensagem">
    Troque `+5511999999999` pelo seu número de WhatsApp. Troque `pedido_confirmado` pelo nome do seu template aprovado e `templateVariables` pelos valores das variáveis dele, na ordem.

    <CodeGroup>
      ```bash cURL theme={null}
      curl -X POST https://api.ararahq.com/v1/messages \
        -H "Authorization: Bearer $ARARA_API_KEY" \
        -H "Content-Type: application/json" \
        -d '{
          "receiver": "+5511999999999",
          "templateName": "pedido_confirmado",
          "templateVariables": ["João", "12345"]
        }'
      ```

      ```javascript Node.js theme={null}
      // enviar.js
      // Instale: npm install @ararahq/sdk
      // Rode:    node enviar.js
      const { NodeSDK } = require('@ararahq/sdk');

      const sdk = new NodeSDK({ apiKey: process.env.ARARA_API_KEY });

      async function main() {
        const response = await sdk.messages.send({
          receiver: '+5511999999999',
          templateName: 'pedido_confirmado',
          templateVariables: ['João', '12345'],
        });

        console.log(response.id, response.status);
      }

      main().catch((err) => {
        console.error(err);
        process.exit(1);
      });
      ```

      ```python Python theme={null}
      # enviar.py
      # Instale: pip install ararahq-sdk
      # Rode:    python enviar.py
      from arara_api_sdk import AraraClient
      from arara_api_sdk.models.message import SendMessageRequest

      with AraraClient() as client:  # lê ARARA_API_KEY do ambiente
          response = client.messages.send(SendMessageRequest(
              receiver="+5511999999999",
              template_name="pedido_confirmado",
              template_variables=["João", "12345"],
          ))

      print(response.id, response.status)
      ```

      ```php PHP theme={null}
      <?php
      // enviar.php
      // Instale: composer require ararahq/sdk
      // Rode:    php enviar.php
      require __DIR__ . '/vendor/autoload.php';

      use Arara\Arara;
      use Arara\Config;

      $sdk = new Arara(new Config(apiKey: getenv('ARARA_API_KEY')));

      $response = $sdk->messages->send(
          receiver: '+5511999999999',
          templateName: 'pedido_confirmado',
          variables: ['João', '12345'],
      );

      echo $response['id'] . ' ' . $response['status'] . PHP_EOL;
      ```
    </CodeGroup>
  </Step>

  <Step title="Veja a resposta">
    A API responde `202 Accepted`. A mensagem foi aceita e entrou na fila de envio.

    ```json theme={null}
    {
      "id": "ara_msg_k9Bf2Xq",
      "status": "PENDING",
      "mode": "LIVE",
      "sender": "whatsapp:+5511888888888",
      "receiver": "+5511999999999",
      "body": "Olá João, seu pedido 12345 foi confirmado.",
      "cost": 0.3835,
      "reason": null
    }
    ```

    `status` começa em `PENDING` e passa por `SENT`, `DELIVERED` e `READ`, ou termina em `FAILED` com o motivo em `reason`. Na API o status vem em maiúsculas. No webhook vem em minúsculas (`sent`, `delivered`, `read`, `failed`).

    Guarde o `id`. Você usa ele no próximo passo.
  </Step>

  <Step title="Consulte o status">
    Troque `ara_msg_k9Bf2Xq` pelo `id` que você recebeu:

    ```bash theme={null}
    curl https://api.ararahq.com/v1/messages/ara_msg_k9Bf2Xq \
      -H "Authorization: Bearer $ARARA_API_KEY"
    ```

    A resposta tem o mesmo formato do passo anterior, com o `status` atual.

    Em produção, não consulte em loop. Receba cada mudança de status por [webhook](/webhooks).
  </Step>
</Steps>

## Deu erro?

| Resposta | O que aconteceu | O que fazer |
| - | - | - |
| `401` | A chave não existe, foi revogada, expirou ou não começa com `ara_live_`. | Confira o valor de `ARARA_API_KEY`. |
| `403` sem `error.code` | O header `Authorization` não chegou, ou a chave não tem permissão de envio. | Confira o header `Authorization: Bearer ...` e a permissão `MESSAGES_SEND` da chave. |
| `403 ACCOUNT_NOT_ACTIVATED` | A organização ainda não tem plano assinado (`details.reason` = `FIRST_SUBSCRIPTION_REQUIRED`). | Assine um plano em [Faturamento](https://app.ararahq.com/dashboard/faturamento). |
| `403 NO_DEDICATED_NUMBER` | A organização não tem número conectado. | Conecte um número em [Números](https://app.ararahq.com/dashboard/numeros). |
| `409 CONFLICT` | Não existe template com esse nome na sua organização. | Confira o `templateName` em [Templates](https://app.ararahq.com/dashboard/templates). |
| `422 TEMPLATE_NOT_SENDABLE` | O template ainda está em análise, foi reprovado ou desativado. | Aguarde a aprovação da Meta ou corrija o template. |
| `422 TEMPLATE_VARIABLES_MISMATCH` | A quantidade de variáveis não bate com o template. | Compare `templateVariables` com `details.expected`. |
| `422 INVALID_RECIPIENT` | O telefone não é válido. | Use o formato `+5511999999999`, com código do país e DDD. |
| `402 INSUFFICIENT_FUNDS` | A carteira não tem saldo para a mensagem. | Recarregue em [Faturamento](https://app.ararahq.com/dashboard/faturamento). |

A resposta foi `202` mas a mensagem não chegou? Veja [Erros de envio](/erros-de-envio). A lista completa de recusas está em [Erros](/erros).

## Próximos passos

<CardGroup cols={2}>
  <Card title="Webhooks" icon="bell" href="/webhooks">
    Receba status de entrega e mensagens dos clientes.
  </Card>

  <Card title="Templates" icon="file-lines" href="/concepts/templates">
    Categorias, aprovação e variáveis.
  </Card>

  <Card title="SDKs" icon="cube" href="/sdks">
    Bibliotecas oficiais, incluindo Java e Go.
  </Card>

  <Card title="Convenções da API" icon="code" href="/api-reference/introduction">
    Idempotência, paginação e rate limit.
  </Card>
</CardGroup>


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