# Envio para um contato

Todas as rotas abaixo exigem `--lgpd` (cabeçalho `X-LGPD-Consent-Logged: true`) e aceitam `--idempotencia`. Em
produção, também `--confirmado`, depois do "sim" do usuário.

Campos comuns a todos os canais:

- `contactName` (opcional, até 120 caracteres): o nome do contato, para o histórico.
- `reference` (opcional, até 100, numa linha): o seu identificador (pedido, lead). Volta na resposta e no webhook.

Telefone (`to`): de 10 a 15 dígitos, com o código do país — `5511987654321` ou `+351912345678`. Ligação e vídeo só
para números do Brasil.

## WhatsApp (conexão por QR Code) — `POST /v1/whatsapp/messages` · `messages.whatsapp.send`

```json
{ "to": "5511987654321", "text": "Olá Carlos, preparamos uma proposta para a sua empresa.", "contactName": "Carlos Silva", "reference": "pedido-4521" }
```

- `text` obrigatório, até 4.096 caracteres.
- `from` (opcional): qual número da conta envia, pelo nome que aparece em `GET /v1/channels`.
- `reply: true` (opcional): marca como resposta. Se o contato escreveu pelo WhatsApp nos últimos 7 dias, a mensagem
  sai também fora da janela e não conta como abordagem do dia; se não escreveu, vale como abordagem normal.

## WhatsApp Oficial (API da Meta) — `POST /v1/whatsapp-official/messages` · `messages.whatsappOfficial.send`

```json
{ "to": "5511987654321", "template": { "name": "proposta_comercial", "language": "pt_BR", "params": ["Carlos"] }, "reference": "pedido-4521" }
```

- Envie `template` **ou** `text`, nunca os dois. O modelo precisa estar aprovado pela Meta na conta.
- `text` (até 4.096) só para responder dentro das 24 h da última mensagem do contato; passou disso, 409 `template_required`.
- `template.params`: até 20 textos, na ordem das variáveis do modelo.

## SMS — `POST /v1/sms/messages` · `messages.sms.send`

```json
{ "to": "5511987654321", "text": "Ola Carlos, sua proposta esta pronta. Confira no e-mail de hoje." }
```

- `text` obrigatório. A plataforma acrescenta o "P/ SAIR digite SAIR"; com ele, a mensagem cabe em até 10 SMS
  (senão 400 `SMS_TOO_LONG`, com `segments`). A resposta diz quantos SMS (`segments`) e créditos foram usados.
- Janela própria: segunda a sábado, das 09:00 às 12:00 e das 13:30 às 22:00 (Brasília).

## E-mail — `POST /v1/email/messages` · `messages.email.send`

```json
{ "to": "carlos@empresa.example", "subject": "Proposta exclusiva", "text": "Olá Carlos,\npreparamos uma proposta." }
```

- Um destinatário por chamada. `subject` obrigatório (até 200).
- Exatamente um corpo: `text` (até 50.000) **ou** `html` (até 200.000).
- O e-mail de login da conta precisa estar confirmado (senão 403 `email_unverified`).
- 422 `recipient_rejected`: o servidor do destinatário recusou (endereço inexistente costuma vir com `hardBounce`).

## Ligação com IA — `POST /v1/voice/calls` · `calls.voice.create`

```json
{ "to": "5511987654321", "script": "Olá, aqui é a Ana, da Empresa Exemplo. Posso enviar a proposta pelo WhatsApp?" }
```

- `script` obrigatório (até 2.500): o roteiro que a IA usa na conversa. Só números do Brasil.
- Cobrada por minuto, em reais, da carteira de voz. O status passa por `calling`, `answered` / `not_answered`;
  no fim aparecem `durationSeconds`, `billedMinutes` e `chargedBrl`.

## Vídeo com avatar — `POST /v1/video/messages` · `messages.video.send`

```json
{ "to": "5511987654321", "script": "Olá Carlos! Gravei este vídeo para apresentar a proposta que preparamos." }
```

- `script` obrigatório (até 1.200). Destino: `to` (telefone do Brasil), `email`, ou os dois.
- O vídeo é gerado depois: o status começa em `processing`.

## Resposta

Sucesso: `201` (ou `202` quando o desfecho ainda não é conhecido):

```json
{ "id": "MSG-MG1ABC2-7F3E1A", "channel": "whatsapp", "status": "sent", "to": "5511987654321", "reference": "pedido-4521", "creditsUsed": 1, "createdAt": "2026-09-18T14:02:11.000Z", "statusUrl": "/v1/messages/MSG-MG1ABC2-7F3E1A" }
```

Com a chave de sandbox: `{ "dryRun": true, "accepted": true, "channel": "…", "to": "…" }` — nada sai e nada é cobrado.
Repetir com a mesma `Idempotency-Key` (24 h) devolve a primeira resposta com `idempotentReplay: true`.

## Acompanhar

- `GET /v1/messages/{messageId}` (`messages.get`): status atual — `sent`, `delivered`, `read`, `replied`, `failed`,
  `blocked`, `unknown`, `calling`, `answered`, `not_answered`, `processing` — com `deliveredAt`, `readAt` e
  `repliedAt` quando houver. O registro fica 90 dias.
- `GET /v1/messages?limit=20` (`messages.list`, até 50): os últimos envios da conta, com o status do momento do envio.
  Serve para recuperar o `id` depois de um tempo esgotado; o status atual sai em `statusUrl`.
- Para saber na hora, sem consultar: o webhook (veja [lgpd-bloqueios-webhooks.md](lgpd-bloqueios-webhooks.md)).

## Recusas mais comuns

| Código | O que fazer |
| --- | --- |
| 409 `outside_send_window` | Fora da janela; `nextOpenAt` diz quando abre. Agende para depois. |
| 409 `daily_outreach_limit` | Esse contato já foi abordado hoje nesse canal. Tente amanhã ou outro canal. |
| 403 `contact_blocked` / `contact_opt_out` | O contato está bloqueado ou pediu para sair. Não insista. |
| 402 `CREDITOS_INSUFICIENTES` | Falta saldo (`missing`). Ofereça a recarga por Pix. |
| 409 `whatsapp_not_connected` | Nenhum número de WhatsApp conectado (`GET /v1/channels`). |
| 422 `content_blocked` | Texto com termo proibido ou link encurtado (`terms`). Reescreva. |

Todos os códigos: [erros.md](erros.md).
