- No navegador,
@polymorfa/browserconecta microfones, câmeras e alto-falantes a uma chamada, e@polymorfa/reacte@polymorfa/elementsrenderizam a interface da chamada. - No código do servidor,
@polymorfa/sdk/callspermite que a sua aplicação fale e ouça em uma chamada, por exemplo para executar um agente de voz. - No seu servidor,
@polymorfa/sdkfaz, atende e encerra chamadas e gerencia as configurações de chamadas.
Como as chamadas funcionam
- A chamada. Ela toca, é atendida ou recusada e termina. Encerrá-la desconecta todos.
- Participantes. Um participante é quem age na chamada. A Polymorfa o
deriva da credencial:
- Um token de cliente age como
client:<ephemeralId>, usando oephemeralIdcom que foi emitido. Tokens de cliente não podem indicar outro participante. - Uma chave de equipe ou um token de projeto age como
server:<participant>. Informe o nome opcionalparticipant(de 1 a 128 caracteres entreA-Z,a-z,0-9,.,_,:,@e-). O padrão éserver:default.
- Um token de cliente age como
- Conexões. Cada aba do navegador ou cliente de servidor que transporta o áudio e o vídeo de um participante é uma conexão. Um participante pode ter várias conexões. Sair fecha uma conexão e nunca encerra a chamada.
Autentique clientes de navegador
Navegadores e aplicativos móveis usam um token de cliente. Emita o token no seu servidor comPOST /platform/client-tokens e envie-o ao cliente. Mantenha as
chaves de equipe e os tokens de projeto no seu servidor. Consulte
Tokens de cliente.
Ative as ações de chamada de que o cliente precisa nas
regras de cliente da sessão:
O SDK de navegador precisa das três para fazer e atender chamadas. Um token de
cliente age apenas em chamadas da sessão à qual está vinculado, e essa sessão
ainda precisa pertencer ao projeto do token. O
ephemeralId dele precisa usar
os caracteres de participante listados acima; caso contrário, as requisições
de chamada retornam 403.
Tokens de cliente expiram. Passe ao SDK uma função que busca um token novo no
seu servidor; o SDK renova o token nas conexões abertas antes que ele expire.
Quando um token é revogado ou deixa de autorizar a sessão, o SDK informa um
erro unauthorized e pede um novo token à sua função. Ele faz o mesmo quando a
Polymorfa não consegue confirmar o token por 3 minutos porque as verificações
estão com limite de taxa ou temporariamente indisponíveis.
Chamadas no navegador
createClientTokenProvider() solicita tokens a /api/polymorfa/token na sua
própria origem. Implemente essa rota no seu servidor e retorne um token de
cliente para o usuário conectado.
CallSurface mostra as chamadas que estão tocando, o palco da chamada, o vídeo
dos participantes, a lista de participantes e os controles de microfone,
câmera, dispositivos, saída e encerramento da chamada. IncomingCallCard,
CallStage, ParticipantVideoGrid, ParticipantList, CallControls e
DialPad estão disponíveis individualmente. Em HTML puro, atribua o mesmo
controlador ao elemento <pmfa-call> de @polymorfa/elements.
Para construir (build) a sua própria interface, leia
calls.controller.getSnapshot() e chame place, answer, join, reject,
leave, end, setMuted e switchDevice no controlador. Várias chamadas
podem tocar ao mesmo tempo; o controlador as lista em snapshot.invitations e
nunca recusa uma chamada por você. O vídeo de cada participante remoto é um
stream separado em controller.remoteVideos, identificado pelo participante.
Chame await calls.dispose() quando a sua aplicação liberar a interface de
chamadas.
Chamadas a partir do código do servidor
call.audiotransporta o áudio combinado da chamada como PCM mono de 16 bits com sinal, na taxacall.audio.sampleRate, nos dois sentidos. Escreva o áudio em tempo real.call.videorecebe o vídeo de cada um dos outros participantes como um stream separado de quadros H.264 e envia um stream H.264 seu.call.video.sourcesindica o participante por trás de cada stream. Envie um keyframe (uma unidade de acesso com uma fatia IDR, com SPS e PPS nela ou antes dela) quando o eventokeyframeRequestdisparar. Os outros participantes começam a receber o seu vídeo a partir do seu primeiro IDR.- Quando a conexão cai, o cliente a reconecta e mantém a chamada.
@polymorfa/sdk/calls roda no Node.js 22 ou posterior, ou no Node.js 20 com
uma implementação de WebSocket passada nas opções.
Atender, entrar ou recusar
Toda chamada recebida geracall.received. Os SDKs a expõem como uma chamada
que está tocando.
Escolha
exclusive em cada atendimento:
exclusive: truefaz o claim da chamada. Os outros participantes param de tocar, não podem atender nem se conectar, e as conexões abertas deles são fechadas. Use quando uma pessoa cuida da chamada, por exemplo quando o primeiro agente a atender fica com ela.exclusive: false(o padrão) mantém a chamada compartilhada. Os outros participantes continuam tocando e podem entrar.
call_claimed, e assim os participantes
que já entraram continuam conectados. Em uma chamada que você fez, o
participante que fez a chamada é o participante que atendeu.
Quando outro participante faz o claim de uma chamada, o SDK indica que o claim
foi feito em outro lugar. Pare de tocar e não recuse a chamada: recusar encerra
a chamada para o participante que atendeu.
Uma chamada que ninguém atende nem recusa dentro da janela de toque termina com
call.missed e o motivo ring_timeout. Depois de atender, conecte a mídia logo;
uma chamada sem mídia conectada termina com o motivo setup_timeout.
Fazer uma chamada
No navegador, chamecalls.controller.place("+15550100", { video: true }).
No código do servidor, chame client.place("+15550100"). No seu servidor:
callId enquanto o dispositivo da pessoa chamada toca.
call.accepted vem em seguida, quando a pessoa atende, e call.ended quando a
chamada termina. to é um número de telefone E.164 ou um ID de usuário. Um
token de cliente faz chamadas pela sessão à qual está vinculado; uma chave de
equipe ou um token de projeto precisa indicar session.
Chamadas para pessoas que nunca conversaram com o número
O WhatsApp às vezes restringe um número a iniciar conversas e chamadas apenas com pessoas com quem ele já conversou. Enquanto essa restrição está ativa, a Polymorfa recusa uma chamada para qualquer outra pessoa com403 number_restricted antes que algo chegue ao WhatsApp, e retorna
Retry-After quando o WhatsApp informou um horário de término. Chamadas para
pessoas com quem o número já conversou continuam funcionando, assim como as
chamadas recebidas. A mesma verificação vale para
convites.
session.restriction_updated avisa quando a restrição começa, muda e termina,
para que você possa pausar a prospecção a frio e retomá-la automaticamente. Se
uma chamada chegar ao WhatsApp enquanto o número está restrito, ela termina com
reason: "call_restricted".
Consulte Boas práticas de chamadas para
saber como escolher para quem ligar e como aumentar o volume de um número novo.
Os inícios de chamadas realizadas compartilham um limite por minuto para cada
sessão de origem da sua equipe. Mudar o destino ou usar outra chave ou outro
token de cliente não reinicia esse limite. Uma chamada acima do limite falha
com 429 sem tocar no destino. Espere o próximo minuto antes de tentar
novamente.
O WhatsApp pode restringir um número de dispositivo vinculado cujas chamadas
recebem denúncias. O risco é maior em chamadas para pessoas que nunca
interagiram com o número. Consulte Boas práticas de chamadas
antes de fazer chamadas em volume.
Controle de chamadas pelo servidor
messaging.voip também atende, entra, recusa e encerra chamadas a partir do
seu servidor, e convida mais pessoas:
accept retorna answered (true quando esta requisição atendeu a chamada,
false quando ela entrou em uma chamada já atendida), answeredBy e
exclusive. Consulte a referência da API para os campos de
requisição e resposta.
Convidar mais pessoas
addParticipant faz tocar o telefone de outro usuário do WhatsApp para que ele
entre em uma chamada ao vivo, transformando uma chamada individual em uma
chamada em grupo. Os SDKs informam quando participantes entram, mudam de estado
e saem; os webhooks informam as mesmas mudanças como
call.participant_joined, call.participant_state e
call.participant_left. Os participantes usam o mesmo id de usuário da
Polymorfa em todos os lugares. Aliases conhecidos aparecem como phoneNumber,
bsuid ou username. Os campos audioMuted e video são reservados e
continuam false porque o WhatsApp não informa nenhum dos dois estados por
participante.
Para adicionar pessoas pela sua própria aplicação, dê um token de cliente a
cada pessoa e peça que ela entre na chamada
compartilhada.
Áudio, vídeo e configurações de chamadas
Cada participante recebe um único stream de áudio combinado. As pessoas no WhatsApp ouvem todos os participantes que você conecta à chamada. O que os seus próprios participantes ouvem depende do modo conferência.Modo conferência
Os seus participantes são todos que você conecta a uma chamada: pessoas em um navegador, os seus servidores e bots e o seu PBX por meio de um tronco SIP. O modo conferência decide se eles ouvem uns aos outros.
Ninguém ouve a própria voz em nenhum dos modos. Um participante com mais de uma
conexão com a mesma chamada, por exemplo durante uma reconexão, não ouve a si
mesmo pela outra conexão.
Desative o modo conferência quando cada participante fala com o lado do
WhatsApp de forma independente, por exemplo um bot que transcreve a chamada ao
lado de um agente humano que não deve ouvir o bot. Altere o modo por sessão:
revision aumenta a cada alteração. Para aplicar uma
alteração somente se ninguém tiver alterado as configurações desde a sua
leitura, envie a revision que você leu como expectedRevision; a atualização
então falha com 409 state_conflict se elas tiverem mudado. Leia as
configurações de novo e tente novamente.
Uma sessão sem configurações salvas retorna callsEnabled: true,
conferenceMode: true, inboundRoute: "clients", sipTrunkId: null,
sipClaim: true, hostCloudApiCalls: false, revision: 0 e
updatedAt: null. Ler exige sessions:read e salvar exige
sessions:manage, com uma chave de equipe ou um token de projeto. Tokens de
cliente não podem ler nem alterar as configurações de chamadas. Uma
configuração salva vale para uma chamada na próxima vez que um participante a
atender ou se conectar a ela, inclusive em chamadas em andamento. Quando não é
possível ler a configuração, atender e conectar falham com 503 em vez de usar
um valor que você não escolheu. Você também pode alterá-la no Console, nos
detalhes do número. Consulte Get call settings
e Update call settings.
Desativar chamadas em um número
DefinacallsEnabled como false para interromper as chamadas em uma sessão
sem desconectá-la:
- fazer uma chamada, atender ou entrar em uma, convidar um participante e
conectar mídia falham com
403 calls_disabled. Iniciar ou atender uma chamada pelo endpoint/callsda Graph API falha com um erro de permissão; - as chamadas recebidas são recusadas. Você ainda recebe
call.received, seguido decall.rejectedecall.ended; e - um tronco SIP não pode fazer chamadas pela sessão.
callsEnabled de volta como true para permitir
chamadas novamente. Uma alteração chega às chamadas recebidas e aos troncos SIP
em cerca de um minuto.
A Polymorfa encaminha o vídeo de cada participante como um stream separado e
não os combina em uma grade. O lado do WhatsApp da chamada recebe um único
stream de vídeo: a câmera do primeiro participante que envia vídeo, enquanto
esse participante continuar conectado.
Cada chamada informa as suas capabilities: video e invite. Os componentes
do SDK ocultam os controles que uma chamada não suporta.
Números da Cloud API
Um número conectado pela WhatsApp Business Cloud API continua atendendo as chamadas recebidas pela sua integração com a Graph API até que você ativehostCloudApiCalls nas configurações de chamadas dele:
hostCloudApiCalls: true, os seus apps de chamadas recebem e atendem as
chamadas recebidas do número, e o endpoint /calls da Graph API se recusa a
atendê-las. Com false (o padrão), o Polymorfa Calls não hospeda chamadas
recebidas no número, e a sua integração com a Graph API as atende. Enquanto as
chamadas estão desativadas, a Polymorfa
recusa as chamadas recebidas do número, seja qual for essa configuração.
A configuração vale para chamadas que chegam depois da alteração. As chamadas
que você faz com os SDKs sempre usam o Polymorfa Calls.
As chamadas em um número da Cloud API funcionam da mesma forma nos SDKs, com
estes limites:
- As chamadas são individuais e somente de áudio. As
capabilitiesdelas informamvideo: falseeinvite: false. Fazer uma chamada de vídeo ou convidar um participante falha comunsupported_for_connection. Atender com vídeo atende apenas com áudio. - Antes de você fazer uma chamada, o destinatário precisa conceder à sua
empresa permissão para ligar para ele. Sem isso, fazer a chamada falha com
call_permission_required. - O WhatsApp permite de 30 a 60 segundos para atender uma chamada recebida da Cloud API. Atenda em até 30 segundos para evitar uma chamada perdida.
Webhooks
Histórico de chamadas
O Console lista as suas chamadas com estado, direção e duração, e mostra os participantes, as conexões e as medições de qualidade de cada chamada, os diagnósticos que o seu app informou e os resultados das entregas de webhook. Proprietários e administradores podem encerrar uma chamada ao vivo ou remover uma conexão dela ali.Análises e registros de chamadas
Três endpoints da Platform API leem o seu histórico de chamadas. Eles aceitam uma chave de equipe ou um token de projeto comsessions:read. Um
token de projeto lê apenas o próprio projeto; uma chave de equipe lê a
equipe inteira, a menos que você informe projectId. O resumo das chamadas do
Console usa o mesmo endpoint de estatísticas.
Uma chamada mantém o projeto original depois que o número dela é excluído.
Reutilizar o nome do número em outro projeto não transfere o histórico, as
estatísticas nem o uso dele. Registros cujo projeto original é desconhecido têm
projectId: null e aparecem apenas em leituras de toda a equipe.
Os três aceitam os mesmos filtros:
Cada chamada tem um único resultado:
answered: a mídia se conectou. Chamadas atendidas ainda em andamento contam aqui.declined: um participante ou a outra parte recusou, ou a linha estava ocupada.missed: ninguém atendeu antes de a chamada parar de tocar, ou quem ligou desligou primeiro.failed: a chamada terminou antes de se conectar por qualquer outro motivo, como uma falha de conexão ou de capacidade.in_progress: a chamada ainda está tocando.
Estatísticas
since e until, o intervalo são os últimos 7 dias. groupBy seleciona
os grupos:
day(o padrão) ehourretornam um grupo por dia ou por hora emtimezone, incluindo os vazios. Um intervalo comdaycobre no máximo 366 dias, e um intervalo comhour, no máximo 31 dias.sessionretorna um grupo por número, começando pelos que têm mais chamadas, até 500 números.groupsTruncatedétruequando mais números tiveram chamadas.outcomeretorna um grupo por resultado.
timezone aceita um nome IANA como UTC, CET ou Europe/Lisbon, em
maiúsculas ou minúsculas; o timezone da resposta é o nome canônico.
Deslocamentos UTC e strings POSIX como UTC+3 são recusados. Os grupos por
hora são horas do relógio local: no dia em que um fuso muda o relógio, a hora
pulada não tem grupo e a hora repetida forma um único grupo. Cada grupo e os
totals informam calls, a contagem de cada resultado, answerRate,
totalDurationSeconds e averageDurationSeconds. answerRate é o número de
chamadas atendidas dividido pelo número de chamadas que não estão mais tocando.
As durações contam apenas o tempo conectado. heatmap sempre tem 168 células,
uma por dia da semana (1 é segunda-feira) e hora, em timezone.
Registros detalhados de chamadas
Cada registro temcallId, projectId, sessionId, direction, upstream,
outcome, state, hasVideo, peerRef, startedAt, connectedAt,
endedAt, durationSeconds e endReason. peerRef é o pseudônimo da outra
parte, específico da equipe: a mesma pessoa tem o mesmo peerRef em todas as
chamadas da sua equipe, mas ele não é um número de telefone e a Polymorfa não
consegue convertê-lo de volta em um.
GET /platform/calls retorna os registros do mais novo para o mais antigo.
Passe page.nextCursor como cursor, com os mesmos filtros, para ler a
próxima página.
GET /platform/calls/export retorna os mesmos registros em CSV (format=csv,
o padrão) ou em JSON delimitado por quebras de linha (format=ndjson), até
1.000 por requisição. Cada página CSV começa com uma linha de cabeçalho. Quando
mais registros correspondem aos filtros, o cabeçalho de resposta
Polymorfa-Next-Cursor contém o cursor da próxima página:
=, +, -, @, uma tabulação ou um
retorno de carro recebe um apóstrofo como prefixo, para que planilhas não o
executem como fórmula.
Use os endpoints HTTP autenticados acima para análises, registros e
exportações de chamadas. O SDK TypeScript e a CLI não expõem essas operações de
análise.
O histórico de chamadas pode ficar atrasado em relação aos eventos ao vivo
durante uma falha temporária de registro. As escritas que falharam são tentadas
novamente por até 24 horas. Um evento atrasado não faz uma chamada aceita ou
finalizada voltar a tocar.
Retenção de dados de chamadas
A exclusão começa em uma data anunciada com antecedência no
changelog. Até lá, escolher um período registra a sua escolha e
não exclui nada.
- registros de chamadas: o histórico de chamadas que o Console e a API listam;
- eventos de chamadas: o histórico de participantes e conexões de cada chamada;
- os diagnósticos que os seus apps informam sobre as conexões deles nas chamadas.
Depois que a exclusão estiver em funcionamento, a Polymorfa exclui os dados de
chamadas em até 24 horas depois que eles ficam mais antigos que o período. Um
acúmulo grande, como os dados de chamadas já armazenados quando a exclusão
começa ou quando você encurta o período, pode levar mais tempo para ser
excluído. Uma chamada é medida a partir do momento em que começou; uma chamada
que ainda está tocando ou em andamento é mantida até terminar. O período cobre
todos os projetos da equipe.
Leia a configuração com qualquer chave de equipe ou token de projeto que tenha
sessions:read:
sessions:manage.
Envie retentionDays apenas com a política custom:
- Tokens de projeto podem ler a configuração, mas não alterá-la; uma alteração
falha com
403. Tokens de cliente não podem fazer nenhuma das duas coisas. - Uma equipe sem configuração salva retorna
revision: 0eupdatedAt: null.revisionaumenta a cada alteração. Envie arevisionque você leu comoexpectedRevisionpara recusar a atualização com409 state_conflictse alguém tiver alterado a configuração depois da sua leitura. - Uma política nomeada com um
retentionDaysdiferente, oucustomsem um, falha com400 invalid_parameter. appliesTolista os tipos de dados de chamadas que o período cobre. Quando a Polymorfa passar a armazenar um novo tipo de dado de chamada, ele será adicionado a essa lista e seguirá o mesmo período.
Informar diagnósticos de chamadas pelo seu app
O seu app pode enviar as medições de qualidade e os erros que mede em cada uma das conexões dele. O Console os mostra na página de detalhes da chamada, ao lado das medições do serviço de mídia da Polymorfa. Os relatórios são opcionais; uma chamada sem eles funciona da mesma forma. Envie os relatórios comPOST /messaging/voip/calls/{id}/reports. Os SDKs da
Polymorfa não os enviam por você; chame o endpoint pelo seu app. Use a
credencial que transporta a chamada: um token de cliente precisa da ação
voip_signal, e uma chave de equipe ou um token de projeto informa como
server:<participant>.
202 com { "success": true }.
As medições de qualidade são números inteiros ou nomes curtos:
Códigos de erro:
Os relatórios aceitam apenas esses campos. A Polymorfa não aceita mensagens de
erro, nomes de dispositivos, endereços IP, SDP nem user agents em um relatório;
uma requisição que os contenha falha com
400.
Limites:
- Cada conexão pode enviar um relatório de qualidade a cada 5 segundos e 20
relatórios de erro por minuto. Os excedentes falham com
429. Os relatórios também contam para a regrarateLimitde um token de cliente. - A Polymorfa aceita relatórios enquanto a chamada está ao vivo e por 10
minutos depois que ela termina. Relatórios posteriores falham com
409, ou com410quando a chamada terminou porque o host de mídia dela foi perdido. - A Polymorfa mantém até 200 relatórios por chamada. Nesse limite, um relatório
de qualidade substitui o relatório de qualidade mais antigo da mesma conexão.
Um relatório de qualidade de uma conexão sem nenhum relatório de qualidade
armazenado, e todo relatório de erro, retornam
202, mas não são mantidos. - A Polymorfa autoriza a chamada, não a conexão: qualquer participante como o
qual a sua credencial pode agir pode enviar relatórios de qualquer
connectionIdem uma chamada que essa credencial alcança.
Limites de acesso
Toda operação de chamada fica dentro do limite de recursos da credencial. Chaves de equipe podem controlar chamadas em toda a equipe. Tokens de projeto podem controlar chamadas em qualquer sessão desse projeto. Tokens de cliente podem controlar chamadas apenas na sessão à qual estão vinculados. Uma chamada fora desse limite falha com409 antes que a operação altere o estado da
chamada.
As regras de cliente valem para estabelecimentos de chamada, chamadas feitas e
convites:
maxSetupsPerMinutelimita os estabelecimentos de chamada por usuário de token de cliente (padrão 10). Cada chamada feita e cada convite contam como um estabelecimento. Em uma chamada existente, o primeiro atendimento ou a primeira conexão bem-sucedida conta como um estabelecimento; os seguintes na mesma chamada não contam.allowedNumberé uma lista separada por vírgulas de números E.164 para os quais um token de cliente pode ligar ou que ele pode convidar.maxConcurrencylimita as chamadas que um usuário de token de cliente mantém ao mesmo tempo. Uma chamada ocupa a vaga dela até terminar.
429.
Uma chamada libera a vaga de simultaneidade quando termina, mesmo que o seu
cliente se desconecte sem encerrá-la. Se uma chamada feita ou um
estabelecimento falhar sem um resultado confirmado, a vaga fica reservada por
até quatro horas, porque a chamada ainda pode estar ativa caso a resposta tenha
se perdido.
Erros
Os SDKs geram esses erros como erros tipados;
call_claimed é um
CallClaimedError. Consulte Erros para o objeto de erro.