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

# Humanizador de saída

> Respostas com pausa e 'digitando', áudio por ElevenLabs com prévia, resposta em áudio e aviso de assistente virtual.

O Convex (ou o motor de fluxo) decide a resposta; o ZapMeow a **executa** como uma pessoa: espera, mostra "digitando…" ou "gravando áudio…", e só então envia. Tudo vem da config do tenant da sessão (`humanizer`, `voice` e `roles`, em `/admin/tenants/{id}/config`).

Quem não quer humanizar continua usando `POST /api/sendText` e `sendVoice`, que enviam na hora.

## Enfileirar

`POST /api/{sessão}/outbox` responde `202` com o item. O envio acontece em segundo plano, **em ordem por conversa** (conversas diferentes andam juntas).

| Campo | O que é |
| - | - |
| `chatId` | conversa (`…@c.us` ou `…@g.us`) |
| `text` | a resposta (até 4000 caracteres; 4500 se virar áudio) |
| `as` | `auto` (padrão), `text` ou `audio` |
| `inbound` | o que o lead mandou por último (`audio` ou `text`); sem ele, o ZapMeow lê o histórico da conversa |
| `stage` | etapa do funil; decide a voz (papel da etapa) e o envio direto |
| `role` | papel/vendedor cuja voz fala (`roles` na config) |
| `voiceId` | voz explícita; vence papel e config |
| `reply_to` | id WAHA da mensagem a citar |
| `fallbackText` | booleano: se o TTS falhar, envia o texto em vez de falhar |
| `idempotencyKey` | repetir a mesma chave devolve o item que já existe e não envia de novo |

Estados: `queued` → `sending` → `sent` | `failed`; áudio com prévia passa por `awaiting_preview` → `queued` (aprovado) ou `rejected`.

## Regras (config `humanizer`)

* **Pausa e presença.** Antes de enviar, espera um tempo e mostra a presença (renovada a cada 8 s). Texto: `tamanho ÷ charsPerSecond` (com ±10%), ou um valor sorteado entre `minDelayMs` e `maxDelayMs`. Áudio: a duração do áudio. Sempre limitado a `[minDelayMs, maxDelayMs]`; `maxDelayMs = 0` desliga a pausa. `typingEnabled = false` mantém a pausa mas sem mostrar "digitando".
* **Áudio por TTS.** O modelo é **sempre `eleven_v4_turbo`**, fixo no código: não há recuo para outro modelo e `voice.modelId` da config não vale para este TTS. A voz vem de `voiceId` do pedido > papel (pelo nome ou pela etapa) > `voice.voiceId`. `stability` e `similarity` só vão à ElevenLabs se estiverem na config; sem eles valem os parâmetros salvos da voz no painel da ElevenLabs. A chave da ElevenLabs fica no cofre do tenant com o nome `elevenlabs_api_key`; só o tenant Glow cai na variável `ELEVENLABS_API_KEY` da plataforma. A saída é Ogg Opus (`ZAPMEOW_TTS_FORMAT`, padrão `opus_48000_32`) e vai como nota de voz; outro formato vai como áudio comum.
* **Tags de voz.** O v4 turbo interpreta tags entre colchetes, de entonação e de efeito sonoro (`[warmly]`, `[laughs softly]`, `[pausa]`, `[sussurrando]`, `[som de porta]`). O TTS comum da ElevenLabs **não tem** gerador automático de tags (o `expressive_mode` existe só no ElevenLabs Agents, que a ligação já usa): quem escreve a resposta (Convex ou motor de fluxo) deve incluir as tags no `text`. O ZapMeow entrega o texto com as tags ao TTS e **nunca as manda ao lead**: no envio como texto e no `fallbackText` elas são removidas (só as reconhecidas; `[Glow]` ou `[1]` ficam). Texto só com tags falha em vez de sair vazio.
* **Prévia.** Com `audioPreview = true` (padrão) o áudio gerado **não sai**: o item fica em `awaiting_preview`, sem presença nem mensagem para o lead. Toque com `GET …/outbox/{id}/audio`; envie com `POST …/approve` ou descarte com `POST …/reject` (`{"asText": true}` manda a mesma resposta como texto).
* **Envio direto por etapa.** Etapas em `audioDirectStages` (sem diferenciar maiúsculas) pulam a prévia. Com `audioPreview = false` nenhum áudio passa por prévia.
* **Áudio responde áudio.** Com `audioReplyToAudio = true` e `as = auto`, a resposta sai em áudio quando a última mensagem do lead foi áudio.
* **Aviso de assistente virtual.** Com `virtualAssistantNotice = true`, a primeira mensagem de cada conversa é precedida do aviso (`virtualAssistantText` ou um texto padrão), uma vez só. No áudio com prévia, o aviso sai junto com o áudio aprovado.

## Prévia e acompanhamento

| Método e rota | O que faz |
| - | - |
| `GET /api/{sessão}/outbox?status=&chatId=&limit=` | lista, do mais novo ao mais antigo |
| `GET /api/{sessão}/outbox/{id}` | um item |
| `GET /api/{sessão}/outbox/{id}/audio` | o áudio da prévia (`audio/ogg`) |
| `POST /api/{sessão}/outbox/{id}/approve` | libera o áudio (`202`); `409` se não espera prévia |
| `POST /api/{sessão}/outbox/{id}/reject` | descarta; `{"asText": true}` reenvia como texto |

Eventos no webhook e no stream: `outbox.preview` (há áudio esperando OK), `outbox.sent` e `outbox.failed`, com o item no `payload`.

## Detalhes

* O áudio é apagado depois de enviado ou recusado. Itens `sent`, `failed` e `rejected` somem após 14 dias.
* Reinício: o que estava `sending` vira `failed` (pode ter saído; não repete); o que estava `queued` segue depois de 20 s.
* Um áudio que espera prévia não trava as mensagens seguintes da mesma conversa. Quem decide a resposta controla a ordem.
* Erros: `400` corpo inválido, `404` item de outra sessão ou inexistente, `409` estado errado.


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