Appearance
Integração utilizando Webphone API4COM
Essa integração permite que os usuários façam chamadas telefônicas de dentro do seu CRM ou aplicação, atendendo no Webphone da API4COM, a extensão para o Google Chrome. A sua aplicação pede a chamada pela API e recebe o resultado de cada chamada no seu webhook, sem precisar carregar um Webphone.
O Webphone da API4COM já entrega o atendimento automático das chamadas pedidas pela API, a transferência, o histórico de chamadas e as atualizações, sem desenvolvimento do seu lado.
Um token por usuário
Cada usuário que faz chamadas cadastra na sua aplicação o próprio token de acesso. Tudo o que a aplicação faz em nome dele (buscar o ramal, configurar o webhook e realizar chamadas) usa o token dele.
A API4COM confere o plano, a situação e os limites de requisições do usuário dono do token, e envia o webhook para o endereço cadastrado por esse usuário. Por isso, cada usuário precisa ligar com o próprio token: assim, cada um liga dentro do próprio plano e os resultados chegam separados por usuário.
Resumo do que a integração guarda para cada usuário:
- O token de acesso do usuário
- O ramal do usuário
- A configuração do webhook do usuário
Criação da conta e dos usuários
- Crie a conta da empresa no Portal da API4COM e ative-a pelo link enviado por e-mail. Quem cria a conta é o administrador.
- No portal, o administrador convida os usuários que vão fazer chamadas, informando e-mail, senha e plano de cada um.
- Cada usuário ativa o próprio acesso pelo e-mail de convite. O e-mail só ativa o usuário: a senha é a que o administrador definiu no convite.
Importante:
- O ramal de cada usuário é criado pela API4COM junto com o usuário, quando ele é convidado com plano. A sua aplicação não cria ramais: ela busca o ramal do usuário (veja Buscando o ramal do usuário).
- O administrador também é um usuário: se ele também for fazer chamadas, cadastra o próprio token como os demais.
- Para um usuário novo, repita os passos 2 e 3 e cadastre o token dele na sua aplicação. Os usuários já cadastrados não mudam.
Gerando o token de cada usuário
Cada usuário gera o próprio token no Portal da API4COM no menu Tokens de acesso → Novo Token de Acesso, com validade Nunca expira, e cola o token na tela de integrações da sua aplicação. O administrador da conta não gera token por outro usuário.
O token também pode ser criado pela API, com o login do próprio usuário. Faça o Login com o e-mail e a senha do usuário e, com o token retornado, crie um token que nunca expira:
JavaScript
const axios = require('axios');
const url = 'https://api.api4com.com/api/v1/users/accessTokens';
const config = {
headers: {
'Authorization': '<token do login do usuário>'
}
};
const payload = {
ttl: -1
};
axios.post(url, payload, config).then(response => {
console.log(response.data);
}).catch(error => {
console.error(error);
});Resposta de sucesso:
JSON
{
"id": "YggyHfrLEHAWmKiUFbXsT93Tkw2xjwHUbwJ6mgw4Vz5YGubReFGw34HmhrhZDUBM",
"ttl": -1,
"created": "2025-01-01T00:00:00.000Z"
}O id retornado é o token de acesso do usuário.
Para confirmar que o token é válido, consulte o usuário dono do token e mostre na sua aplicação a quem ele pertence:
JavaScript
const axios = require('axios');
const url = 'https://api.api4com.com/api/v1/users/me';
const config = {
headers: {
'Authorization': '<token do usuário>'
}
};
axios.get(url, config).then(response => {
console.log(response.data);
}).catch(error => {
console.error(error);
});Resposta de sucesso:
JSON
{
"uuid": "356b20ce-143f-4847-8cf1-a79959f4b390",
"name": "Marina Alves",
"email": "marina@empresa.com.br",
"role": "USER"
}Importante:
- Guarde o token só no seu backend. Ele não expira e permite ligar em nome do usuário: nunca o envie para o navegador nem o coloque em URL, log ou mensagem de erro.
- O token deixa de valer quando é removido no portal, quando vence ou quando o usuário troca a senha. A partir daí, qualquer requisição responde
401: marque o token do usuário como inválido e peça um token novo. - Se o usuário for trocar a senha que recebeu do administrador, ele deve trocar antes de gerar o token, pois a troca invalida os tokens já gerados.
- Mais detalhes em Autenticação.
Buscando o ramal do usuário
Ao cadastrar o token do usuário, busque uma vez o ramal dele com o token dele e guarde junto do token:
JavaScript
const axios = require('axios');
const url = 'https://api.api4com.com/api/v1/integrations';
const config = {
headers: {
'Authorization': '<token do usuário>'
},
params: {
'filter[where][gateway]': 'sippulse'
}
};
axios.get(url, config).then(response => {
console.log(response.data);
}).catch(error => {
console.error(error);
});Resposta de sucesso:
JSON
[
{
"id": 5821,
"gateway": "sippulse",
"metadata": {
"domain": "empresa.api4com.com",
"username": "1012",
"password": "Xk3pQ7rTm2"
}
}
]Importante:
- O
usernameé o ramal do usuário, usado nos camposextensionecallerao realizar uma chamada. - Use o ramal guardado nas chamadas; não consulte a cada chamada.
- Se a lista vier vazia, o ramal ainda não foi vinculado ao usuário. No convite com plano, o ramal só é criado depois do pagamento. Tente novamente mais tarde.
- Busque o ramal de novo quando uma chamada responder
404: o ramal mudou ou foi removido.
Configuração do Webhook
O webhook é configurado uma vez por usuário, com o token do usuário, por meio de uma Integração de Usuário. A API4COM envia para o endereço configurado um aviso quando a chamada é atendida (channel-answer) e outro quando a chamada termina (channel-hangup).
Escolha um identificador para a sua integração, em letras minúsculas e sem espaços (nos exemplos, minha-integracao). Ele é usado no campo gateway da integração e no metadata de cada chamada.
Antes de criar, verifique se o usuário já tem a integração:
JavaScript
const axios = require('axios');
const url = 'https://api.api4com.com/api/v1/integrations';
const config = {
headers: {
'Authorization': '<token do usuário>'
},
params: {
'filter[where][gateway]': 'minha-integracao'
}
};
axios.get(url, config).then(response => {
console.log(response.data);
}).catch(error => {
console.error(error);
});Em seguida, crie ou atualize a integração:
JavaScript
const axios = require('axios');
const url = 'https://api.api4com.com/api/v1/integrations';
const config = {
headers: {
'Authorization': '<token do usuário>'
}
};
const payload = {
// id: 5822, // somente se a consulta acima retornou a integração
gateway: 'minha-integracao',
webhook: true,
webhookConstraint: {
metadata: {
gateway: 'minha-integracao'
}
},
metadata: {
webhookUrl: 'https://seu-webhook.com/callback',
webhookVersion: 'v1.8',
webhookTypes: ['channel-answer', 'channel-hangup']
}
};
axios.patch(url, payload, config).then(response => {
console.log(response.data);
}).catch(error => {
console.error(error);
});Resposta de sucesso:
JSON
{
"id": 5822,
"gateway": "minha-integracao",
"webhook": true,
"webhookConstraint": {
"metadata": {
"gateway": "minha-integracao"
}
},
"metadata": {
"webhookUrl": "https://seu-webhook.com/callback",
"webhookVersion": "v1.8",
"webhookTypes": ["channel-answer", "channel-hangup"]
}
}Importante:
- Somente as chamadas que atenderem as restrições de
webhookConstraintsão enviadas para o webhook, ou seja, somente aquelas que tenhamgateway: 'minha-integracao'nometadatada chamada. - Se a integração já existir e o
idnão for enviado, a API responde422com o códigoINTEGRATION_ALREADY_EXISTS. - O campo
webhookUrldeve usar HTTPS. Uma URL por cliente ou conta (por exemplo,https://seu-webhook.com/callback/cliente-8841) ajuda a identificar de quem é cada aviso assim que ele chega.
Instalação do Webphone
Cada usuário instala o Webphone da API4COM no Google Chrome. No Portal da API4COM, acesse o menu "Webphone" e clique no link para instalar, ou instale a extensão direto na Chrome Web Store.
Após instalar, o usuário clica no ícone do Webphone na barra de ferramentas do Chrome e faz login com o próprio usuário da API4COM, o mesmo que gerou o token cadastrado na sua aplicação.
Para validar a instalação, verifique na parte superior do Webphone se o status está como "Você está online" (ícone circular verde). Caso haja algum problema, o ícone fica laranja ou vermelho.
Atendimento automático
Ao realizar uma chamada pela API, a API4COM primeiro liga para o ramal do usuário e só depois para o número de destino. A chamada para o ramal chega identificada pelo cabeçalho SIP X-Api4comintegratedcall: true, e o Webphone da API4COM a atende automaticamente. O Webphone não avisa a sua aplicação: use o aviso channel-answer do webhook para mostrar que a chamada foi atendida.
Importante:
- Com o Webphone fechado ou offline, a chamada não é realizada e a API responde
424. Oriente o usuário a manter o Webphone aberto e com o status "Você está online" para ligar pela sua aplicação. - O Webphone deve estar aberto em apenas um navegador por usuário.
Realizando uma chamada
Endpoint descontinuado
A rota POST /dialer está descontinuada. Se a sua integração ainda utiliza /dialer, migre para POST /calls (documentado abaixo) assim que possível.
O botão de ligar da sua aplicação chama o seu backend, que realiza a chamada com o token e o ramal do mesmo usuário:
JavaScript
const axios = require('axios');
const url = 'https://api.api4com.com/api/v1/calls';
const config = {
headers: {
'Authorization': '<token do usuário>'
},
timeout: 90000
};
const payload = {
extension: '1012',
caller: '1012',
called: '+5511987654321',
metadata: {
gateway: 'minha-integracao',
clienteId: 'c_207',
dealId: 'deal_48213',
callRef: 'cr_000731'
}
};
axios.post(url, payload, config).then(response => {
console.log(response.data);
}).catch(error => {
console.error(error);
});Resposta de sucesso:
JSON
{
"status": "200",
"id": "1PkXhmBsYAvr9legLB2d7BimT0Q",
"message": "successful request"
}Importante:
- O campo
Authorizationdeve ser preenchido com o token do usuário dono do ramal informado emextension. - O campo
extensiondeve ser preenchido com o ramal do usuário (ousernameobtido em Buscando o ramal do usuário). - O campo
callerdeve ser preenchido com o mesmo valor deextension. - O campo
calleddeve ser preenchido com o número de telefone que você deseja ligar, com código do país + DDD + número (exemplo:+5511987654321). - O campo
metadatadeve conter ogatewayconfigurado no webhook, para que a chamada seja enviada ao seu webhook. As demais chaves são devolvidas em todos os avisos da chamada: use identificadores simples, em texto, e não envie dados pessoais como nome ou telefone do cliente. Um identificador único por tentativa (comocallRef) ajuda a localizar a chamada depois. - A resposta
200é enviada quando o Webphone do usuário atende, o que leva menos de um segundo com o atendimento automático. Ela não indica que o destino atendeu: para isso, use o avisochannel-answerdo webhook. Configure um timeout HTTP de 90 segundos. - O
idretornado corresponde ao mesmo ID da chamada exibido na Lista de Chamadas e pode ser usado para encerrar a chamada comPOST /calls/{id}/hangup. - Faça uma chamada por vez por usuário. O limite é de 15 chamadas por minuto por ramal (veja Rate Limit).
Respostas possíveis:
| Resposta | O que aconteceu | O que a aplicação deve fazer |
|---|---|---|
200 | O Webphone do usuário atendeu | Mostrar "Chamando" e guardar o id |
401 | Token inválido, removido ou vencido | Marcar o token do usuário como inválido e pedir um token novo |
402 · 403 | O plano ou a situação do usuário não permitem ligar agora | Orientar o usuário a falar com o administrador da conta |
404 | Ramal não encontrado (EXTENSION_NOT_FOUND) | Buscar o ramal de novo |
422 | Número ou parâmetro inválido | Pedir para corrigir o número |
424 | Webphone fechado, offline ou não atendeu | Pedir ao usuário para deixar o Webphone aberto e online |
429 | Mais de 15 chamadas por minuto no ramal | Aguardar o tempo indicado em RateLimit-Reset |
503 | Indisponibilidade temporária | Tentar novamente em alguns segundos |
| Sem resposta | Tempo esgotado | Não repetir automaticamente: a chamada pode ter sido realizada |
Recebendo o Webhook
O endereço configurado recebe uma requisição POST com um JSON em dois momentos de cada chamada: quando o destino atende (channel-answer) e quando a chamada termina (channel-hangup).
Somente chamadas feitas pela API geram webhook
Faça todas as chamadas por POST /calls. Uma chamada discada direto no teclado do Webphone não tem o metadata com o gateway da sua integração e não é enviada ao seu webhook.
Exemplo do aviso de chamada atendida:
JSON
{
"version": "v1.8",
"eventType": "channel-answer",
"id": "2ee13fa4-975c-499d-bbb8-5177ff418316",
"domain": "empresa.api4com.com",
"direction": "outbound",
"caller": "1012",
"called": "+5511987654321",
"startedAt": "2026-10-23 14:02:11",
"recordUrl": "https://listener.api4com.com/files/listen/2ee13fa4-975c-499d-bbb8-5177ff418316.mp3",
"metadata": {
"gateway": "minha-integracao",
"clienteId": "c_207",
"dealId": "deal_48213",
"callRef": "cr_000731"
}
}Exemplo do aviso de chamada finalizada:
JSON
{
"version": "v1.8",
"eventType": "channel-hangup",
"id": "2ee13fa4-975c-499d-bbb8-5177ff418316",
"domain": "empresa.api4com.com",
"direction": "outbound",
"caller": "1012",
"called": "+5511987654321",
"startedAt": "2026-10-23 14:02:05",
"answeredAt": "2026-10-23 14:02:11",
"endedAt": "2026-10-23 14:06:40",
"duration": 269,
"hangupCause": "NORMAL_CLEARING",
"hangupCauseCode": "16",
"recordUrl": "https://listener.api4com.com/files/listen/2ee13fa4-975c-499d-bbb8-5177ff418316.mp3",
"metadata": {
"gateway": "minha-integracao",
"clienteId": "c_207",
"dealId": "deal_48213",
"callRef": "cr_000731"
}
}Os campos retornados são:
- O campo
versionindica a versão do webhook. - O campo
eventTypeindica o tipo de evento:channel-answerouchannel-hangup. - O campo
idé o identificador da chamada. - O campo
domainé o domínio da conta. - O campo
directionindica se a chamada é de entrada ou saída. - O campo
calleré o ramal que realizou a chamada. - O campo
calledé o número de telefone que recebeu a chamada, no formato internacional (E.164). - O campo
startedAté a data e hora de início da chamada. Nochannel-answer, é a data e hora em que o destino atendeu. - O campo
answeredAté a data e hora em que a chamada foi atendida (somente nochannel-hangup). - O campo
endedAté a data e hora em que a chamada foi finalizada (somente nochannel-hangup). - O campo
durationé a duração da conversa em segundos (somente nochannel-hangup). - O campo
hangupCauseé o motivo do desligamento da chamada (somente nochannel-hangup). Consulte a tabela de códigos de status. - O campo
hangupCauseCodeé o código do motivo do desligamento da chamada (somente nochannel-hangup). - O campo
recordUrlé a URL do arquivo de áudio da chamada. - O campo
metadataé um objeto com os dados enviados emmetadataao realizar a chamada.
Importante:
- Responda
200imediatamente e processe o aviso depois. Sem200, a entrega é repetida uma vez, cerca de um minuto depois. - O mesmo aviso pode chegar mais de uma vez: use
id+eventTypepara identificar cada aviso. - O
recordUrlsó tem áudio quando a chamada foi atendida, e o arquivo pode levar alguns minutos para ficar disponível. - Uma chamada finalizada com
NORMAL_CLEARINGe duração zero é enviada comoNO_ANSWER. - Se o aviso de fim de uma chamada não chegar em alguns minutos, consulte as chamadas do usuário com o token dele em
GET /callse procure o identificador enviado nometadata. - Os avisos trazem o número discado e o link da gravação: não os grave em logs abertos.
Removendo um usuário da integração
Quando um usuário deixar de usar a sua aplicação, remova a integração do webhook dele com DELETE /integrations/{id}, usando o token dele, e apague o token e o ramal guardados. Isso não altera o Webphone nem o usuário na conta da API4COM.
Considerações finais
Neste guia, você aprendeu como integrar o Webphone da API4COM com o seu CRM ou aplicação, com cada usuário usando o próprio token.
A documentação completa da API4COM está disponível em https://developers.api4com.com.
Se você tiver alguma dúvida ou precisar de ajuda, entre em contato com o suporte da API4COM.
