Revenda por API — Alfred Voice
Esta página é para quem vai colocar o Alfred Voice dentro do próprio sistema (um CRM, uma plataforma de atendimento) e oferecer para os seus clientes: agentes de IA no WhatsApp e no site, ligação com agente, torpedo de voz e SMS.
A ideia em uma frase: você tem uma conta de revendedor; cada cliente seu vira uma subconta; você age em nome de qualquer subconta mandando um header.
- Base:
https://alfredvoice.com.br/api - Autenticação:
Authorization: Bearer av_...(a chave de API da sua conta de revendedor) - Agir em nome de um cliente seu: header
X-Subconta: <id da subconta> - Formato: JSON em tudo (
Content-Type: application/json), exceto o envio de arquivo de áudio - Erros: sempre
{"error":"CODIGO"}com o código HTTP correspondente (tabela completa na seção 15) - Dinheiro: sempre em centavos inteiros (
5000= R$ 50,00) - Datas: em UTC, no formato
AAAA-MM-DD HH:MM:SS - Para o seu desenvolvedor começar rápido: baixe o arquivo de integração (botão no menu ao lado) e importe no Postman ou Insomnia — explicado em Arquivo de integração
A parte básica (criar chave, testar a chave, assinatura dos avisos, reenvio) está em Integração por API. Esta página cobre tudo o que é próprio da revenda.
1. Como funciona
Sua conta de revendedor ── saldo (você recarrega por PIX no painel)
├── Subconta "Pizzaria do João" ── agentes, WhatsApp, balão do site, torpedos, SMS, saldo próprio
├── Subconta "Clínica Sorriso" ── idem
└── ...- Você recarrega a sua conta pelo painel (Carteira → Recarregar, PIX na hora).
- Cria uma subconta para cada cliente seu, com o id que ele tem no seu sistema (
referencia). - Transfere saldo da sua conta para a subconta. O consumo do cliente sai do saldo dele — um cliente nunca gasta o saldo de outro.
- Opera em nome do cliente mandando
X-Subcontanas rotas: criar agente, conectar o WhatsApp, ligar o balão do site, disparar torpedo, mandar SMS, ler as conversas. - Recebe tudo no seu servidor por aviso automático, com a subconta identificada.
- Consulta o consumo de cada cliente no período e fatura ele como quiser. O preço que você cobra do seu cliente é decisão sua; do nosso lado a tarifa é a da sua conta.
Os seus clientes não têm login no Alfred Voice: eles só existem pelo seu sistema. No painel, o menu Revenda mostra os seus clientes, o saldo de cada um e o consumo, para você conferir e resolver na mão.
2. Antes de começar
- Revenda liberada: a conta precisa estar com a revenda ligada pela nossa equipe. Sem isso, as rotas de revenda respondem
403 SEM_REVENDA. - Chave de API: crie em Conta → Chaves de API (a chave aparece uma vez só). Até 5 chaves ativas; use uma para testes e outra para produção.
- Aviso automático: cadastre em Conta → Aviso automático a URL
https://que vai receber os eventos. Os eventos de todas as suas subcontas chegam nela (seção 13). - Teste com o seu próprio celular antes de pôr cliente real (roteiro na seção 17).
Arquivo de integração (Postman / Insomnia)
Além desta página, existe um arquivo de integração: é a lista de todas as rotas da API num formato padrão que os programas de desenvolvedor entendem sozinhos (chamado OpenAPI). Não é para ler — é para o seu desenvolvedor importar e ter tudo pronto para testar, sem digitar rota nenhuma.
Baixar: use o botão Baixar arquivo de integração no menu ao lado (sai o arquivo alfred-voice-api.json). Ou importe direto pelo endereço https://alfredvoice.com.br/api/openapi.json, que é sempre a versão mais nova.
No Postman
- Clique em Import (canto superior esquerdo).
- Arraste o arquivo
alfred-voice-api.json— ou escolha Link e colehttps://alfredvoice.com.br/api/openapi.json. - Confirme em Import. Aparece a coleção Alfred Voice — API, com as rotas separadas em pastas: revenda, agentes, canais, conversas, voz, sms, ligações.
- Abra a coleção → aba Authorization → tipo Bearer Token → cole a sua chave
av_.... Todas as rotas passam a usar a chave. - Nas rotas que agem em nome de um cliente, marque o header X-Subconta e coloque o
idda subconta. Sem ele, a chamada vale para a sua própria conta. - Clique em Send. A resposta aparece embaixo — os formatos e os erros são os desta página.
No Insomnia
Create → Import → cole o endereço https://alfredvoice.com.br/api/openapi.json (ou escolha o arquivo baixado). A chave vai em Auth → Bearer Token, e o X-Subconta em Headers.
Gerar código de integração
Com o mesmo arquivo, ferramentas como o OpenAPI Generator (gratuito) geram o código de acesso à API na linguagem do seu sistema — PHP, Node, Python, Java, C# e outras. O desenvolvedor parte de um cliente pronto em vez de escrever cada chamada à mão.
Sempre atualizado
O arquivo é publicado junto com cada atualização da API, e o campo version mostra a data da versão. Se o seu desenvolvedor importou pelo endereço, basta reimportar para pegar as novidades. Toda rota citada no arquivo e nesta página é conferida automaticamente a cada atualização nossa: se está escrita aqui, existe de verdade.
3. Subcontas
Criar
curl -X POST https://alfredvoice.com.br/api/revenda/subcontas \
-H "Authorization: Bearer av_..." \
-H "Content-Type: application/json" \
-d '{"nome":"Pizzaria do João","referencia":"crm-cliente-1042"}'{"id":2,"nome":"Pizzaria do João","referencia":"crm-cliente-1042","ativa":true,"saldoCentavos":0,"disponivelCentavos":0,"criadaEm":"2026-09-24 15:05:37"}| Campo | Obrigatório | Descrição |
|---|---|---|
nome | sim | Nome do seu cliente (até 120 caracteres). Também vira o nome do primeiro agente dele. |
referencia | não | O id desse cliente no seu sistema (até 120). Única por revendedor: repetir dá 409 REFERENCIA_EM_USO. |
Guarde o id devolvido: é ele que vai no header X-Subconta. A subconta nasce com um agente de ligação pronto, a mesma tarifa da sua conta, saldo zero e sem login no painel.
Listar e achar pela sua referência
curl "https://alfredvoice.com.br/api/revenda/subcontas?referencia=crm-cliente-1042" \
-H "Authorization: Bearer av_..."{"subcontas":[{"id":2,"nome":"Pizzaria do João","referencia":"crm-cliente-1042","ativa":true,"saldoCentavos":0,"disponivelCentavos":0,"criadaEm":"2026-09-24 15:05:37"}],"temMais":false,"proximoAntesDe":null}Sem referencia, lista todas (50 por página, limite até 200). Para a próxima página, mande antesDe com o proximoAntesDe recebido.
Ver, editar, desativar
GET /revenda/subcontas/:id: uma subconta.PUT /revenda/subcontas/:idcom qualquer um denome,referenciaeativa.
curl -X PUT https://alfredvoice.com.br/api/revenda/subcontas/2 \
-H "Authorization: Bearer av_..." -H "Content-Type: application/json" \
-d '{"ativa":false}'Subconta desativada não faz nada novo: qualquer chamada com X-Subconta dela responde 403 SUBCONTA_INATIVA, ela não recebe transferência e o link de conexão dela deixa de valer. Campanha que já estava discando continua até o fim; se quiser interromper, pause ou pare a campanha antes de desativar (seção 9). Reativar é {"ativa":true}.
Resumo da sua conta
curl https://alfredvoice.com.br/api/revenda -H "Authorization: Bearer av_..."{"saldoCentavos":50000,"disponivelCentavos":50000,"subcontas":{"total":1,"ativas":1,"maximo":100,"saldoCentavos":4000}}subcontas.saldoCentavos é a soma do que está nas mãos dos seus clientes. O limite de subcontas (maximo) é combinado com a nossa equipe.
4. Saldo: transferir e devolver
Transferir para o cliente
curl -X POST https://alfredvoice.com.br/api/revenda/subcontas/2/transferir \
-H "Authorization: Bearer av_..." \
-H "Content-Type: application/json" \
-H "Idempotency-Key: pedido-778" \
-d '{"valorCentavos":5000}'{"id":1,"subcontaId":2,"sentido":"envio","valorCentavos":5000,"criadaEm":"2026-09-24 15:05:37","repetida":false,
"subconta":{"id":2,"nome":"Pizzaria do João","referencia":"crm-cliente-1042","ativa":true,"saldoCentavos":5000,"disponivelCentavos":5000,"criadaEm":"2026-09-24 15:05:37"},
"revendedor":{"saldoCentavos":45000}}Devolver para você
POST /revenda/subcontas/:id/devolver com o mesmo corpo. O dinheiro volta do cliente para a sua conta.
{"id":2,"subcontaId":2,"sentido":"devolucao","valorCentavos":1000,"repetida":false,"subconta":{"...":"..."},"revendedor":{"saldoCentavos":46000}}Regras que protegem o dinheiro
- `valorCentavos` é número inteiro positivo (
5000, nunca"5000"nem50.00). Qualquer outra coisa:400 VALOR_INVALIDO. Teto de R$ 100.000 por operação. - Só sai o que está disponível. Se não houver saldo, a resposta é
402 SALDO_INSUFICIENTEcomdisponivelCentavos, e nada se move. Ao devolver, o valor que está reservado por ligação em andamento não pode sair:disponivelCentavosjá desconta essa reserva. - `Idempotency-Key` evita transferência dupla. Mande nele o id da operação no seu sistema (até 80 caracteres). Se a resposta se perder e você repetir a mesma chamada com a mesma chave, a transferência não acontece de novo: você recebe a original com
"repetida": truee HTTP200(a primeira vez é201). A mesma chave com outro valor ou outra subconta dá409 IDEMPOTENCIA_CONFLITO. Recomendamos mandar sempre. - As duas pontas (a sua carteira e a do cliente) mudam juntas, numa operação só. Não existe meio-termo.
Extrato do cliente
curl "https://alfredvoice.com.br/api/revenda/subcontas/2/extrato?limite=50" -H "Authorization: Bearer av_..."{"subconta":{"id":2,"nome":"Pizzaria do João","...":"..."},
"extrato":[
{"id":4,"quando":"2026-09-24 15:05:37","titulo":"Crédito devolvido","detalhe":"Devolvido ao revendedor","valorCentavos":-1000,"saldoDepoisCentavos":4000,"entrada":false},
{"id":3,"quando":"2026-09-24 15:05:37","titulo":"Crédito recebido","detalhe":"Recebido do revendedor","valorCentavos":5000,"saldoDepoisCentavos":5000,"entrada":true}
],"temMais":false,"proximoAntesDe":null}Cada ligação, torpedo, SMS e conversa cobrada aparece aqui, com o saldo depois de cada linha. Paginação igual à lista de subcontas (limite, antesDe).
5. Agir em nome do cliente (X-Subconta)
Mande o header em qualquer rota abaixo e ela passa a valer para aquele cliente: os agentes são dele, o WhatsApp é dele, o custo sai do saldo dele.
curl https://alfredvoice.com.br/api/saldo \
-H "Authorization: Bearer av_..." \
-H "X-Subconta: 2"{"saldoCentavos":4000,"disponivelCentavos":4000}| Área | Rotas |
|---|---|
| Conta | GET /me, GET /saldo, GET /carteira (extrato) |
| Agentes de IA | GET /agentes, POST /agentes, GET /agentes/:id, PUT /agentes/:id, DELETE /agentes/:id |
POST /canais/whatsapp/conectar, POST /canais/whatsapp/link-conexao, GET /canais/whatsapp/status, PUT /canais/whatsapp, POST /canais/whatsapp/desconectar | |
| Balão do site | GET /agentes/:id/canal-site, PUT /agentes/:id/canal-site, DELETE /agentes/:id/canal-site |
| Torpedo de voz | GET /voz/vozes, POST /voz/sintetizar, POST /voz/audios, GET /voz/audios, DELETE /voz/audios/:id, GET /voz/preco/:audioId, POST /voz/campanhas, GET /voz/campanhas, GET /voz/campanhas/:id, PUT /voz/campanhas/:id, POST /voz/campanhas/:id/pausar, POST /voz/campanhas/:id/retomar, POST /voz/campanhas/:id/parar |
| Ligação com agente | POST /ligacoes, GET /ligacoes, GET /ligacoes/:id, campanhas em lote (ver Integração por API) |
| SMS | GET /sms, POST /sms/orcamento, POST /sms/enviar, GET /sms/relatorio, GET /sms/relatorio/:id, POST /sms/relatorio/:id/parar |
| Conversas | GET /conversas, GET /conversas/:id, GET /conversas/:id/mensagens, POST /conversas/:id/modo, POST /conversas/:id/responder, POST /conversas/:id/status, POST /conversas/:id/vista |
Regras:
- O
X-Subcontasó funciona com a sua chave e só com subconta sua. Subconta de outro revendedor responde404 SUBCONTA_NAO_ENCONTRADA, sem dizer se ela existe. - Dentro de uma subconta não dá para mexer na revenda (
403 SO_REVENDEDOR), e o dinheiro não entra por recarga direta:POST /carteira/recargaresponde403 RECARGA_PELO_REVENDEDOR. O saldo do cliente entra só por transferência sua. - Sem o header, a chamada vale para a sua conta de revendedor.
6. Agentes de IA
Cada subconta nasce com um agente de ligação. Para atender no WhatsApp ou no site, crie um agente do canal certo — cada canal tem o seu.
curl -X POST https://alfredvoice.com.br/api/agentes \
-H "Authorization: Bearer av_..." -H "X-Subconta: 2" -H "Content-Type: application/json" \
-d '{"nome":"Atendente WhatsApp","canal":"whatsapp"}'{"id":2}canal: ligacoes (padrão), whatsapp ou site. Depois ensine o agente:
curl -X PUT https://alfredvoice.com.br/api/agentes/2 \
-H "Authorization: Bearer av_..." -H "X-Subconta: 2" -H "Content-Type: application/json" \
-d '{"promptRobo":"Você atende a Pizzaria do João. Seja cordial e objetivo.","contextoProduto":"Pizza grande: R$ 59\nPizza média: R$ 45\nEntrega grátis acima de R$ 80"}'| Campo | Para que serve |
|---|---|
promptRobo | Quem o agente é e como ele fala. |
contextoProduto | A base de conhecimento: cardápio, tabela de preço, perguntas frequentes. Pode ser longa (até cerca de 900 KB). Numa ligação de voz, o agente consulta a base na hora em vez de decorar tudo. |
roteiroRobo | Passo a passo da conversa (opcional, um passo por linha). |
nome | Como o agente se apresenta. |
smsTexto, smsGatilho | SMS depois da ligação (desligado, conectadas, todas). |
Ver um agente:
curl https://alfredvoice.com.br/api/agentes/2 -H "Authorization: Bearer av_..." -H "X-Subconta: 2"{"id":2,"nome":"Atendente WhatsApp","personaId":"yasmin","voz":"feminina","canal":"whatsapp","promptRobo":"","contextoProduto":"","roteiroRobo":"","smsHabilitado":1,"principal":0,"smsTexto":"","smsGatilho":"desligado"}GET /agentesdevolve{"smsHabilitado":1,"agentes":[{"id","nome","voz","canal","ativo"}]}.DELETE /agentes/:idapaga. Não apaga o agente principal da conta (409 AGENTE_PRINCIPAL) nem um agente que está atendendo no WhatsApp ou no site (409 CANAL_LIGADO): troque o agente do canal ou desligue o canal antes.
7. WhatsApp do cliente
O número de WhatsApp do seu cliente responde texto, áudio e ligação de voz com o agente, tudo no mesmo número. Para conectar, o cliente precisa ler um QR Code com o celular. Você escolhe como entregar esse QR:
- Opção A — no seu sistema: a API devolve o QR e você mostra na sua tela. É o caminho 100% com a sua marca.
- Opção B — link pronto: a API devolve um link que você manda para o cliente (e-mail, WhatsApp, SMS). Ele abre, vê o QR e conecta. Você não desenha nada. A página não mostra a nossa marca, mas o endereço é do nosso domínio.
Nas duas opções, agenteId é um agente de canal whatsapp da subconta (senão 400 AGENTE_NAO_E_DE_WHATSAPP), e quando o número entra ou cai você recebe whatsapp.conectado / whatsapp.desconectado no aviso automático.
Opção A — mostrar o QR no seu sistema
curl -X POST https://alfredvoice.com.br/api/canais/whatsapp/conectar \
-H "Authorization: Bearer av_..." -H "X-Subconta: 2" -H "Content-Type: application/json" \
-d '{"agenteId":2}'{"status":"aguardando_qr","qrcode":"data:image/png;base64,iVBORw0KGgo...","qrTexto":null}qrcodeé uma imagem (data URL) pronta para um<img src>. Quando viernull, useqrTexto: é o conteúdo do código, para você desenhar o QR com qualquer biblioteca de QR Code.- O código expira em segundos. Consulte o status a cada 3 a 5 segundos até conectar: enquanto ninguém lê, cada consulta traz um código novo.
- Logo depois de conectar, o código pode levar alguns segundos para existir:
statusvemaguardando_qrcomqrcodeeqrTextonulos. Não é erro — mostre "gerando o código" e siga consultando.
curl https://alfredvoice.com.br/api/canais/whatsapp/status -H "Authorization: Bearer av_..." -H "X-Subconta: 2"{"status":"aguardando_qr","numero":null,"qrcode":"data:image/png;base64,iVBORw0KGgo...","qrTexto":null}{"status":"conectado","numero":"5521999990000"}status: nao_conectado, aguardando_qr (com qrcode/qrTexto novos), conectado ou desconectado.
O que dizer ao seu cliente na tela: *"Abra o WhatsApp no celular → Aparelhos conectados → Conectar um aparelho → aponte a câmera para o código."*
Opção B — link de conexão pronto
curl -X POST https://alfredvoice.com.br/api/canais/whatsapp/link-conexao \
-H "Authorization: Bearer av_..." -H "X-Subconta: 2" -H "Content-Type: application/json" \
-d '{"agenteId":2}'{"url":"https://alfredvoice.com.br/conectar/bm5p5Sxb1nFtzNf1ZOBtIYgL15sPWoOPxknXykkFiI8","expiraEm":"2026-09-24 16:00:38"}- O link vale 30 minutos. Passou disso, a página avisa que expirou e você gera outro. Pode gerar quantos precisar.
- A página mostra o nome do seu cliente, as instruções e o QR, troca o código sozinha e mostra Conectado! quando ele lê.
- O link é a autorização: mande só para o seu cliente. Não guardamos o link, só uma impressão dele.
- Se o número já estiver conectado:
409 JA_CONECTADOcom onumero.
Trocar o agente, desconectar
PUT /canais/whatsappcom{"agenteId": 5}: outro agente de WhatsApp passa a atender o mesmo número.POST /canais/whatsapp/desconectar: solta o número (o cliente também pode desconectar pelo celular).
Um aviso para o seu cliente: o número precisa estar só no WhatsApp Business do celular dele. Número ligado também a outra plataforma de API oficial pode recusar ligações de voz.
8. Balão no site do cliente
O agente de canal site atende num balão de conversa (texto e voz) no site do seu cliente. Você liga o balão pela API e entrega ao cliente uma linha para colar no site.
curl -X PUT https://alfredvoice.com.br/api/agentes/3/canal-site \
-H "Authorization: Bearer av_..." -H "X-Subconta: 2" -H "Content-Type: application/json" \
-d '{"dominios":["pizzariadojoao.com.br","www.pizzariadojoao.com.br"],"cor":"#E53935","nomeExibido":"Pizzaria do João","saudacao":"Oi! Quer ver o cardápio?"}'{"canal":{"id":1,"ativo":1,"chavePublica":"pk_de7184a4b98e575f0a30652ca86d390b","dominios":["pizzariadojoao.com.br"],"cor":"#E53935","nomeExibido":"Pizzaria do João","saudacao":"Oi! Quer ver o cardápio?","vozAtiva":1,"criado_em":"2026-09-24 15:30:38"}}A linha que o cliente cola antes do </body> do site (com a chavePublica da resposta):
<script src="https://alfredvoice.com.br/widget.js" data-chave="pk_de7184a4b98e575f0a30652ca86d390b" async></script>| Campo | Descrição |
|---|---|
dominios | Os endereços do site, sem https:// e sem caminho (pizzariadojoao.com.br). Até 20. O balão só abre nesses domínios: colado em outro site, ele não responde. Formato errado: 400 DOMINIOS_INVALIDOS. |
cor | Cor do balão, #RRGGBB. Errada: 400 COR_INVALIDA. |
nomeExibido | Nome no topo do balão (até 40). |
saudacao | Primeira mensagem (até 200). |
vozAtiva | 1/0: se o visitante pode falar com o agente por voz. |
gerarChave | true troca a chavePublica (o código antigo para de funcionar — o cliente precisa colar o novo). |
GET /agentes/:id/canal-sitedevolve a configuração atual ({"canal": null}se ainda não foi ligado).DELETE /agentes/:id/canal-sitedesliga o balão.- O agente precisa ser de canal
site: senão400 AGENTE_NAO_E_DE_SITE. - A
chavePublicafica visível no site do cliente de propósito: ela só abre o balão, nos domínios cadastrados. Não é a sua chave de API.
As conversas do balão aparecem em GET /conversas?canal=site (seção 12).
9. Torpedo de voz
Uma gravação que toca para uma lista inteira. Só é cobrado o que conecta; quem não atende não custa nada.
1) O áudio: gerar por texto ou enviar o seu
Gerar a gravação a partir de texto (a geração tem custo, debitado na hora):
curl https://alfredvoice.com.br/api/voz/vozes{"vozes":[{"id":"ana","nome":"Ana","genero":"feminina","descricao":"Calorosa e próxima"},{"id":"rafael","nome":"Rafael","genero":"masculina","descricao":"Firme e direto"}]}curl -X POST https://alfredvoice.com.br/api/voz/sintetizar \
-H "Authorization: Bearer av_..." -H "X-Subconta: 2" -H "Content-Type: application/json" \
-d '{"texto":"Olá! A Pizzaria do João está com promoção hoje: pizza grande por 49 reais.","vozId":"ana","nome":"Promo sexta"}'Ou enviar um arquivo seu. O corpo é o arquivo cru, não JSON:
curl -X POST "https://alfredvoice.com.br/api/voz/audios?nome=Promo%20sexta" \
-H "Authorization: Bearer av_..." -H "X-Subconta: 2" \
-H "Content-Type: audio/mpeg" --data-binary @promo.mp3Os dois devolvem o áudio (201):
{"id":1,"nome":"Promo sexta","token":"va_...","duracaoSeg":18,"bytes":150000,"criadoEm":"2026-09-24 15:31:11"}Aceitamos até 25 MB e até 5 minutos; o arquivo é convertido para MP3 no servidor. Texto para gerar: até 4.000 caracteres. GET /voz/audios lista; DELETE /voz/audios/:id apaga.
Quanto custa cada ligação que conectar com esse áudio:
curl https://alfredvoice.com.br/api/voz/preco/1 -H "Authorization: Bearer av_..." -H "X-Subconta: 2"{"duracaoSeg":18,"custoPorLigacaoCentavos":20,"custoProvavelCentavos":20,"risco":false,"margemSeg":5,"duracaoSeguraSeg":24}2) A campanha
curl -X POST https://alfredvoice.com.br/api/voz/campanhas \
-H "Authorization: Bearer av_..." -H "X-Subconta: 2" -H "Content-Type: application/json" \
-d '{"nome":"Promo sexta","audioId":1,"numeros":["21999990001","+55 21 98888-0002","abc"],"quando":"2026-09-26T18:00:00Z","smsGatilho":"conectadas","smsTexto":"Peça pelo link: exemplo.com"}'{"id":1,"clienteId":2,"nome":"Promo sexta","audioId":1,"status":"agendada","motivo":null,"quando":"2026-09-26 18:00:00","smsTexto":"Peça pelo link: exemplo.com","smsGatilho":"conectadas","iniciadaEm":null,"concluidaEm":null,"criadaEm":"2026-09-24 15:31:11","total":2,"fila":2,"conectaram":0,"naoConectaram":0,"gastoCentavos":0,"invalidos":["abc"]}| Campo | Descrição |
|---|---|
audioId | O áudio do passo 1. |
numeros | Lista (array) ou texto separado por linha, vírgula ou ponto e vírgula. Até 100.000. Os inválidos voltam em invalidos, e o resto segue. |
quando | Data e hora ISO (UTC). Vazio ou "agora" dispara em seguida. |
nome | Nome da campanha (opcional). |
smsGatilho / smsTexto | SMS depois da ligação: desligado, conectadas ou todas; texto até 160 caracteres. |
status da campanha: agendada, disparando, pausada (com motivo), concluida, cancelada ou perdida.
3) Controlar
POST /voz/campanhas/:id/pausar: segura a fila (o que já foi chamado fica).POST /voz/campanhas/:id/retomar: continua de onde parou, sem ligar de novo para quem já foi chamado.POST /voz/campanhas/:id/parar: encerra; o resto da fila não é chamado.PUT /voz/campanhas/:id(mesmo corpo da criação): edita, só enquanto ainda não começou (depois disso,409 JA_COMECOU).GET /voz/campanhas/GET /voz/campanhas/:id: andamento, comtotal,fila,conectaram,naoConectaram,gastoCentavosemotivo.
Sem saldo para continuar, a campanha pausa sozinha com o motivo; transfira saldo e chame retomar.
O torpedo dispara na hora que você marcar: escolha horário comercial. Campanha que não conseguiu começar até 2 horas depois da hora marcada vira perdida e não dispara mais (para não ligar para ninguém fora de hora).
Cada número que termina gera torpedo.finalizado; a lista inteira gera torpedo.campanha_concluida (seção 13).
10. Ligação com agente de IA
É o agente conversando com a pessoa, não uma gravação. Funciona igual à Integração por API (seções 3, 4 e 6), com X-Subconta no header:
curl -X POST https://alfredvoice.com.br/api/ligacoes \
-H "Authorization: Bearer av_..." -H "X-Subconta: 2" -H "Content-Type: application/json" \
-d '{"numero":"21999990001","agenteId":1,"referencia":"lead-8842"}'Sem agenteId, atende o agente principal da subconta. O resultado chega em ligacao.finalizada. Ligações com agente saem entre 8h e 20h (horário de Brasília).
11. SMS
curl -X POST https://alfredvoice.com.br/api/sms/orcamento \
-H "Authorization: Bearer av_..." -H "X-Subconta: 2" -H "Content-Type: application/json" \
-d '{"texto":"Seu pedido saiu!","destinos":["21999990001","x"]}'{"quantidade":1,"invalidos":1,"custoCentavos":7,"saldoCentavos":0}POST /sms/enviar com o mesmo corpo envia de verdade. Até 160 caracteres por mensagem e até 200.000 números por envio (maxDestinos); fora isso, o limite é o seu saldo. GET /sms mostra se o SMS está liberado, o saldo, o preço e o máximo de números por envio:
{"liberado":1,"saldoCentavos":4000,"custoPorCemCentavos":650,"maxDestinos":200000,"maxTexto":160}Até 500 números, nada muda: a resposta só volta depois do envio, já com o resultado (200, com enviados e falharam). Acima de 500 números, o envio inteiro é cobrado na hora e a resposta volta logo, com 202, enquanto os SMS saem em segundo plano:
{"ok":true,"envioId":"a1b2c3","total":5000,"emSegundoPlano":true,"cobradoCentavos":32500,"saldoCentavos":7500,"invalidos":["x"]}Acompanhe pelo relatório (GET /sms/relatorio/{id}): status fica enviando até terminar e pendentes diz quantos números ainda estão na fila. Quando termina, tudo que não saiu volta sozinho ao saldo e custoCentavos mostra o valor final: o preço por SMS do momento do envio vezes os que saíram. Mudança de preço durante o envio não altera a conta desse envio.
Para interromper, POST /sms/relatorio/{id}/parar. O que ainda não saiu não é mais enviado e volta ao saldo na hora:
{"ok":true,"status":"parado","estornadoCentavos":20800}Se algum número estava preso no canal exatamente na hora, a resposta vem com "status":"parando" e estornadoCentavos: 0: o envio já não manda mais nada e o estorno entra sozinho em seguida. Acompanhe pelo relatório até o status virar parado.
Envio de outra conta ou inexistente responde 404 {"error":"NAO_ENCONTRADO"}; envio que já terminou (ou já foi parado) responde 409 {"error":"JA_TERMINOU"}. Se a nossa plataforma reiniciar no meio, o envio continua sozinho de onde parou. Um número que estava saindo exatamente na hora do reinício não é mandado de novo (para não chegar duas vezes) e o valor dele volta ao saldo.
Sem saldo, o envio não sai:
{"error":"SEM_SALDO","custoCentavos":7,"saldoCentavos":0}Relatório de SMS
GET /sms/relatorio lista os envios da conta (ou da subconta, com X-Subconta), do mais recente para o mais antigo, até 500:
[{"id":"a1b2c3","criadoEm":"2026-10-02 14:30:00","texto":"Seu pedido saiu!","total":2,"enviados":1,"falharam":1,"invalidos":0,"custoCentavos":7,"origem":"api","legado":false,"status":"concluido","pendentes":0}]totalé quantos números foram para envio;enviadosefalharamsão o resultado;invalidossão os números descartados antes de enviar.custoCentavosé o que foi cobrado, já descontado o estorno dos que falharam.origeméapi(chave) oupainel.statuséenviando(ainda saindo, em segundo plano),parando(você parou e o estorno ainda vai entrar),parado(você parou, conta fechada) ouconcluido.pendentesé quantos números ainda estão na fila (0 quando terminou).- Enquanto está
enviando,custoCentavosé o valor cobrado na hora; o estorno do que não saiu entra quando o envio termina ou é parado. entregamostra o aviso de entrega recebido, só para consulta (não muda cobrança nem estorno):entregues,naoEntregues(não entregue, rejeitado ou expirado),aguardando(já saiu, ainda sem aviso) esemAviso(enviados antes do aviso existir, ou sem identificador). Sem aviso ainda não quer dizer que falhou.- Envios feitos antes do relatório aparecem com
legado: true: só têm data, quantidade (pode virnull) e custo;texto,enviados,falharam,invalidoseorigemvêmnull(statusvemconcluido).
GET /sms/relatorio/{id} devolve o mesmo envio com a lista dos números, em páginas de até 1.000 (?limite= até 5.000). numerosTotal é quantos números já foram processados e proximo é o valor para pedir a página seguinte (?apos=<proximo>); null quando acabou:
{"id":"a1b2c3","criadoEm":"2026-10-02 14:30:00","texto":"Seu pedido saiu!","total":2,"enviados":1,"falharam":1,"invalidos":0,"custoCentavos":7,"origem":"api","legado":false,"status":"concluido","pendentes":0,
"numeros":[{"numero":"5521999990001","status":"enviado","motivo":null},{"numero":"5521999990002","status":"falhou","motivo":"FALHOU"}],"numerosTotal":2,"proximo":null}Em cada número, entrega é o último aviso de entrega (DELIVRD entregue, UNDELIV não entregue, REJECTD rejeitado, EXPIRED expirado; null se ainda não chegou aviso), entregaEm é quando o aviso chegou e temAviso diz se esse número pode receber aviso de entrega (false para envios antigos ou sem identificador).
O id é um texto (o mesmo da lista). Envio de outra conta, inexistente ou legado responde 404 {"error":"NAO_ENCONTRADO"}. Durante um envio em segundo plano, numeros traz só os que já foram processados; os que estão na fila aparecem em pendentes. Um número com motivo INTERROMPIDO estava saindo quando a plataforma reiniciou: não foi mandado de novo e o valor voltou ao saldo.
12. Conversas (WhatsApp e site)
Tudo o que o agente conversou, para você mostrar no seu sistema e deixar um atendente humano assumir quando precisar.
curl "https://alfredvoice.com.br/api/conversas?canal=whatsapp&limite=50" -H "Authorization: Bearer av_..." -H "X-Subconta: 2"{"conversas":[{"id":1,"canal":"whatsapp","agenteId":2,"agenteNome":"Atendente WhatsApp","origemDominio":null,"modo":"agente","status":"aberta","contatoNome":"Maria","contatoNumero":"5521988887777","iniciadaEm":"2026-09-24 15:31:11","ultimaEm":"2026-09-24 15:31:11","vistaEm":null,"mensagens":2,"vozSeg":0,"custoCentavos":0,"ultimaMensagem":"Oi, Maria! A pizza grande sai por R$ 59.","naoLidas":1}]}Filtros: canal (whatsapp ou site), modo (agente ou humano), busca (nome ou telefone), limite e antes (id, para a próxima página).
curl https://alfredvoice.com.br/api/conversas/1/mensagens -H "Authorization: Bearer av_..." -H "X-Subconta: 2"{"mensagens":[{"id":1,"quem":"visitante","tipo":"texto","texto":"Oi, qual o preço da pizza grande?","criadoEm":"2026-09-24 15:31:11"},{"id":2,"quem":"agente","tipo":"texto","texto":"Oi, Maria! A pizza grande sai por R$ 59.","criadoEm":"2026-09-24 15:31:11"}],"temMais":false}quem: visitante (a pessoa) ou agente (o agente ou o atendente).
Atendente humano assume e responde:
curl -X POST https://alfredvoice.com.br/api/conversas/1/modo \
-H "Authorization: Bearer av_..." -H "X-Subconta: 2" -H "Content-Type: application/json" \
-d '{"modo":"humano"}'{"modo":"humano"}curl -X POST https://alfredvoice.com.br/api/conversas/1/responder \
-H "Authorization: Bearer av_..." -H "X-Subconta: 2" -H "Content-Type: application/json" \
-d '{"texto":"Oi, Maria! Aqui é o João. Posso te ajudar?"}'- No modo
humanoo agente para de responder;{"modo":"agente"}devolve a conversa para ele. respondersó funciona no modohumano(senão409 AGENTE_NO_COMANDO) e com o WhatsApp conectado (senão503 NUMERO_DESCONECTADO). Texto de 1 a 2.000 caracteres.POST /conversas/:id/vistamarca como lida;POST /conversas/:id/statuscom{"status":"concluida"}arquiva e{"status":"aberta"}reabre.
13. Avisos automáticos
Os avisos de todas as subcontas chegam na URL cadastrada na sua conta, no envelope de sempre, com um campo a mais: subconta.
{
"evento": "torpedo.finalizado",
"entrega_id": "8f14e45f-ceea-467a-9c2e-6b1d2b8a3f41",
"enviado_em": "2026-09-26T18:02:11.204Z",
"subconta": { "id": 2, "referencia": "crm-cliente-1042" },
"dados": {
"campanha_id": 51, "numero": "5521999990001", "codigo": "17288241",
"status": "conectou", "resultado": "Atendido", "duracao_seg": 18, "custo_centavos": 20
}
}Use subconta.referencia para achar o cliente no seu banco. Assinatura, headers, repetição e reenvio funcionam igual à Integração por API (seção 5). Responda 2xx em até 8 segundos; se não, repetimos.
| Evento | Quando dispara | `dados` |
|---|---|---|
torpedo.finalizado | Um número do torpedo terminou (uma vez por número). | campanha_id, numero, codigo, status (conectou/nao_conectou), resultado, duracao_seg, custo_centavos |
torpedo.campanha_concluida | A lista inteira do torpedo terminou. | campanha_id, nome, total, conectaram, nao_conectaram, gasto_centavos |
whatsapp.conectado | O número do cliente entrou no ar. | numero, status |
whatsapp.desconectado | O número caiu ou foi desconectado. | numero, status |
ligacao.finalizada | Uma ligação com agente terminou. | ver Integração por API |
campanha.concluida | Uma lista de ligações com agente terminou. | idem |
sms.enviado | Saiu o SMS de pós-ligação. | idem |
conversa.contato | O agente colheu nome, telefone ou e-mail numa conversa. | idem |
reuniao.marcada | O agente marcou uma reunião. | idem |
torpedo.finalizado com resultado: "sem retorno" significa que a operadora não confirmou o desfecho em até 60 minutos: fica como não conectado e não é cobrado.
14. Consumo: quanto cada cliente gastou
curl "https://alfredvoice.com.br/api/revenda/consumo?de=2026-09-01&ate=2026-09-30" -H "Authorization: Bearer av_..."{"de":"2026-09-01","ate":"2026-09-30","gastoTotalCentavos":470,
"subcontas":[{"subcontaId":2,"nome":"Pizzaria do João","referencia":"crm-cliente-1042",
"centavos":{"ligacaoAgente":120,"torpedo":300,"sinteseDeVoz":0,"sms":50,"conversas":0,"outros":0,"recebido":5000,"devolvido":1000,"estornos":0},
"gastoTotalCentavos":470}]}de/ateno formatoAAAA-MM-DD, em UTC, comateincluso. Sem eles: os últimos 30 dias. Data em outro formato:400 PERIODO_INVALIDO.subcontaId=2filtra um cliente só.gastoTotalCentavosé o consumo: ligação com agente, torpedo, geração de voz, SMS e conversas, menos estornos.recebidoedevolvidosão as suas transferências e não entram no gasto.- É o valor que saiu do nosso lado. Quanto você cobra do seu cliente é com você.
15. Erros
Todo erro vem como {"error":"CODIGO"}, às vezes com campos que ajudam (disponivelCentavos, invalidos, mensagem). Nunca devolvemos detalhe interno.
Gerais
| HTTP | Código | Significado | O que fazer |
|---|---|---|---|
| 401 | TOKEN_REQUERIDO | Faltou o header Authorization. | Mande Bearer av_.... |
| 401 | NAO_AUTORIZADO | Chave inexistente, revogada ou de conta desativada. | Confira a chave no painel. |
| 403 | SO_SESSAO | Rota só do painel (ex.: criar chave, cadastrar aviso). | Faça pelo painel. |
| 404 | NAO_ENCONTRADO | Recurso não existe ou não é dessa conta. | Confira o id e o X-Subconta. |
| 429 | LIMITE | Passou do teto de requisições da chave. | Espere o Retry-After (segundos). |
| 500 | ERRO_INTERNO | Deu errado do nosso lado. | Tente de novo; se insistir, fale com o suporte com o horário. |
Revenda e saldo
| HTTP | Código | Significado |
|---|---|---|
| 400 | FALTA_NOME | Subconta sem nome. |
| 400 | VALOR_INVALIDO | valorCentavos não é inteiro positivo (ou passou de R$ 100.000). |
| 400 | PERIODO_INVALIDO | de/ate fora do formato AAAA-MM-DD ou invertidos. |
| 402 | SALDO_INSUFICIENTE | Não há saldo disponível para mover. Vem com disponivelCentavos. |
| 403 | SEM_REVENDA | A conta não tem revenda liberada, ou a chave não é de revendedor. |
| 403 | SO_REVENDEDOR | Rota de revenda chamada com X-Subconta. |
| 403 | SUBCONTA_INATIVA | A subconta está desativada. |
| 403 | RECARGA_PELO_REVENDEDOR | Recarga direta dentro de uma subconta: o saldo entra só por transferência. |
| 404 | SUBCONTA_NAO_ENCONTRADA | Não existe, ou não é sua. |
| 409 | REFERENCIA_EM_USO | Já existe subconta sua com essa referencia. |
| 409 | LIMITE_SUBCONTAS | Você chegou ao máximo combinado. Fale com a gente. |
| 409 | IDEMPOTENCIA_CONFLITO | A mesma Idempotency-Key foi usada para outra operação. |
Agentes e balão do site
| HTTP | Código | Significado |
|---|---|---|
| 400 | FALTA_NOME | Agente sem nome. |
| 400 | CANAL_INVALIDO | canal diferente de ligacoes, whatsapp ou site. |
| 400 | GATILHO_INVALIDO | smsGatilho diferente de desligado, conectadas ou todas. |
| 400 | CORPO_INVALIDO | Corpo da requisição malformado. |
| 413 | TEXTO_GRANDE_DEMAIS | Base de conhecimento acima do limite. |
| 409 | AGENTE_PRINCIPAL | Apagar o agente principal da conta. |
| 409 | CANAL_LIGADO | Apagar um agente que está atendendo no WhatsApp ou no site. |
| 400 | AGENTE_NAO_E_DE_SITE | Ligar o balão num agente que não é de canal site. |
| 400 | DOMINIOS_INVALIDOS | Domínio com https://, caminho, porta ou mais de 20. |
| 400 | COR_INVALIDA | Cor fora do formato #RRGGBB. |
| HTTP | Código | Significado | O que fazer |
|---|---|---|---|
| 400 | AGENTE_NAO_E_DE_WHATSAPP | O agenteId não é de canal whatsapp. | Crie ou use um agente whatsapp. |
| 409 | JA_CONECTADO | O número já está conectado (vem com numero). | Nada a fazer; para trocar, desconecte antes. |
| 404 | LINK_INVALIDO | Link de conexão que não existe (ou de subconta desativada). | Gere outro. |
| 410 | LINK_EXPIRADO | Passaram os 30 minutos do link. | Gere outro. |
| 502 | MOTOR_INDISPONIVEL | O serviço de WhatsApp não respondeu agora. | Tente de novo em alguns segundos. |
| 503 | INDISPONIVEL | Conexão de WhatsApp temporariamente fora do ar. | Tente de novo em alguns minutos. |
Torpedo de voz
| HTTP | Código | Significado |
|---|---|---|
| 400 | SEM_AUDIO / AUDIO_NAO_ENCONTRADO | Faltou o audioId, ou o áudio não existe mais. |
| 400 | SEM_NUMERO | Nenhum número válido na lista (vem com invalidos). |
| 400 | NUMEROS_DEMAIS | A lista passou de 100.000 números. |
| 400 | HORA_INVALIDA | quando que não é data e hora. |
| 409 | JA_COMECOU | Editar campanha que já começou (dá para pausar ou parar). |
| 404 | NAO_ENCONTRADA | Campanha não existe ou não é dessa conta. |
| 400 | SEM_ARQUIVO / GRANDE_DEMAIS / NAO_E_AUDIO | Envio de áudio vazio, acima de 25 MB ou que não é áudio. |
| 400 | CURTO_DEMAIS / LONGO_DEMAIS | Áudio com menos de 1 segundo ou mais de 5 minutos. |
| 400 | TEXTO_VAZIO / TEXTO_LONGO / VOZ_DESCONHECIDA | Geração de áudio sem texto, com texto acima do limite ou com vozId fora da lista. |
| 402 | SALDO_INSUFICIENTE | Sem saldo para gerar o áudio por texto. |
| 503 | SINTESE_INDISPONIVEL | A geração de voz não respondeu agora; tente de novo em instantes. |
Os erros de áudio e de campanha vêm com mensagem em português, pronta para mostrar ao usuário.
SMS
| HTTP | Código | Significado |
|---|---|---|
| 400 | TEXTO_VAZIO | Mensagem sem texto. |
| 400 | SEM_DESTINO | Nenhum número válido (vem com invalidos). |
| 402 | SEM_SALDO | Saldo não cobre o envio inteiro (vem com custoCentavos e saldoCentavos). Nada é cobrado. |
| 404 | NAO_ENCONTRADO | Parar: envio inexistente ou de outra conta. |
| 400 | DESTINOS_DEMAIS | Mais de 200.000 números num envio (vem com limite). |
| 409 | JA_TERMINOU | Parar: o envio já terminou ou já foi parado. |
| 403 | SMS_NAO_LIBERADO | SMS não está liberado nesta conta. Fale com a gente. |
Conversas
| HTTP | Código | Significado |
|---|---|---|
| 400 | MODO_INVALIDO | modo diferente de agente ou humano. |
| 400 | MENSAGEM_INVALIDA | Resposta vazia ou com mais de 2.000 caracteres. |
| 400 | STATUS_INVALIDO | status diferente de aberta ou concluida. |
| 409 | AGENTE_NO_COMANDO | Responder sem antes passar para o modo humano. |
| 503 | NUMERO_DESCONECTADO | O WhatsApp da subconta está desconectado. |
Ligação com agente
| HTTP | Código | Significado |
|---|---|---|
| 400 | NUMERO_INVALIDO | O telefone não é um número brasileiro válido. |
| 403 | SO_DEMO | A conta ainda não está liberada para ligação real. |
| 404 | AGENTE_NAO_ENCONTRADO | O agenteId não é dessa conta. |
16. Limites
| Limite | Valor |
|---|---|
| Requisições por chave | 120 por minuto, somando todas as subcontas que usam aquela chave. Ao estourar: 429 LIMITE + Retry-After. Com muitos clientes, distribua em até 5 chaves. |
| Consultas ao link de conexão | 60 por minuto por IP (a página consulta a cada 4 segundos). |
| Subcontas | O máximo combinado com a gente (veja maximo em GET /revenda). |
| Transferência | Até R$ 100.000 por operação. |
| Base de conhecimento do agente | Cerca de 900 KB de texto. |
| Torpedo | 100.000 números por campanha; áudio até 25 MB e 5 minutos; texto para gerar voz até 4.000 caracteres. |
| SMS | 160 caracteres por mensagem; até 200.000 números por envio (e o saldo). Acima de 500 números, o envio sai em segundo plano. |
Orçamento de SMS (POST /sms/orcamento) | 600 por hora por conta. Corpo até 10 MB só em conta com SMS liberado (as outras: 256 KB). |
| Resposta de atendente na conversa | 2.000 caracteres. |
| Link de conexão do WhatsApp | 30 minutos. |
| Resposta do seu servidor ao aviso | 8 segundos. |
17. Roteiro de teste de ponta a ponta
Faça uma vez com o seu próprio celular antes de pôr um cliente real:
GET /revenda: confirma a chave e o saldo.POST /revenda/subcontascom{"nome":"Teste","referencia":"teste-1"}e anote oid.POST /revenda/subcontas/:id/transferircom{"valorCentavos":500}e umaIdempotency-Key. Repita a mesma chamada e confira"repetida": true.- WhatsApp: com
X-Subconta, crie um agentewhatsapp, ponha umcontextoProdutocurto e gere o link em/canais/whatsapp/link-conexao. Abra o link, leia o QR com um WhatsApp de teste e mande uma mensagem para esse número: o agente responde, e chegawhatsapp.conectadona sua URL. - Site: crie um agente
site, ligue o balão com o domínio de uma página sua, cole a linha<script>e converse. - Torpedo: gere um áudio em
/voz/sintetizare crie uma campanha com o seu número. Atenda: chegatorpedo.finalizadoe depoistorpedo.campanha_concluida, com asubconta. GET /revenda/consumo: o torpedo e a geração de voz aparecem no gasto da subconta.POST /revenda/subcontas/:id/devolvercom o que sobrou, depoisPUTcom{"ativa":false}.
Fechou o roteiro, a integração está pronta.